diff options
author | asteinb <asteinb@google.com> | 2018-05-25 11:16:34 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-25 11:17:48 -0700 |
commit | c2cf1132a75d03cc37888fe8c2b9583c7ce198c5 (patch) | |
tree | 77d981b934797bb9e335cabf1c9c496023bb74e9 /src/main/java | |
parent | 2643d4b7543403eae52c038e769231f539938195 (diff) |
Automated rollback of commit 372fbc2f016157b0331f83a20edad10d4b4cf9f7.
*** Reason for rollback ***
Roll forward with fix:
I was assuming that R.txt and symbols files are always set, but they can be
null in some cases (especially in the old data processing pipeline). Properly
handle them here.
RELNOTES: none
PiperOrigin-RevId: 198075743
Diffstat (limited to 'src/main/java')
20 files changed, 398 insertions, 882 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java index ed24747882..1e9f5c58d7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java @@ -100,8 +100,7 @@ public class AarImport implements RuleConfiguredTargetFactory { final AndroidDataContext dataContext = androidSemantics.makeContextForNative(ruleContext); final ResourceApk resourceApk; if (AndroidResources.decoupleDataProcessing(dataContext)) { - StampedAndroidManifest manifest = - AndroidManifest.forAarImport(androidManifestArtifact); + StampedAndroidManifest manifest = AndroidManifest.forAarImport(androidManifestArtifact); boolean neverlink = JavaCommon.isNeverLink(ruleContext); ValidatedAndroidResources validatedResources = @@ -122,6 +121,7 @@ public class AarImport implements RuleConfiguredTargetFactory { resourceApk = androidManifest.packAarWithDataAndResources( ruleContext, + dataContext, AndroidAssets.forAarImport(assets), AndroidResources.forAarImport(resources), ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext)), @@ -168,8 +168,6 @@ public class AarImport implements RuleConfiguredTargetFactory { .addCompileTimeJarAsFullJar(mergedJar) .build()); - - JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class); // TODO(cnsun): need to pass the transitive classpath too to emit add dep command. NestedSet<Artifact> directDeps = getCompileTimeJarsFromCollection(targets, /*isStrict=*/ true); 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 0bc24677dd..96d4fb3e71 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 @@ -261,6 +261,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { resourceApk = applicationManifest.packBinaryWithDataAndResources( ruleContext, + dataContext, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK), resourceDeps, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT), diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java index 0c8d4cf7cb..b344411ba8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryMobileInstall.java @@ -101,6 +101,7 @@ public final class AndroidBinaryMobileInstall { .addMobileInstallStubApplication(ruleContext) .packIncrementalBinaryWithDataAndResources( ruleContext, + dataContext, ruleContext.getImplicitOutputArtifact( AndroidRuleClasses.ANDROID_INCREMENTAL_RESOURCES_APK), resourceDeps, @@ -114,6 +115,7 @@ public final class AndroidBinaryMobileInstall { .createSplitManifest(ruleContext, "android_resources", false) .packIncrementalBinaryWithDataAndResources( ruleContext, + dataContext, getMobileInstallArtifact(ruleContext, "android_resources.ap_"), resourceDeps, ruleContext.getExpander().withDataLocations().tokenized("nocompress_extensions"), diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataConverter.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataConverter.java index 5aaf6cad99..28d242c033 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataConverter.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataConverter.java @@ -16,7 +16,6 @@ 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.actions.CommandLineItem.ParametrizedMapFn; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; @@ -26,6 +25,7 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; +import javax.annotation.Nullable; /** * Factory for functions to convert a {@code T} to a commandline argument. Uses a certain convention @@ -42,7 +42,7 @@ public class AndroidDataConverter<T> extends ParametrizedMapFn<T> { .withRoots(MergableAndroidData::getResourceRoots) .withRoots(MergableAndroidData::getAssetRoots) .withLabel(MergableAndroidData::getLabel) - .withArtifact(MergableAndroidData::getSymbols) + .maybeWithArtifact(MergableAndroidData::getSymbols) .build(); /** Indicates the type of joiner between options expected by the command line. */ @@ -119,14 +119,6 @@ public class AndroidDataConverter<T> extends ParametrizedMapFn<T> { return new Builder<>(joinerType); } - public void addDepsToCommandLine( - CustomCommandLine.Builder cmdBuilder, - NestedSet<? extends T> direct, - NestedSet<? extends T> transitive) { - cmdBuilder.addAll("--data", getVectorArg(transitive)); - cmdBuilder.addAll("--directData", getVectorArg(direct)); - } - public VectorArg<String> getVectorArg(NestedSet<? extends T> values) { return VectorArg.join(joinerType.listSeparator).each(values).mapped(this); } @@ -145,31 +137,24 @@ public class AndroidDataConverter<T> extends ParametrizedMapFn<T> { } Builder<T> withRoots(Function<T, ImmutableList<PathFragment>> rootsFunction) { - return with(new Function<T, String>() { - @Override - public String apply(T t) { - return rootsToString(rootsFunction.apply(t)); - } - }); + return with(t -> rootsToString(rootsFunction.apply(t))); } Builder<T> withArtifact(Function<T, Artifact> artifactFunction) { - return with(new Function<T, String>() { - @Override - public String apply(T t) { - return artifactFunction.apply(t).getExecPathString(); - } - }); + return with(t -> artifactFunction.apply(t).getExecPathString()); + } + + Builder<T> maybeWithArtifact(Function<T, Artifact> nullableArtifactFunction) { + return with( + t -> { + @Nullable Artifact artifact = nullableArtifactFunction.apply(t); + return artifact == null ? "" : artifact.getExecPathString(); + }); } Builder<T> withLabel(Function<T, Label> labelFunction) { // Escape labels, since they are known to contain separating characters (specifically, ':'). - return with(new Function<T, String>() { - @Override - public String apply(T t) { - return joinerType.escape(labelFunction.apply(t).toString()); - } - }); + return with(t -> joinerType.escape(labelFunction.apply(t).toString())); } Builder<T> with(Function<T, String> stringFunction) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java index 67dbd5a85e..f4ed5d53eb 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java @@ -169,6 +169,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory { resourceApk = applicationManifest.packLibraryWithDataAndResources( ruleContext, + dataContext, resourceDeps, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT), ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_MERGED_SYMBOLS), diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java index e32d12c1b2..2dccf13cb6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java @@ -117,6 +117,7 @@ public abstract class AndroidLocalTestBase implements RuleConfiguredTargetFactor resourceApk = applicationManifest.packBinaryWithDataAndResources( ruleContext, + dataContext, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK), resourceDependencies, ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT), diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestMergeHelper.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestMergeHelper.java index be6c9baf15..4d99f6d6d7 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestMergeHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidManifestMergeHelper.java @@ -71,4 +71,4 @@ public final class AndroidManifestMergeHelper { .addCommandLine(commandLine.build()) .build(context)); } -}
\ No newline at end of file +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java index 1d5256374b..9d945e2104 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java @@ -14,21 +14,10 @@ package com.google.devtools.build.lib.rules.android; import com.google.common.base.Preconditions; -import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ParamFileInfo; -import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; -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.CustomCommandLine; -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.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.android.AndroidDataConverter.JoinerType; -import com.google.devtools.build.lib.util.OS; -import java.util.ArrayList; -import java.util.List; import javax.annotation.Nullable; /** @@ -52,9 +41,6 @@ public class AndroidResourceMergingActionBuilder { .withArtifact(CompiledMergableAndroidData::getCompiledSymbols) .build(); - private final RuleContext ruleContext; - private final AndroidSdkProvider sdk; - // Inputs private CompiledMergableAndroidData primary; private ResourceDependencies dependencies; @@ -70,12 +56,6 @@ public class AndroidResourceMergingActionBuilder { private boolean throwOnResourceConflict; private boolean useCompiledMerge; - /** @param ruleContext The RuleContext that was used to create the SpawnAction.Builder. */ - public AndroidResourceMergingActionBuilder(RuleContext ruleContext) { - this.ruleContext = ruleContext; - this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext); - } - /** * The primary resource for merging. This resource will overwrite any resource or data value in * the transitive closure. @@ -132,172 +112,102 @@ public class AndroidResourceMergingActionBuilder { return this; } - private NestedSetBuilder<Artifact> createInputsForBuilder(CustomCommandLine.Builder builder) { - // Use a FluentIterable to avoid flattening the NestedSets - NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); - - builder.addExecPath("--androidJar", sdk.getAndroidJar()); - inputs.add(sdk.getAndroidJar()); - - Preconditions.checkNotNull(primary.getManifest()); - builder.addExecPath("--primaryManifest", primary.getManifest()); - inputs.add(primary.getManifest()); - - if (!Strings.isNullOrEmpty(customJavaPackage)) { - // Sets an alternative java package for the generated R.java - // this allows android rules to generate resources outside of the java{,tests} tree. - builder.add("--packageForR", customJavaPackage); - } - - if (throwOnResourceConflict) { - builder.add("--throwOnResourceConflict"); - } - - return inputs; + private BusyBoxActionBuilder createInputsForBuilder(BusyBoxActionBuilder builder) { + return builder + .addAndroidJar() + .addInput("--primaryManifest", primary.getManifest()) + .maybeAddFlag("--packageForR", customJavaPackage) + .maybeAddFlag("--throwOnResourceConflict", throwOnResourceConflict); } - private void buildCompiledResourceMergingAction( - CustomCommandLine.Builder builder, - List<Artifact> outputs, - ActionConstructionContext context) { - NestedSetBuilder<Artifact> inputs = createInputsForBuilder(builder); - + private void buildCompiledResourceMergingAction(BusyBoxActionBuilder builder) { Preconditions.checkNotNull(primary); - builder.add("--primaryData", RESOURCE_CONTAINER_TO_ARG_FOR_COMPILED.map(primary)); - inputs.addAll(primary.getArtifacts()); - inputs.add(primary.getCompiledSymbols()); + + createInputsForBuilder(builder) + .addInput( + "--primaryData", + RESOURCE_CONTAINER_TO_ARG_FOR_COMPILED.map(primary), + Iterables.concat( + primary.getArtifacts(), ImmutableList.of(primary.getCompiledSymbols()))); if (dependencies != null) { - RESOURCE_CONTAINER_TO_ARG_FOR_COMPILED.addDepsToCommandLine( - builder, - dependencies.getDirectResourceContainers(), - dependencies.getTransitiveResourceContainers()); - inputs.addTransitive(dependencies.getTransitiveResources()); - inputs.addTransitive(dependencies.getTransitiveAssets()); - inputs.addTransitive(dependencies.getTransitiveCompiledSymbols()); + builder + .addTransitiveFlag( + "--data", + dependencies.getTransitiveResourceContainers(), + RESOURCE_CONTAINER_TO_ARG_FOR_COMPILED) + .addTransitiveFlag( + "--directData", + dependencies.getDirectResourceContainers(), + RESOURCE_CONTAINER_TO_ARG_FOR_COMPILED) + .addTransitiveInputValues(dependencies.getTransitiveResources()) + .addTransitiveInputValues(dependencies.getTransitiveAssets()) + .addTransitiveInputValues(dependencies.getTransitiveCompiledSymbols()); } - SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); - ParamFileInfo.Builder compiledParamFileInfo = ParamFileInfo.builder(ParameterFileType.UNQUOTED); - compiledParamFileInfo.setUseAlways(OS.getCurrent() == OS.WINDOWS); - // Create the spawn action. - ruleContext.registerAction( - spawnActionBuilder - .useDefaultShellEnvironment() - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.copyOf(outputs)) - .addCommandLine(builder.build(), compiledParamFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Merging compiled Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidCompiledResourceMerger") - .build(context)); + builder.buildAndRegister("Merging compiled Android resources", "AndroidCompiledResourceMerger"); } - private void buildParsedResourceMergingAction( - CustomCommandLine.Builder builder, - List<Artifact> outputs, - ActionConstructionContext context) { - NestedSetBuilder<Artifact> inputs = createInputsForBuilder(builder); - + private void buildParsedResourceMergingAction(BusyBoxActionBuilder builder) { Preconditions.checkNotNull(primary); - builder.add("--primaryData", RESOURCE_CONTAINER_TO_ARG.map(primary)); - inputs.addAll(primary.getArtifacts()); - inputs.add(primary.getSymbols()); + + createInputsForBuilder(builder) + .addInput( + "--primaryData", + RESOURCE_CONTAINER_TO_ARG.map(primary), + Iterables.concat(primary.getArtifacts(), ImmutableList.of(primary.getSymbols()))); if (dependencies != null) { - RESOURCE_CONTAINER_TO_ARG.addDepsToCommandLine( - builder, - dependencies.getDirectResourceContainers(), - dependencies.getTransitiveResourceContainers()); - inputs.addTransitive(dependencies.getTransitiveResources()); - inputs.addTransitive(dependencies.getTransitiveAssets()); - inputs.addTransitive(dependencies.getTransitiveSymbolsBin()); + builder + .addTransitiveFlag( + "--data", dependencies.getTransitiveResourceContainers(), RESOURCE_CONTAINER_TO_ARG) + .addTransitiveFlag( + "--directData", dependencies.getDirectResourceContainers(), RESOURCE_CONTAINER_TO_ARG) + .addTransitiveInputValues(dependencies.getTransitiveResources()) + .addTransitiveInputValues(dependencies.getTransitiveAssets()) + .addTransitiveInputValues(dependencies.getTransitiveSymbolsBin()); } - SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); - ParamFileInfo.Builder paramFileInfo = ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED); - // Some flags (e.g. --mainData) may specify lists (or lists of lists) separated by special - // characters (colon, semicolon, hashmark, ampersand) that don't work on Windows, and quoting - // semantics are very complicated (more so than in Bash), so let's just always use a parameter - // file. - // TODO(laszlocsomor), TODO(corysmith): restructure the Android BusyBux's flags by deprecating - // list-type and list-of-list-type flags that use such problematic separators in favor of - // multi-value flags (to remove one level of listing) and by changing all list separators to a - // platform-safe character (= comma). - paramFileInfo.setUseAlways(OS.getCurrent() == OS.WINDOWS); - - // Create the spawn action. - ruleContext.registerAction( - spawnActionBuilder - .useDefaultShellEnvironment() - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.copyOf(outputs)) - .addCommandLine(builder.build(), paramFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Merging Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidResourceMerger") - .build(context)); + builder.buildAndRegister("Merging Android resources", "AndroidResourceMerger"); } - private void build(RuleContext context) { - CustomCommandLine.Builder parsedMergeBuilder = - new CustomCommandLine.Builder().add("--tool").add("MERGE").add("--"); - CustomCommandLine.Builder compiledMergeBuilder = - new CustomCommandLine.Builder().add("--tool").add("MERGE_COMPILED").add("--"); - List<Artifact> parsedMergeOutputs = new ArrayList<>(); - List<Artifact> compiledMergeOutputs = new ArrayList<>(); + private void build(AndroidDataContext dataContext) { + BusyBoxActionBuilder parsedMergeBuilder = BusyBoxActionBuilder.create(dataContext, "MERGE"); + BusyBoxActionBuilder compiledMergeBuilder = + BusyBoxActionBuilder.create(dataContext, "MERGE_COMPILED"); - if (mergedResourcesOut != null) { - parsedMergeBuilder.addExecPath("--resourcesOutput", mergedResourcesOut); - parsedMergeOutputs.add(mergedResourcesOut); - } + parsedMergeBuilder.addOutput("--resourcesOutput", mergedResourcesOut); // TODO(corysmith): Move the data binding parsing out of the merging pass to enable faster // aapt2 builds. - if (dataBindingInfoZip != null) { - parsedMergeBuilder.addExecPath("--dataBindingInfoOut", dataBindingInfoZip); - parsedMergeOutputs.add(dataBindingInfoZip); - } - - CustomCommandLine.Builder jarAndManifestBuilder = - useCompiledMerge ? compiledMergeBuilder : parsedMergeBuilder; - List<Artifact> jarAndManifestOutputs = - useCompiledMerge ? compiledMergeOutputs : parsedMergeOutputs; + parsedMergeBuilder.maybeAddOutput("--dataBindingInfoOut", dataBindingInfoZip); - if (classJarOut != null) { - jarAndManifestBuilder.addExecPath("--classJarOutput", classJarOut); - jarAndManifestBuilder.addLabel("--targetLabel", ruleContext.getLabel()); - jarAndManifestOutputs.add(classJarOut); - } + (useCompiledMerge ? compiledMergeBuilder : parsedMergeBuilder) + .addOutput("--classJarOutput", classJarOut) + .addLabelFlag("--targetLabel") - // For now, do manifest processing to remove placeholders that aren't handled by the legacy - // manifest merger. Remove this once enough users migrate over to the new manifest merger. - if (manifestOut != null) { - jarAndManifestBuilder.addExecPath("--manifestOutput", manifestOut); - jarAndManifestOutputs.add(manifestOut); - } + // For now, do manifest processing to remove placeholders that aren't handled by the legacy + // manifest merger. Remove this once enough users migrate over to the new manifest merger. + .maybeAddOutput("--manifestOutput", manifestOut); - if (!compiledMergeOutputs.isEmpty()) { - buildCompiledResourceMergingAction(compiledMergeBuilder, compiledMergeOutputs, context); + if (useCompiledMerge) { + buildCompiledResourceMergingAction(compiledMergeBuilder); } - if (!parsedMergeOutputs.isEmpty()) { - buildParsedResourceMergingAction(parsedMergeBuilder, parsedMergeOutputs, context); - } + // Always make an action for merging parsed resources - the merged resources are still created + // this way. + buildParsedResourceMergingAction(parsedMergeBuilder); } - public ResourceContainer build(RuleContext ruleContext, ResourceContainer resourceContainer) { - withPrimary(resourceContainer).build(ruleContext); + public ResourceContainer build( + AndroidDataContext dataContext, ResourceContainer resourceContainer) { + withPrimary(resourceContainer).build(dataContext); // Return the full set of processed transitive dependencies. ResourceContainer.Builder result = resourceContainer.toBuilder(); - if (classJarOut != null) { - // ensure the classJar is propagated if it exists. Otherwise, AndroidCommon tries to make it. - // TODO(corysmith): Centralize the class jar generation. - result.setJavaClassJar(classJarOut); - } + + result.setJavaClassJar(classJarOut); + if (manifestOut != null) { result.setManifest(manifestOut); } @@ -307,8 +217,9 @@ public class AndroidResourceMergingActionBuilder { return result.build(); } - public MergedAndroidResources build(RuleContext ruleContext, ParsedAndroidResources parsed) { - withPrimary(parsed).build(ruleContext); + public MergedAndroidResources build( + AndroidDataContext dataContext, ParsedAndroidResources parsed) { + withPrimary(parsed).build(dataContext); return MergedAndroidResources.of( parsed, diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java index a3bd4773d6..13976552ef 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java @@ -15,31 +15,16 @@ package com.google.devtools.build.lib.rules.android; import static java.util.stream.Collectors.joining; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ParamFileInfo; -import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; -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.CustomCommandLine; -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.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.util.OS; +import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import com.google.devtools.build.lib.vfs.PathFragment; -import java.util.ArrayList; -import java.util.List; import javax.annotation.Nullable; /** Builder for creating $android_resource_parser action. */ public class AndroidResourceParsingActionBuilder { - private final RuleContext ruleContext; - private final AndroidSdkProvider sdk; - // These are only needed when parsing resources with data binding @Nullable private Artifact manifest; @Nullable private String javaPackage; @@ -54,12 +39,6 @@ public class AndroidResourceParsingActionBuilder { @Nullable private Artifact compiledSymbols; @Nullable private Artifact dataBindingInfoZip; - /** @param ruleContext The RuleContext that was used to create the SpawnAction.Builder. */ - public AndroidResourceParsingActionBuilder(RuleContext ruleContext) { - this.ruleContext = ruleContext; - this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext); - } - /** Set the artifact location for the output protobuf. */ public AndroidResourceParsingActionBuilder setOutput(Artifact output) { this.output = output; @@ -103,86 +82,32 @@ public class AndroidResourceParsingActionBuilder { return Streams.stream(roots).map(Object::toString).collect(joining("#")); } - private void build(ActionConstructionContext context) { - CustomCommandLine.Builder builder = new CustomCommandLine.Builder(); - - // Set the busybox tool. - builder.add("--tool").add("PARSE").add("--"); - - NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); - + private void build(AndroidDataContext dataContext) { String resourceDirectories = convertRoots(resources.getResourceRoots()) + ":" + convertRoots(assets.getAssetRoots()); - builder.add("--primaryData", resourceDirectories); - inputs.addTransitive( - NestedSetBuilder.<Artifact>naiveLinkOrder() - .addAll(assets.getAssets()) - .addAll(resources.getResources()) - .build()); - - Preconditions.checkNotNull(output); - builder.addExecPath("--output", output); - - SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); - ParamFileInfo.Builder paramFileInfo = ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED); - // Some flags (e.g. --mainData) may specify lists (or lists of lists) separated by special - // characters (colon, semicolon, hashmark, ampersand) that don't work on Windows, and quoting - // semantics are very complicated (more so than in Bash), so let's just always use a parameter - // file. - // TODO(laszlocsomor), TODO(corysmith): restructure the Android BusyBux's flags by deprecating - // list-type and list-of-list-type flags that use such problematic separators in favor of - // multi-value flags (to remove one level of listing) and by changing all list separators to a - // platform-safe character (= comma). - paramFileInfo.setUseAlways(OS.getCurrent() == OS.WINDOWS); - - // Create the spawn action. - ruleContext.registerAction( - spawnActionBuilder - .useDefaultShellEnvironment() - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.of(output)) - .addCommandLine(builder.build(), paramFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Parsing Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidResourceParser") - .build(context)); + Iterable<Artifact> resourceArtifacts = + Iterables.concat(assets.getAssets(), resources.getResources()); + + BusyBoxActionBuilder.create(dataContext, "PARSE") + .addInput("--primaryData", resourceDirectories, resourceArtifacts) + .addOutput("--output", output) + .buildAndRegister("Parsing Android resources", "AndroidResourceParser"); if (compiledSymbols != null) { - List<Artifact> outs = new ArrayList<>(); - CustomCommandLine.Builder flatFileBuilder = new CustomCommandLine.Builder(); - flatFileBuilder - .add("--tool") - .add("COMPILE_LIBRARY_RESOURCES") - .add("--") - .addExecPath("--aapt2", sdk.getAapt2().getExecutable()) - .add("--resources", resourceDirectories) - .addExecPath("--output", compiledSymbols); - inputs.add(sdk.getAapt2().getExecutable()); - outs.add(compiledSymbols); - - // The databinding needs to be processed before compilation, so the stripping happens here. + BusyBoxActionBuilder compiledBuilder = + BusyBoxActionBuilder.create(dataContext, "COMPILE_LIBRARY_RESOURCES") + .addAapt(AndroidAaptVersion.AAPT2) + .addInput("--resources", resourceDirectories, resourceArtifacts) + .addOutput("--output", compiledSymbols); + if (dataBindingInfoZip != null) { - flatFileBuilder.addExecPath("--manifest", manifest); - inputs.add(manifest); - if (!Strings.isNullOrEmpty(javaPackage)) { - flatFileBuilder.add("--packagePath", javaPackage); - } - flatFileBuilder.addExecPath("--dataBindingInfoOut", dataBindingInfoZip); - outs.add(dataBindingInfoZip); + compiledBuilder + .addInput("--manifest", manifest) + .maybeAddFlag("--packagePath", javaPackage) + .addOutput("--dataBindingInfoOut", dataBindingInfoZip); } - // Create the spawn action. - ruleContext.registerAction( - new SpawnAction.Builder() - .useDefaultShellEnvironment() - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.copyOf(outs)) - .addCommandLine(flatFileBuilder.build(), paramFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Compiling Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidResourceCompiler") - .build(context)); + + compiledBuilder.buildAndRegister("Compiling Android resources", "AndroidResourceCompiler"); } } @@ -191,7 +116,9 @@ public class AndroidResourceParsingActionBuilder { * parsed and compiled information. */ public ParsedAndroidResources build( - AndroidResources androidResources, StampedAndroidManifest manifest) { + AndroidDataContext dataContext, + AndroidResources androidResources, + StampedAndroidManifest manifest) { if (dataBindingInfoZip != null) { // Manifest information is needed for data binding setManifest(manifest.getManifest()); @@ -199,17 +126,17 @@ public class AndroidResourceParsingActionBuilder { } setResources(androidResources); - build(ruleContext); + build(dataContext); return ParsedAndroidResources.of( - androidResources, output, compiledSymbols, ruleContext.getLabel(), manifest); + androidResources, output, compiledSymbols, dataContext.getLabel(), manifest); } - public ParsedAndroidAssets build(AndroidAssets assets) { + public ParsedAndroidAssets build(AndroidDataContext dataContext, AndroidAssets assets) { setAssets(assets); - build(ruleContext); + build(dataContext); - return ParsedAndroidAssets.of(assets, output, ruleContext.getLabel()); + return ParsedAndroidAssets.of(assets, output, dataContext.getLabel()); } /** @@ -217,8 +144,8 @@ public class AndroidResourceParsingActionBuilder { * symbols. */ public ResourceContainer buildAndUpdate( - RuleContext ruleContext, ResourceContainer resourceContainer) { - build(ruleContext); + AndroidDataContext dataContext, ResourceContainer resourceContainer) { + build(dataContext); ResourceContainer.Builder builder = resourceContainer diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java index 41abe2f7a3..13a7c04753 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceValidatorActionBuilder.java @@ -14,19 +14,8 @@ package com.google.devtools.build.lib.rules.android; import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ParamFileInfo; -import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; -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.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; -import com.google.devtools.build.lib.analysis.actions.SpawnAction; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import java.util.ArrayList; -import java.util.List; +import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; /** * Builder for creating $android_resource_validator action. This action validates merged resources @@ -37,9 +26,6 @@ import java.util.List; */ public class AndroidResourceValidatorActionBuilder { - private final RuleContext ruleContext; - private final AndroidSdkProvider sdk; - // Inputs private CompiledMergableAndroidData primary; private Artifact mergedResources; @@ -58,12 +44,6 @@ public class AndroidResourceValidatorActionBuilder { private Artifact compiledSymbols; private Artifact apkOut; - /** @param ruleContext The RuleContext that was used to create the SpawnAction.Builder. */ - public AndroidResourceValidatorActionBuilder(RuleContext ruleContext) { - this.ruleContext = ruleContext; - this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext); - } - public AndroidResourceValidatorActionBuilder setStaticLibraryOut(Artifact staticLibraryOut) { this.staticLibraryOut = staticLibraryOut; return this; @@ -116,19 +96,19 @@ public class AndroidResourceValidatorActionBuilder { return this; } - private void build(ActionConstructionContext context) { + private void build(AndroidDataContext dataContext) { if (rTxtOut != null) { - createValidateAction(context); + createValidateAction(dataContext); } if (compiledSymbols != null) { - createLinkStaticLibraryAction(context); + createLinkStaticLibraryAction(dataContext); } } public ResourceContainer build( - ActionConstructionContext context, ResourceContainer resourceContainer) { - withPrimary(resourceContainer).build(context); + AndroidDataContext dataContext, ResourceContainer resourceContainer) { + withPrimary(resourceContainer).build(dataContext); ResourceContainer.Builder builder = resourceContainer.toBuilder(); if (rTxtOut != null) { @@ -146,17 +126,11 @@ public class AndroidResourceValidatorActionBuilder { } public ValidatedAndroidResources build( - ActionConstructionContext context, MergedAndroidResources merged) { - withPrimary(merged).build(context); + AndroidDataContext dataContext, MergedAndroidResources merged) { + withPrimary(merged).build(dataContext); return ValidatedAndroidResources.of( - merged, - rTxtOut, - sourceJarOut, - apkOut, - aapt2RTxtOut, - aapt2SourceJarOut, - staticLibraryOut); + merged, rTxtOut, sourceJarOut, apkOut, aapt2RTxtOut, aapt2SourceJarOut, staticLibraryOut); } public AndroidResourceValidatorActionBuilder setCompiledSymbols(Artifact compiledSymbols) { @@ -175,130 +149,47 @@ public class AndroidResourceValidatorActionBuilder { * <p>This allows the link action to replace the validate action for builds that use aapt2, as * opposed to executing both actions. */ - private void createLinkStaticLibraryAction(ActionConstructionContext context) { - Preconditions.checkNotNull(staticLibraryOut); - Preconditions.checkNotNull(aapt2SourceJarOut); - Preconditions.checkNotNull(aapt2RTxtOut); + private void createLinkStaticLibraryAction(AndroidDataContext dataContext) { Preconditions.checkNotNull(resourceDeps); - CustomCommandLine.Builder builder = new CustomCommandLine.Builder(); - ImmutableList.Builder<Artifact> inputs = ImmutableList.builder(); - ImmutableList.Builder<Artifact> outs = ImmutableList.builder(); - - // Set the busybox tool. - builder.add("--tool").add("LINK_STATIC_LIBRARY").add("--"); - - builder.addExecPath("--aapt2", sdk.getAapt2().getExecutable()); - - builder.add("--libraries").addExecPath(sdk.getAndroidJar()); - inputs.add(sdk.getAndroidJar()); - - builder.addExecPath("--compiled", compiledSymbols); - inputs.add(compiledSymbols); + BusyBoxActionBuilder builder = + BusyBoxActionBuilder.create(dataContext, "LINK_STATIC_LIBRARY") + .addAapt(AndroidAaptVersion.AAPT2) + .addInput("--libraries", dataContext.getSdk().getAndroidJar()) + .addInput("--compiled", compiledSymbols) + .addInput("--manifest", primary.getManifest()) - builder.addExecPath("--manifest", primary.getManifest()); - inputs.add(primary.getManifest()); - - if (!Strings.isNullOrEmpty(customJavaPackage)) { - // Sets an alternative java package for the generated R.java - // this allows android rules to generate resources outside of the java{,tests} tree. - builder.add("--packageForR", customJavaPackage); - } + // Sets an alternative java package for the generated R.java + // this allows android rules to generate resources outside of the java{,tests} tree. + .maybeAddFlag("--packageForR", customJavaPackage); if (!resourceDeps.getTransitiveCompiledSymbols().isEmpty()) { - builder.addExecPaths( - "--compiledDep", - VectorArg.join(context.getConfiguration().getHostPathSeparator()) - .each(resourceDeps.getTransitiveCompiledSymbols())); - inputs.addAll(resourceDeps.getTransitiveCompiledSymbols()); - } - - builder.addExecPath("--sourceJarOut", aapt2SourceJarOut); - outs.add(aapt2SourceJarOut); - - builder.addExecPath("--rTxtOut", aapt2RTxtOut); - outs.add(aapt2RTxtOut); - - builder.addExecPath("--staticLibraryOut", staticLibraryOut); - outs.add(staticLibraryOut); - - ruleContext.registerAction( - new SpawnAction.Builder() - .useDefaultShellEnvironment() - .addTool(sdk.getAapt2()) - .addInputs(inputs.build()) - .addOutputs(outs.build()) - .addCommandLine( - builder.build(), ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED).build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage( - "Linking static android resource library for %s", ruleContext.getLabel()) - .setMnemonic("AndroidResourceLink") - .build(context)); - } - - private void createValidateAction(ActionConstructionContext context) { - CustomCommandLine.Builder builder = new CustomCommandLine.Builder(); - - // Set the busybox tool. - builder.add("--tool").add("VALIDATE").add("--"); - - if (!Strings.isNullOrEmpty(sdk.getBuildToolsVersion())) { - builder.add("--buildToolsVersion", sdk.getBuildToolsVersion()); - } - - builder.addExecPath("--aapt", sdk.getAapt().getExecutable()); - - ImmutableList.Builder<Artifact> inputs = ImmutableList.builder(); - - builder.addExecPath("--androidJar", sdk.getAndroidJar()); - inputs.add(sdk.getAndroidJar()); - - Preconditions.checkNotNull(mergedResources); - builder.addExecPath("--mergedResources", mergedResources); - inputs.add(mergedResources); - - builder.addExecPath("--manifest", primary.getManifest()); - inputs.add(primary.getManifest()); - - if (debug) { - builder.add("--debug"); - } - - if (!Strings.isNullOrEmpty(customJavaPackage)) { - // Sets an alternative java package for the generated R.java - // this allows android rules to generate resources outside of the java{,tests} tree. - builder.add("--packageForR", customJavaPackage); - } - List<Artifact> outs = new ArrayList<>(); - Preconditions.checkNotNull(rTxtOut); - builder.addExecPath("--rOutput", rTxtOut); - outs.add(rTxtOut); - - Preconditions.checkNotNull(sourceJarOut); - builder.addExecPath("--srcJarOutput", sourceJarOut); - outs.add(sourceJarOut); - - if (apkOut != null) { - builder.addExecPath("--packagePath", apkOut); - outs.add(apkOut); + builder.addTransitiveVectoredInput( + "--compiledDep", resourceDeps.getTransitiveCompiledSymbols()); } - SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); - // Create the spawn action. - ruleContext.registerAction( - spawnActionBuilder - .useDefaultShellEnvironment() - .addTool(sdk.getAapt()) - .addInputs(inputs.build()) - .addOutputs(ImmutableList.copyOf(outs)) - .addCommandLine( - builder.build(), ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED).build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Validating Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidResourceValidator") - .build(context)); + builder + .addOutput("--sourceJarOut", aapt2SourceJarOut) + .addOutput("--rTxtOut", aapt2RTxtOut) + .addOutput("--staticLibraryOut", staticLibraryOut) + .buildAndRegister("Linking static android resource library", "AndroidResourceLink"); + } + + private void createValidateAction(AndroidDataContext dataContext) { + BusyBoxActionBuilder.create(dataContext, "VALIDATE") + .maybeAddFlag("--buildToolsVersion", dataContext.getSdk().getBuildToolsVersion()) + .addAapt(AndroidAaptVersion.AAPT) + .addAndroidJar() + .addInput("--mergedResources", mergedResources) + .addInput("--manifest", primary.getManifest()) + .maybeAddFlag("--debug", debug) + + // Sets an alternative java package for the generated R.java + // this allows android rules to generate resources outside of the java{,tests} tree. + .maybeAddFlag("--packageForR", customJavaPackage) + .addOutput("--rOutput", rTxtOut) + .addOutput("--srcJarOutput", sourceJarOut) + .maybeAddOutput("--packagePath", apkOut) + .buildAndRegister("Validating Android resources", "AndroidResourceValidator"); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java index 3417f538c6..58c0a6669a 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java @@ -13,55 +13,45 @@ // limitations under the License. package com.google.devtools.build.lib.rules.android; -import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ParamFileInfo; -import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; -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.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; -import com.google.devtools.build.lib.rules.android.ResourceContainerConverter.ToArg; -import com.google.devtools.build.lib.rules.android.ResourceContainerConverter.ToArg.Includes; -import com.google.devtools.build.lib.util.OS; -import java.util.ArrayList; +import com.google.devtools.build.lib.rules.android.AndroidDataConverter.JoinerType; import java.util.Collections; import java.util.List; /** Builder for creating resource processing action. */ public class AndroidResourcesProcessorBuilder { - private static final ResourceContainerConverter.ToArg AAPT2_RESOURCE_DEP_TO_ARG = - ResourceContainerConverter.builder() - .include(Includes.ResourceRoots) - .include(Includes.Manifest) - .include(Includes.Aapt2RTxt) - .include(Includes.SymbolsBin) - .include(Includes.CompiledSymbols) - .withSeparator(ToArg.SeparatorType.COLON_COMMA) - .toArgConverter(); - - private static final ResourceContainerConverter.ToArg AAPT2_RESOURCE_DEP_TO_ARG_NO_PARSE = - ResourceContainerConverter.builder() - .include(Includes.ResourceRoots) - .include(Includes.Manifest) - .include(Includes.Aapt2RTxt) - .include(Includes.CompiledSymbols) - .withSeparator(ToArg.SeparatorType.COLON_COMMA) - .toArgConverter(); - - private static final ResourceContainerConverter.ToArg RESOURCE_DEP_TO_ARG = - ResourceContainerConverter.builder() - .include(Includes.ResourceRoots) - .include(Includes.Manifest) - .include(Includes.RTxt) - .include(Includes.SymbolsBin) - .withSeparator(ToArg.SeparatorType.COLON_COMMA) - .toArgConverter(); + private static final AndroidDataConverter<ValidatedAndroidData> AAPT2_RESOURCE_DEP_TO_ARG = + AndroidDataConverter.<ValidatedAndroidData>builder(JoinerType.COLON_COMMA) + .withRoots(ValidatedAndroidData::getResourceRoots) + .withRoots(ValidatedAndroidData::getAssetRoots) + .withArtifact(ValidatedAndroidData::getManifest) + .maybeWithArtifact(ValidatedAndroidData::getAapt2RTxt) + .maybeWithArtifact(ValidatedAndroidData::getCompiledSymbols) + .maybeWithArtifact(ValidatedAndroidData::getSymbols) + .build(); + + private static final AndroidDataConverter<ValidatedAndroidData> + AAPT2_RESOURCE_DEP_TO_ARG_NO_PARSE = + AndroidDataConverter.<ValidatedAndroidData>builder(JoinerType.COLON_COMMA) + .withRoots(ValidatedAndroidData::getResourceRoots) + .withRoots(ValidatedAndroidData::getAssetRoots) + .withArtifact(ValidatedAndroidData::getManifest) + .maybeWithArtifact(ValidatedAndroidData::getAapt2RTxt) + .maybeWithArtifact(ValidatedAndroidData::getCompiledSymbols) + .build(); + + private static final AndroidDataConverter<ValidatedAndroidData> RESOURCE_DEP_TO_ARG = + AndroidDataConverter.<ValidatedAndroidData>builder(JoinerType.COLON_COMMA) + .withRoots(ValidatedAndroidData::getResourceRoots) + .withRoots(ValidatedAndroidData::getAssetRoots) + .withArtifact(ValidatedAndroidData::getManifest) + .maybeWithArtifact(ValidatedAndroidData::getRTxt) + .maybeWithArtifact(ValidatedAndroidData::getSymbols) + .build(); private ResourceDependencies resourceDependencies = ResourceDependencies.empty(); private AssetDependencies assetDependencies = AssetDependencies.empty(); @@ -75,10 +65,7 @@ public class AndroidResourcesProcessorBuilder { private ResourceFilterFactory resourceFilterFactory = ResourceFilterFactory.empty(); private List<String> uncompressedExtensions = Collections.emptyList(); private Artifact apkOut; - private final AndroidSdkProvider sdk; - private SpawnAction.Builder spawnActionBuilder; private String customJavaPackage; - private final RuleContext ruleContext; private String versionCode; private String applicationId; private String versionName; @@ -97,13 +84,6 @@ public class AndroidResourcesProcessorBuilder { private boolean useCompiledResourcesForMerge; private boolean isTestWithResources = false; - /** @param ruleContext The RuleContext that was used to create the SpawnAction.Builder. */ - public AndroidResourcesProcessorBuilder(RuleContext ruleContext) { - this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext); - this.ruleContext = ruleContext; - this.spawnActionBuilder = new SpawnAction.Builder(); - } - /** * The output zip for resource-processed data binding expressions (i.e. a zip of .xml files). * @@ -227,9 +207,10 @@ public class AndroidResourcesProcessorBuilder { * @return a {@link ResourceApk} containing the processed resource, asset, and manifest * information. */ - public ResourceApk buildWithoutLocalResources(StampedAndroidManifest manifest) { + public ResourceApk buildWithoutLocalResources( + AndroidDataContext dataContext, StampedAndroidManifest manifest) { - build(AndroidResources.empty(), AndroidAssets.empty(), manifest); + build(dataContext, AndroidResources.empty(), AndroidAssets.empty(), manifest); return ResourceApk.fromTransitiveResources( resourceDependencies, @@ -238,8 +219,9 @@ public class AndroidResourcesProcessorBuilder { rTxtOut); } - public ResourceContainer build(ResourceContainer primary) { + public ResourceContainer build(AndroidDataContext dataContext, ResourceContainer primary) { build( + dataContext, primary.getAndroidResources(), primary.getAndroidAssets(), ProcessedAndroidManifest.from(primary)); @@ -265,14 +247,15 @@ public class AndroidResourcesProcessorBuilder { } public ProcessedAndroidData build( + AndroidDataContext dataContext, AndroidResources primaryResources, AndroidAssets primaryAssets, StampedAndroidManifest primaryManifest) { if (aaptVersion == AndroidAaptVersion.AAPT2) { - createAapt2ApkAction(primaryResources, primaryAssets, primaryManifest); + createAapt2ApkAction(dataContext, primaryResources, primaryAssets, primaryManifest); } else { - createAaptAction(primaryResources, primaryAssets, primaryManifest); + createAaptAction(dataContext, primaryResources, primaryAssets, primaryManifest); } // Wrap the new manifest, if any @@ -288,12 +271,12 @@ public class AndroidResourcesProcessorBuilder { primaryResources, symbols, /* compiledSymbols = */ null, - ruleContext.getLabel(), + dataContext.getLabel(), processedManifest); // Wrap the parsed and merged assets ParsedAndroidAssets parsedAssets = - ParsedAndroidAssets.of(primaryAssets, symbols, ruleContext.getLabel()); + ParsedAndroidAssets.of(primaryAssets, symbols, dataContext.getLabel()); MergedAndroidAssets mergedAssets = MergedAndroidAssets.of(parsedAssets, mergedResourcesOut, assetDependencies); @@ -349,289 +332,145 @@ public class AndroidResourcesProcessorBuilder { } private void createAapt2ApkAction( + AndroidDataContext dataContext, AndroidResources primaryResources, AndroidAssets primaryAssets, StampedAndroidManifest primaryManifest) { - List<Artifact> outs = new ArrayList<>(); - // TODO(corysmith): Convert to an immutable list builder, as there is no benefit to a NestedSet - // here, as it will already have been flattened. - NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); - CustomCommandLine.Builder builder = new CustomCommandLine.Builder(); + BusyBoxActionBuilder builder = + BusyBoxActionBuilder.create(dataContext, "AAPT2_PACKAGE").addAapt(AndroidAaptVersion.AAPT2); - // Set the busybox tool. - builder.add("--tool").add("AAPT2_PACKAGE").add("--"); - - builder.addExecPath("--aapt2", sdk.getAapt2().getExecutable()); if (resourceDependencies != null) { - ResourceContainerConverter.addToCommandLine( - resourceDependencies, - builder, - useCompiledResourcesForMerge - ? AAPT2_RESOURCE_DEP_TO_ARG_NO_PARSE - : AAPT2_RESOURCE_DEP_TO_ARG); - inputs - .addTransitive(resourceDependencies.getTransitiveResources()) - .addTransitive(resourceDependencies.getTransitiveAssets()) - .addTransitive(resourceDependencies.getTransitiveManifests()) - .addTransitive(resourceDependencies.getTransitiveAapt2RTxt()) - .addTransitive(resourceDependencies.getTransitiveCompiledSymbols()); + builder + .addTransitiveFlag( + "--data", + resourceDependencies.getTransitiveResourceContainers(), + useCompiledResourcesForMerge + ? AAPT2_RESOURCE_DEP_TO_ARG_NO_PARSE + : AAPT2_RESOURCE_DEP_TO_ARG) + .addTransitiveFlag( + "--directData", + resourceDependencies.getDirectResourceContainers(), + useCompiledResourcesForMerge + ? AAPT2_RESOURCE_DEP_TO_ARG_NO_PARSE + : AAPT2_RESOURCE_DEP_TO_ARG) + .addTransitiveInputValues(resourceDependencies.getTransitiveResources()) + .addTransitiveInputValues(resourceDependencies.getTransitiveAssets()) + .addTransitiveInputValues(resourceDependencies.getTransitiveManifests()) + .addTransitiveInputValues(resourceDependencies.getTransitiveAapt2RTxt()) + .addTransitiveInputValues(resourceDependencies.getTransitiveCompiledSymbols()); if (!useCompiledResourcesForMerge) { - inputs.addTransitive(resourceDependencies.getTransitiveSymbolsBin()); + builder.addTransitiveInputValues(resourceDependencies.getTransitiveSymbolsBin()); } } - addAssetDeps(builder, inputs); - - if (useCompiledResourcesForMerge) { - builder.add("--useCompiledResourcesForMerge"); - } - - if (conditionalKeepRules) { - builder.add("--conditionalKeepRules"); - } + addAssetDeps(builder) + .maybeAddFlag("--useCompiledResourcesForMerge", useCompiledResourcesForMerge) + .maybeAddFlag("--conditionalKeepRules", conditionalKeepRules); - configureCommonFlags(primaryResources, primaryAssets, primaryManifest, outs, inputs, builder); - - ParamFileInfo.Builder paramFileInfo = ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED); - // Some flags (e.g. --mainData) may specify lists (or lists of lists) separated by special - // characters (colon, semicolon, hashmark, ampersand) that don't work on Windows, and quoting - // semantics are very complicated (more so than in Bash), so let's just always use a parameter - // file. - // TODO(laszlocsomor), TODO(corysmith): restructure the Android BusyBux's flags by deprecating - // list-type and list-of-list-type flags that use such problematic separators in favor of - // multi-value flags (to remove one level of listing) and by changing all list separators to a - // platform-safe character (= comma). - paramFileInfo.setUseAlways(OS.getCurrent() == OS.WINDOWS); - - // Create the spawn action. - ruleContext.registerAction( - this.spawnActionBuilder - .useDefaultShellEnvironment() - .addTool(sdk.getAapt2()) - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.<Artifact>copyOf(outs)) - .addCommandLine(builder.build(), paramFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Processing Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AndroidAapt2") - .build(ruleContext)); + configureCommonFlags(dataContext, primaryResources, primaryAssets, primaryManifest, builder) + .buildAndRegister("Processing Android resources", "AndroidAapt2"); } private void createAaptAction( + AndroidDataContext dataContext, AndroidResources primaryResources, AndroidAssets primaryAssets, StampedAndroidManifest primaryManifest) { - List<Artifact> outs = new ArrayList<>(); - // TODO(corysmith): Convert to an immutable list builder, as there is no benefit to a NestedSet - // here, as it will already have been flattened. - NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); - CustomCommandLine.Builder builder = new CustomCommandLine.Builder(); - - // Set the busybox tool. - builder.add("--tool").add("PACKAGE").add("--"); + BusyBoxActionBuilder builder = BusyBoxActionBuilder.create(dataContext, "PACKAGE"); if (resourceDependencies != null) { - ResourceContainerConverter.addToCommandLine( - resourceDependencies, builder, RESOURCE_DEP_TO_ARG); - inputs - .addTransitive(resourceDependencies.getTransitiveResources()) - .addTransitive(resourceDependencies.getTransitiveAssets()) - .addTransitive(resourceDependencies.getTransitiveManifests()) - .addTransitive(resourceDependencies.getTransitiveRTxt()) - .addTransitive(resourceDependencies.getTransitiveSymbolsBin()); + builder + .addTransitiveFlag( + "--data", resourceDependencies.getTransitiveResourceContainers(), RESOURCE_DEP_TO_ARG) + .addTransitiveFlag( + "--directData", + resourceDependencies.getDirectResourceContainers(), + RESOURCE_DEP_TO_ARG) + .addTransitiveInputValues(resourceDependencies.getTransitiveResources()) + .addTransitiveInputValues(resourceDependencies.getTransitiveAssets()) + .addTransitiveInputValues(resourceDependencies.getTransitiveManifests()) + .addTransitiveInputValues(resourceDependencies.getTransitiveRTxt()) + .addTransitiveInputValues(resourceDependencies.getTransitiveSymbolsBin()); } - addAssetDeps(builder, inputs); + addAssetDeps(builder).addAapt(AndroidAaptVersion.AAPT); - builder.addExecPath("--aapt", sdk.getAapt().getExecutable()); - configureCommonFlags(primaryResources, primaryAssets, primaryManifest, outs, inputs, builder); - - ImmutableList<String> filteredResources = - resourceFilterFactory.getResourcesToIgnoreInExecution(); - if (!filteredResources.isEmpty()) { - builder.addAll("--prefilteredResources", VectorArg.join(",").each(filteredResources)); - } + configureCommonFlags(dataContext, primaryResources, primaryAssets, primaryManifest, builder) + .maybeAddVectoredFlag( + "--prefilteredResources", resourceFilterFactory.getResourcesToIgnoreInExecution()) + .buildAndRegister("Processing Android resources", "AaptPackage"); + } - ParamFileInfo.Builder paramFileInfo = ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED); - // Some flags (e.g. --mainData) may specify lists (or lists of lists) separated by special - // characters (colon, semicolon, hashmark, ampersand) that don't work on Windows, and quoting - // semantics are very complicated (more so than in Bash), so let's just always use a parameter - // file. - // TODO(laszlocsomor), TODO(corysmith): restructure the Android BusyBux's flags by deprecating - // list-type and list-of-list-type flags that use such problematic separators in favor of - // multi-value flags (to remove one level of listing) and by changing all list separators to a - // platform-safe character (= comma). - paramFileInfo.setUseAlways(OS.getCurrent() == OS.WINDOWS); - - // Create the spawn action. - ruleContext.registerAction( - this.spawnActionBuilder - .useDefaultShellEnvironment() - .addTool(sdk.getAapt()) - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.copyOf(outs)) - .addCommandLine(builder.build(), paramFileInfo.build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Processing Android resources for %s", ruleContext.getLabel()) - .setMnemonic("AaptPackage") - .build(ruleContext)); - } - - private void addAssetDeps(CustomCommandLine.Builder builder, NestedSetBuilder<Artifact> inputs) { + private BusyBoxActionBuilder addAssetDeps(BusyBoxActionBuilder builder) { if (assetDependencies == null || assetDependencies.getTransitiveAssets().isEmpty()) { - return; + return builder; } - builder - .addAll( + return builder + .addTransitiveFlag( "--directAssets", - AndroidDataConverter.MERGABLE_DATA_CONVERTER.getVectorArg( - assetDependencies.getDirectParsedAssets())) - .addAll( + assetDependencies.getDirectParsedAssets(), + AndroidDataConverter.MERGABLE_DATA_CONVERTER) + .addTransitiveFlag( "--assets", - AndroidDataConverter.MERGABLE_DATA_CONVERTER.getVectorArg( - assetDependencies.getTransitiveParsedAssets())); - - inputs.addTransitive(assetDependencies.getTransitiveAssets()); - inputs.addTransitive(assetDependencies.getTransitiveSymbols()); + assetDependencies.getTransitiveParsedAssets(), + AndroidDataConverter.MERGABLE_DATA_CONVERTER) + .addTransitiveInputValues(assetDependencies.getTransitiveAssets()) + .addTransitiveInputValues(assetDependencies.getTransitiveSymbols()); } - private void configureCommonFlags( + private BusyBoxActionBuilder configureCommonFlags( + AndroidDataContext dataContext, AndroidResources primaryResources, AndroidAssets primaryAssets, StampedAndroidManifest primaryManifest, - List<Artifact> outs, - NestedSetBuilder<Artifact> inputs, - CustomCommandLine.Builder builder) { - - // Add data - builder.add( - "--primaryData", - String.format( - "%s:%s:%s", - AndroidDataConverter.rootsToString(primaryResources.getResourceRoots()), - AndroidDataConverter.rootsToString(primaryAssets.getAssetRoots()), - primaryManifest.getManifest().getExecPathString())); - inputs.addAll(primaryResources.getResources()); - inputs.addAll(primaryAssets.getAssets()); - inputs.add(primaryManifest.getManifest()); - - if (!Strings.isNullOrEmpty(sdk.getBuildToolsVersion())) { - builder.add("--buildToolsVersion", sdk.getBuildToolsVersion()); - } - - builder.addExecPath("--androidJar", sdk.getAndroidJar()); - inputs.add(sdk.getAndroidJar()); - - if (isLibrary) { - builder.add("--packageType").add("LIBRARY"); - } - - if (rTxtOut != null) { - builder.addExecPath("--rOutput", rTxtOut); - outs.add(rTxtOut); - } - - if (symbols != null) { - builder.addExecPath("--symbolsOut", symbols); - outs.add(symbols); - } - if (sourceJarOut != null) { - builder.addExecPath("--srcJarOutput", sourceJarOut); - outs.add(sourceJarOut); - } - if (proguardOut != null) { - builder.addExecPath("--proguardOutput", proguardOut); - outs.add(proguardOut); - } - - if (mainDexProguardOut != null) { - builder.addExecPath("--mainDexProguardOutput", mainDexProguardOut); - outs.add(mainDexProguardOut); - } - - if (manifestOut != null) { - builder.addExecPath("--manifestOutput", manifestOut); - outs.add(manifestOut); - } - - if (mergedResourcesOut != null) { - builder.addExecPath("--resourcesOutput", mergedResourcesOut); - outs.add(mergedResourcesOut); - } - - if (apkOut != null) { - builder.addExecPath("--packagePath", apkOut); - outs.add(apkOut); - } - - // Always pass density and resource configuration filter strings to execution, even when - // filtering in analysis. Filtering in analysis cannot remove resources from Filesets, and, in - // addition, aapt needs access to resource filters to generate pseudolocalized resources and - // because its resource filtering is somewhat stricter for locales, and - // resource processing needs access to densities to add them to the manifest. - if (resourceFilterFactory.hasConfigurationFilters()) { - builder.add("--resourceConfigs", resourceFilterFactory.getConfigurationFilterString()); - } - if (resourceFilterFactory.hasDensities()) { - builder.add("--densities", resourceFilterFactory.getDensityString()); - } - if (!uncompressedExtensions.isEmpty()) { - builder.addAll("--uncompressedExtensions", VectorArg.join(",").each(uncompressedExtensions)); - } - if (!crunchPng) { - builder.add("--useAaptCruncher=no"); - } - if (debug) { - builder.add("--debug"); - } - - if (versionCode != null) { - builder.add("--versionCode", versionCode); - } - - if (versionName != null) { - builder.add("--versionName", versionName); - } - - if (applicationId != null) { - builder.add("--applicationId", applicationId); - } - - if (dataBindingInfoZip != null) { - builder.addExecPath("--dataBindingInfoOut", dataBindingInfoZip); - outs.add(dataBindingInfoZip); - } - - if (!Strings.isNullOrEmpty(customJavaPackage)) { - // Sets an alternative java package for the generated R.java - // this allows android rules to generate resources outside of the java{,tests} tree. - builder.add("--packageForR", customJavaPackage); - } - - if (featureOf != null) { - builder.addExecPath("--featureOf", featureOf); - inputs.add(featureOf); - } - - if (featureAfter != null) { - builder.addExecPath("--featureAfter", featureAfter); - inputs.add(featureAfter); - } - - if (throwOnResourceConflict) { - builder.add("--throwOnResourceConflict"); - } - - if (packageUnderTest != null) { - builder.add("--packageUnderTest", packageUnderTest); - } - - if (isTestWithResources) { - builder.add("--isTestWithResources"); - } + BusyBoxActionBuilder builder) { + + return builder + .addInput( + "--primaryData", + String.format( + "%s:%s:%s", + AndroidDataConverter.rootsToString(primaryResources.getResourceRoots()), + AndroidDataConverter.rootsToString(primaryAssets.getAssetRoots()), + primaryManifest.getManifest().getExecPathString()), + Iterables.concat( + primaryResources.getResources(), + primaryAssets.getAssets(), + ImmutableList.of(primaryManifest.getManifest()))) + .maybeAddFlag("--buildToolsVersion", dataContext.getSdk().getBuildToolsVersion()) + .addAndroidJar() + .maybeAddFlag("--packageType", isLibrary) + .maybeAddFlag("LIBRARY", isLibrary) + .maybeAddOutput("--rOutput", rTxtOut) + .maybeAddOutput("--symbolsOut", symbols) + .maybeAddOutput("--srcJarOutput", sourceJarOut) + .maybeAddOutput("--proguardOutput", proguardOut) + .maybeAddOutput("--mainDexProguardOutput", mainDexProguardOut) + .maybeAddOutput("--manifestOutput", manifestOut) + .maybeAddOutput("--resourcesOutput", mergedResourcesOut) + .maybeAddOutput("--packagePath", apkOut) + + // Always pass density and resource configuration filter strings to execution, even when + // filtering in analysis. Filtering in analysis cannot remove resources from Filesets, and, + // in addition, aapt needs access to resource filters to generate pseudolocalized resources + // and because its resource filtering is somewhat stricter for locales, and resource + // processing needs access to densities to add them to the manifest. + .maybeAddFlag("--resourceConfigs", resourceFilterFactory.getConfigurationFilterString()) + .maybeAddFlag("--densities", resourceFilterFactory.getDensityString()) + .maybeAddVectoredFlag("--uncompressedExtensions", uncompressedExtensions) + .maybeAddFlag("--useAaptCruncher=no", !crunchPng) + .maybeAddFlag("--debug", debug) + .maybeAddFlag("--versionCode", versionCode) + .maybeAddFlag("--versionName", versionName) + .maybeAddFlag("--applicationId", applicationId) + .maybeAddOutput("--dataBindingInfoOut", dataBindingInfoZip) + .maybeAddFlag("--packageForR", customJavaPackage) + .maybeAddInput("--featureOf", featureOf) + .maybeAddInput("--featureAfter", featureAfter) + .maybeAddFlag("--throwOnResourceConflict", throwOnResourceConflict) + .maybeAddFlag("--packageUnderTest", packageUnderTest) + .maybeAddFlag("--isTestWithResources", isTestWithResources); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java index 900f1056a9..d93b8a2b7f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java @@ -370,6 +370,7 @@ public final class ApplicationManifest { public ResourceApk packTestWithDataAndResources( RuleContext ruleContext, + AndroidDataContext dataContext, Artifact resourceApk, ResourceDependencies resourceDeps, @Nullable Artifact rTxt, @@ -390,7 +391,7 @@ public final class ApplicationManifest { .build(); AndroidResourcesProcessorBuilder builder = - new AndroidResourcesProcessorBuilder(ruleContext) + new AndroidResourcesProcessorBuilder() .setLibrary(false) .setApkOut(resourceContainer.getApk()) .setUncompressedExtensions(ImmutableList.of()) @@ -417,16 +418,16 @@ public final class ApplicationManifest { .setSymbols(resourceContainer.getSymbols()) .setSourceJarOut(resourceContainer.getJavaSourceJar()); } - ResourceContainer processed = builder.build(resourceContainer); + ResourceContainer processed = builder.build(dataContext, resourceContainer); ResourceContainer finalContainer = - new RClassGeneratorActionBuilder(ruleContext) + new RClassGeneratorActionBuilder() .targetAaptVersion(AndroidAaptVersion.chooseTargetAaptVersion(ruleContext)) .withDependencies(resourceDeps) .setClassJarOut( ruleContext.getImplicitOutputArtifact( AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) - .build(processed); + .build(dataContext, processed); return ResourceApk.of(finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg); } @@ -434,6 +435,7 @@ public final class ApplicationManifest { /** Packages up the manifest with resource and assets from the LocalResourceContainer. */ public ResourceApk packAarWithDataAndResources( RuleContext ruleContext, + AndroidDataContext dataContext, AndroidAssets assets, AndroidResources resources, ResourceDependencies resourceDeps, @@ -455,14 +457,14 @@ public final class ApplicationManifest { ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR); resourceContainer = - new AndroidResourceParsingActionBuilder(ruleContext) + new AndroidResourceParsingActionBuilder() .setAssets(assets) .setResources(resources) .setOutput(symbols) - .buildAndUpdate(ruleContext, resourceContainer); + .buildAndUpdate(dataContext, resourceContainer); ResourceContainer merged = - new AndroidResourceMergingActionBuilder(ruleContext) + new AndroidResourceMergingActionBuilder() .setJavaPackage(resourceContainer.getJavaPackage()) .withDependencies(resourceDeps) .setMergedResourcesOut(mergedResources) @@ -473,10 +475,10 @@ public final class ApplicationManifest { .getConfiguration() .getFragment(AndroidConfiguration.class) .throwOnResourceConflict()) - .build(ruleContext, resourceContainer); + .build(dataContext, resourceContainer); ResourceContainer processed = - new AndroidResourceValidatorActionBuilder(ruleContext) + new AndroidResourceValidatorActionBuilder() .setJavaPackage(merged.getJavaPackage()) .setDebug(ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT) .setMergedResources(mergedResources) @@ -489,7 +491,7 @@ public final class ApplicationManifest { .setAapt2RTxtOut(merged.getAapt2RTxt()) .setAapt2SourceJarOut(merged.getAapt2JavaSourceJar()) .setStaticLibraryOut(merged.getStaticLibrary()) - .build(ruleContext, merged); + .build(dataContext, merged); return ResourceApk.of(processed, resourceDeps); } @@ -497,6 +499,7 @@ public final class ApplicationManifest { /* Creates an incremental apk from assets and data. */ public ResourceApk packIncrementalBinaryWithDataAndResources( RuleContext ruleContext, + AndroidDataContext dataContext, Artifact resourceApk, ResourceDependencies resourceDeps, List<String> uncompressedExtensions, @@ -525,7 +528,7 @@ public final class ApplicationManifest { .build(); ResourceContainer processed = - new AndroidResourcesProcessorBuilder(ruleContext) + new AndroidResourcesProcessorBuilder() .setLibrary(false) .setApkOut(resourceContainer.getApk()) .setResourceFilterFactory(resourceFilterFactory) @@ -544,7 +547,7 @@ public final class ApplicationManifest { .getFragment(AndroidConfiguration.class) .throwOnResourceConflict()) .setPackageUnderTest(null) - .build(resourceContainer); + .build(dataContext, resourceContainer); // Intentionally skip building an R class JAR - incremental binaries handle this separately. @@ -555,6 +558,7 @@ public final class ApplicationManifest { // TODO(bazel-team): this method calls for some refactoring, 15+ params including some nullables. public ResourceApk packBinaryWithDataAndResources( RuleContext ruleContext, + AndroidDataContext dataContext, Artifact resourceApk, ResourceDependencies resourceDeps, @Nullable Artifact rTxt, @@ -600,7 +604,7 @@ public final class ApplicationManifest { } ResourceContainer processed = - new AndroidResourcesProcessorBuilder(ruleContext) + new AndroidResourcesProcessorBuilder() .setLibrary(false) .setApkOut(resourceContainer.getApk()) .setResourceFilterFactory(resourceFilterFactory) @@ -626,22 +630,23 @@ public final class ApplicationManifest { .setRTxtOut(resourceContainer.getRTxt()) .setSymbols(resourceContainer.getSymbols()) .setSourceJarOut(resourceContainer.getJavaSourceJar()) - .build(resourceContainer); + .build(dataContext, resourceContainer); ResourceContainer finalContainer = - new RClassGeneratorActionBuilder(ruleContext) + new RClassGeneratorActionBuilder() .targetAaptVersion(AndroidAaptVersion.chooseTargetAaptVersion(ruleContext)) .withDependencies(resourceDeps) .setClassJarOut( ruleContext.getImplicitOutputArtifact( AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) - .build(processed); + .build(dataContext, processed); return ResourceApk.of(finalContainer, resourceDeps, proguardCfg, mainDexProguardCfg); } public ResourceApk packLibraryWithDataAndResources( RuleContext ruleContext, + AndroidDataContext dataContext, ResourceDependencies resourceDeps, Artifact rTxt, Artifact symbols, @@ -689,7 +694,7 @@ public final class ApplicationManifest { targetAaptVersion == AndroidAaptVersion.AAPT2 && androidConfiguration.skipParsingAction(); AndroidResourceParsingActionBuilder parsingBuilder = - new AndroidResourceParsingActionBuilder(ruleContext) + new AndroidResourceParsingActionBuilder() .setAssets(assets) .setResources(resources) .setOutput(resourceContainer.getSymbols()) @@ -708,10 +713,10 @@ public final class ApplicationManifest { .setManifest(resourceContainer.getManifest()) .setJavaPackage(resourceContainer.getJavaPackage()); } - resourceContainer = parsingBuilder.buildAndUpdate(ruleContext, resourceContainer); + resourceContainer = parsingBuilder.buildAndUpdate(dataContext, resourceContainer); ResourceContainer merged = - new AndroidResourceMergingActionBuilder(ruleContext) + new AndroidResourceMergingActionBuilder() .setJavaPackage(resourceContainer.getJavaPackage()) .withDependencies(resourceDeps) .setThrowOnResourceConflict(androidConfiguration.throwOnResourceConflict()) @@ -721,10 +726,10 @@ public final class ApplicationManifest { .setManifestOut(manifestOut) .setClassJarOut(rJavaClassJar) .setDataBindingInfoZip(dataBindingInfoZip) - .build(ruleContext, resourceContainer); + .build(dataContext, resourceContainer); ResourceContainer processed = - new AndroidResourceValidatorActionBuilder(ruleContext) + new AndroidResourceValidatorActionBuilder() .setJavaPackage(merged.getJavaPackage()) .setDebug(ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT) .setMergedResources(mergedResources) @@ -737,7 +742,7 @@ public final class ApplicationManifest { .setAapt2RTxtOut(merged.getAapt2RTxt()) .setAapt2SourceJarOut(merged.getAapt2JavaSourceJar()) .setStaticLibraryOut(merged.getStaticLibrary()) - .build(ruleContext, merged); + .build(dataContext, merged); return ResourceApk.of(processed, resourceDeps); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/BusyBoxActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/BusyBoxActionBuilder.java index 07552fe2c1..16e55f8993 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/BusyBoxActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/BusyBoxActionBuilder.java @@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ParamFileInfo; import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; +import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; import com.google.devtools.build.lib.analysis.actions.SpawnAction; @@ -49,7 +50,7 @@ public final class BusyBoxActionBuilder { private final AndroidDataContext dataContext; private final NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); private final ImmutableList.Builder<Artifact> outputs = ImmutableList.builder(); - private final ImmutableList.Builder<Artifact> tools = ImmutableList.builder(); + private final SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); private final CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); public static BusyBoxActionBuilder create( @@ -287,16 +288,16 @@ public final class BusyBoxActionBuilder { /** Adds aapt to the command line and inputs. */ public BusyBoxActionBuilder addAapt(AndroidAaptVersion aaptVersion) { - Artifact aapt; + FilesToRunProvider aapt; if (aaptVersion == AndroidAaptVersion.AAPT2) { - aapt = dataContext.getSdk().getAapt2().getExecutable(); - commandLine.addExecPath("--aapt2", aapt); + aapt = dataContext.getSdk().getAapt2(); + commandLine.addExecPath("--aapt2", aapt.getExecutable()); } else { - aapt = dataContext.getSdk().getAapt().getExecutable(); - commandLine.addExecPath("--aapt", aapt); + aapt = dataContext.getSdk().getAapt(); + commandLine.addExecPath("--aapt", aapt.getExecutable()); } - tools.add(aapt); + spawnActionBuilder.addTool(aapt); return this; } @@ -315,11 +316,10 @@ public final class BusyBoxActionBuilder { */ public void buildAndRegister(String message, String mnemonic) { dataContext.registerAction( - new SpawnAction.Builder() + spawnActionBuilder .useDefaultShellEnvironment() .addTransitiveInputs(inputs.build()) .addOutputs(outputs.build()) - .addTools(tools.build()) .addCommandLine(commandLine.build(), FORCED_PARAM_FILE_INFO) .setExecutable(dataContext.getBusybox()) .setProgressMessage("%s for %s", message, dataContext.getLabel()) diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidResources.java index da7ceda7b4..29da58659f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidResources.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/MergedAndroidResources.java @@ -54,7 +54,7 @@ public class MergedAndroidResources extends ParsedAndroidResources { "Should not use compiled merge if no compiled symbols are available!"); AndroidResourceMergingActionBuilder builder = - new AndroidResourceMergingActionBuilder(dataContext.getRuleContext()) + new AndroidResourceMergingActionBuilder() .setJavaPackage(parsed.getJavaPackage()) .withDependencies(resourceDeps) .setThrowOnResourceConflict(androidConfiguration.throwOnResourceConflict()) @@ -72,7 +72,7 @@ public class MergedAndroidResources extends ParsedAndroidResources { dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP)) .setClassJarOut( dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) - .build(dataContext.getRuleContext(), parsed); + .build(dataContext, parsed); } public static MergedAndroidResources of( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidAssets.java index 265f22f9d6..b1b2971045 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidAssets.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidAssets.java @@ -24,9 +24,9 @@ public class ParsedAndroidAssets extends AndroidAssets implements MergableAndroi public static ParsedAndroidAssets parseFrom(AndroidDataContext dataContext, AndroidAssets assets) throws InterruptedException { - return new AndroidResourceParsingActionBuilder(dataContext.getRuleContext()) + return new AndroidResourceParsingActionBuilder() .setOutput(dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_ASSET_SYMBOLS)) - .build(assets); + .build(dataContext, assets); } public static ParsedAndroidAssets of(AndroidAssets assets, Artifact symbols, Label label) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidResources.java index 4ff37879c9..83b49b62d1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidResources.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ParsedAndroidResources.java @@ -40,15 +40,14 @@ public class ParsedAndroidResources extends AndroidResources boolean isAapt2 = aaptVersion == AndroidAaptVersion.AAPT2; - AndroidResourceParsingActionBuilder builder = - new AndroidResourceParsingActionBuilder(dataContext.getRuleContext()); + AndroidResourceParsingActionBuilder builder = new AndroidResourceParsingActionBuilder(); if (enableDataBinding && isAapt2) { // TODO(corysmith): Centralize the data binding processing and zipping into a single // action. Data binding processing needs to be triggered here as well as the merger to // avoid aapt2 from throwing an error during compilation. builder.setDataBindingInfoZip( - DataBinding.getSuffixedInfoFile(dataContext.getRuleContext(), "_unused")); + DataBinding.getSuffixedInfoFile(dataContext.getActionConstructionContext(), "_unused")); } return builder @@ -57,7 +56,7 @@ public class ParsedAndroidResources extends AndroidResources isAapt2 ? dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_COMPILED_SYMBOLS) : null) - .build(resources, manifest); + .build(dataContext, resources, manifest); } public static ParsedAndroidResources of( diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java index cbb1034924..a9d4267978 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java @@ -95,6 +95,7 @@ public class ProcessedAndroidData { .setFeatureOf(featureOf) .setFeatureAfter(featureAfter); return buildActionForBinary( + dataContext, errorConsumer, builder, manifest, @@ -121,6 +122,7 @@ public class ProcessedAndroidData { .setApkOut(apkOut); return buildActionForBinary( + dataContext, ruleContext, builder, manifest, @@ -134,6 +136,7 @@ public class ProcessedAndroidData { } private static ProcessedAndroidData buildActionForBinary( + AndroidDataContext dataContext, RuleErrorConsumer errorConsumer, AndroidResourcesProcessorBuilder builder, StampedAndroidManifest manifest, @@ -159,7 +162,7 @@ public class ProcessedAndroidData { .setCrunchPng(crunchPng) .withResourceDependencies(resourceDeps) .withAssetDependencies(assetDeps) - .build(resources, assets, manifest); + .build(dataContext, resources, assets, manifest); } /** Processes Android data (assets, resources, and manifest) for android_local_test targets. */ @@ -186,7 +189,7 @@ public class ProcessedAndroidData { .setCrunchPng(false) .withResourceDependencies(resourceDeps) .withAssetDependencies(assetDeps) - .build(resources, assets, manifest); + .build(dataContext, resources, assets, manifest); } /** Processes Android data (assets, resources, and manifest) for android_test targets. */ @@ -213,7 +216,7 @@ public class ProcessedAndroidData { .withResourceDependencies(resourceDeps) .withAssetDependencies(assetDeps); - return builder.build(resources, assets, manifest); + return builder.build(dataContext, resources, assets, manifest); } /** @@ -249,7 +252,7 @@ public class ProcessedAndroidData { StampedAndroidManifest manifest, String proguardPrefix, Map<String, String> manifestValues) { - return new AndroidResourcesProcessorBuilder(dataContext.getRuleContext()) + return new AndroidResourcesProcessorBuilder() // Settings .setDebug(dataContext.useDebug()) .setJavaPackage(manifest.getPackage()) @@ -321,12 +324,12 @@ public class ProcessedAndroidData { */ public ResourceApk generateRClass(AndroidDataContext dataContext, AndroidAaptVersion aaptVersion) throws InterruptedException { - return new RClassGeneratorActionBuilder(dataContext.getRuleContext()) + return new RClassGeneratorActionBuilder() .targetAaptVersion(aaptVersion) .withDependencies(resourceDeps) .setClassJarOut( dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR)) - .build(this); + .build(dataContext, this); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java index 849881297c..c4e33f1eee 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/RClassGeneratorActionBuilder.java @@ -13,21 +13,9 @@ // limitations under the License. package com.google.devtools.build.lib.rules.android; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.actions.ParamFileInfo; -import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.Builder; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; -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.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.android.AndroidConfiguration.AndroidAaptVersion; import com.google.devtools.build.lib.rules.android.AndroidDataConverter.JoinerType; -import java.util.ArrayList; -import java.util.List; import java.util.function.Function; /** Builds up the spawn action for $android_rclass_generator. */ @@ -42,18 +30,12 @@ public class RClassGeneratorActionBuilder { .with(chooseDepsToArg(AndroidAaptVersion.AAPT2)) .build(); - private final RuleContext ruleContext; private ResourceDependencies dependencies; private Artifact classJarOut; private AndroidAaptVersion version; - /** @param ruleContext The RuleContext that is used to create a SpawnAction.Builder. */ - public RClassGeneratorActionBuilder(RuleContext ruleContext) { - this.ruleContext = ruleContext; - } - public RClassGeneratorActionBuilder withDependencies(ResourceDependencies resourceDeps) { this.dependencies = resourceDeps; return this; @@ -69,72 +51,43 @@ public class RClassGeneratorActionBuilder { return this; } - public ResourceContainer build(ResourceContainer primary) { - build(primary.getRTxt(), ProcessedAndroidManifest.from(primary)); + public ResourceContainer build(AndroidDataContext dataContext, ResourceContainer primary) { + build(dataContext, primary.getRTxt(), ProcessedAndroidManifest.from(primary)); return primary.toBuilder().setJavaClassJar(classJarOut).build(); } - public ResourceApk build(ProcessedAndroidData data) { - build(data.getRTxt(), data.getManifest()); + public ResourceApk build(AndroidDataContext dataContext, ProcessedAndroidData data) { + build(dataContext, data.getRTxt(), data.getManifest()); return data.withValidatedResources(classJarOut); } - private void build(Artifact rTxt, ProcessedAndroidManifest manifest) { - Builder builder = new Builder(); - - // Set the busybox tool. - builder.add("--tool").add("GENERATE_BINARY_R").add("--"); - - NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder(); - inputs.addAll( - ruleContext - .getExecutablePrerequisite("$android_resources_busybox", Mode.HOST) - .getRunfilesSupport() - .getRunfilesArtifacts()); - - List<Artifact> outs = new ArrayList<>(); - builder.addExecPath("--primaryRTxt", rTxt); - inputs.add(rTxt); - builder.addExecPath("--primaryManifest", manifest.getManifest()); - inputs.add(manifest.getManifest()); - if (!Strings.isNullOrEmpty(manifest.getPackage())) { - builder.add("--packageForR", manifest.getPackage()); + private void build( + AndroidDataContext dataContext, Artifact rTxt, ProcessedAndroidManifest manifest) { + BusyBoxActionBuilder builder = + BusyBoxActionBuilder.create(dataContext, "GENERATE_BINARY_R") + .addInput("--primaryRTxt", rTxt) + .addInput("--primaryManifest", manifest.getManifest()) + .maybeAddFlag("--packageForR", manifest.getPackage()); + + if (dependencies != null && !dependencies.getResourceContainers().isEmpty()) { + builder + .addTransitiveFlagForEach( + "--library", + dependencies.getResourceContainers(), + version == AndroidAaptVersion.AAPT2 ? AAPT2_CONVERTER : AAPT_CONVERTER) + .addTransitiveInputValues( + version == AndroidAaptVersion.AAPT2 + ? dependencies.getTransitiveAapt2RTxt() + : dependencies.getTransitiveRTxt()) + .addTransitiveInputValues(dependencies.getTransitiveManifests()); } - if (dependencies != null) { - if (!dependencies.getResourceContainers().isEmpty()) { - builder.addAll( - VectorArg.addBefore("--library") - .each(dependencies.getResourceContainers()) - .mapped(version == AndroidAaptVersion.AAPT2 ? AAPT2_CONVERTER : AAPT_CONVERTER)); - if (version == AndroidAaptVersion.AAPT2) { - inputs.addTransitive(dependencies.getTransitiveAapt2RTxt()); - } else { - inputs.addTransitive(dependencies.getTransitiveRTxt()); - } - inputs.addTransitive(dependencies.getTransitiveManifests()); - } - } - builder.addExecPath("--classJarOutput", classJarOut); - outs.add(classJarOut); - builder.addLabel("--targetLabel", ruleContext.getLabel()); - - // Create the spawn action. - SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder(); - - ruleContext.registerAction( - spawnActionBuilder - .useDefaultShellEnvironment() - .addTransitiveInputs(inputs.build()) - .addOutputs(ImmutableList.<Artifact>copyOf(outs)) - .addCommandLine( - builder.build(), ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED).build()) - .setExecutable( - ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST)) - .setProgressMessage("Generating R Classes: %s", ruleContext.getLabel()) - .setMnemonic("RClassGenerator") - .build(ruleContext)); + + builder + .addOutput("--classJarOutput", classJarOut) + .addLabelFlag("--targetLabel") + .buildAndRegister("Generating R Classes", "RClassGenerator"); } private static Function<ValidatedAndroidData, String> chooseDepsToArg( 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 46048e90a1..99d545d097 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 @@ -304,7 +304,7 @@ public final class ResourceApk { StampedAndroidManifest manifest) throws InterruptedException { - return new AndroidResourcesProcessorBuilder(dataContext.getRuleContext()) + return new AndroidResourcesProcessorBuilder() .setLibrary(true) .setRTxtOut(dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT)) .setManifestOut( @@ -316,6 +316,6 @@ public final class ResourceApk { .withAssetDependencies(assetDeps) .setDebug(dataContext.useDebug()) .setThrowOnResourceConflict(dataContext.getAndroidConfig().throwOnResourceConflict()) - .buildWithoutLocalResources(manifest); + .buildWithoutLocalResources(dataContext, manifest); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java index 7abd103de8..b84803e4f0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/ValidatedAndroidResources.java @@ -56,7 +56,7 @@ public class ValidatedAndroidResources extends MergedAndroidResources AndroidDataContext dataContext, MergedAndroidResources merged, AndroidAaptVersion aaptVersion) throws InterruptedException { AndroidResourceValidatorActionBuilder builder = - new AndroidResourceValidatorActionBuilder(dataContext.getRuleContext()) + new AndroidResourceValidatorActionBuilder() .setJavaPackage(merged.getJavaPackage()) .setDebug(dataContext.useDebug()) .setMergedResources(merged.getMergedResources()) @@ -82,7 +82,7 @@ public class ValidatedAndroidResources extends MergedAndroidResources AndroidRuleClasses.ANDROID_RESOURCES_AAPT2_LIBRARY_APK)); } - return builder.build(dataContext.getRuleContext(), merged); + return builder.build(dataContext, merged); } static ValidatedAndroidResources of( |