diff options
3 files changed, 149 insertions, 121 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java new file mode 100644 index 0000000000..3466cb346c --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java @@ -0,0 +1,120 @@ +// Copyright 2018 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 com.google.devtools.build.lib.actions.ActionAnalysisMetadata; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; + +/** + * Wraps common tools and settings used for working with Android assets, resources, and manifests. + * + * <p>Do not create implementation classes directly - instead, get the appropriate one from {@link + * com.google.devtools.build.lib.rules.android.AndroidSemantics}. + * + * <p>The {@link Label}, {@link ActionConstructionContext}, and BusyBox {@link FilesToRunProvider} + * are needed to create virtually all actions for working with Android data, so it makes sense to + * bundle them together. Additionally, this class includes some common tools (such as an SDK) that + * are used in BusyBox actions. + */ +@SkylarkModule( + name = "AndroidDataContext", + doc = + "Wraps common tools and settings used for working with Android assets, resources, and" + + " manifests") +public class AndroidDataContext { + private final RuleContext ruleContext; + + private final Label label; + private final ActionConstructionContext actionConstructionContext; + private final FilesToRunProvider busybox; + private final AndroidSdkProvider sdk; + + public static AndroidDataContext forNative(RuleContext ruleContext) { + return new AndroidDataContext( + ruleContext, + ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST), + AndroidSdkProvider.fromRuleContext(ruleContext)); + } + + protected AndroidDataContext( + RuleContext ruleContext, FilesToRunProvider busybox, AndroidSdkProvider sdk) { + this.ruleContext = ruleContext; + this.label = ruleContext.getLabel(); + this.actionConstructionContext = ruleContext; + this.busybox = busybox; + this.sdk = sdk; + } + + public Label getLabel() { + return label; + } + + public ActionConstructionContext getActionConstructionContext() { + return actionConstructionContext; + } + + public FilesToRunProvider getBusybox() { + return busybox; + } + + public AndroidSdkProvider getSdk() { + return sdk; + } + + /** + * Gets the current RuleContext. + * + * @deprecated RuleContext is only exposed to help migrate away from it. New code should only be + * written using other methods from this class. + */ + @Deprecated + public RuleContext getRuleContext() { + return ruleContext; + } + + /* + * Convenience methods. These are just slightly cleaner ways of doing common tasks. + */ + + /** Builds and registers a {@link SpawnAction.Builder}. */ + public void registerAction(SpawnAction.Builder spawnActionBuilder) { + registerAction(spawnActionBuilder.build(actionConstructionContext)); + } + + /** Registers one or more actions. */ + public void registerAction(ActionAnalysisMetadata... actions) { + actionConstructionContext.registerAction(actions); + } + + public Artifact createOutputArtifact(SafeImplicitOutputsFunction function) + throws InterruptedException { + return actionConstructionContext.getImplicitOutputArtifact(function); + } + + public Artifact getUniqueDirectoryArtifact(String uniqueDirectorySuffix, String relative) { + return actionConstructionContext.getUniqueDirectoryArtifact(uniqueDirectorySuffix, relative); + } + + public AndroidConfiguration getAndroidConfig() { + return actionConstructionContext.getConfiguration().getFragment(AndroidConfiguration.class); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSemantics.java index 1620f3bc30..0bdb85ed89 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSemantics.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSemantics.java @@ -112,4 +112,8 @@ public interface AndroidSemantics { Artifact classesDexZip, ProguardOutput proguardOutput) throws InterruptedException; + + default AndroidDataContext makeContextForNative(RuleContext ruleContext) { + return AndroidDataContext.forNative(ruleContext); + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java index d5e08dde21..64e1883b1b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java @@ -20,7 +20,6 @@ import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.FileProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; -import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; @@ -36,6 +35,7 @@ import com.google.devtools.build.lib.rules.java.ProguardSpecProvider; import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.Runtime; import com.google.devtools.build.lib.syntax.SkylarkDict; @@ -56,17 +56,8 @@ public abstract class AndroidSkylarkData { public abstract AndroidSemantics getAndroidSemantics(); - /** - * Skylark API for getting a asset provider for android_library targets that don't specify assets. - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "assets_from_deps", - mandatoryPositionals = 1, // context parameters = { @Param( name = "deps", @@ -86,25 +77,16 @@ public abstract class AndroidSkylarkData { "Defaults to False. If true, assets will not be exposed to targets that depend on" + " them.") }, + useEnvironment = true, doc = "Creates an AndroidAssetsInfo from this target's asset dependencies, ignoring local" + " assets. No processing will be done. This method is deprecated and exposed only" + " for backwards-compatibility with existing Native behavior.") public static AndroidAssetsInfo assetsFromDeps( - SkylarkRuleContext ctx, SkylarkList<AndroidAssetsInfo> deps, boolean neverlink) - throws EvalException { - return AssetDependencies.fromProviders(deps, neverlink).toInfo(ctx.getLabel()); + SkylarkList<AndroidAssetsInfo> deps, boolean neverlink, Environment env) { + return AssetDependencies.fromProviders(deps, neverlink).toInfo(env.getCallerLabel()); } - /** - * Skylark API for getting a resource provider for android_library targets that don't specify - * resources. - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "resources_from_deps", mandatoryPositionals = 1, // context @@ -146,11 +128,11 @@ public abstract class AndroidSkylarkData { + " manifest will be generated and included in the provider - this path should not" + " be used when an explicit manifest is specified.") public static AndroidResourcesInfo resourcesFromDeps( - SkylarkRuleContext ctx, + AndroidDataContext ctx, SkylarkList<AndroidResourcesInfo> deps, boolean neverlink, Object customPackage) - throws EvalException, InterruptedException { + throws InterruptedException { String pkg = fromNoneable(customPackage, String.class); if (pkg == null) { pkg = AndroidManifest.getDefaultPackage(ctx.getRuleContext()); @@ -163,17 +145,9 @@ public abstract class AndroidSkylarkData { .toResourceInfo(ctx.getLabel()); } - /** - * Skylark API for stamping an Android manifest - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "stamp_manifest", - mandatoryPositionals = 1, // SkylarkRuleContext ctx is mandatory + mandatoryPositionals = 1, // AndroidDataContext ctx is mandatory parameters = { @Param( name = "manifest", @@ -208,7 +182,7 @@ public abstract class AndroidSkylarkData { }, doc = "Stamps a manifest with package information.") public AndroidManifestInfo stampAndroidManifest( - SkylarkRuleContext ctx, Object manifest, Object customPackage, boolean exported) + AndroidDataContext ctx, Object manifest, Object customPackage, boolean exported) throws InterruptedException { String pkg = fromNoneable(customPackage, String.class); if (pkg == null) { @@ -229,14 +203,6 @@ public abstract class AndroidSkylarkData { .toProvider(); } - /** - * Skylark API for merging android_library assets - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "merge_assets", mandatoryPositionals = 1, // context @@ -288,7 +254,7 @@ public abstract class AndroidSkylarkData { + " You may want to force these actions to be called - see the 'validation_result'" + " field in AndroidAssetsInfo") public AndroidAssetsInfo mergeAssets( - SkylarkRuleContext ctx, + AndroidDataContext ctx, Object assets, Object assetsDir, SkylarkList<AndroidAssetsInfo> deps, @@ -309,14 +275,6 @@ public abstract class AndroidSkylarkData { } } - /** - * Skylark API for merging android_library resources - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "merge_resources", mandatoryPositionals = 2, // context, manifest @@ -368,7 +326,7 @@ public abstract class AndroidSkylarkData { + " manifest, so in the future, you may want to use the manifest contained in this" + " method's output instead of this one.") public SkylarkDict<NativeProvider<?>, NativeInfo> mergeResources( - SkylarkRuleContext ctx, + AndroidDataContext ctx, AndroidManifestInfo manifest, SkylarkList<ConfiguredTarget> resources, SkylarkList<AndroidResourcesInfo> deps, @@ -403,14 +361,6 @@ public abstract class AndroidSkylarkData { } } - /** - * Skylark API for building an Aar for an android_library - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "make_aar", mandatoryPositionals = 4, // context, resource info, asset info, and library class jar @@ -448,7 +398,7 @@ public abstract class AndroidSkylarkData { + " providers from this same target must both be passed, as must the class JAR output" + " of building the Android Java library.") public AndroidLibraryAarInfo makeAar( - SkylarkRuleContext ctx, + AndroidDataContext ctx, AndroidResourcesInfo resourcesInfo, AndroidAssetsInfo assetsInfo, Artifact libraryClassJar, @@ -513,14 +463,6 @@ public abstract class AndroidSkylarkData { .toProvider(deps, definesLocalResources); } - /** - * Skylark API for doing all resource, asset, and manifest processing for an android_library - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "process_library_data", mandatoryPositionals = 2, // ctx and libraryClassJar are required @@ -627,11 +569,12 @@ public abstract class AndroidSkylarkData { "Dependency targets. Providers will be extracted from these dependencies for each" + " type of data."), }, + useEnvironment = true, doc = "Performs full processing of data for android_library or similar rules. Returns a dict" + " from provider type to providers for the target.") public SkylarkDict<NativeProvider<?>, NativeInfo> processLibraryData( - SkylarkRuleContext ctx, + AndroidDataContext ctx, Artifact libraryClassJar, Object manifest, Object resources, @@ -642,7 +585,8 @@ public abstract class AndroidSkylarkData { boolean neverlink, boolean enableDataBinding, SkylarkList<ConfiguredTarget> proguardSpecs, - SkylarkList<ConfiguredTarget> deps) + SkylarkList<ConfiguredTarget> deps, + Environment env) throws InterruptedException, EvalException { SkylarkList<AndroidResourcesInfo> resourceDeps = @@ -662,7 +606,7 @@ public abstract class AndroidSkylarkData { // If none of these parameters were specified, for backwards compatibility, do not trigger // data processing. resourcesInfo = resourcesFromDeps(ctx, resourceDeps, neverlink, customPackage); - assetsInfo = assetsFromDeps(ctx, assetDeps, neverlink); + assetsInfo = assetsFromDeps(assetDeps, neverlink, env); infoBuilder.put(AndroidResourcesInfo.PROVIDER, resourcesInfo); } else { @@ -718,14 +662,6 @@ public abstract class AndroidSkylarkData { .build()); } - /** - * Skylark API for doing all resource, asset, and manifest processing for an aar_import target - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "process_aar_import_data", // context, resource and asset TreeArtifacts, and manifest artifact are all mandatory @@ -742,7 +678,7 @@ public abstract class AndroidSkylarkData { }, doc = "Processes assets, resources, and manifest for aar_import targets") public SkylarkDict<NativeProvider<?>, NativeInfo> processAarImportData( - SkylarkRuleContext ctx, + AndroidDataContext ctx, SpecialArtifact resources, SpecialArtifact assets, Artifact androidManifestArtifact, @@ -775,14 +711,6 @@ public abstract class AndroidSkylarkData { return getNativeInfosFrom(resourceApk, ctx.getLabel()); } - /** - * Skylark API for processing assets, resources, and manifest for android_local_test - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "process_local_test_data", mandatoryPositionals = 1, // context is mandatory @@ -870,7 +798,7 @@ public abstract class AndroidSkylarkData { "Processes resources, assets, and manifests for android_local_test and returns a dict" + " from provider type to the appropriate provider.") public SkylarkDict<NativeProvider<?>, NativeInfo> processLocalTestData( - SkylarkRuleContext ctx, + AndroidDataContext ctx, Object manifest, SkylarkList<ConfiguredTarget> resources, Object assets, @@ -917,17 +845,9 @@ public abstract class AndroidSkylarkData { } } - /** - * Skylark API for bundling common setting for working with resources in android_binary - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "make_binary_settings", - mandatoryPositionals = 1, // SkylarkRuleContext is mandatory + mandatoryPositionals = 1, // AndroidDataContext is mandatory parameters = { @Param( name = "shrink_resources", @@ -982,7 +902,7 @@ public abstract class AndroidSkylarkData { "Returns a wrapper object containing various settings shared across multiple methods for" + " processing binary data.") public BinaryDataSettings makeBinarySettings( - SkylarkRuleContext ctx, + AndroidDataContext ctx, Object shrinkResources, SkylarkList<String> resourceConfigurationFilters, SkylarkList<String> densities, @@ -1015,7 +935,7 @@ public abstract class AndroidSkylarkData { * Helper method to get default {@link * com.google.devtools.build.lib.rules.android.AndroidSkylarkData.BinaryDataSettings}. */ - private BinaryDataSettings defaultBinaryDataSettings(SkylarkRuleContext ctx) + private BinaryDataSettings defaultBinaryDataSettings(AndroidDataContext ctx) throws EvalException { return makeBinarySettings( ctx, @@ -1047,17 +967,9 @@ public abstract class AndroidSkylarkData { } } - /** - * Skylark API for processing assets, resources, and manifest for android_binary - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "process_binary_data", - mandatoryPositionals = 1, // SkylarkRuleContext is mandatory + mandatoryPositionals = 1, // AndroidDataContext is mandatory parameters = { @Param( name = "resources", @@ -1168,7 +1080,7 @@ public abstract class AndroidSkylarkData { "Processes resources, assets, and manifests for android_binary and returns the" + " appropriate providers.") public AndroidBinaryDataInfo processBinaryData( - SkylarkRuleContext ctx, + AndroidDataContext ctx, SkylarkList<ConfiguredTarget> resources, Object assets, Object assetsDir, @@ -1241,17 +1153,9 @@ public abstract class AndroidSkylarkData { resourceApk.toManifestInfo().get()); } - /** - * Skylark API for shrinking a resource APK - * - * <p>TODO(b/79159379): Stop passing SkylarkRuleContext here - * - * @param ctx the SkylarkRuleContext. We will soon change to using an ActionConstructionContext - * instead. See b/79159379 - */ @SkylarkCallable( name = "shrink_data_apk", - // Required: SkylarkRuleContext, AndroidBinaryDataInfo to shrink, and two proguard outputs + // Required: AndroidDataContext, AndroidBinaryDataInfo to shrink, and two proguard outputs mandatoryPositionals = 4, parameters = { @Param( @@ -1299,7 +1203,7 @@ public abstract class AndroidSkylarkData { "Possibly shrinks the data APK by removing resources that were marked as unused during" + " proguarding.") public AndroidBinaryDataInfo shrinkDataApk( - SkylarkRuleContext ctx, + AndroidDataContext ctx, AndroidBinaryDataInfo binaryDataInfo, Artifact proguardOutputJar, Artifact proguardMapping, |