diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java | 229 |
1 files changed, 70 insertions, 159 deletions
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, |