aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar asteinb <asteinb@google.com>2018-05-02 14:22:47 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-02 14:24:37 -0700
commit4b810d5afd32472271820b3e7bdae36d564a3bd4 (patch)
tree84e0e2c40a2482db219ef70c5529ef6bbcdd3ffb /src/main/java/com/google/devtools/build
parent2ce45a21dbd6891a3b7ec92e4862ee822b7e8dd1 (diff)
Expose stamp_manifest method to Skylark
RELNOTES: none PiperOrigin-RevId: 195151119
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java101
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java94
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/StampedAndroidManifest.java11
6 files changed, 233 insertions, 5 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java
index 5cbb11ad57..12dae484b6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifest.java
@@ -116,7 +116,7 @@ public class AndroidManifest {
}
/** Gets the default Java package */
- private static String getDefaultPackage(RuleContext ruleContext) {
+ static String getDefaultPackage(RuleContext ruleContext) {
PathFragment dummyJar = ruleContext.getPackageDirectory().getChild("Dummy.jar");
return getJavaPackageFromPath(ruleContext, dummyJar);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java
new file mode 100644
index 0000000000..1e44f46ab4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestInfo.java
@@ -0,0 +1,101 @@
+// 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.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.NativeInfo;
+import com.google.devtools.build.lib.packages.NativeProvider;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.FunctionSignature;
+import com.google.devtools.build.lib.syntax.SkylarkType;
+
+/** A provider of information about this target's manifest. */
+@SkylarkModule(
+ name = "AndroidManifestInfo",
+ doc =
+ "Information about the Android manifest provided by a rule. Note that, as of now, the"
+ + " information exposed in this object is not directly consumed by Android rules -"
+ + " instead, use an AndroidResourcesInfo.",
+ category = SkylarkModuleCategory.PROVIDER)
+public class AndroidManifestInfo extends NativeInfo {
+ private static final String SKYLARK_NAME = "AndroidManifestInfo";
+
+ private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE =
+ FunctionSignature.WithValues.create(
+ FunctionSignature.of(
+ /* numMandatoryPositionals = */ 2, // Manifest file and package
+ /* numOptionalPositionals = */ 1, // exports_manifest
+ /* numMandatoryNamedOnly = */ 0,
+ /* starArg = */ false,
+ /* kwArg = */ false,
+ /* names = */ "manifest",
+ "package",
+ "exports_manifest"),
+ /* defaultValues = */ ImmutableList.of(false), // is_dummy
+ /* types = */ ImmutableList.of(
+ SkylarkType.of(Artifact.class), // manifest
+ SkylarkType.STRING, // package
+ SkylarkType.BOOL)); // exports_manifest
+
+ public static final NativeProvider<AndroidManifestInfo> PROVIDER =
+ new NativeProvider<AndroidManifestInfo>(AndroidManifestInfo.class, SKYLARK_NAME, SIGNATURE) {
+ @Override
+ public AndroidManifestInfo createInstanceFromSkylark(
+ Object[] args, Environment env, Location loc) {
+ // Skylark support code puts positional inputs in the correct order and validates types.
+ return of((Artifact) args[0], (String) args[1], (boolean) args[2]);
+ }
+ };
+
+ private final Artifact manifest;
+ private final String pkg;
+ private final boolean exportsManifest;
+
+ static AndroidManifestInfo of(Artifact manifest, String pkg, boolean exportsManifest) {
+ return new AndroidManifestInfo(manifest, pkg, exportsManifest);
+ }
+
+ private AndroidManifestInfo(Artifact manifest, String pkg, boolean exportsManifest) {
+ super(PROVIDER);
+ this.manifest = manifest;
+ this.pkg = pkg;
+ this.exportsManifest = exportsManifest;
+ }
+
+ @SkylarkCallable(
+ name = "manifest",
+ doc = "This target's manifest, merged with manifests from dependencies",
+ structField = true)
+ public Artifact getManifest() {
+ return manifest;
+ }
+
+ @SkylarkCallable(name = "package", doc = "This target's package", structField = true)
+ public String getPackage() {
+ return pkg;
+ }
+
+ @SkylarkCallable(
+ name = "exports_manifest",
+ doc = "If this manifest should be exported to targets that depend on it",
+ structField = true)
+ public boolean exportsManifest() {
+ return exportsManifest;
+ }
+}
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 ffcb299a6a..a6b8466a73 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
@@ -13,13 +13,101 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.android;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext;
+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.Runtime;
+import javax.annotation.Nullable;
/** Skylark-visible methods for working with Android data (manifests, resources, and assets). */
@SkylarkModule(
- name = "android_data",
- doc = "Utilities for working with Android data (manifests, resources, and assets)"
-)
+ name = "android_data",
+ doc =
+ "Utilities for working with Android data (manifests, resources, and assets). "
+ + "This API is non-final and subject to change without warning; do not rely on it.")
public class AndroidSkylarkData {
+ /**
+ * 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
+ parameters = {
+ @Param(
+ name = "manifest",
+ positional = false,
+ defaultValue = "None",
+ type = Artifact.class,
+ noneable = true,
+ named = true,
+ doc = "The manifest to stamp. If not passed, a dummy manifest will be generated"),
+ @Param(
+ name = "custom_package",
+ positional = false,
+ defaultValue = "None",
+ type = String.class,
+ noneable = true,
+ named = true,
+ doc =
+ "The Android application package to stamp the manifest with. If not provided, the"
+ + " current Java package, derived from the location of this target's BUILD"
+ + " file, will be used. For example, given a BUILD file in"
+ + " 'java/com/foo/bar/BUILD', the package would be 'com.foo.bar'."),
+ @Param(
+ name = "exports_manifest",
+ positional = false,
+ defaultValue = "False",
+ type = Boolean.class,
+ named = true,
+ doc =
+ "Defaults to False. If passed as True, this manifest will be exported to and"
+ + " eventually merged into targets that depend on it. Otherwise, it won't be"
+ + " inherited."),
+ },
+ doc = "Stamps a manifest with package information.")
+ public AndroidManifestInfo stampAndroidManifest(
+ SkylarkRuleContext ctx, Object manifest, Object customPackage, boolean exported) {
+ String pkg = fromNoneable(customPackage, String.class);
+ if (pkg == null) {
+ pkg = AndroidManifest.getDefaultPackage(ctx.getRuleContext());
+ }
+
+ Artifact primaryManifest = fromNoneable(manifest, Artifact.class);
+ if (primaryManifest == null) {
+ return StampedAndroidManifest.createEmpty(ctx.getRuleContext(), pkg, exported).toProvider();
+ }
+
+ return new AndroidManifest(primaryManifest, pkg, exported)
+ .stamp(ctx.getRuleContext())
+ .toProvider();
+ }
+
+ /**
+ * Converts a "Noneable" Object passed by Skylark to an nullable object of the appropriate type.
+ *
+ * <p>Skylark "Noneable" types are passed in as an Object that may be either the correct type or a
+ * Runtime.NONE object. Skylark will handle type checking, based on the appropriate @param
+ * annotation, but we still need to do the actual cast (or conversion to null) ourselves.
+ *
+ * @param object the Noneable object
+ * @param clazz the correct class, as defined in the @Param annotation
+ * @param <T> the type to cast to
+ * @return {@code null}, if the noneable argument was None, or the cast object, otherwise.
+ */
+ @Nullable
+ private static <T> T fromNoneable(Object object, Class<T> clazz) {
+ if (object == Runtime.NONE) {
+ return null;
+ }
+
+ return clazz.cast(object);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
index ec54de473c..11c63df827 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
@@ -226,6 +226,14 @@ public final class ResourceApk {
// TODO(b/77574966): Remove this cast once we get rid of ResourceContainer and can guarantee
// that only properly merged resources are passed into this object.
+ if (validatedResources instanceof ValidatedAndroidResources) {
+ ValidatedAndroidResources validated = (ValidatedAndroidResources) validatedResources;
+
+ builder.addNativeDeclaredProvider(validated.getStampedManifest().toProvider());
+ }
+
+ // TODO(b/77574966): Remove this cast once we get rid of ResourceContainer and can guarantee
+ // that only properly merged resources are passed into this object.
if (primaryAssets instanceof MergedAndroidAssets) {
MergedAndroidAssets merged = (MergedAndroidAssets) primaryAssets;
builder.addNativeDeclaredProvider(merged.toProvider());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
index 27bba1bd4d..43b8ba0345 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
@@ -132,6 +132,28 @@ public final class ResourceDependencies {
transitiveRTxt.build());
}
+ static ResourceDependencies wrapManifestInfo(Label label, AndroidManifestInfo manifestInfo) {
+ return new ResourceDependencies(
+ false,
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.create(
+ Order.NAIVE_LINK_ORDER,
+ ResourceContainer.builder()
+ .setManifest(manifestInfo.getManifest())
+ .setJavaPackage(manifestInfo.getPackage())
+ .setManifestExported(manifestInfo.exportsManifest())
+ .setLabel(label)
+ .build()),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, manifestInfo.getManifest()),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER));
+ }
+
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/StampedAndroidManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/StampedAndroidManifest.java
index 9ba17bb533..10e6ff4bab 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/StampedAndroidManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/StampedAndroidManifest.java
@@ -48,7 +48,12 @@ public class StampedAndroidManifest extends AndroidManifest {
/** Creates an empty manifest stamped with the default Java package for this target. */
public static StampedAndroidManifest createEmpty(RuleContext ruleContext, boolean exported) {
- String pkg = AndroidCommon.getJavaPackage(ruleContext);
+ return createEmpty(ruleContext, AndroidCommon.getJavaPackage(ruleContext), exported);
+ }
+
+ /** Creates an empty manifest stamped with a specified package. */
+ public static StampedAndroidManifest createEmpty(
+ RuleContext ruleContext, String pkg, boolean exported) {
return new StampedAndroidManifest(
ApplicationManifest.generateManifest(ruleContext, pkg), pkg, exported);
}
@@ -68,4 +73,8 @@ public class StampedAndroidManifest extends AndroidManifest {
getPackage(),
isExported());
}
+
+ public AndroidManifestInfo toProvider() {
+ return AndroidManifestInfo.of(getManifest(), getPackage(), isExported());
+ }
}