Class AndroidBuildConfig

  • All Implemented Interfaces:
    BuildEngineAction, AllowsNonAnnotatedFields, HasDeclaredAndExtraDeps, BuildRule, HasNameAndType, Comparable<BuildRule>

    public class AndroidBuildConfig
    extends AbstractBuildRuleWithDeclaredAndExtraDeps
    BuildRule that can generate a BuildConfig.java file and compile it so it can be used as a Java library.

    This rule functions as a java_library that can be used as a dependency of an android_library, but whose implementation may be swapped out by the android_binary that transitively includes the android_build_config. Specifically, its compile-time implementation will use non-constant-expression (see JLS 15.28), placeholder values (because they cannot be inlined) for the purposes of compilation that will be swapped out with final, production values (that can be inlined) when building the final APK. Consider the following example:

     android_build_config(
       name = 'build_config',
       package = 'com.example.pkg',
     )
    
     # The .java files in this library may contain references to the boolean
     # com.example.pkg.BuildConfig.DEBUG because :build_config is in the deps.
     android_library(
       name = 'mylib',
       srcs = glob(['src/**/*.java']),
       deps = [
         ':build_config',
       ],
     )
    
     android_binary(
       name = 'debug',
       package_type = 'DEBUG',
       keystore =  '//keystores:debug',
       manifest = 'AndroidManifest.xml',
       target = 'Google Inc.:Google APIs:19',
       deps = [
         ':mylib',
       ],
     )
    
     android_binary(
       name = 'release',
       package_type = 'RELEASE',
       keystore =  '//keystores:release',
       manifest = 'AndroidManifest.xml',
       target = 'Google Inc.:Google APIs:19',
       deps = [
         ':mylib',
       ],
     )
     
    The :mylib rule will be compiled against a version of BuildConfig.java whose contents are:
     package com.example.pkg;
     public class BuildConfig {
       private BuildConfig() {}
       public static final boolean DEBUG = !Boolean.parseBoolean(null);
     }
     
    Note that the value is not a constant expression, so it cannot be inlined by javac. When building :debug and :release, the BuildConfig.class file that :mylib was compiled against will not be included in the APK as the other transitive Java deps of the android_binary will. The BuildConfig.class will be replaced with one that corresponds to the value of the package_type argument to the android_binary rule. For example, :debug will include a BuildConfig.class file that is compiled from:
     package com.example.pkg;
     public class BuildConfig {
       private BuildConfig() {}
       public static final boolean DEBUG = true;
     }
     
    whereas :release will include a BuildConfig.class file that is compiled from:
     package com.example.pkg;
     public class BuildConfig {
       private BuildConfig() {}
       public static final boolean DEBUG = false;
     }
     
    This swap happens before ProGuard is run as part of building the APK, so it will be able to exploit the "final-ness" of the DEBUG constant in any whole-program optimization that it performs.