aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-04-21 22:52:35 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-04-22 11:50:20 +0000
commite345ba54feda0c630679d18e3d039fd1ee8843bd (patch)
tree4df0272a0694df00be0670840bd7d34aae75b123
parentc761661bfcc84eb2bdd229e10ecee338a53d3b41 (diff)
Add android deploy info.
Each android binary build operation will output a deploy info proto providing information about how to deploy and launch the APK. The information will vary between build mode (normal, mobile-install, split-apk) and is configuration-dependent. NO_SQ: Presubmit broken -- MOS_MIGRATED_REVID=120494036
-rw-r--r--src/main/java/com/google/devtools/build/lib/BUILD1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java48
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeployInfoAction.java132
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java13
-rw-r--r--src/main/protobuf/BUILD1
-rw-r--r--src/main/protobuf/android_deploy_info.proto36
7 files changed, 233 insertions, 4 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index ecf9acf8df..ffb3ff33ef 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -757,6 +757,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/rules/cpp",
"//src/main/java/com/google/devtools/common/options",
+ "//src/main/protobuf:android_deploy_info_java_proto",
"//src/main/protobuf:apk_manifest_java_proto",
"//third_party:jsr305",
"//third_party/protobuf",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index e534f372a8..9e8117ad2a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -365,6 +365,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
splitResourceApk,
resourceClasses,
ImmutableList.<Artifact>of(),
+ ImmutableList.<Artifact>of(),
proguardMapping);
}
@@ -385,6 +386,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ResourceApk splitResourceApk,
JavaTargetAttributes resourceClasses,
ImmutableList<Artifact> apksUnderTest,
+ ImmutableList<Artifact> additionalMergedManifests,
Artifact proguardMapping) throws InterruptedException {
ImmutableList<Artifact> proguardSpecs = ProguardHelper.collectTransitiveProguardSpecs(
@@ -449,6 +451,14 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
filesBuilder.add(unsignedApk);
filesBuilder.add(zipAlignedApk);
+ Artifact deployInfo = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.DEPLOY_INFO);
+ AndroidDeployInfoAction.createDeployInfoAction(ruleContext,
+ deployInfo,
+ applicationManifest.getManifest(),
+ additionalMergedManifests,
+ Iterables.concat(ImmutableList.of(zipAlignedApk), apksUnderTest));
+ filesBuilder.add(deployInfo);
+
NestedSet<Artifact> filesToBuild = filesBuilder.build();
NestedSet<Artifact> coverageMetadata = (androidCommon.getInstrumentedJar() != null)
@@ -518,6 +528,25 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
nativeLibs,
stubData);
+ Artifact incrementalDeployInfo = ruleContext.getImplicitOutputArtifact(
+ AndroidRuleClasses.DEPLOY_INFO_INCREMENTAL);
+
+ AndroidDeployInfoAction.createDeployInfoAction(ruleContext,
+ incrementalDeployInfo,
+ applicationManifest.getManifest(),
+ additionalMergedManifests,
+ ImmutableList.<Artifact>of());
+
+ NestedSet<Artifact> fullOutputGroup = NestedSetBuilder.<Artifact>stableOrder()
+ .add(fullDeployMarker)
+ .add(incrementalDeployInfo)
+ .build();
+
+ NestedSet<Artifact> incrementalOutputGroup = NestedSetBuilder.<Artifact>stableOrder()
+ .add(incrementalDeployMarker)
+ .add(incrementalDeployInfo)
+ .build();
+
NestedSetBuilder<Artifact> splitApkSetBuilder = NestedSetBuilder.compileOrder();
// Put the Android resource APK first so that this split gets installed first.
@@ -599,9 +628,19 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
createSplitInstallAction(ruleContext, splitDeployMarker, argsArtifact, splitMainApk,
splitApks, stubData);
+ Artifact splitDeployInfo = ruleContext.getImplicitOutputArtifact(
+ AndroidRuleClasses.DEPLOY_INFO_SPLIT);
+ AndroidDeployInfoAction.createDeployInfoAction(
+ ruleContext,
+ splitDeployInfo,
+ applicationManifest.getManifest(),
+ additionalMergedManifests,
+ ImmutableList.<Artifact>of());
+
NestedSet<Artifact> splitOutputGroup = NestedSetBuilder.<Artifact>stableOrder()
.addTransitive(allSplitApks)
.add(splitDeployMarker)
+ .add(splitDeployInfo)
.build();
Artifact apkManifest =
@@ -653,10 +692,13 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.add(
ApkProvider.class,
new ApkProvider(
- NestedSetBuilder.create(Order.STABLE_ORDER, zipAlignedApk), coverageMetadata))
+ NestedSetBuilder.create(Order.STABLE_ORDER, zipAlignedApk),
+ coverageMetadata,
+ NestedSetBuilder.create(Order.STABLE_ORDER, applicationManifest.getManifest())
+ ))
.add(AndroidPreDexJarProvider.class, new AndroidPreDexJarProvider(jarToDex))
- .addOutputGroup("mobile_install_full", fullDeployMarker)
- .addOutputGroup("mobile_install_incremental", incrementalDeployMarker)
+ .addOutputGroup("mobile_install_full", fullOutputGroup)
+ .addOutputGroup("mobile_install_incremental", incrementalOutputGroup)
.addOutputGroup("mobile_install_split", splitOutputGroup)
.addOutputGroup("apk_manifest", apkManifest)
.addOutputGroup("apk_manifest_text", apkManifestText);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeployInfoAction.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeployInfoAction.java
new file mode 100644
index 0000000000..cae2cece29
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDeployInfoAction.java
@@ -0,0 +1,132 @@
+// 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 com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionOwner;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.actions.AbstractFileWriteAction;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.rules.android.deployinfo.AndroidDeployInfoOuterClass;
+import com.google.devtools.build.lib.rules.android.deployinfo.AndroidDeployInfoOuterClass.AndroidDeployInfo;
+import com.google.devtools.build.lib.util.Fingerprint;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Writes AndroidDeployInfo proto message. This proto describes how
+ * to deploy and launch an android_binary/android_test.
+ */
+@Immutable
+public final class AndroidDeployInfoAction extends AbstractFileWriteAction {
+
+ private static Iterable<Artifact> makeInputs(
+ Artifact mergedManifest,
+ Iterable<Artifact> additionalMergedManifests,
+ Iterable<Artifact> apksToDeploy) {
+
+ return ImmutableList.<Artifact>builder()
+ .add(mergedManifest)
+ .addAll(additionalMergedManifests)
+ .addAll(apksToDeploy)
+ .build();
+ }
+
+ private static final String GUID = "eda283ba-9000-4b80-8dc4-7939101c44ba";
+ private final ByteString byteString;
+
+ AndroidDeployInfoAction(
+ ActionOwner owner,
+ Artifact outputFile,
+ Artifact mergedManifest,
+ Iterable<Artifact> additionalMergedManifests,
+ Iterable<Artifact> apksToDeploy) {
+ super(owner, makeInputs(mergedManifest, additionalMergedManifests, apksToDeploy),
+ outputFile, false);
+ AndroidDeployInfoOuterClass.AndroidDeployInfo.Builder builder =
+ AndroidDeployInfoOuterClass.AndroidDeployInfo.newBuilder();
+ builder.setMergedManifest(makeArtifactProto(mergedManifest));
+ for (Artifact additionMergedManifest : additionalMergedManifests) {
+ builder.addAdditionalMergedManifests(makeArtifactProto(additionMergedManifest));
+ }
+ for (Artifact apk : apksToDeploy) {
+ builder.addApksToDeploy(makeArtifactProto(apk));
+ }
+ this.byteString = builder.build().toByteString();
+ }
+
+ static void createDeployInfoAction(
+ RuleContext ruleContext,
+ Artifact deployInfo,
+ Artifact mergedManifest,
+ Iterable<Artifact> additionalMergedManifests,
+ Iterable<Artifact> apksToDeploy) {
+ Action action = new AndroidDeployInfoAction(ruleContext.getActionOwner(),
+ deployInfo, mergedManifest, additionalMergedManifests, apksToDeploy);
+ ruleContext.registerAction(action);
+ }
+
+ @Override
+ public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx) throws IOException {
+
+ return new DeterministicWriter() {
+ @Override
+ public void writeOutputFile(OutputStream out) throws IOException {
+ try (InputStream in = byteString.newInput()) {
+ ByteStreams.copy(in, out);
+ }
+ out.flush();
+ }
+ };
+ }
+
+ @VisibleForTesting
+ public AndroidDeployInfo getDeployInfo() throws InvalidProtocolBufferException {
+ return AndroidDeployInfo.parseFrom(byteString);
+ }
+
+ @Override
+ protected String computeKey() {
+ Fingerprint f = new Fingerprint()
+ .addString(GUID);
+
+ try (InputStream in = byteString.newInput()) {
+ byte[] buffer = new byte[512];
+ int amountRead;
+ while ((amountRead = in.read(buffer)) != -1) {
+ f.addBytes(buffer, 0, amountRead);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return f.hexDigestAndReset();
+ }
+
+ private static AndroidDeployInfoOuterClass.Artifact makeArtifactProto(Artifact artifact) {
+ return AndroidDeployInfoOuterClass.Artifact.newBuilder()
+ .setExecRootPath(artifact.getExecPathString())
+ .build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index 56db345650..7cd976d654 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -137,6 +137,12 @@ public final class AndroidRuleClasses {
fromTemplates("%{name}_files/apk_manifest");
public static final SafeImplicitOutputsFunction APK_MANIFEST_TEXT =
fromTemplates("%{name}_files/apk_manifest_text");
+ 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");
// 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
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java
index 0f943dcfa2..2ac6c0d69b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApkProvider.java
@@ -28,9 +28,13 @@ public final class ApkProvider implements TransitiveInfoProvider {
private final NestedSet<Artifact> coverageMetadata;
- public ApkProvider(NestedSet<Artifact> transitiveApks, NestedSet<Artifact> coverageMetdata) {
+ private final NestedSet<Artifact> mergedManifests;
+
+ public ApkProvider(NestedSet<Artifact> transitiveApks, NestedSet<Artifact> coverageMetdata,
+ NestedSet<Artifact> mergedManifests) {
this.transitiveApks = transitiveApks;
this.coverageMetadata = coverageMetdata;
+ this.mergedManifests = mergedManifests;
}
/**
@@ -46,4 +50,11 @@ public final class ApkProvider implements TransitiveInfoProvider {
public NestedSet<Artifact> getCoverageMetadata() {
return coverageMetadata;
}
+
+ /**
+ * Returns the merged manifests
+ */
+ public NestedSet<Artifact> getMergedManifests() {
+ return mergedManifests;
+ }
}
diff --git a/src/main/protobuf/BUILD b/src/main/protobuf/BUILD
index 663b5988c4..1e71e025bb 100644
--- a/src/main/protobuf/BUILD
+++ b/src/main/protobuf/BUILD
@@ -19,6 +19,7 @@ FILES = [
"worker_protocol",
"invocation_policy",
"remote_protocol",
+ "android_deploy_info",
"apk_manifest",
]
diff --git a/src/main/protobuf/android_deploy_info.proto b/src/main/protobuf/android_deploy_info.proto
new file mode 100644
index 0000000000..c93c9dc584
--- /dev/null
+++ b/src/main/protobuf/android_deploy_info.proto
@@ -0,0 +1,36 @@
+// Copyright 2016 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.
+
+syntax = "proto3";
+package blaze;
+
+option java_package = "com.google.devtools.build.lib.rules.android.deployinfo";
+
+message Artifact {
+ // This path is relative to "bazel info execution_root"
+ string exec_root_path = 1;
+}
+
+// Information about how to deploy and launch the result of an android build
+message AndroidDeployInfo {
+ // The merged manifest in the resource APK
+ Artifact merged_manifest = 1;
+
+ // Merged manifests of dependencies
+ repeated Artifact additional_merged_manifests = 2;
+
+ // If the build supports an external deploy, this will have the APKs.
+ // mobile-install does its own deployment, so this list will be empty
+ repeated Artifact apks_to_deploy = 3;
+}