aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Eric Fellheimer <felly@google.com>2015-10-19 13:57:39 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2015-10-20 16:35:16 +0000
commit40229e3cf37b30bc7a68693e337de41e276b8659 (patch)
treeec33d33081df65ae0ce5de76f19071325c4206f8 /src
parent30c0a635ba50c43467c80527a6c12abc4f8ed29e (diff)
Automated [] rollback of [].
*** Reason for rollback *** Breaks many android targets in the depot. *** Original change description *** Trying again with checking for the presence of the "resources" attribute. Change the resource dependency handling to separate between the transitive and direct resources from libraries. This slightly increases the complexity of resource propagation. The initial algorithm was to simply merge all transitive ResourceContainers together with any new ResourceContainer and propagate them via the AndroidResourcesProvider. The new algorithm is encapsulated inside a new ResourceDependencies class which... *** ROLLBACK_OF=105631635 -- MOS_MIGRATED_REVID=105752015
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java43
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java39
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java18
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java230
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProvider.java49
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java65
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java180
-rw-r--r--src/test/java/com/google/devtools/build/lib/actions/CustomCommandLineTest.java7
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java26
11 files changed, 228 insertions, 493 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java
index 584944f0e9..8eed18804e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/CustomCommandLine.java
@@ -129,22 +129,6 @@ public final class CustomCommandLine extends CommandLine {
}
}
- private static final class JoinStringsArg extends ArgvFragment {
-
- private final String delimiter;
- private final Iterable<String> strings;
-
- private JoinStringsArg(String delimiter, Iterable<String> strings) {
- this.delimiter = delimiter;
- this.strings = CollectionUtils.makeImmutable(strings);
- }
-
- @Override
- void eval(ImmutableList.Builder<String> builder) {
- builder.add(Joiner.on(delimiter).join(strings));
- }
- }
-
/**
* Arguments that intersperse strings between the items in a sequence. There are two forms of
* interspersing, and either may be used by this implementation:
@@ -277,14 +261,6 @@ public final class CustomCommandLine extends CommandLine {
return this;
}
- public Builder addJoinStrings(String arg, String delimiter, Iterable<String> strings) {
- if (arg != null && strings != null) {
- arguments.add(new ObjectArg(arg));
- arguments.add(new JoinStringsArg(delimiter, strings));
- }
- return this;
- }
-
public Builder addJoinExecPaths(String arg, String delimiter, Iterable<Artifact> artifacts) {
if (arg != null && artifacts != null) {
arguments.add(new ObjectArg(arg));
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 6c8fd51b0b..876d796fc8 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
@@ -49,6 +49,7 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
@@ -96,19 +97,11 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
AndroidCommon androidCommon = new AndroidCommon(
ruleContext, javaCommon, true /* asNeverLink */, true /* exportDeps */);
try {
- ResourceDependencies resourceDeps = LocalResourceContainer.definesAndroidResources(
- ruleContext.attributes())
- ? ResourceDependencies.fromRuleDeps(ruleContext)
- : ResourceDependencies.fromRuleResourceAndDeps(ruleContext);
- RuleConfiguredTargetBuilder builder = init(
- ruleContext,
- filesBuilder,
- resourceDeps,
- javaCommon,
- androidCommon,
- javaSemantics,
- androidSemantics,
- ImmutableList.<String>of("deps"));
+ RuleConfiguredTargetBuilder builder =
+ init(ruleContext, filesBuilder,
+ AndroidCommon.getTransitiveResourceContainers(ruleContext, true),
+ javaCommon, androidCommon, javaSemantics, androidSemantics,
+ ImmutableList.<String>of("deps"));
if (builder == null) {
return null;
}
@@ -123,7 +116,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
private static RuleConfiguredTargetBuilder init(
RuleContext ruleContext,
NestedSetBuilder<Artifact> filesBuilder,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
JavaCommon javaCommon,
AndroidCommon androidCommon,
JavaSemantics javaSemantics,
@@ -190,11 +183,11 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
throw new RuleConfigurationException();
}
applicationManifest = androidSemantics.getManifestForRule(ruleContext)
- .mergeWith(ruleContext, resourceDeps);
+ .mergeWith(ruleContext, resourceContainers);
resourceApk = applicationManifest.packWithDataAndResources(
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK),
ruleContext,
- resourceDeps,
+ resourceContainers,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
@@ -208,7 +201,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.packWithDataAndResources(ruleContext
.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_INCREMENTAL_RESOURCES_APK),
ruleContext,
- resourceDeps,
+ resourceContainers,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
@@ -222,7 +215,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.createSplitManifest(ruleContext, "android_resources", false)
.packWithDataAndResources(getDxArtifact(ruleContext, "android_resources.ap_"),
ruleContext,
- resourceDeps,
+ resourceContainers,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
@@ -236,13 +229,13 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
// Retrieve the resources from the resources attribute on the android_binary rule
// and recompile them if necessary.
applicationManifest = ApplicationManifest.fromResourcesRule(ruleContext).mergeWith(
- ruleContext, resourceDeps);
+ ruleContext, resourceContainers);
// Always recompiling resources causes AndroidTest to fail in certain circumstances.
- if (shouldRegenerate(ruleContext, resourceDeps)) {
+ if (shouldRegenerate(ruleContext, resourceContainers)) {
resourceApk = applicationManifest.packWithResources(
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK),
ruleContext,
- resourceDeps,
+ resourceContainers,
true,
getProguardConfigArtifact(ruleContext, ""));
} else {
@@ -255,7 +248,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ruleContext.getImplicitOutputArtifact(
AndroidRuleClasses.ANDROID_INCREMENTAL_RESOURCES_APK),
ruleContext,
- resourceDeps,
+ resourceContainers,
false,
getProguardConfigArtifact(ruleContext, "incremental"));
@@ -263,7 +256,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.createSplitManifest(ruleContext, "android_resources", false)
.packWithResources(getDxArtifact(ruleContext, "android_resources.ap_"),
ruleContext,
- resourceDeps,
+ resourceContainers,
false,
getProguardConfigArtifact(ruleContext, "incremental_split"));
}
@@ -1279,8 +1272,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
* </ul>
*/
public static boolean shouldRegenerate(RuleContext ruleContext,
- ResourceDependencies resourceDeps) {
- return Iterables.size(resourceDeps.getResources()) > 1
+ Iterable<ResourceContainer> resourceContainers) {
+ return Iterables.size(resourceContainers) > 1
|| ruleContext.attributes().isAttributeValueExplicitlySpecified("densities")
|| ruleContext.attributes().isAttributeValueExplicitlySpecified(
"resource_configuration_filters")
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 2712eb298e..59f7ac7770 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -95,6 +95,7 @@ public class AndroidCommon {
private Artifact genClassJar;
private Artifact genSourceJar;
+ private NestedSet<ResourceContainer> transitiveResources;
private boolean asNeverLink;
private boolean exportDeps;
private Artifact manifestProtoOutput;
@@ -258,11 +259,36 @@ public class AndroidCommon {
return jackCompilationHelper.compileAsDex(mode, mainDexList, proguardSpecs);
}
+ public static NestedSet<ResourceContainer> getTransitiveResourceContainers(
+ RuleContext ruleContext, boolean withDeps) {
+ // Traverse through all android_library targets looking for resources
+ NestedSetBuilder<ResourceContainer> resourcesBuilder = NestedSetBuilder.naiveLinkOrder();
+ List<String> attributes = new ArrayList<>();
+ attributes.add("resources");
+ if (withDeps) {
+ attributes.add("deps");
+ }
+
+ for (String attribute : attributes) {
+ if (!ruleContext.attributes().has(attribute, BuildType.LABEL)
+ && !ruleContext.attributes().has(attribute, BuildType.LABEL_LIST)) {
+ continue;
+ }
+
+ for (AndroidResourcesProvider resources :
+ ruleContext.getPrerequisites(attribute, Mode.TARGET, AndroidResourcesProvider.class)) {
+ resourcesBuilder.addTransitive(resources.getTransitiveAndroidResources());
+ }
+ }
+
+ return resourcesBuilder.build();
+ }
+
private void compileResources(
JavaSemantics javaSemantics,
JavaCompilationArtifacts.Builder artifactsBuilder,
JavaTargetAttributes.Builder attributes,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
ResourceContainer updatedResources) throws InterruptedException {
Artifact binaryResourcesJar =
ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_CLASS_JAR);
@@ -273,7 +299,7 @@ public class AndroidCommon {
// Repackages the R.java for each dependency package and places the resultant jars
// before the dependency libraries to ensure that the generated resource ids are
// correct.
- createJarJarActions(attributes, resourceDeps.getResources(),
+ createJarJarActions(attributes, resourceContainers,
updatedResources.getJavaPackage(),
binaryResourcesJar);
}
@@ -369,11 +395,12 @@ public class AndroidCommon {
JavaTargetAttributes.Builder attributes = init(
androidSemantics,
+ resourceApk.getTransitiveResources(),
extraSourcesBuilder.build());
JavaCompilationArtifacts.Builder artifactsBuilder = new JavaCompilationArtifacts.Builder();
if (resourceApk.isLegacy()) {
compileResources(javaSemantics, artifactsBuilder, attributes,
- resourceApk.getResourceDependencies(), resourceApk.getPrimaryResource());
+ resourceApk.getTransitiveResources(), resourceApk.getPrimaryResource());
}
JavaCompilationHelper helper = initAttributes(attributes, javaSemantics);
@@ -404,9 +431,12 @@ public class AndroidCommon {
private JavaTargetAttributes.Builder init(
AndroidSemantics androidSemantics,
+ NestedSet<AndroidResourcesProvider.ResourceContainer> transitiveResources,
Collection<Artifact> extraArtifacts) {
+ this.transitiveResources = transitiveResources;
javaCommon.initializeJavacOpts(androidSemantics.getJavacArguments());
JavaTargetAttributes.Builder attributes = javaCommon.initCommon(extraArtifacts);
+
attributes.setBootClassPath(ImmutableList.of(
AndroidSdkProvider.fromRuleContext(ruleContext).getAndroidJar()));
return attributes;
@@ -568,7 +598,8 @@ public class AndroidCommon {
new JavaRuntimeJarProvider(javaCommon.getJavaCompilationArtifacts().getRuntimeJars()))
.add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
.add(
- AndroidResourcesProvider.class, resourceApk.toResourceProvider(ruleContext.getLabel()))
+ AndroidResourcesProvider.class,
+ new AndroidResourcesProvider(ruleContext.getLabel(), transitiveResources))
.add(
AndroidIdeInfoProvider.class,
createAndroidIdeInfoProvider(ruleContext, androidSemantics, idlHelper,
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 0eec811d57..bb90189242 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
@@ -62,6 +62,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
List<? extends TransitiveInfoCollection> deps =
ruleContext.getPrerequisites("deps", Mode.TARGET);
checkResourceInlining(ruleContext);
+ NestedSet<AndroidResourcesProvider.ResourceContainer> transitiveResources =
+ AndroidCommon.getTransitiveResourceContainers(ruleContext, true);
NestedSetBuilder<Aar> transitiveAars = collectTransitiveAars(ruleContext);
NestedSet<LinkerInput> transitiveNativeLibraries =
AndroidCommon.collectTransitiveNativeLibraries(deps);
@@ -82,8 +84,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
try {
resourceApk = applicationManifest.packWithDataAndResources(
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK),
- ruleContext,
- ResourceDependencies.fromRuleDeps(ruleContext),
+ ruleContext, transitiveResources,
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_SYMBOLS_TXT),
ImmutableList.<String>of(), /* configurationFilters */
@@ -101,8 +102,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
return null;
}
} else {
- resourceApk = ResourceApk.fromTransitiveResources(
- ResourceDependencies.fromRuleResourceAndDeps(ruleContext));
+ resourceApk = ResourceApk.fromTransitiveResources(transitiveResources);
}
JavaTargetAttributes javaTargetAttributes = androidCommon.init(
@@ -129,7 +129,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
transitiveAars.add(aar);
} else if (AndroidCommon.getAndroidResources(ruleContext) != null) {
primaryResources = Iterables.getOnlyElement(
- AndroidCommon.getAndroidResources(ruleContext).getDirectAndroidResources());
+ AndroidCommon.getAndroidResources(ruleContext).getTransitiveAndroidResources());
aar = new Aar(aarOut, primaryResources.getManifest());
transitiveAars.add(aar);
} else {
@@ -157,7 +157,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
.setSourceJarOut(resourceContainer.getJavaSourceJar())
.setJavaPackage(resourceContainer.getJavaPackage())
.withPrimary(resourceContainer)
- .withDependencies(resourceApk.getResourceDependencies())
+ .withDependencies(transitiveResources)
.setDebug(
ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT)
.build(ruleContext);
@@ -172,8 +172,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
.build(ruleContext);
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
- androidCommon.addTransitiveInfoProviders(builder, androidSemantics, resourceApk, null,
- ImmutableList.<Artifact>of());
+ androidCommon.addTransitiveInfoProviders(builder, androidSemantics,
+ definesLocalResources ? resourceApk : null, null, ImmutableList.<Artifact>of());
androidSemantics.addTransitiveInfoProviders(
builder, ruleContext, javaCommon, androidCommon, null);
@@ -220,7 +220,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
}
ResourceContainer container = Iterables.getOnlyElement(
- resources.getDirectAndroidResources());
+ resources.getTransitiveAndroidResources());
if (container.getConstantsInlined()
&& !container.getArtifacts(ResourceType.RESOURCES).isEmpty()) {
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 2e1c274004..0fa9ecd291 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
@@ -14,11 +14,9 @@
package com.google.devtools.build.lib.rules.android;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
-import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
@@ -26,11 +24,7 @@ import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
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.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer;
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceType;
@@ -38,25 +32,13 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import javax.annotation.Nullable;
-
/**
* Builder for creating resource processing action.
*/
public class AndroidResourcesProcessorBuilder {
- private static final ResourceContainerToArtifacts RESOURCE_CONTAINER_TO_ARTIFACTS =
- new ResourceContainerToArtifacts(false);
-
- private static final ResourceContainerToArtifacts RESOURCE_DEP_TO_ARTIFACTS =
- new ResourceContainerToArtifacts(true);
-
- private static final ResourceContainerToArg RESOURCE_CONTAINER_TO_ARG =
- new ResourceContainerToArg(false);
- private static final ResourceContainerToArg RESOURCE_DEP_TO_ARG =
- new ResourceContainerToArg(true);
private ResourceContainer primary;
- private ResourceDependencies dependencies;
+ private List<ResourceContainer> dependencies = Collections.emptyList();
private Artifact proguardOut;
private Artifact rTxtOut;
private Artifact sourceJarOut;
@@ -93,8 +75,8 @@ public class AndroidResourcesProcessorBuilder {
return this;
}
- public AndroidResourcesProcessorBuilder withDependencies(ResourceDependencies resourceDeps) {
- this.dependencies = resourceDeps;
+ public AndroidResourcesProcessorBuilder withDependencies(Iterable<ResourceContainer> nestedSet) {
+ this.dependencies = ImmutableList.copyOf(nestedSet);
return this;
}
@@ -149,179 +131,160 @@ public class AndroidResourcesProcessorBuilder {
return this;
}
- private static class ResourceContainerToArg implements Function<ResourceContainer, String> {
- private boolean includeSymbols;
-
- public ResourceContainerToArg(boolean includeSymbols) {
- this.includeSymbols = includeSymbols;
- }
-
- @Override
- public String apply(ResourceContainer container) {
- StringBuilder builder = new StringBuilder();
- builder.append(convertRoots(container, ResourceType.RESOURCES))
- .append(":")
- .append(convertRoots(container, ResourceType.ASSETS))
- .append(":")
- .append(container.getManifest().getExecPathString());
- if (includeSymbols) {
- builder.append(":")
- .append(container.getRTxt() == null ? "" : container.getRTxt().getExecPath())
- .append(":")
- .append(
- container.getSymbolsTxt() == null ? "" : container.getSymbolsTxt().getExecPath());
- }
- return builder.toString();
- }
+ private void addResourceContainer(List<Artifact> inputs, List<String> args,
+ ResourceContainer container) {
+ Iterables.addAll(inputs, container.getArtifacts());
+ inputs.add(container.getManifest());
+ inputs.add(container.getRTxt());
+
+ args.add(String.format("%s:%s:%s:%s:%s",
+ convertRoots(container, ResourceType.RESOURCES),
+ convertRoots(container, ResourceType.ASSETS),
+ container.getManifest().getExecPathString(),
+ container.getRTxt() == null ? "" : container.getRTxt().getExecPath(),
+ container.getSymbolsTxt() == null ? "" : container.getSymbolsTxt().getExecPath()
+ ));
}
- private static class ResourceContainerToArtifacts
- implements Function<ResourceContainer, NestedSet<Artifact>> {
-
- private boolean includeSymbols;
-
- public ResourceContainerToArtifacts(boolean includeSymbols) {
- this.includeSymbols = includeSymbols;
- }
-
- @Override
- public NestedSet<Artifact> apply(ResourceContainer container) {
- NestedSetBuilder<Artifact> artifacts = NestedSetBuilder.naiveLinkOrder();
- addIfNotNull(container.getManifest(), artifacts);
- if (includeSymbols) {
- addIfNotNull(container.getRTxt(), artifacts);
- addIfNotNull(container.getSymbolsTxt(), artifacts);
- }
- artifacts.addAll(container.getArtifacts());
- return artifacts.build();
- }
-
- private void addIfNotNull(@Nullable Artifact artifact, NestedSetBuilder<Artifact> artifacts) {
- if (artifact != null) {
- artifacts.add(artifact);
- }
- }
+ private void addPrimaryResourceContainer(List<Artifact> inputs, List<String> args,
+ ResourceContainer container) {
+ Iterables.addAll(inputs, container.getArtifacts());
+ inputs.add(container.getManifest());
+
+ // no R.txt, because it will be generated from this action.
+ args.add(String.format("%s:%s:%s",
+ convertRoots(container, ResourceType.RESOURCES),
+ convertRoots(container, ResourceType.ASSETS),
+ container.getManifest().getExecPathString()
+ ));
}
@VisibleForTesting
public static String convertRoots(ResourceContainer container, ResourceType resourceType) {
- return Joiner.on("#").join(Iterators.transform(
- container.getRoots(resourceType).iterator(), Functions.toStringFunction()));
+ return Joiner.on("#").join(
+ Iterators.transform(
+ container.getRoots(resourceType).iterator(), Functions.toStringFunction()));
}
public ResourceContainer build(ActionConstructionContext context) {
List<Artifact> outs = new ArrayList<>();
- CustomCommandLine.Builder builder = new CustomCommandLine.Builder();
+ List<Artifact> ins = new ArrayList<>();
+ List<String> args = new ArrayList<>();
+
+ args.add("--aapt");
+ args.add(sdk.getAapt().getExecutable().getExecPathString());
- builder.addExecPath("--aapt", sdk.getAapt().getExecutable());
- // Use a FluentIterable to avoid flattening the NestedSets
- NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder();
- inputs.addAll(ruleContext.getExecutablePrerequisite("$android_resources_processor", Mode.HOST)
+ Iterables.addAll(ins,
+ ruleContext.getExecutablePrerequisite("$android_resources_processor", Mode.HOST)
.getRunfilesSupport()
.getRunfilesArtifactsWithoutMiddlemen());
- builder.addExecPath("--annotationJar", sdk.getAnnotationsJar());
- inputs.add(sdk.getAnnotationsJar());
-
- builder.addExecPath("--androidJar", sdk.getAndroidJar());
- inputs.add(sdk.getAndroidJar());
-
- builder.add("--primaryData").add(RESOURCE_CONTAINER_TO_ARG.apply(primary));
- inputs.addTransitive(RESOURCE_CONTAINER_TO_ARTIFACTS.apply(primary));
-
- if (dependencies != null) {
- // add transitive data
- builder.addJoinStrings("--data", ",",
- Iterables.transform(dependencies.getTransitiveResources(), RESOURCE_DEP_TO_ARG));
- // add direct data
- builder.addJoinStrings("--directData", ",",
- Iterables.transform(dependencies.getDirectResources(), RESOURCE_DEP_TO_ARG));
-
- // This flattens the nested set. Since each ResourceContainer needs to be transformed into
- // Artifacts, and the NestedSetBuilder.wrap doesn't support lazy Iterator evaluation
- // and SpawnActionBuilder.addInputs evaluates Iterables, it becomes necessary to make the
- // best effort and let it get flattened.
- inputs.addTransitive(
- NestedSetBuilder.wrap(
- Order.NAIVE_LINK_ORDER,
- FluentIterable.from(dependencies.getResources())
- .transformAndConcat(RESOURCE_DEP_TO_ARTIFACTS)));
+ args.add("--annotationJar");
+ args.add(sdk.getAnnotationsJar().getExecPathString());
+ ins.add(sdk.getAnnotationsJar());
+ args.add("--androidJar");
+ args.add(sdk.getAndroidJar().getExecPathString());
+ ins.add(sdk.getAndroidJar());
+
+ args.add("--primaryData");
+ addPrimaryResourceContainer(ins, args, primary);
+ if (!dependencies.isEmpty()) {
+ args.add("--data");
+ List<String> data = new ArrayList<>();
+ for (ResourceContainer container : dependencies) {
+ addResourceContainer(ins, data, container);
+ }
+ args.add(Joiner.on(",").join(data));
}
if (rTxtOut != null) {
- builder.addExecPath("--rOutput", rTxtOut);
+ args.add("--rOutput");
+ args.add(rTxtOut.getExecPathString());
outs.add(rTxtOut);
// If R.txt is not null, dependency R.javas will not be regenerated from the R.txt found in
// the deps, which means the resource processor needs to be told it is creating a library so
// that it will generate the R.txt.
- builder.add("--packageType").add("LIBRARY");
+ args.add("--packageType");
+ args.add("LIBRARY");
}
-
if (symbolsTxt != null) {
- builder.addExecPath("--symbolsTxtOut", symbolsTxt);
+ args.add("--symbolsTxtOut");
+ args.add(symbolsTxt.getExecPathString());
outs.add(symbolsTxt);
}
if (sourceJarOut != null) {
- builder.addExecPath("--srcJarOutput", sourceJarOut);
+ args.add("--srcJarOutput");
+ args.add(sourceJarOut.getExecPathString());
outs.add(sourceJarOut);
}
if (proguardOut != null) {
- builder.addExecPath("--proguardOutput", proguardOut);
+ args.add("--proguardOutput");
+ args.add(proguardOut.getExecPathString());
outs.add(proguardOut);
}
if (apkOut != null) {
- builder.addExecPath("--packagePath", apkOut);
+ args.add("--packagePath");
+ args.add(apkOut.getExecPathString());
outs.add(apkOut);
}
if (!resourceConfigs.isEmpty()) {
- builder.addJoinStrings("--resourceConfigs", ",", resourceConfigs);
+ args.add("--resourceConfigs");
+ args.add(Joiner.on(',').join(resourceConfigs));
}
if (!densities.isEmpty()) {
- builder.addJoinStrings("--densities", "'", densities);
+ args.add("--densities");
+ args.add(Joiner.on(',').join(densities));
}
if (!uncompressedExtensions.isEmpty()) {
- builder.addJoinStrings("--uncompressedExtensions", ",", uncompressedExtensions);
+ args.add("--uncompressedExtensions");
+ args.add(Joiner.on(',').join(uncompressedExtensions));
}
if (!assetsToIgnore.isEmpty()) {
- builder.addJoinStrings("--assetsToIgnore", ",", assetsToIgnore);
+ args.add("--assetsToIgnore");
+ args.add(
+ Joiner.on(',').join(assetsToIgnore));
}
if (debug) {
- builder.add("--debug");
+ args.add("--debug");
}
if (versionCode != null) {
- builder.add("--versionCode").add(versionCode);
+ args.add("--versionCode");
+ args.add(versionCode);
}
if (versionName != null) {
- builder.add("--versionName").add(versionName);
+ args.add("--versionName");
+ args.add(versionName);
}
if (applicationId != null) {
- builder.add("--applicationId").add(applicationId);
+ args.add("--applicationId");
+ args.add(applicationId);
}
if (!Strings.isNullOrEmpty(customJavaPackage)) {
// Sets an alternative java package for the generated R.java
// this is allows android rules to generate resources outside of the java{,tests} tree.
- builder.add("--packageForR").add(customJavaPackage);
+ args.add("--packageForR");
+ args.add(customJavaPackage);
}
// Create the spawn action.
- ruleContext.registerAction(
- this.spawnActionBuilder
- .addTool(sdk.getAapt())
- .addTransitiveInputs(inputs.build())
- .addOutputs(ImmutableList.<Artifact>copyOf(outs))
- .setCommandLine(builder.build())
- .setExecutable(
- ruleContext.getExecutablePrerequisite("$android_resources_processor", Mode.HOST))
- .setProgressMessage("Processing resources")
- .setMnemonic("AndroidAapt")
- .build(context));
+ ruleContext.registerAction(this.spawnActionBuilder
+ .addTool(sdk.getAapt())
+ .addInputs(ImmutableList.<Artifact>copyOf(ins))
+ .addOutputs(ImmutableList.<Artifact>copyOf(outs))
+ .addArguments(ImmutableList.<String>copyOf(args))
+ .setExecutable(
+ ruleContext.getExecutablePrerequisite("$android_resources_processor", Mode.HOST))
+ .setProgressMessage("Processing resources")
+ .setMnemonic("AndroidAapt")
+ .build(context));
// Return the full set of processed transitive dependencies.
- return new ResourceContainer(primary.getLabel(),
+ return new ResourceContainer(
+ primary.getLabel(),
primary.getJavaPackage(),
primary.getRenameManifestPackage(),
primary.getConstantsInlined(),
@@ -330,7 +293,8 @@ public class AndroidResourcesProcessorBuilder {
// for this resource processing action (in case of just creating an R.txt or
// proguard merging), reuse the primary resource from the dependencies.
apkOut != null ? apkOut : primary.getApk(),
- primary.getManifest(), sourceJarOut,
+ primary.getManifest(),
+ sourceJarOut,
primary.getArtifacts(ResourceType.ASSETS),
primary.getArtifacts(ResourceType.RESOURCES),
primary.getRoots(ResourceType.ASSETS),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProvider.java
index 24e3174a42..e2fda51aba 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProvider.java
@@ -28,50 +28,43 @@ import java.util.Objects;
import javax.annotation.Nullable;
/**
- * A provider that supplies ResourceContainers from its transitive closure.
+ * A provider that supplies Android resources from its transitive closure.
*/
@Immutable
public final class AndroidResourcesProvider implements TransitiveInfoProvider {
+
private final Label label;
private final NestedSet<ResourceContainer> transitiveAndroidResources;
- private final NestedSet<ResourceContainer> directAndroidResources;
- public AndroidResourcesProvider(
- Label label, NestedSet<ResourceContainer> transitiveAndroidResources,
- NestedSet<ResourceContainer> directAndroidResources) {
+ public AndroidResourcesProvider(Label label,
+ NestedSet<ResourceContainer> transitiveAndroidResources) {
this.label = label;
- this.directAndroidResources = directAndroidResources;
this.transitiveAndroidResources = transitiveAndroidResources;
}
/**
* Returns the label that is associated with this piece of information.
+ *
+ * <p>
+ * This is usually the label of the target that provides the information.
*/
public Label getLabel() {
return label;
}
/**
- * Returns the transitive ResourceContainers for the label.
+ * Returns transitive Android resources (APK, assets, etc.).
*/
public NestedSet<ResourceContainer> getTransitiveAndroidResources() {
return transitiveAndroidResources;
}
- /**
- * Returns the immediate ResourceContainers for the label.
- */
- public NestedSet<ResourceContainer> getDirectAndroidResources() {
- return directAndroidResources;
- }
-
/**
* The type of resource in question: either asset or a resource.
*/
public enum ResourceType {
- ASSETS("assets"),
- RESOURCES("resources");
+ ASSETS("assets"), RESOURCES("resources");
private final String attribute;
@@ -90,6 +83,7 @@ public final class AndroidResourcesProvider implements TransitiveInfoProvider {
*/
@Immutable
public static final class ResourceContainer {
+
private final Label label;
private final String javaPackage;
private final String renameManifestPackage;
@@ -108,8 +102,10 @@ public final class AndroidResourcesProvider implements TransitiveInfoProvider {
public ResourceContainer(Label label,
String javaPackage,
@Nullable String renameManifestPackage,
- boolean constantsInlined, Artifact apk,
- Artifact manifest, Artifact javaSourceJar,
+ boolean constantsInlined,
+ Artifact apk,
+ Artifact manifest,
+ Artifact javaSourceJar,
ImmutableList<Artifact> assets,
ImmutableList<Artifact> resources,
ImmutableList<PathFragment> assetsRoots,
@@ -188,7 +184,7 @@ public final class AndroidResourcesProvider implements TransitiveInfoProvider {
@Override
public int hashCode() {
- return Objects.hash(label, rTxt, symbolsTxt);
+ return Objects.hashCode(label);
}
@Override
@@ -200,20 +196,7 @@ public final class AndroidResourcesProvider implements TransitiveInfoProvider {
return false;
}
ResourceContainer other = (ResourceContainer) obj;
- return Objects.equals(label, other.label)
- && Objects.equals(rTxt, other.rTxt)
- && Objects.equals(symbolsTxt, other.symbolsTxt);
- }
-
- @Override
- public String toString() {
- return String.format(
- "ResourceContainer [label=%s, javaPackage=%s, renameManifestPackage=%s,"
- + " constantsInlined=%s, apk=%s, manifest=%s, assets=%s, resources=%s, assetsRoots=%s,"
- + " resourcesRoots=%s, manifestExported=%s, javaSourceJar=%s, rTxt=%s, symbolsTxt=%s]",
- label, javaPackage, renameManifestPackage, constantsInlined, apk, manifest, assets,
- resources, assetsRoots, resourcesRoots, manifestExported, javaSourceJar, rTxt,
- symbolsTxt);
+ return label.equals(other.label);
}
}
}
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 42ffbae043..3c14b8ec6e 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
@@ -26,6 +26,9 @@ import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer;
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceType;
import com.google.devtools.build.lib.rules.android.LocalResourceContainer.Builder.InvalidAssetPath;
@@ -45,7 +48,7 @@ public final class ApplicationManifest {
throw new RuleConfigurationException();
}
return new ApplicationManifest(Iterables.getOnlyElement(
- resources.getDirectAndroidResources())
+ resources.getTransitiveAndroidResources())
.getManifest());
}
@@ -88,7 +91,7 @@ public final class ApplicationManifest {
AndroidResourcesProvider resourcesProvider = AndroidCommon.getAndroidResources(ruleContext);
if (resourcesProvider != null) {
ResourceContainer resourceContainer = Iterables.getOnlyElement(
- resourcesProvider.getDirectAndroidResources());
+ resourcesProvider.getTransitiveAndroidResources());
return resourceContainer.getRenameManifestPackage();
} else {
return null;
@@ -165,10 +168,9 @@ public final class ApplicationManifest {
}
public ApplicationManifest mergeWith(RuleContext ruleContext,
- ResourceDependencies resourceDeps) {
- Iterable<Artifact> mergeeManifests = getMergeeManifests(resourceDeps.getResources());
- if (!Iterables.isEmpty(mergeeManifests)) {
- Iterable<Artifact> exportedManifests = mergeeManifests;
+ Iterable<ResourceContainer> resourceContainers) {
+ if (!Iterables.isEmpty(getMergeeManifests(resourceContainers))) {
+ Iterable<Artifact> exportedManifests = getMergeeManifests(resourceContainers);
Artifact outputManifest = ruleContext.getUniqueDirectoryArtifact(
ruleContext.getRule().getName() + "_merged", "AndroidManifest.xml",
ruleContext.getBinOrGenfilesDirectory());
@@ -196,7 +198,7 @@ public final class ApplicationManifest {
public ResourceApk packWithAssets(
Artifact resourceApk,
RuleContext ruleContext,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
Artifact rTxt,
boolean incremental,
Artifact proguardCfg) throws InterruptedException {
@@ -212,7 +214,7 @@ public final class ApplicationManifest {
return createApk(resourceApk,
ruleContext,
- resourceDeps,
+ resourceContainers,
rTxt,
null, /* configurationFilters */
ImmutableList.<String>of(), /* uncompressedExtensions */
@@ -235,7 +237,7 @@ public final class ApplicationManifest {
public ResourceApk packWithDataAndResources(
Artifact resourceApk,
RuleContext ruleContext,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
Artifact rTxt,
Artifact symbolsTxt,
List<String> configurationFilters,
@@ -262,7 +264,7 @@ public final class ApplicationManifest {
return createApk(resourceApk,
ruleContext,
- resourceDeps,
+ resourceContainers,
rTxt,
symbolsTxt,
configurationFilters,
@@ -285,7 +287,7 @@ public final class ApplicationManifest {
private ResourceApk createApk(Artifact resourceApk,
RuleContext ruleContext,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
Artifact rTxt,
Artifact symbolsTxt,
List<String> configurationFilters,
@@ -303,10 +305,7 @@ public final class ApplicationManifest {
.withROutput(rTxt)
.withSymbolsFile(symbolsTxt)
.buildFromRule(ruleContext, resourceApk),
- resourceDeps.getResources(), // TODO(bazel-team): Figure out if we really need to check
- // the ENTIRE transitive closure, or just the direct dependencies. Given that each rule with
- // resources would check for inline resources, we can rely on the previous rule to have
- // checked its dependencies.
+ resourceContainers,
ruleContext);
AndroidResourcesProcessorBuilder builder =
@@ -317,7 +316,7 @@ public final class ApplicationManifest {
.setJavaPackage(resourceContainer.getJavaPackage())
.setDebug(ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT)
.withPrimary(resourceContainer)
- .withDependencies(resourceDeps)
+ .withDependencies(resourceContainers)
.setDensities(densities)
.setProguardOut(proguardCfg)
.setApplicationId(applicationId)
@@ -332,9 +331,16 @@ public final class ApplicationManifest {
}
ResourceContainer processed = builder.build(ruleContext);
+ NestedSet<ResourceContainer> transitiveResources =
+ NestedSetBuilder.<ResourceContainer>naiveLinkOrder()
+ // TODO(bazel-team): If this is replaced with .addTransitive(), a few tests fail.
+ // Investigate.
+ .addAll(resourceContainers)
+ .add(processed)
+ .build();
return new ResourceApk(
- resourceApk, processed.getJavaSourceJar(), resourceDeps, processed, manifest,
+ resourceApk, processed.getJavaSourceJar(), transitiveResources, processed, manifest,
proguardCfg, false);
}
@@ -357,7 +363,15 @@ public final class ApplicationManifest {
/** Uses the resource apk from the resources attribute, as opposed to recompiling. */
public ResourceApk useCurrentResources(RuleContext ruleContext, Artifact proguardCfg) {
ResourceContainer resourceContainer = Iterables.getOnlyElement(
- AndroidCommon.getAndroidResources(ruleContext).getDirectAndroidResources());
+ AndroidCommon.getAndroidResources(ruleContext).getTransitiveAndroidResources());
+ NestedSet<ResourceContainer> resourceContainers =
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+
+ NestedSet<ResourceContainer> transitiveResources =
+ NestedSetBuilder.<ResourceContainer>naiveLinkOrder()
+ .addAll(resourceContainers)
+ .add(resourceContainer)
+ .build();
new AndroidAaptActionHelper(
ruleContext,
@@ -367,7 +381,7 @@ public final class ApplicationManifest {
return new ResourceApk(
resourceContainer.getApk(),
null /* javaSrcJar */,
- ResourceDependencies.empty(),
+ transitiveResources,
resourceContainer,
manifest,
proguardCfg,
@@ -384,7 +398,7 @@ public final class ApplicationManifest {
public ResourceApk packWithResources(
Artifact resourceApk,
RuleContext ruleContext,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> resourceContainers,
boolean createSource,
Artifact proguardCfg) throws InterruptedException {
@@ -392,15 +406,10 @@ public final class ApplicationManifest {
ruleContext.getPrerequisite("resources", Mode.TARGET);
ResourceContainer resourceContainer = Iterables.getOnlyElement(
resourcesPrerequisite.getProvider(AndroidResourcesProvider.class)
- .getDirectAndroidResources());
- // It's ugly, but flattening now is more performant given the rest of the checks.
- List<ResourceContainer> resourceContainers =
- ImmutableList.<ResourceContainer>builder()
- //.add(resourceContainer)
- .addAll(resourceDeps.getResources()).build();
+ .getTransitiveAndroidResources());
// Dealing with Android library projects
- if (Iterables.size(resourceDeps.getResources()) > 1) {
+ if (Iterables.size(resourceContainers) > 1) {
if (resourceContainer.getConstantsInlined()
&& !resourceContainer.getArtifacts(ResourceType.RESOURCES).isEmpty()) {
ruleContext.ruleError("This android_binary depends on an android_library, so the"
@@ -461,7 +470,7 @@ public final class ApplicationManifest {
aaptActionHelper.createGenerateProguardAction(proguardCfg);
return new ResourceApk(resourceApk, updatedResources.getJavaSourceJar(),
- resourceDeps, updatedResources, manifest, proguardCfg, true);
+ resourceContainers, updatedResources, manifest, proguardCfg, true);
}
public Artifact getManifest() {
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 8a14507c95..920f4cd68f 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
@@ -14,7 +14,7 @@
package com.google.devtools.build.lib.rules.android;
import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer;
@@ -31,7 +31,7 @@ public class ResourceApk {
// to do this.
@Nullable private final Artifact resourceApk; // The .ap_ file
@Nullable private final Artifact resourceJavaSrcJar; // Source jar containing R.java and friends
- private final ResourceDependencies resourceDeps;
+ private final NestedSet<ResourceContainer> transitiveResources;
@Nullable private final ResourceContainer primaryResource;
@Nullable private final Artifact manifest; // The non-binary XML version of AndroidManifest.xml
@Nullable private final Artifact resourceProguardConfig;
@@ -40,14 +40,14 @@ public class ResourceApk {
public ResourceApk(
@Nullable Artifact resourceApk,
@Nullable Artifact resourceJavaSrcJar,
- ResourceDependencies resourceDeps,
+ NestedSet<ResourceContainer> transitiveResources,
@Nullable ResourceContainer primaryResource,
@Nullable Artifact manifest,
@Nullable Artifact resourceProguardConfig,
boolean legacy) {
this.resourceApk = resourceApk;
this.resourceJavaSrcJar = resourceJavaSrcJar;
- this.resourceDeps = resourceDeps;
+ this.transitiveResources = transitiveResources;
this.primaryResource = primaryResource;
this.manifest = manifest;
this.resourceProguardConfig = resourceProguardConfig;
@@ -74,36 +74,16 @@ public class ResourceApk {
return legacy;
}
+ public NestedSet<ResourceContainer> getTransitiveResources() {
+ return transitiveResources;
+ }
+
public static ResourceApk fromTransitiveResources(
- ResourceDependencies resourceDeps) {
- return new ResourceApk(null, null, resourceDeps, null, null, null, false);
+ NestedSet<ResourceContainer> transitiveResources) {
+ return new ResourceApk(null, null, transitiveResources, null, null, null, false);
}
public Artifact getResourceProguardConfig() {
return resourceProguardConfig;
}
-
- public ResourceDependencies getResourceDependencies() {
- return resourceDeps;
- }
-
- /**
- * Creates an provider from the resources in the ResourceApk.
- *
- * <p>If the ResourceApk was created from transitive resources, the provider will effectively
- * contain the "forwarded" resources: The merged transitive and merged direct dependencies of this
- * library.
- *
- * <p>If the ResourceApk was generated from a "resources" attribute, it will contain the
- * "resources" container in the direct dependencies and the rest as transitive.
- *
- * <p>If the ResourceApk was generated from local resources, that will be the direct dependencies and
- * the rest will be transitive.
- */
- public AndroidResourcesProvider toResourceProvider(Label label) {
- if (primaryResource == null) {
- return resourceDeps.toProvider(label);
- }
- return resourceDeps.toProvider(label, primaryResource);
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
deleted file mode 100644
index f155128191..0000000000
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2015 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.rules.android;
-
-import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
-import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.Order;
-import com.google.devtools.build.lib.packages.BuildType;
-import com.google.devtools.build.lib.rules.android.AndroidResourcesProvider.ResourceContainer;
-
-/**
- * Represents a container for the {@link ResourceContainer}s for a given library. This is
- * abstraction simplifies the process of managing and exporting the direct and transitive resource
- * dependencies of an android rule, as well as providing type safety.
- */
-public class ResourceDependencies {
- /**
- * Contains all the transitive resources that are not generated by the direct ancestors of the
- * current rule.
- */
- private final NestedSet<ResourceContainer> transitiveResources;
- /**
- * Contains all the direct dependencies of the current target. Since a given direct dependency can
- * act as a "forwarding" library, collecting all the direct resource from it's deps
- * and providing them as "direct" dependencies to maintain merge order, this uses a NestedSet to
- * properly maintain ordering and ease of merging.
- */
- private final NestedSet<ResourceContainer> directResources;
-
- public static ResourceDependencies fromRuleResources(RuleContext ruleContext) {
- if (!hasResourceAttribute(ruleContext)) {
- return empty();
- }
-
- NestedSetBuilder<ResourceContainer> transitiveDependencies = NestedSetBuilder.naiveLinkOrder();
- NestedSetBuilder<ResourceContainer> directDependencies = NestedSetBuilder.naiveLinkOrder();
- extractFromAttribute("resources", ruleContext, transitiveDependencies, directDependencies);
- return new ResourceDependencies(transitiveDependencies.build(), directDependencies.build());
- }
-
- public static ResourceDependencies fromRuleDeps(RuleContext ruleContext) {
- NestedSetBuilder<ResourceContainer> transitiveDependencies = NestedSetBuilder.naiveLinkOrder();
- NestedSetBuilder<ResourceContainer> directDependencies = NestedSetBuilder.naiveLinkOrder();
- extractFromAttribute("deps", ruleContext, transitiveDependencies, directDependencies);
- return new ResourceDependencies(transitiveDependencies.build(), directDependencies.build());
- }
-
- public static ResourceDependencies fromRuleResourceAndDeps(RuleContext ruleContext) {
- NestedSetBuilder<ResourceContainer> transitiveDependencies = NestedSetBuilder.naiveLinkOrder();
- NestedSetBuilder<ResourceContainer> directDependencies = NestedSetBuilder.naiveLinkOrder();
- if (hasResourceAttribute(ruleContext)) {
- extractFromAttribute("resources",ruleContext, transitiveDependencies, directDependencies);
- }
- if (directDependencies.isEmpty()) {
- // There are no resources, so this library will forward the direct and transitive dependencies
- // without changes.
- extractFromAttribute("deps", ruleContext, transitiveDependencies, directDependencies);
- } else {
- // There are resources, so the direct dependencies and the transitive will be merged into
- // the transitive dependencies. This maintains the relationship of the resources being
- // directly on the rule.
- extractFromAttribute("deps", ruleContext, transitiveDependencies, transitiveDependencies);
- }
- return new ResourceDependencies(transitiveDependencies.build(), directDependencies.build());
- }
-
- private static void extractFromAttribute(String attribute,
- RuleContext ruleContext, NestedSetBuilder<ResourceContainer> builderForTransitive,
- NestedSetBuilder<ResourceContainer> builderForDirect) {
- for (AndroidResourcesProvider resources :
- ruleContext.getPrerequisites(attribute, Mode.TARGET, AndroidResourcesProvider.class)) {
- builderForTransitive.addTransitive(resources.getTransitiveAndroidResources());
- builderForDirect.addTransitive(resources.getDirectAndroidResources());
- }
- }
-
- /**
- * Check for the existence of a "resources" attribute.
- *
- * <p>The existence of the resources attribute is not guaranteed on for all android rules, so it
- * is necessary to check for it.
- *
- * @param ruleContext The context to check.
- * @return True if the ruleContext has resources, otherwise, false.
- */
- private static boolean hasResourceAttribute(RuleContext ruleContext) {
- return ruleContext.attributes().has("resources", BuildType.LABEL);
- }
-
- @Override
- public String toString() {
- return "ResourceDependencies [transitiveResources=" + transitiveResources + ", directResources="
- + directResources + "]";
- }
-
- /**
- * Creates an empty ResourceDependencies instance. This is used when an AndroidResources rule
- * is the only resource dependency. The most common case is the AndroidTest rule.
- */
- public static ResourceDependencies empty() {
- return new ResourceDependencies(
- NestedSetBuilder.<ResourceContainer>emptySet(Order.NAIVE_LINK_ORDER),
- NestedSetBuilder.<ResourceContainer>emptySet(Order.NAIVE_LINK_ORDER));
- }
-
- public ResourceDependencies(
- NestedSet<ResourceContainer> transitiveResources,
- NestedSet<ResourceContainer> directResources) {
- this.transitiveResources = transitiveResources;
- this.directResources = directResources;
- }
-
- /**
- * Creates a new AndroidResourcesProvider with the supplied ResourceContainer as the direct dep.
- *
- * <p>When a library produces a new resource container the AndroidResourcesProvider should use
- * that container as a the direct dependency for that library. This makes the consuming rule
- * to identify the new container and merge appropriately. The previous direct dependencies are
- * then added to the transitive dependencies.
- *
- * @param label The label of the library exporting this provider.
- * @param newDirectResource The new direct dependency for AndroidResourcesProvider
- * @return A provider with the current resources and label.
- */
- public AndroidResourcesProvider toProvider(Label label, ResourceContainer newDirectResource) {
- return new AndroidResourcesProvider(
- label,
- NestedSetBuilder.<ResourceContainer>naiveLinkOrder()
- .addTransitive(transitiveResources)
- .addTransitive(directResources)
- .build(),
- NestedSetBuilder.<ResourceContainer>naiveLinkOrder().add(newDirectResource).build());
- }
-
- /**
- * Create a new AndroidResourcesProvider from the dependencies of this library.
- *
- * <p>When a library doesn't export resources it should simply forward the current transitive and
- * direct resources to the consuming rule. This allows the consuming rule to make decisions about
- * the resource merging as if this library didn't exist.
- *
- * @param label The label of the library exporting this provider.
- * @return A provider with the current resources and label.
- */
- public AndroidResourcesProvider toProvider(Label label) {
- return new AndroidResourcesProvider(label, transitiveResources, directResources);
- }
-
- /**
- * Provides an NestedSet of the direct and transitive resources.
- */
- public Iterable<ResourceContainer> getResources() {
- return NestedSetBuilder.<ResourceContainer>naiveLinkOrder()
- .addTransitive(directResources)
- .addTransitive(transitiveResources)
- .build();
- }
-
- public NestedSet<ResourceContainer> getTransitiveResources() {
- return transitiveResources;
- }
-
- public NestedSet<ResourceContainer> getDirectResources() {
- return directResources;
- }
-}
diff --git a/src/test/java/com/google/devtools/build/lib/actions/CustomCommandLineTest.java b/src/test/java/com/google/devtools/build/lib/actions/CustomCommandLineTest.java
index a61790d645..d94780f2ff 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/CustomCommandLineTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/CustomCommandLineTest.java
@@ -69,13 +69,6 @@ public class CustomCommandLineTest {
}
@Test
- public void testArtifactJoinStringArgs() {
- CustomCommandLine cl = CustomCommandLine.builder().addJoinStrings("--path", ":",
- ImmutableList.of("foo", "bar")).build();
- assertEquals(ImmutableList.of("--path", "foo:bar"), cl.arguments());
- }
-
- @Test
public void testArtifactExecPathArgs() {
CustomCommandLine cl = CustomCommandLine.builder().addExecPath("--path", artifact1).build();
assertEquals(ImmutableList.of("--path", "dir/file1.txt"), cl.arguments());
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
index c9a25b26d6..5d8ef6c27c 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
@@ -137,21 +137,11 @@ public class AndroidResourceProcessingAction {
defaultValue = "",
converter = DependencyAndroidDataListConverter.class,
category = "input",
- help = "Transitive Data dependencies. These values will be used if not defined in the "
+ help = "Additional Data dependencies. These values will be used if not defined in the "
+ "primary resources. The expected format is "
- + "resources[#resources]:assets[#assets]:manifest:r.txt:symbols.bin"
- + "[,resources[#resources]:assets[#assets]:manifest:r.txt:symbols.bin]")
- public List<DependencyAndroidData> transitiveData;
-
- @Option(name = "directData",
- defaultValue = "",
- converter = DependencyAndroidDataListConverter.class,
- category = "input",
- help = "Direct Data dependencies. These values will be used if not defined in the "
- + "primary resources. The expected format is "
- + "resources[#resources]:assets[#assets]:manifest:r.txt:symbols.bin"
- + "[,resources[#resources]:assets[#assets]:manifest:r.txt:symbols.bin]")
- public List<DependencyAndroidData> directData;
+ + "resources[#resources]:assets[#assets]:manifest:r.txt:symbols.txt"
+ + "[,resources[#resources]:assets[#assets]:manifest:r.txt:symbols.txt]")
+ public List<DependencyAndroidData> data;
@Option(name = "rOutput",
defaultValue = "null",
@@ -308,15 +298,11 @@ public class AndroidResourceProcessingAction {
new PackedResourceTarExpander(expandedOut, working),
new FileDeDuplicator(Hashing.murmur3_128(), deduplicatedOut, working));
- List<DependencyAndroidData> data = ImmutableList.<DependencyAndroidData>builder()
- .addAll(options.directData)
- .addAll(options.transitiveData)
- .build();
final AndroidBuilder builder = sdkTools.createAndroidBuilder();
final MergedAndroidData mergedData = resourceProcessor.mergeData(
options.primaryData,
- data,
+ options.data,
mergedResources,
mergedAssets,
modifiers,
@@ -343,7 +329,7 @@ public class AndroidResourceProcessingAction {
options.versionCode,
options.versionName,
filteredData,
- data,
+ options.data,
working.resolve("manifest"),
generatedSources,
options.packagePath,