aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-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
9 files changed, 222 insertions, 466 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;
- }
-}