| // Copyright 2015 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.rules.android; |
| |
| import static com.google.devtools.build.lib.packages.Attribute.attr; |
| import static com.google.devtools.build.lib.packages.BuildType.LABEL; |
| import static com.google.devtools.build.lib.packages.BuildType.LABEL_KEYED_STRING_DICT; |
| import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; |
| import static com.google.devtools.build.lib.packages.BuildType.TRISTATE; |
| import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; |
| import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; |
| import static com.google.devtools.build.lib.syntax.Type.INTEGER; |
| import static com.google.devtools.build.lib.syntax.Type.STRING; |
| import static com.google.devtools.build.lib.syntax.Type.STRING_DICT; |
| import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; |
| import static com.google.devtools.build.lib.util.FileTypeSet.NO_FILE; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSortedSet; |
| import com.google.common.collect.Lists; |
| import com.google.devtools.build.lib.analysis.BaseRuleClasses; |
| import com.google.devtools.build.lib.analysis.RuleDefinition; |
| import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; |
| import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
| import com.google.devtools.build.lib.analysis.config.BuildOptions; |
| import com.google.devtools.build.lib.analysis.config.HostTransition; |
| import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.events.EventHandler; |
| import com.google.devtools.build.lib.packages.Attribute; |
| import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet; |
| import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault; |
| import com.google.devtools.build.lib.packages.AttributeMap; |
| import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; |
| import com.google.devtools.build.lib.packages.RuleClass; |
| import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; |
| import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier; |
| import com.google.devtools.build.lib.packages.TriState; |
| import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; |
| import com.google.devtools.build.lib.rules.android.AndroidConfiguration.ConfigurationDistinguisher; |
| import com.google.devtools.build.lib.rules.android.databinding.DataBinding; |
| import com.google.devtools.build.lib.rules.config.ConfigFeatureFlagProvider; |
| import com.google.devtools.build.lib.rules.cpp.CppConfiguration; |
| import com.google.devtools.build.lib.rules.cpp.CppOptions; |
| import com.google.devtools.build.lib.rules.java.JavaConfiguration; |
| import com.google.devtools.build.lib.rules.java.JavaInfo; |
| import com.google.devtools.build.lib.rules.java.JavaRuleClasses; |
| import com.google.devtools.build.lib.rules.java.JavaSemantics; |
| import com.google.devtools.build.lib.rules.java.ProguardHelper; |
| import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
| import com.google.devtools.build.lib.skylarkbuildapi.android.AndroidSplitTransititionApi; |
| import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; |
| import com.google.devtools.build.lib.syntax.Type; |
| import com.google.devtools.build.lib.util.FileType; |
| import com.google.devtools.build.lib.util.FileTypeSet; |
| import java.util.List; |
| |
| /** Rule definitions for Android rules. */ |
| public final class AndroidRuleClasses { |
| /** Sources generated by a given target, in particular, {@code R.java}. */ |
| public static final SafeImplicitOutputsFunction ANDROID_JAVA_SOURCE_JAR = |
| fromTemplates("%{name}.srcjar"); |
| /** Sources compiled in a given target, excluding {@link #ANDROID_JAVA_SOURCE_JAR}. */ |
| public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_SOURCE_JAR = |
| JavaSemantics.JAVA_LIBRARY_SOURCE_JAR; |
| /** |
| * Compiled sources of a given target, excluding {@link #ANDROID_JAVA_SOURCE_JAR}. This is the |
| * conventional output Jar of any java library target, including android libs. |
| */ |
| public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_CLASS_JAR = |
| JavaSemantics.JAVA_LIBRARY_CLASS_JAR; |
| |
| public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_AAR = |
| fromTemplates("%{name}.aar"); |
| // TODO(b/30307842): Remove this once it is no longer needed for resources migration. |
| public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_APK = |
| fromTemplates("%{name}_files/library.ap_"); |
| |
| /** |
| * Source Jar for {@link #ANDROID_RESOURCES_CLASS_JAR}, which should be the same as {@link |
| * #ANDROID_JAVA_SOURCE_JAR}. |
| */ |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_SOURCE_JAR = |
| fromTemplates("%{name}_resources-src.jar"); |
| /** Compiled {@link #ANDROID_JAVA_SOURCE_JAR}. */ |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_CLASS_JAR = |
| fromTemplates("%{name}_resources.jar"); |
| |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_APK = |
| fromTemplates("%{name}.ap_"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_AAPT2_LIBRARY_APK = |
| fromTemplates("%{name}_files/aapt2_library.apk"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_AAPT2_R_TXT = |
| fromTemplates("%{name}_symbols/R.aapt2.txt"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_AAPT2_SOURCE_JAR = |
| fromTemplates("%{name}_files/%{name}_resources_aapt2-src.jar"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_SHRUNK_APK = |
| fromTemplates("%{name}_shrunk.ap_"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_ZIP = |
| fromTemplates("%{name}_files/resource_files.zip"); |
| public static final SafeImplicitOutputsFunction ANDROID_ASSETS_ZIP = |
| fromTemplates("%{name}_files/assets.zip"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCES_SHRUNK_ZIP = |
| fromTemplates("%{name}_files/resource_files_shrunk.zip"); |
| public static final SafeImplicitOutputsFunction ANDROID_RESOURCE_SHRINKER_LOG = |
| fromTemplates("%{name}_files/resource_shrinker.log"); |
| public static final SafeImplicitOutputsFunction ANDROID_INCREMENTAL_RESOURCES_APK = |
| fromTemplates("%{name}_files/incremental.ap_"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_APK = fromTemplates("%{name}.apk"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_INCREMENTAL_APK = |
| fromTemplates("%{name}_incremental.apk"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_UNSIGNED_APK = |
| fromTemplates("%{name}_unsigned.apk"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_DEPLOY_JAR = |
| fromTemplates("%{name}_deploy.jar"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_PROGUARD_JAR = |
| fromTemplates("%{name}_proguard.jar"); |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_INSTRUMENTED_JAR = |
| fromTemplates("%{name}_instrumented.jar"); |
| public static final SafeImplicitOutputsFunction ANDROID_TEST_FILTERED_JAR = |
| fromTemplates("%{name}_filtered.jar"); |
| public static final SafeImplicitOutputsFunction ANDROID_R_TXT = |
| fromTemplates("%{name}_symbols/R.txt"); |
| public static final SafeImplicitOutputsFunction ANDROID_LOCAL_SYMBOLS = |
| fromTemplates("%{name}_symbols/local.bin"); |
| public static final SafeImplicitOutputsFunction ANDROID_MERGED_SYMBOLS = |
| fromTemplates("%{name}_symbols/merged.bin"); |
| public static final SafeImplicitOutputsFunction ANDROID_ASSET_SYMBOLS = |
| fromTemplates("%{name}_symbols/assets.bin"); |
| public static final SafeImplicitOutputsFunction ANDROID_COMPILED_SYMBOLS = |
| fromTemplates("%{name}_symbols/symbols.zip"); |
| public static final SafeImplicitOutputsFunction ANDROID_ASSET_COMPILED_SYMBOLS = |
| fromTemplates("%{name}_symbols/assets.zip"); |
| public static final SafeImplicitOutputsFunction ANDROID_SYMLINKED_MANIFEST = |
| fromTemplates("%{name}_symlinked_manifest/AndroidManifest.xml"); |
| public static final SafeImplicitOutputsFunction ANDROID_PROCESSED_MANIFEST = |
| fromTemplates("%{name}_processed_manifest/AndroidManifest.xml"); |
| public static final SafeImplicitOutputsFunction MOBILE_INSTALL_STUB_APPLICATION_MANIFEST = |
| fromTemplates("%{name}_files/mobile_install/AndroidManifest.xml"); |
| public static final SafeImplicitOutputsFunction FULL_DEPLOY_MARKER = |
| fromTemplates("%{name}_files/full_deploy_marker"); |
| public static final SafeImplicitOutputsFunction INCREMENTAL_DEPLOY_MARKER = |
| fromTemplates("%{name}_files/incremental_deploy_marker"); |
| public static final SafeImplicitOutputsFunction SPLIT_DEPLOY_MARKER = |
| fromTemplates("%{name}_files/split_deploy_marker"); |
| public static final SafeImplicitOutputsFunction MOBILE_INSTALL_ARGS = |
| fromTemplates("%{name}_files/mobile_install_args"); |
| public static final SafeImplicitOutputsFunction DEPLOY_INFO = |
| fromTemplates("%{name}_files/deploy_info.deployinfo.pb"); |
| public static final SafeImplicitOutputsFunction DEPLOY_INFO_INCREMENTAL = |
| fromTemplates("%{name}_files/deploy_info_incremental.deployinfo.pb"); |
| public static final SafeImplicitOutputsFunction DEPLOY_INFO_SPLIT = |
| fromTemplates("%{name}_files/deploy_info_split.deployinfo.pb"); |
| public static final SafeImplicitOutputsFunction REX_OUTPUT_PACKAGE_MAP = |
| fromTemplates("%{name}_rex/rex_output_package.map"); |
| public static final SafeImplicitOutputsFunction INSTRUMENTATION_TEST_CHECK_RESULTS = |
| fromTemplates("%{name}_files/instrumentation_test_check_results.txt"); |
| |
| // This needs to be in its own directory because ApkBuilder only has a function (-rf) for source |
| // folders but not source files, and it's easiest to guarantee that nothing gets put beside this |
| // file in the ApkBuilder invocation in this manner |
| public static final SafeImplicitOutputsFunction MOBILE_INSTALL_STUB_APPLICATION_DATA = |
| fromTemplates("%{name}_files/stub_application_data/stub_application_data.txt"); |
| public static final SafeImplicitOutputsFunction DEX_MANIFEST = |
| fromTemplates("%{name}_files/dexmanifest.txt"); |
| public static final SafeImplicitOutputsFunction JAVA_RESOURCES_JAR = |
| fromTemplates("%{name}_files/java_resources.jar"); |
| public static final String BUILD_INCREMENTAL_DEXMANIFEST_LABEL = |
| "//tools/android:build_incremental_dexmanifest"; |
| public static final String STUBIFY_MANIFEST_LABEL = "//tools/android:stubify_manifest"; |
| public static final String INCREMENTAL_INSTALL_LABEL = "//tools/android:incremental_install"; |
| public static final String BUILD_SPLIT_MANIFEST_LABEL = "//tools/android:build_split_manifest"; |
| public static final String STRIP_RESOURCES_LABEL = "//tools/android:strip_resources"; |
| public static final String DEFAULT_INCREMENTAL_STUB_APPLICATION = |
| "//tools/android:incremental_stub_application"; |
| public static final String DEFAULT_INCREMENTAL_SPLIT_STUB_APPLICATION = |
| "//tools/android:incremental_split_stub_application"; |
| public static final String DEFAULT_RESOURCES_BUSYBOX = "//tools/android:busybox"; |
| public static final String DEFAULT_SDK = "//tools/android:sdk"; |
| public static final SafeImplicitOutputsFunction ANDROID_DEVICE_USERDATA_IMAGES = |
| fromTemplates("%{name}_images/userdata_images.dat"); |
| public static final SafeImplicitOutputsFunction ANDROID_DEVICE_EMULATOR_METADATA = |
| fromTemplates("%{name}_images/emulator-meta-data.pb"); |
| static final FileType APK = FileType.of(".apk"); |
| |
| public static final String NOCOMPRESS_EXTENSIONS_ATTR = "nocompress_extensions"; |
| |
| /** The default label of android_sdk option */ |
| public static LabelLateBoundDefault<?> getAndroidSdkLabel(Label androidSdk) { |
| return LabelLateBoundDefault.fromTargetConfiguration( |
| AndroidConfiguration.class, |
| androidSdk, |
| (rule, attributes, configuration) -> configuration.getSdk()); |
| } |
| |
| @AutoCodec |
| public static final AndroidSplitTransition ANDROID_SPLIT_TRANSITION = |
| new AndroidSplitTransition(); |
| |
| /** Android Split configuration transition for properly handling native dependencies */ |
| public static final class AndroidSplitTransition |
| implements SplitTransition, AndroidSplitTransititionApi { |
| private static void setCrosstoolToAndroid(BuildOptions output, BuildOptions input) { |
| AndroidConfiguration.Options inputAndroidOptions = |
| input.get(AndroidConfiguration.Options.class); |
| AndroidConfiguration.Options outputAndroidOptions = |
| output.get(AndroidConfiguration.Options.class); |
| |
| CppOptions cppOptions = output.get(CppOptions.class); |
| if (inputAndroidOptions.androidCrosstoolTop != null |
| && !cppOptions.crosstoolTop.equals(inputAndroidOptions.androidCrosstoolTop)) { |
| if (cppOptions.hostCrosstoolTop == null) { |
| cppOptions.hostCrosstoolTop = cppOptions.crosstoolTop; |
| } |
| cppOptions.crosstoolTop = inputAndroidOptions.androidCrosstoolTop; |
| } |
| |
| outputAndroidOptions.configurationDistinguisher = ConfigurationDistinguisher.ANDROID; |
| } |
| |
| @Override |
| public List<BuildOptions> split(BuildOptions buildOptions) { |
| |
| AndroidConfiguration.Options androidOptions = |
| buildOptions.get(AndroidConfiguration.Options.class); |
| CppOptions cppOptions = buildOptions.get(CppOptions.class); |
| Label androidCrosstoolTop = androidOptions.androidCrosstoolTop; |
| |
| if (androidOptions.fatApkCpus.isEmpty()) { |
| |
| if (androidOptions.cpu.isEmpty() |
| || androidCrosstoolTop == null |
| || androidCrosstoolTop.equals(cppOptions.crosstoolTop)) { |
| return ImmutableList.of(buildOptions); |
| |
| } else { |
| |
| BuildOptions splitOptions = buildOptions.clone(); |
| splitOptions.get(CppOptions.class).cppCompiler = androidOptions.cppCompiler; |
| splitOptions.get(CppOptions.class).libcTopLabel = androidOptions.androidLibcTopLabel; |
| splitOptions.get(BuildConfiguration.Options.class).cpu = androidOptions.cpu; |
| splitOptions.get(CppOptions.class).dynamicMode = androidOptions.dynamicMode; |
| setCrosstoolToAndroid(splitOptions, buildOptions); |
| return ImmutableList.of(splitOptions); |
| } |
| |
| } else { |
| |
| ImmutableList.Builder<BuildOptions> result = ImmutableList.builder(); |
| for (String cpu : ImmutableSortedSet.copyOf(androidOptions.fatApkCpus)) { |
| BuildOptions splitOptions = buildOptions.clone(); |
| // Disable fat APKs for the child configurations. |
| splitOptions.get(AndroidConfiguration.Options.class).fatApkCpus = ImmutableList.of(); |
| |
| // Set the cpu & android_cpu. |
| // TODO(bazel-team): --android_cpu doesn't follow --cpu right now; it should. |
| splitOptions.get(AndroidConfiguration.Options.class).cpu = cpu; |
| splitOptions.get(BuildConfiguration.Options.class).cpu = cpu; |
| splitOptions.get(CppOptions.class).cppCompiler = androidOptions.cppCompiler; |
| splitOptions.get(CppOptions.class).libcTopLabel = androidOptions.androidLibcTopLabel; |
| splitOptions.get(CppOptions.class).dynamicMode = androidOptions.dynamicMode; |
| setCrosstoolToAndroid(splitOptions, buildOptions); |
| result.add(splitOptions); |
| } |
| return result.build(); |
| } |
| } |
| |
| @Override |
| public boolean isImmutable() { |
| return true; |
| } |
| |
| @Override |
| public void repr(SkylarkPrinter printer) { |
| printer.append("android_common.multi_cpu_configuration"); |
| } |
| } |
| |
| public static final FileType ANDROID_IDL = FileType.of(".aidl"); |
| |
| public static final String[] ALLOWED_DEPENDENCIES = { |
| "aar_import", |
| "android_library", |
| "cc_library", |
| "java_import", |
| "java_library", |
| "java_lite_proto_library", |
| }; |
| |
| public static boolean hasProguardSpecs(AttributeMap rule) { |
| // The below is a hack to support configurable attributes (proguard_specs seems like |
| // too valuable an attribute to make nonconfigurable, and we don't currently |
| // have the ability to know the configuration when determining implicit outputs). So if the |
| // attribute is configurable, we create the proguard implicit output. At analysis time, we know |
| // the actual value of proguard_specs, and if it is empty we do not use the proguarded jar for |
| // dexing. If the user explicitly tries to build the proguard jar, it will fail. |
| // |
| // TODO(bazel-team): find a stronger approach for this. One simple approach is to somehow |
| // receive 'rule' as an AggregatingAttributeMapper instead of a RawAttributeMapper, |
| // check that all possible values are non-empty, and simply don't support configurable |
| // instances that mix empty and non-empty lists. A more ambitious approach would be |
| // to somehow determine implicit outputs after the configuration is known. A third |
| // approach is to refactor the Android rule logic to avoid these dependencies in the |
| // first place. |
| return rule.isConfigurable("proguard_specs") |
| || !rule.get("proguard_specs", LABEL_LIST).isEmpty(); |
| } |
| |
| public static final SafeImplicitOutputsFunction ANDROID_BINARY_IMPLICIT_OUTPUTS = |
| new SafeImplicitOutputsFunction() { |
| |
| @Override |
| public Iterable<String> getImplicitOutputs(EventHandler eventHandler, AttributeMap rule) { |
| List<SafeImplicitOutputsFunction> functions = Lists.newArrayList(); |
| functions.add(AndroidRuleClasses.ANDROID_BINARY_APK); |
| functions.add(AndroidRuleClasses.ANDROID_BINARY_UNSIGNED_APK); |
| functions.add(AndroidRuleClasses.ANDROID_BINARY_DEPLOY_JAR); |
| |
| if (hasProguardSpecs(rule)) { |
| functions.add(AndroidRuleClasses.ANDROID_BINARY_PROGUARD_JAR); |
| functions.add(JavaSemantics.JAVA_BINARY_PROGUARD_CONFIG); |
| if (ProguardHelper.genProguardMapping(rule)) { |
| functions.add(JavaSemantics.JAVA_BINARY_PROGUARD_MAP); |
| } |
| } |
| return fromFunctions(functions).getImplicitOutputs(eventHandler, rule); |
| } |
| }; |
| |
| public static final SafeImplicitOutputsFunction ANDROID_LIBRARY_IMPLICIT_OUTPUTS = |
| new SafeImplicitOutputsFunction() { |
| @Override |
| public Iterable<String> getImplicitOutputs( |
| EventHandler eventHandler, AttributeMap attributes) { |
| |
| ImmutableList.Builder<SafeImplicitOutputsFunction> implicitOutputs = |
| ImmutableList.builder(); |
| |
| implicitOutputs.add( |
| AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR, |
| AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR, |
| AndroidRuleClasses.ANDROID_LIBRARY_AAR); |
| |
| if (AndroidResources.definesAndroidResources(attributes)) { |
| implicitOutputs.add( |
| AndroidRuleClasses.ANDROID_JAVA_SOURCE_JAR, |
| AndroidRuleClasses.ANDROID_R_TXT, |
| AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR); |
| } |
| |
| return fromFunctions(implicitOutputs.build()) |
| .getImplicitOutputs(eventHandler, attributes); |
| } |
| }; |
| |
| /** Base class for rule definitions that support resource declarations. */ |
| public static final class AndroidResourceSupportRule implements RuleDefinition { |
| @Override |
| public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) { |
| return builder |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(manifest) --> |
| The name of the Android manifest file, normally <code>AndroidManifest.xml</code>. |
| Must be defined if resource_files or assets are defined. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("manifest", LABEL).allowedFileTypes(FileType.of(".xml"))) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(resource_files) --> |
| The list of resources to be packaged. |
| This is typically a <code>glob</code> of all files under the |
| <code>res</code> directory. |
| <br/> |
| Generated files (from genrules) can be referenced by |
| <a href="../build-ref.html#labels">Label</a> here as well. The only restriction is that |
| the generated outputs must be under the same "<code>res</code>" directory as any other |
| resource files that are included. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("resource_files", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(assets_dir) --> |
| The string giving the path to the files in <code>assets</code>. |
| The pair <code>assets</code> and <code>assets_dir</code> describe packaged |
| assets and either both attributes should be provided or none of them. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("assets_dir", STRING)) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(assets) --> |
| The list of assets to be packaged. |
| This is typically a <code>glob</code> of all files under the |
| <code>assets</code> directory. You can also reference other rules (any rule that produces |
| files) or exported files in the other packages, as long as all those files are under the |
| <code>assets_dir</code> directory in the corresponding package. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("assets", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(inline_constants) --> |
| Let the compiler inline the constants defined in the generated java sources. |
| This attribute must be set to 0 for all <code>android_library</code> rules |
| used directly by an <code>android_binary</code>, |
| and for any <code>android_binary</code> that has an <code>android_library</code> |
| in its transitive closure. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("inline_constants", BOOLEAN) |
| .undocumented("deprecated noop on library") |
| .value(false)) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(custom_package) --> |
| Java package for which java sources will be generated. |
| By default the package is inferred from the directory where the BUILD file |
| containing the rule is. You can specify a different package but this is |
| highly discouraged since it can introduce classpath conflicts with other |
| libraries that will only be detected at runtime. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("custom_package", STRING)) |
| /* <!-- #BLAZE_RULE($android_resource_support).ATTRIBUTE(enable_data_binding) --> |
| If true, this rule processes |
| <a href="https://developer.android.com/topic/libraries/data-binding/index.html">data |
| binding</a> expressions in layout resources included through the |
| <a href="${link android_binary.resource_files}">resource_files</a> attribute. Without this |
| setting, data binding expressions produce build failures. |
| <p> |
| To build an Android app with data binding, you must also do the following: |
| <ol> |
| <li>Set this attribute for all Android rules that transitively depend on this one. |
| This is because dependers inherit the rule's data binding expressions through resource |
| merging. So they also need to build with data binding to parse those expressions. |
| <li>Add a <code>deps =</code> entry for the data binding runtime library to all targets |
| that set this attribute. The location of this library depends on your depot setup. |
| </ol> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("enable_data_binding", Type.BOOLEAN)) |
| // The javac annotation processor from Android's data binding library that turns |
| // processed XML expressions into Java code. |
| .add( |
| attr(DataBinding.DATABINDING_ANNOTATION_PROCESSOR_ATTR, LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .value(env.getToolsLabel("//tools/android:databinding_annotation_processor"))) |
| .add( |
| attr(DataBinding.DATABINDING_EXEC_PROCESSOR_ATTR, LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:databinding_exec"))) |
| .advertiseSkylarkProvider( |
| SkylarkProviderIdentifier.forKey(AndroidResourcesInfo.PROVIDER.getKey())) |
| .advertiseSkylarkProvider( |
| SkylarkProviderIdentifier.forKey(AndroidNativeLibsInfo.PROVIDER.getKey())) |
| .build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return RuleDefinition.Metadata.builder() |
| .name("$android_resource_support") |
| .type(RuleClassType.ABSTRACT) |
| .ancestors(AndroidRuleClasses.AndroidBaseRule.class) |
| .build(); |
| } |
| } |
| |
| /** Base class for Android rule definitions. */ |
| public static final class AndroidBaseRule implements RuleDefinition { |
| @Override |
| public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { |
| return builder |
| .add( |
| attr(":android_sdk", LABEL) |
| .allowedRuleClasses("android_sdk") |
| .value(getAndroidSdkLabel(env.getToolsLabel(AndroidRuleClasses.DEFAULT_SDK)))) |
| /* <!-- #BLAZE_RULE($android_base).ATTRIBUTE(plugins) --> |
| Java compiler plugins to run at compile-time. |
| Every <code>java_plugin</code> specified in |
| the plugins attribute will be run whenever |
| this target is built. Resources generated by |
| the plugin will be included in the result jar of |
| the target. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("plugins", LABEL_LIST) |
| .cfg(HostTransition.INSTANCE) |
| .allowedRuleClasses("java_plugin") |
| .legacyAllowAnyFileType()) |
| .add( |
| attr(":java_plugins", LABEL_LIST) |
| .cfg(HostTransition.INSTANCE) |
| .allowedRuleClasses("java_plugin") |
| .silentRuleClassFilter() |
| .value(JavaSemantics.JAVA_PLUGINS)) |
| /* <!-- #BLAZE_RULE($android_base).ATTRIBUTE(javacopts) --> |
| Extra compiler options for this target. |
| Subject to <a href="${link make-variables}">"Make variable"</a> substitution and |
| <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>. |
| <p> |
| These compiler options are passed to javac after the global compiler options.</p> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("javacopts", STRING_LIST)) |
| .add( |
| attr("$idlclass", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:IdlClass"))) |
| .add( |
| attr("$desugar_java8_extra_bootclasspath", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .value(env.getToolsLabel("//tools/android:desugar_java8_extra_bootclasspath"))) |
| .add( |
| attr("$android_resources_busybox", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(DEFAULT_RESOURCES_BUSYBOX))) |
| .build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return RuleDefinition.Metadata.builder() |
| .name("$android_base") |
| .type(RuleClassType.ABSTRACT) |
| .ancestors(BaseRuleClasses.RuleBase.class) |
| .build(); |
| } |
| } |
| |
| /** Base class for Android rule definitions that produce binaries. */ |
| public static final class AndroidBinaryBaseRule implements RuleDefinition { |
| |
| private final AndroidNeverlinkAspect androidNeverlinkAspect; |
| private final DexArchiveAspect dexArchiveAspect; |
| |
| public AndroidBinaryBaseRule( |
| AndroidNeverlinkAspect androidNeverlinkAspect, DexArchiveAspect dexArchiveAspect) { |
| this.androidNeverlinkAspect = androidNeverlinkAspect; |
| this.dexArchiveAspect = dexArchiveAspect; |
| } |
| |
| @Override |
| public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) { |
| return builder |
| .requiresConfigurationFragments( |
| AndroidConfiguration.class, JavaConfiguration.class, CppConfiguration.class) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(srcs) --> |
| The list of source files that are processed to create the target. |
| <p><code>srcs</code> files of type <code>.java</code> are compiled. |
| <em>For readability's sake</em>, it is not good to put the name of a |
| generated <code>.java</code> source file into the <code>srcs</code>. |
| Instead, put the depended-on rule name in the <code>srcs</code>, as |
| described below. |
| </p> |
| <p><code>srcs</code> files of type <code>.srcjar</code> are unpacked and |
| compiled. (This is useful if you need to generate a set of .java files with |
| a genrule or build extension.) |
| </p> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("srcs", LABEL_LIST) |
| .direct_compile_time_input() |
| .allowedFileTypes(JavaSemantics.JAVA_SOURCE, JavaSemantics.SOURCE_JAR)) |
| // manifest is required for android_binary to ensure that we have an Android package. |
| .override(builder.copy("manifest").mandatory()) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(deps) --> |
| The list of other libraries to be linked in to the binary target. |
| Permitted library types are: <code>android_library</code>, |
| <code>java_library</code> with <code>android</code> constraint and |
| <code>cc_library</code> wrapping or producing <code>.so</code> native libraries for the |
| Android target platform. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .override( |
| builder |
| .copy("deps") |
| .cfg(ANDROID_SPLIT_TRANSITION) |
| .allowedRuleClasses(ALLOWED_DEPENDENCIES) |
| .allowedFileTypes() |
| .mandatoryProviders(JavaRuleClasses.CONTAINS_JAVA_PROVIDER) |
| .mandatoryProviders( |
| SkylarkProviderIdentifier.forKey(AndroidResourcesInfo.PROVIDER.getKey()), |
| SkylarkProviderIdentifier.forKey(AndroidAssetsInfo.PROVIDER.getKey())) |
| .aspect(androidNeverlinkAspect) |
| .aspect(dexArchiveAspect, DexArchiveAspect.PARAM_EXTRACTOR)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(debug_key) --> |
| File containing the debug keystore to be used to sign the debug apk. Usually you do not |
| want to use a key other than the default key, so this attribute should be omitted. |
| <p><em class="harmful">WARNING: Do not use your production keys, they should be |
| strictly safeguarded and not kept in your source tree</em>.</p> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("debug_key", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .legacyAllowAnyFileType() |
| .value(env.getToolsLabel("//tools/android:debug_keystore"))) |
| .add( |
| attr("feature_of", LABEL) |
| .allowedRuleClasses("android_binary") |
| .allowedFileTypes() |
| .undocumented("experimental, see b/36226333")) |
| .add( |
| attr("feature_after", LABEL) |
| .allowedRuleClasses("android_binary") |
| .allowedFileTypes() |
| .undocumented("experimental, see b/36226333")) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(nocompress_extensions) --> |
| A list of file extension to leave uncompressed in apk. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("nocompress_extensions", STRING_LIST)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(crunch_png) --> |
| Do PNG crunching (or not). This is independent of nine-patch processing, which is always |
| done. Currently only supported for local resources (not android_resources). |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("crunch_png", BOOLEAN).value(true)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(resource_configuration_filters) --> |
| A list of resource configuration filters, such 'en' that will limit the resources in the |
| apk to only the ones in the 'en' configuration. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr(ResourceFilterFactory.RESOURCE_CONFIGURATION_FILTERS_NAME, STRING_LIST)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(shrink_resources) --> |
| Whether to perform resource shrinking. Resources that are not used by the binary will be |
| removed from the APK. This is only supported for rules using local resources (i.e. the |
| <code>manifest</code> and <code>resource_files</code> attributes) and requires ProGuard. |
| It operates in mostly the same manner as the Gradle resource shrinker |
| (https://developer.android.com/studio/build/shrink-code.html#shrink-resources). |
| <p>Notable differences: |
| <ul> |
| <li>resources in <code>values/</code> will be removed as well as file based |
| resources</li> |
| <li>uses <code>strict mode</code> by default</li> |
| <li>removing unused ID resources is not supported</li> |
| </ul> |
| If resource shrinking is enabled, <code><var>name</var>_files/resource_shrinker.log</code> |
| will also be generated, detailing the analysis and deletions performed. |
| <p>Possible values: |
| <ul> |
| <li><code>shrink_resources = 1</code>: Turns on Android resource shrinking</li> |
| <li><code>shrink_resources = 0</code>: Turns off Android resource shrinking</li> |
| <li><code>shrink_resources = -1</code>: Shrinking is controlled by the |
| <a href="../user-manual.html#flag--android_resource_shrinking"> |
| --android_resource_shrinking</a> flag.</li> |
| </ul> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("shrink_resources", TRISTATE).value(TriState.AUTO)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(densities) --> |
| Densities to filter for when building the apk. |
| This will strip out raster drawable resources that would not be loaded by a device with |
| the specified screen densities, to reduce APK size. A corresponding compatible-screens |
| section will also be added to the manifest if it does not already contain a superset |
| listing. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr(ResourceFilterFactory.DENSITIES_NAME, STRING_LIST)) |
| .add( |
| attr("$build_incremental_dexmanifest", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(BUILD_INCREMENTAL_DEXMANIFEST_LABEL))) |
| .add( |
| attr("$stubify_manifest", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(STUBIFY_MANIFEST_LABEL))) |
| .add( |
| attr("$shuffle_jars", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:shuffle_jars"))) |
| .add( |
| attr("$dexbuilder", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:dexbuilder"))) |
| .add( |
| attr("$dexbuilder_after_proguard", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:dexbuilder_after_proguard"))) |
| .add( |
| attr("$dexsharder", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:dexsharder"))) |
| .add( |
| attr("$dexmerger", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:dexmerger"))) |
| .add( |
| attr("$merge_dexzips", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:merge_dexzips"))) |
| .add( |
| attr("$incremental_install", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(INCREMENTAL_INSTALL_LABEL))) |
| .add( |
| attr("$build_split_manifest", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(BUILD_SPLIT_MANIFEST_LABEL))) |
| .add( |
| attr("$strip_resources", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel(STRIP_RESOURCES_LABEL))) |
| .add( |
| attr("$incremental_stub_application", LABEL) |
| .value(env.getToolsLabel(DEFAULT_INCREMENTAL_STUB_APPLICATION)) |
| .aspect(dexArchiveAspect, DexArchiveAspect.ONLY_DESUGAR_JAVA8)) |
| .add( |
| attr("$incremental_split_stub_application", LABEL) |
| .value(env.getToolsLabel(DEFAULT_INCREMENTAL_SPLIT_STUB_APPLICATION)) |
| .aspect(dexArchiveAspect, DexArchiveAspect.ONLY_DESUGAR_JAVA8)) |
| .add( |
| attr("$desugar", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:desugar_java8"))) |
| .add( |
| attr("$java8_legacy_dex", LABEL) |
| .value(env.getToolsLabel("//tools/android:java8_legacy_dex"))) |
| .add( |
| attr("$build_java8_legacy_dex", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:build_java8_legacy_dex"))) |
| .add( |
| attr("$desugared_java8_legacy_apis", LABEL) |
| .value(env.getToolsLabel("//tools/android:desugared_java8_legacy_apis"))) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(dexopts) --> |
| Additional command-line flags for the dx tool when generating classes.dex. |
| Subject to <a href="${link make-variables}">"Make variable"</a> substitution and |
| <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("dexopts", STRING_LIST)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(dex_shards) --> |
| Number of shards dexing should be decomposed into. |
| This is makes dexing much faster at the expense of app installation and startup time. The |
| larger the binary, the more shards should be used. 25 is a good value to start |
| experimenting with. |
| <p> |
| Note that each shard will result in at least one dex in the final app. For this reason, |
| setting this to more than 1 is not recommended for release binaries. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("dex_shards", INTEGER).value(1)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(incremental_dexing) --> |
| Force the target to be built with or without incremental dexing, overriding defaults |
| and --incremental_dexing flag. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("incremental_dexing", TRISTATE) |
| // Read by DexArchiveAspect's attribute extractor |
| .nonconfigurable("AspectParameters don't support configurations.")) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(multidex) --> |
| Whether to split code into multiple dex files.<br/> |
| Possible values: |
| <ul> |
| <li><code>native</code>: Split code into multiple dex files when the dex 64K index limit |
| is exceeded. Assumes native platform support for loading multidex classes at runtime. |
| <em class="harmful">This works with only Android L and newer</em>.</li> |
| <li><code>legacy</code>: Split code into multiple dex files when the dex 64K index limit |
| is exceeded. Assumes multidex classes are loaded through application code (i.e. no |
| native platform support).</li> |
| <li><code>manual_main_dex</code>: Split code into multiple dex files when the dex 64K |
| index limit is exceeded. The content of the main dex file needs to be specified by |
| providing a list of classes in a text file using the |
| <a href="${link android_binary.main_dex_list}">main_dex_list</a> attribute.</li> |
| <li><code>off</code>: Compile all code to a single dex file, even if it exceeds the |
| index limit.</li> |
| </ul> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("multidex", STRING) |
| .allowedValues(new AllowedValueSet(MultidexMode.getValidValues())) |
| .value(MultidexMode.OFF.getAttributeValue())) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(main_dex_list_opts) --> |
| Command line options to pass to the main dex list builder. |
| Use this option to affect the classes included in the main dex list. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("main_dex_list_opts", STRING_LIST)) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(main_dex_list) --> |
| |
| A text file contains a list of class file names. Classes defined by those class files are |
| put in the primary classes.dex. e.g.:<pre class="code"> |
| android/support/multidex/MultiDex$V19.class |
| android/support/multidex/MultiDex.class |
| android/support/multidex/MultiDexApplication.class |
| com/google/common/base/Objects.class |
| </pre> |
| Must be used with <code>multidex="manual_main_dex"</code>. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("main_dex_list", LABEL).legacyAllowAnyFileType()) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(main_dex_proguard_specs) --> |
| Files to be used as the Proguard specifications to determine classes that must be kept in |
| the main dex. |
| Only allowed if the <code>multidex</code> attribute is set to <code>legacy</code>. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("main_dex_proguard_specs", LABEL_LIST).legacyAllowAnyFileType()) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(proguard_specs) --> |
| Files to be used as Proguard specification. |
| This file will describe the set of specifications to be used by Proguard. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("proguard_specs", LABEL_LIST).legacyAllowAnyFileType()) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(proguard_generate_mapping) --> |
| Whether to generate Proguard mapping file. |
| The mapping file will be generated only if <code>proguard_specs</code> is |
| specified. This file will list the mapping between the original and |
| obfuscated class, method, and field names. |
| <p><em class="harmful">WARNING: If this attribute is used, the Proguard |
| specification should contain neither <code>-dontobfuscate</code> nor |
| <code>-printmapping</code>.</em></p> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("proguard_generate_mapping", BOOLEAN) |
| .value(false) |
| .nonconfigurable("value is referenced in an ImplicitOutputsFunction")) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(proguard_apply_mapping) --> |
| File to be used as a mapping for proguard. |
| A mapping file generated by <code>proguard_generate_mapping</code> to be |
| re-used to apply the same mapping to a new build. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("proguard_apply_mapping", LABEL).legacyAllowAnyFileType()) |
| /* <!-- #BLAZE_RULE($android_binary_base).ATTRIBUTE(proguard_apply_dictionary) --> |
| File to be used as a mapping for proguard. |
| A line separated file of "words" to pull from when renaming classes and members during |
| obfuscation. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("proguard_apply_dictionary", LABEL).legacyAllowAnyFileType()) |
| .add(attr(":extra_proguard_specs", LABEL_LIST).value(JavaSemantics.EXTRA_PROGUARD_SPECS)) |
| .add( |
| attr("$dex_list_obfuscator", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:dex_list_obfuscator"))) |
| .add( |
| attr(":bytecode_optimizers", LABEL_LIST) |
| .cfg(HostTransition.INSTANCE) |
| .value(JavaSemantics.BYTECODE_OPTIMIZERS)) |
| // We need the C++ toolchain for every sub-configuration to get the correct linker. |
| .add( |
| attr("$cc_toolchain_split", LABEL) |
| .cfg(AndroidRuleClasses.ANDROID_SPLIT_TRANSITION) |
| .value(env.getToolsLabel("//tools/cpp:current_cc_toolchain"))) |
| /* <!-- #BLAZE_RULE(android_binary).ATTRIBUTE(manifest_values) --> |
| A dictionary of values to be overridden in the manifest. Any instance of ${name} in the |
| manifest will be replaced with the value corresponding to name in this dictionary. |
| applicationId, versionCode, versionName, minSdkVersion, targetSdkVersion and |
| maxSdkVersion will also override the corresponding attributes of the manifest and |
| uses-sdk tags. packageName will be ignored and will be set from either applicationId if |
| specified or the package in manifest. When manifest_merger is set to legacy, only |
| applicationId, versionCode and versionName will have any effect. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add(attr("manifest_values", STRING_DICT)) |
| /* <!-- #BLAZE_RULE(android_binary).ATTRIBUTE(aapt_version) --> |
| Select the version of aapt for this rule.<br/> |
| Possible values: |
| <ul> |
| <li><code>aapt_version = "aapt"</code>: Use aapt. This is the current default |
| behaviour, and should be used for production binaries.</li> |
| <li><code>aapt_version = "aapt2"</code>: Use aapt2. This is the new resource |
| packaging system that provides improved incremental resource processing, smaller apks |
| and more.</li> |
| <li><code>aapt_version = "auto"</code>: aapt is controlled by the |
| --android_aapt flag.</li> |
| </ul> |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("aapt_version", STRING) |
| .allowedValues(new AllowedValueSet(AndroidAaptVersion.getAttributeValues())) |
| .value(AndroidAaptVersion.getRuleAttributeDefault())) |
| .add( |
| attr(AndroidFeatureFlagSetProvider.FEATURE_FLAG_ATTR, LABEL_KEYED_STRING_DICT) |
| .undocumented("the feature flag feature has not yet been launched") |
| .allowedRuleClasses("config_feature_flag") |
| .allowedFileTypes() |
| .nonconfigurable("defines an aspect of configuration") |
| .mandatoryProviders(ImmutableList.of(ConfigFeatureFlagProvider.id()))) |
| .add(AndroidFeatureFlagSetProvider.getWhitelistAttribute(env)) |
| // The resource extractor is used at the binary level to extract java resources from the |
| // deploy jar so that they can be added to the APK. |
| .add( |
| attr("$resource_extractor", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:resource_extractor"))) |
| /* <!-- #BLAZE_RULE(android_binary).ATTRIBUTE(instruments) --> |
| <p>The <code>android_binary</code> target to instrument.</p> |
| <p>If this attribute is set, this <code>android_binary</code> will be treated as a test |
| application for instrumentation tests. An <code>android_instrumentation_test</code> |
| target can then specify this target in its |
| <a href="${link android_instrumentation_test.test_app}">test_app</a> attribute. |
| <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ |
| .add( |
| attr("instruments", LABEL) |
| .allowedRuleClasses("android_binary") |
| .allowedFileTypes(NO_FILE)) |
| .add( |
| attr("$instrumentation_test_check", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .value( |
| new Attribute.ComputedDefault() { |
| @Override |
| public Object getDefault(AttributeMap rule) { |
| return rule.isAttributeValueExplicitlySpecified("instruments") |
| ? env.getToolsLabel("//tools/android:instrumentation_test_check") |
| : null; |
| } |
| }) |
| .exec()) |
| .add( |
| attr("$zip_filter", LABEL) |
| .cfg(HostTransition.INSTANCE) |
| .exec() |
| .value(env.getToolsLabel("//tools/android:zip_filter"))) |
| .removeAttribute("data") |
| .advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(ApkInfo.PROVIDER.getKey())) |
| .advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(JavaInfo.PROVIDER.getKey())) |
| .build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return RuleDefinition.Metadata.builder() |
| .name("$android_binary_base") |
| .type(RuleClassType.ABSTRACT) |
| .ancestors(AndroidResourceSupportRule.class) |
| .build(); |
| } |
| } |
| |
| /** Semantic options for the dexer's multidex behavior. */ |
| public enum MultidexMode { |
| // Build dexes with multidex, assuming native platform support for multidex. |
| NATIVE, |
| // Build dexes with multidex and implement support at the application level. |
| LEGACY, |
| // Build dexes with multidex, main dex list needs to be manually specified. |
| MANUAL_MAIN_DEX, |
| // Build all dex code into a single classes.dex file. |
| OFF; |
| |
| /** Returns the attribute value that specifies this mode. */ |
| public String getAttributeValue() { |
| return toString().toLowerCase(); |
| } |
| |
| /** |
| * Returns the name of the output dex classes file. In multidex mode, this is an archive of |
| * (possibly) multiple files. |
| */ |
| public String getOutputDexFilename() { |
| return this == OFF ? "classes.dex" : "classes.dex.zip"; |
| } |
| |
| /** Converts an attribute value to a corresponding mode. Returns null on no match. */ |
| public static MultidexMode fromValue(String value) { |
| for (MultidexMode mode : values()) { |
| if (mode.getAttributeValue().equals(value)) { |
| return mode; |
| } |
| } |
| return null; |
| } |
| |
| /** Enumerates valid values for the "multidex" attribute. */ |
| public static List<String> getValidValues() { |
| List<String> ans = Lists.newArrayList(); |
| for (MultidexMode mode : MultidexMode.values()) { |
| ans.add(mode.getAttributeValue()); |
| } |
| return ans; |
| } |
| } |
| |
| /** Definition of the {@code android_tools_defaults_jar} rule. */ |
| public static final class AndroidToolsDefaultsJarRule implements RuleDefinition { |
| |
| private final Label[] compatibleWithAndroidEnvironments; |
| |
| public AndroidToolsDefaultsJarRule(Label... compatibleWithAndroidEnvironments) { |
| this.compatibleWithAndroidEnvironments = compatibleWithAndroidEnvironments; |
| } |
| |
| @Override |
| public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) { |
| builder |
| .setUndocumented() |
| .add( |
| attr(":android_sdk", LABEL) |
| .allowedRuleClasses("android_sdk") |
| .value(getAndroidSdkLabel(environment.getToolsLabel(DEFAULT_SDK)))); |
| if (compatibleWithAndroidEnvironments.length > 0) { |
| builder.compatibleWith(compatibleWithAndroidEnvironments); |
| } |
| return builder.build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return Metadata.builder() |
| .name("android_tools_defaults_jar") |
| .ancestors(BaseRuleClasses.BaseRule.class) |
| .factoryClass(AndroidToolsDefaultsJar.class) |
| .build(); |
| } |
| } |
| } |