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.