aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar asteinb <asteinb@google.com>2018-05-22 05:56:48 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-22 05:58:07 -0700
commit090f46313b33d94d4d0fd2b10606bc7947fd9a98 (patch)
tree9792a1fc3380a6cb8ecbfed70ad88cf68d0da4c2
parent8ba0475d4aecd964049d22486fbbc4817a31aa9c (diff)
Create AndroidDataContext to wrap context needed when working with Android data
This new object wraps Label, ActionConstructionContext, and various data-related tools (currently, just the resource Busybox and the Android SDK). All three of these things are required for creating pretty much any action for working with Android assets, resources, and manifests, so it makes sense to pass them around together. Eventually, we'll use this class instead of RuleContext in any code called from the Skylark APIs. For now, though, just have it wrap a RuleContext - the migration away from that will happen in future changes. Change the current Skylark API to take this class, rather than a SkylarkRuleContext. This is the first step towards not passing RuleContext (or SkylarkRuleContext) into the Skylark API. RELNOTES: none PiperOrigin-RevId: 197549155
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java120
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidSemantics.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java146
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,