Modify UberRDotJavaUtil.getAndroidResourceDeps() so it no longer needs a DependencyGraph.
Summary:
This makes `UberRDotJavaUtil` more general, which will make it easier to repurpose for
use by a standalone `aapt package` rule.
Test Plan: Sandcastle builds.
diff --git a/src/com/facebook/buck/android/AndroidBinaryRule.java b/src/com/facebook/buck/android/AndroidBinaryRule.java
index e5a1bc3..595afd2 100644
--- a/src/com/facebook/buck/android/AndroidBinaryRule.java
+++ b/src/com/facebook/buck/android/AndroidBinaryRule.java
@@ -38,7 +38,6 @@
import com.facebook.buck.rules.Buildable;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.DoNotUseAbstractBuildable;
import com.facebook.buck.rules.InstallableBuildRule;
import com.facebook.buck.rules.RuleKey;
@@ -477,11 +476,10 @@
steps.add(new MkdirAndSymlinkFileStep(getManifest().resolve(context).toString(),
getAndroidManifestXml()));
- final AndroidTransitiveDependencies transitiveDependencies = findTransitiveDependencies(
- context.getDependencyGraph());
+ final AndroidTransitiveDependencies transitiveDependencies = findTransitiveDependencies();
final AndroidDexTransitiveDependencies dexTransitiveDependencies =
- findDexTransitiveDependencies(context.getDependencyGraph());
+ findDexTransitiveDependencies();
// Add the steps for the aapt_package command. This method returns data that the ApkBuilder
// needs to create a final, unsigned APK.
@@ -866,13 +864,13 @@
return Optional.of(destination);
}
- public AndroidTransitiveDependencies findTransitiveDependencies(DependencyGraph graph) {
- return getTransitiveDependencyGraph().findDependencies(getAndroidResourceDepsInternal(graph));
+ public AndroidTransitiveDependencies findTransitiveDependencies() {
+ return getTransitiveDependencyGraph().findDependencies(getAndroidResourceDepsInternal());
}
- public AndroidDexTransitiveDependencies findDexTransitiveDependencies(DependencyGraph graph) {
+ public AndroidDexTransitiveDependencies findDexTransitiveDependencies() {
return getTransitiveDependencyGraph().findDexDependencies(
- getAndroidResourceDepsInternal(graph),
+ getAndroidResourceDepsInternal(),
buildRulesToExcludeFromDex);
}
@@ -880,9 +878,8 @@
* @return a list of {@link HasAndroidResourceDeps}s that should be passed, in order, to {@code aapt}
* when generating the {@code R.java} files for this APK.
*/
- protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal(
- DependencyGraph graph) {
- return UberRDotJavaUtil.getAndroidResourceDeps(this, graph);
+ protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal() {
+ return UberRDotJavaUtil.getAndroidResourceDeps(this);
}
private boolean canSkipAaptResourcePackaging() {
diff --git a/src/com/facebook/buck/android/AndroidInstrumentationApk.java b/src/com/facebook/buck/android/AndroidInstrumentationApk.java
index 356b035..4b791bb 100644
--- a/src/com/facebook/buck/android/AndroidInstrumentationApk.java
+++ b/src/com/facebook/buck/android/AndroidInstrumentationApk.java
@@ -25,7 +25,6 @@
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.InstallableBuildRule;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePath;
@@ -105,13 +104,12 @@
}
@Override
- protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal(
- DependencyGraph graph) {
+ protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal() {
// Filter out the AndroidResourceRules that are needed by this APK but not the APK under test.
ImmutableSet<HasAndroidResourceDeps> originalResources = ImmutableSet.copyOf(
- UberRDotJavaUtil.getAndroidResourceDeps(apkUnderTest, graph));
+ UberRDotJavaUtil.getAndroidResourceDeps(apkUnderTest));
ImmutableList<HasAndroidResourceDeps> instrumentationResources =
- UberRDotJavaUtil.getAndroidResourceDeps(this, graph);
+ UberRDotJavaUtil.getAndroidResourceDeps(this);
// Include all of the instrumentation resources first, in their original order.
ImmutableList.Builder<HasAndroidResourceDeps> allResources = ImmutableList.builder();
diff --git a/src/com/facebook/buck/android/AndroidManifest.java b/src/com/facebook/buck/android/AndroidManifest.java
index fb7270d..bc85177 100644
--- a/src/com/facebook/buck/android/AndroidManifest.java
+++ b/src/com/facebook/buck/android/AndroidManifest.java
@@ -116,10 +116,9 @@
* @return a list of {@link AndroidResourceRule}s that should be passed,
* in order, to {@code aapt} when generating the {@code R.java} files for this APK.
*/
- private ImmutableList<HasAndroidResourceDeps> getAndroidResourceDeps(
- DependencyGraph graph) {
+ private ImmutableList<HasAndroidResourceDeps> getAndroidResourceDeps(DependencyGraph graph) {
BuildRule self = graph.findBuildRuleByTarget(buildTarget);
- return UberRDotJavaUtil.getAndroidResourceDeps(self, graph);
+ return UberRDotJavaUtil.getAndroidResourceDeps(self);
}
public static Builder newManifestMergeRuleBuilder(AbstractBuildRuleBuilderParams params) {
diff --git a/src/com/facebook/buck/android/AndroidResourceRule.java b/src/com/facebook/buck/android/AndroidResourceRule.java
index e4a6e58..1e228c9 100644
--- a/src/com/facebook/buck/android/AndroidResourceRule.java
+++ b/src/com/facebook/buck/android/AndroidResourceRule.java
@@ -172,7 +172,7 @@
// Searching through the deps, find any additional res directories to pass to aapt.
ImmutableList<HasAndroidResourceDeps> androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(
- this, context.getDependencyGraph());
+ this);
Set<String> resDirectories = ImmutableSet.copyOf(
Iterables.transform(androidResourceDeps, GET_RES_FOR_RULE));
diff --git a/src/com/facebook/buck/android/UberRDotJavaUtil.java b/src/com/facebook/buck/android/UberRDotJavaUtil.java
index ebf81c1..a725aa3 100644
--- a/src/com/facebook/buck/android/UberRDotJavaUtil.java
+++ b/src/com/facebook/buck/android/UberRDotJavaUtil.java
@@ -16,6 +16,9 @@
package com.facebook.buck.android;
+import com.facebook.buck.graph.DefaultImmutableDirectedAcyclicGraph;
+import com.facebook.buck.graph.ImmutableDirectedAcyclicGraph;
+import com.facebook.buck.graph.MutableDirectedGraph;
import com.facebook.buck.graph.TopologicalSort;
import com.facebook.buck.java.JavacInMemoryStep;
import com.facebook.buck.java.JavacOptions;
@@ -24,7 +27,6 @@
import com.facebook.buck.rules.BuildDependencies;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleType;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.WriteFileStep;
@@ -39,6 +41,8 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -122,13 +126,55 @@
/**
* Finds the transitive set of {@code rule}'s {@link AndroidResourceRule} dependencies with
* non-null {@code res} directories, which can also include {@code rule} itself.
- * This set will be returned as an {@link ImmutableList} with the rules topologically sorted as
- * determined by {@code graph}. Rules will be ordered from least dependent to most dependent.
+ * This set will be returned as an {@link ImmutableList} with the rules topologically sorted.
+ * Rules will be ordered from least dependent to most dependent.
+ */
+ public static ImmutableList<HasAndroidResourceDeps> getAndroidResourceDeps(BuildRule rule) {
+ return getAndroidResourceDeps(Collections.singleton(rule));
+ }
+
+ /**
+ * Finds the transitive set of {@code rules}' {@link AndroidResourceRule} dependencies with
+ * non-null {@code res} directories, which can also include any of the {@code rules} themselves.
+ * This set will be returned as an {@link ImmutableList} with the rules topologically sorted.
+ * Rules will be ordered from least dependent to most dependent.
*/
public static ImmutableList<HasAndroidResourceDeps> getAndroidResourceDeps(
- BuildRule rule,
- DependencyGraph graph) {
- final Set<HasAndroidResourceDeps> allAndroidResourceRules = findAllAndroidResourceDeps(rule);
+ Collection<BuildRule> rules) {
+ // This visitor finds all AndroidResourceRules that are reachable from the specified rules via
+ // rules with types in the TRAVERSABLE_TYPES collection. It also builds up the dependency graph
+ // that was traversed to find the AndroidResourceRules.
+ final MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<>();
+ final ImmutableSet.Builder<HasAndroidResourceDeps> androidResources = ImmutableSet.builder();
+ AbstractDependencyVisitor visitor = new AbstractDependencyVisitor(rules) {
+
+ @Override
+ public ImmutableSet<BuildRule> visit(BuildRule rule) {
+ mutableGraph.addNode(rule);
+
+ if (rule instanceof HasAndroidResourceDeps) {
+ HasAndroidResourceDeps androidResourceRule = (HasAndroidResourceDeps)rule;
+ if (androidResourceRule.getRes() != null) {
+ androidResources.add(androidResourceRule);
+ }
+ }
+
+ // Only certain types of rules should be considered as part of this traversal.
+ BuildRuleType type = rule.getType();
+ ImmutableSet<BuildRule> depsToVisit = maybeVisitAllDeps(rule,
+ TRAVERSABLE_TYPES.contains(type));
+ for (BuildRule dep : depsToVisit) {
+ mutableGraph.addEdge(rule, dep);
+ }
+ return depsToVisit;
+ }
+
+ };
+ visitor.start();
+
+ final Set<HasAndroidResourceDeps> allAndroidResourceRules = androidResources.build();
+ final ImmutableDirectedAcyclicGraph<BuildRule> graph =
+ new DefaultImmutableDirectedAcyclicGraph<>(mutableGraph);
// Now that we have the transitive set of AndroidResourceRules, we need to return them in
// topologically sorted order. This is critical because the order in which -S flags are passed
@@ -160,30 +206,6 @@
}
};
- private static ImmutableSet<HasAndroidResourceDeps> findAllAndroidResourceDeps(BuildRule buildRule) {
- final ImmutableSet.Builder<HasAndroidResourceDeps> androidResources = ImmutableSet.builder();
- AbstractDependencyVisitor visitor = new AbstractDependencyVisitor(buildRule) {
-
- @Override
- public ImmutableSet<BuildRule> visit(BuildRule rule) {
- if (rule instanceof HasAndroidResourceDeps) {
- HasAndroidResourceDeps androidResourceRule = (HasAndroidResourceDeps)rule;
- if (androidResourceRule.getRes() != null) {
- androidResources.add(androidResourceRule);
- }
- }
-
- // Only certain types of rules should be considered as part of this traversal.
- BuildRuleType type = rule.getType();
- return maybeVisitAllDeps(rule, TRAVERSABLE_TYPES.contains(type));
- }
-
- };
- visitor.start();
-
- return androidResources.build();
- }
-
/**
* Aggregate information about a list of {@link AndroidResourceRule}s.
*/
diff --git a/src/com/facebook/buck/command/Project.java b/src/com/facebook/buck/command/Project.java
index a6c2e90..2f88689 100644
--- a/src/com/facebook/buck/command/Project.java
+++ b/src/com/facebook/buck/command/Project.java
@@ -350,7 +350,7 @@
if (srcRule instanceof AndroidBinaryRule) {
AndroidBinaryRule androidBinary = (AndroidBinaryRule)srcRule;
AndroidDexTransitiveDependencies binaryDexTransitiveDependencies =
- androidBinary.findDexTransitiveDependencies(dependencyGraph);
+ androidBinary.findDexTransitiveDependencies();
noDxJarsBuilder.addAll(binaryDexTransitiveDependencies.noDxClasspathEntries);
}
@@ -360,7 +360,7 @@
ImmutableSet<String> noDxJars = noDxJarsBuilder.build();
// Update module dependencies to apply scope="PROVIDED", where appropriate.
- markNoDxJarsAsProvided(modules, noDxJars, dependencyGraph);
+ markNoDxJarsAsProvided(modules, noDxJars);
return modules;
}
@@ -664,10 +664,7 @@
* to the android_binary that <em>does not</em> list the library in its {@code no_dx} list.
*/
@VisibleForTesting
- static void markNoDxJarsAsProvided(
- List<Module> modules,
- Set<String> noDxJars,
- DependencyGraph dependencyGraph) {
+ static void markNoDxJarsAsProvided(List<Module> modules, Set<String> noDxJars) {
Map<String, String> intelliJLibraryNameToJarPath = Maps.newHashMap();
for (String jarPath : noDxJars) {
String libraryName = getIntellijNameForBinaryJar(jarPath);
@@ -683,7 +680,7 @@
if (module.srcRule instanceof AndroidBinaryRule) {
AndroidBinaryRule androidBinaryRule = (AndroidBinaryRule)module.srcRule;
AndroidDexTransitiveDependencies dexTransitiveDependencies =
- androidBinaryRule.findDexTransitiveDependencies(dependencyGraph);
+ androidBinaryRule.findDexTransitiveDependencies();
classpathEntriesToDex = Sets.newHashSet(Sets.intersection(noDxJars,
dexTransitiveDependencies.classpathEntriesToDex));
} else {
diff --git a/src/com/facebook/buck/java/DefaultJavaLibraryRule.java b/src/com/facebook/buck/java/DefaultJavaLibraryRule.java
index b9c9fee..952f695 100644
--- a/src/com/facebook/buck/java/DefaultJavaLibraryRule.java
+++ b/src/com/facebook/buck/java/DefaultJavaLibraryRule.java
@@ -518,8 +518,7 @@
// If this rule depends on AndroidResourceRules, then we need to generate the R.java files that
// this rule needs in order to be able to compile itself.
- androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this,
- context.getDependencyGraph());
+ androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this);
boolean dependsOnAndroidResourceRules = !androidResourceDeps.isEmpty();
if (dependsOnAndroidResourceRules) {
UberRDotJavaUtil.createDummyRDotJavaFiles(androidResourceDeps, buildTarget, commands);
diff --git a/src/com/facebook/buck/java/JavaTestRule.java b/src/com/facebook/buck/java/JavaTestRule.java
index dc091d8..76efdb3 100644
--- a/src/com/facebook/buck/java/JavaTestRule.java
+++ b/src/com/facebook/buck/java/JavaTestRule.java
@@ -153,8 +153,7 @@
// androidResourceDeps will be null if this test is re-run without being rebuilt.
if (androidResourceDeps == null) {
- androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this,
- buildContext.getDependencyGraph());
+ androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this);
}
ImmutableList.Builder<Step> steps = ImmutableList.builder();
diff --git a/test/com/facebook/buck/android/AndroidBinaryRuleTest.java b/test/com/facebook/buck/android/AndroidBinaryRuleTest.java
index 26277f4..ed8849f 100644
--- a/test/com/facebook/buck/android/AndroidBinaryRuleTest.java
+++ b/test/com/facebook/buck/android/AndroidBinaryRuleTest.java
@@ -36,7 +36,6 @@
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.FileSourcePath;
import com.facebook.buck.rules.SourcePath;
@@ -45,7 +44,6 @@
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirAndSymlinkFileStep;
import com.facebook.buck.testutil.MoreAsserts;
-import com.facebook.buck.testutil.RuleMap;
import com.facebook.buck.util.DirectoryTraversal;
import com.facebook.buck.util.DirectoryTraverser;
import com.facebook.buck.util.MorePaths;
@@ -104,11 +102,10 @@
.setKeystore(addKeystoreRule(ruleResolver))
.setPackageType("debug"));
- DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
AndroidTransitiveDependencies transitiveDependencies =
- androidBinary.findTransitiveDependencies(graph);
+ androidBinary.findTransitiveDependencies();
AndroidDexTransitiveDependencies dexTransitiveDependencies =
- androidBinary.findDexTransitiveDependencies(graph);
+ androidBinary.findDexTransitiveDependencies();
ImmutableList.Builder<Step> commands = ImmutableList.builder();
BuildContext context = createMock(BuildContext.class);
diff --git a/test/com/facebook/buck/android/AndroidResourceRuleTest.java b/test/com/facebook/buck/android/AndroidResourceRuleTest.java
index 2480d94..2a95529 100644
--- a/test/com/facebook/buck/android/AndroidResourceRuleTest.java
+++ b/test/com/facebook/buck/android/AndroidResourceRuleTest.java
@@ -25,12 +25,10 @@
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.FakeBuildRuleParams;
import com.facebook.buck.rules.FileSourcePath;
import com.facebook.buck.testutil.MoreAsserts;
-import com.facebook.buck.testutil.RuleMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
@@ -125,8 +123,7 @@
.addDep(BuildTargetFactory.newInstance("//:c"))
.addDep(BuildTargetFactory.newInstance("//:d")));
- DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
- ImmutableList<HasAndroidResourceDeps> deps = UberRDotJavaUtil.getAndroidResourceDeps(a, graph);
+ ImmutableList<HasAndroidResourceDeps> deps = UberRDotJavaUtil.getAndroidResourceDeps(a);
// Note that a topological sort for a DAG is not guaranteed to be unique. In this particular
// case, there are two possible valid outcomes.
@@ -157,8 +154,7 @@
.addDep(BuildTargetFactory.newInstance("//:a"))
.addDep(BuildTargetFactory.newInstance("//:c")));
- DependencyGraph graph2 = RuleMap.createGraphFromBuildRules(ruleResolver);
- ImmutableList<HasAndroidResourceDeps> deps2 = UberRDotJavaUtil.getAndroidResourceDeps(e, graph2);
+ ImmutableList<HasAndroidResourceDeps> deps2 = UberRDotJavaUtil.getAndroidResourceDeps(e);
assertTrue(
String.format(
"Topological sort %s should be either %s or %s", deps, validResult1, validResult2),
diff --git a/test/com/facebook/buck/android/AndroidTransitiveDependencyGraphTest.java b/test/com/facebook/buck/android/AndroidTransitiveDependencyGraphTest.java
index 799f08c..54a8539 100644
--- a/test/com/facebook/buck/android/AndroidTransitiveDependencyGraphTest.java
+++ b/test/com/facebook/buck/android/AndroidTransitiveDependencyGraphTest.java
@@ -26,10 +26,8 @@
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
-import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.rules.FakeAbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.FileSourcePath;
-import com.facebook.buck.testutil.RuleMap;
import com.facebook.buck.util.BuckConstant;
import com.google.common.collect.ImmutableSet;
@@ -107,10 +105,9 @@
.setKeystore(keystoreTarget));
// Verify that the correct transitive dependencies are found.
- DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
- AndroidTransitiveDependencies transitiveDeps = binaryRule.findTransitiveDependencies(graph);
+ AndroidTransitiveDependencies transitiveDeps = binaryRule.findTransitiveDependencies();
AndroidDexTransitiveDependencies dexTransitiveDeps =
- binaryRule.findDexTransitiveDependencies(graph);
+ binaryRule.findDexTransitiveDependencies();
assertEquals(
"Because guava was passed to no_dx, it should not be in the classpathEntriesToDex list",
ImmutableSet.of("third_party/jsr-305/jsr305.jar"),
@@ -188,9 +185,8 @@
.setKeystore(keystoreTarget)
.addClasspathDep(androidLibraryTarget));
- DependencyGraph dependencyGraph = RuleMap.createGraphFromBuildRules(ruleResolver);
AndroidDexTransitiveDependencies androidTransitiveDeps = androidBinaryRule
- .findDexTransitiveDependencies(dependencyGraph);
+ .findDexTransitiveDependencies();
assertEquals(
"Classpath entries should include facebook/base but not keystore/base.",
ImmutableSet.of(BuckConstant.GEN_DIR + "/java/com/facebook/base/lib__base__output/base.jar"),
diff --git a/test/com/facebook/buck/java/DefaultJavaLibraryRuleTest.java b/test/com/facebook/buck/java/DefaultJavaLibraryRuleTest.java
index 44ec6e5..9681815 100644
--- a/test/com/facebook/buck/java/DefaultJavaLibraryRuleTest.java
+++ b/test/com/facebook/buck/java/DefaultJavaLibraryRuleTest.java
@@ -461,10 +461,7 @@
.addSrc("java/src/com/libtwo/Foo.java")
.addDep(BuildTargetFactory.newInstance("//:libone")));
- DependencyGraph graph = RuleMap.createGraphFromBuildRules(ruleResolver);
-
BuildContext buildContext = EasyMock.createMock(BuildContext.class);
- expect(buildContext.getDependencyGraph()).andReturn(graph);
expect(buildContext.getBuildDependencies()).andReturn(BuildDependencies.FIRST_ORDER_ONLY)
.times(2);
JavaPackageFinder javaPackageFinder = EasyMock.createMock(JavaPackageFinder.class);