@Override public <A extends Arg> JavaTest createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) throws NoSuchBuildTargetException { SourcePathResolver pathResolver = new SourcePathResolver(resolver); JavacOptions javacOptions = JavacOptionsFactory.create(templateJavacOptions, params, resolver, pathResolver, args); CxxLibraryEnhancement cxxLibraryEnhancement = new CxxLibraryEnhancement( params, args.useCxxLibraries, resolver, pathResolver, cxxPlatform); params = cxxLibraryEnhancement.updatedParams; BuildTarget abiJarTarget = params.getBuildTarget().withAppendedFlavors(CalculateAbi.FLAVOR); JavaTest test = resolver.addToIndex( new JavaTest( params.appendExtraDeps( Iterables.concat( BuildRules.getExportedRules( Iterables.concat( params.getDeclaredDeps().get(), resolver.getAllRules(args.providedDeps.get()))), pathResolver.filterBuildRuleInputs(javacOptions.getInputs(pathResolver)))), pathResolver, args.srcs.get(), ResourceValidator.validateResources( pathResolver, params.getProjectFilesystem(), args.resources.get()), javacOptions.getGeneratedSourceFolderName(), args.labels.get(), args.contacts.get(), args.proguardConfig.transform( SourcePaths.toSourcePath(params.getProjectFilesystem())), new BuildTargetSourcePath(abiJarTarget), javacOptions.trackClassUsage(), /* additionalClasspathEntries */ ImmutableSet.<Path>of(), args.testType.or(TestType.JUNIT), new JavacToJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY), javaOptions.getJavaRuntimeLauncher(), args.vmArgs.get(), cxxLibraryEnhancement.nativeLibsEnvironment, validateAndGetSourcesUnderTest( args.sourceUnderTest.get(), params.getBuildTarget(), resolver), args.resourcesRoot, args.mavenCoords, args.testRuleTimeoutMs.or(defaultTestRuleTimeoutMs), args.env.get(), args.getRunTestSeparately(), args.stdOutLogLevel, args.stdErrLogLevel)); resolver.addToIndex( CalculateAbi.of( abiJarTarget, pathResolver, params, new BuildTargetSourcePath(test.getBuildTarget()))); return test; }
public static CxxHeaderSourceSpec requireLexYaccSources( BuildRuleParams params, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, CxxPlatform cxxPlatform, ImmutableMap<String, SourcePath> lexSources, ImmutableMap<String, SourcePath> yaccSources) { BuildTarget lexYaccTarget = createLexYaccSourcesBuildTarget(params.getBuildTarget()); // Check the cache... Optional<BuildRule> rule = ruleResolver.getRuleOptional(lexYaccTarget); if (rule.isPresent()) { @SuppressWarnings("unchecked") ContainerBuildRule<CxxHeaderSourceSpec> containerRule = (ContainerBuildRule<CxxHeaderSourceSpec>) rule.get(); return containerRule.get(); } // Setup the rules to run lex/yacc. CxxHeaderSourceSpec lexYaccSources = CxxDescriptionEnhancer.createLexYaccBuildRules( params, ruleResolver, cxxPlatform, ImmutableList.<String>of(), lexSources, ImmutableList.<String>of(), yaccSources); ruleResolver.addToIndex( ContainerBuildRule.of(params, pathResolver, lexYaccTarget, lexYaccSources)); return lexYaccSources; }
@Test public void ruleKeyDoesNotChangeWhenOnlyDependencyRuleKeyChanges() throws Exception { ProjectFilesystem filesystem = new FakeProjectFilesystem(); BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver pathResolver = new SourcePathResolver(resolver); Path depOutput = Paths.get("output"); FakeBuildRule dep = resolver.addToIndex( new FakeBuildRule(BuildTargetFactory.newInstance("//:dep"), filesystem, pathResolver)); dep.setOutputFile(depOutput.toString()); filesystem.writeContentsToPath("hello", dep.getPathToOutput()); FakeFileHashCache hashCache = new FakeFileHashCache(ImmutableMap.of(filesystem.resolve(depOutput), HashCode.fromInt(0))); BuildRule rule = GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:rule")) .setOut("out") .setSrcs(ImmutableList.<SourcePath>of(new BuildTargetSourcePath(dep.getBuildTarget()))) .build(resolver, filesystem); RuleKey inputKey1 = new InputBasedRuleKeyBuilderFactory(0, hashCache, pathResolver).build(rule); RuleKey inputKey2 = new InputBasedRuleKeyBuilderFactory(0, hashCache, pathResolver).build(rule); assertThat(inputKey1, Matchers.equalTo(inputKey2)); }
@Test public void shouldSetInputsFromSourcePaths() { ExportFileBuilder builder = ExportFileBuilder.newExportFileBuilder(target) .setSrc(new TestSourcePath("chips")) .setOut("cake"); ExportFile exportFile = (ExportFile) builder.build(new BuildRuleResolver()); assertIterablesEquals(singleton(Paths.get("chips")), exportFile.getSource()); BuildRuleResolver ruleResolver = new BuildRuleResolver(); FakeBuildRule rule = ruleResolver.addToIndex( new FakeBuildRule( BuildTargetFactory.newInstance("//example:one"), new SourcePathResolver(ruleResolver))); builder.setSrc(new BuildTargetSourcePath(rule.getBuildTarget())); exportFile = (ExportFile) builder.build(ruleResolver); assertTrue(Iterables.isEmpty(exportFile.getSource())); builder.setSrc(null); exportFile = (ExportFile) builder.build(new BuildRuleResolver()); assertIterablesEquals(singleton(Paths.get("example.html")), exportFile.getSource()); }
/** * There was a bug where `BuildTargetSourcePath` sources were written to the classes file using * their string representation, rather than their resolved path. */ @Test public void shouldWriteResolvedBuildTargetSourcePathsToClassesFile() throws IOException, InterruptedException { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); BuildRule rule = new FakeBuildRule("//:fake", pathResolver); resolver.addToIndex(rule); Jsr199Javac javac = createJavac(/* withSyntaxError */ false); ExecutionContext executionContext = TestExecutionContext.newInstance(); int exitCode = javac.buildWithClasspath( executionContext, createProjectFilesystem(), PATH_RESOLVER, BuildTargetFactory.newInstance("//some:example"), ImmutableList.<String>of(), SOURCE_PATHS, Optional.of(pathToSrcsList), Optional.<Path>absent()); assertEquals("javac should exit with code 0.", exitCode, 0); File srcsListFile = pathToSrcsList.toFile(); assertTrue(srcsListFile.exists()); assertTrue(srcsListFile.isFile()); assertEquals("Example.java", Files.toString(srcsListFile, Charsets.UTF_8).trim()); }
@Test public void ruleKeyDoesNotChangeWhenOnlyDependencyRuleKeyChanges() { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); Path depOutput = Paths.get("output"); FakeBuildRule dep = resolver.addToIndex( new FakeBuildRule(BuildTargetFactory.newInstance("//:dep"), pathResolver)); dep.setOutputFile(depOutput.toString()); FakeFileHashCache hashCache = new FakeFileHashCache(ImmutableMap.of(depOutput, HashCode.fromInt(0))); BuildRule rule = new FakeAbiRuleBuildRule("//:rule", pathResolver, dep); dep.setRuleKey(new RuleKey("aaaa")); RuleKey inputKey1 = new AbiRuleKeyBuilderFactory(hashCache, pathResolver).newInstance(rule).build(); dep.setRuleKey(new RuleKey("bbbb")); RuleKey inputKey2 = new AbiRuleKeyBuilderFactory(hashCache, pathResolver).newInstance(rule).build(); assertThat(inputKey1, equalTo(inputKey2)); }
@Test public void testGetExecutableCommand() { BuildRuleResolver ruleResolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(ruleResolver); // prebuilt_jar //third_party/generator:generator PrebuiltJarBuilder.createBuilder( BuildTargetFactory.newInstance("//third_party/generator:generator")) .setBinaryJar(PATH_TO_GENERATOR_JAR) .build(ruleResolver); // prebuilt_jar //third_party/guava:guava BuildRule guava = PrebuiltJarBuilder.createBuilder( BuildTargetFactory.newInstance("//third_party/guava:guava")) .setBinaryJar(PATH_TO_GUAVA_JAR) .build(ruleResolver); // java_library //java/com/facebook/base:base BuildRule libraryRule = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//java/com/facebook/base:base")) .addSrc(Paths.get("java/com/facebook/base/Base.java")) .addDep(guava.getBuildTarget()) .build(ruleResolver); BuildRuleParams params = new FakeBuildRuleParamsBuilder( BuildTargetFactory.newInstance("//java/com/facebook/base:Main")) .setDeps(ImmutableSortedSet.of(libraryRule)) .build(); // java_binary //java/com/facebook/base:Main JavaBinary javaBinary = ruleResolver.addToIndex( new JavaBinary( params, new SourcePathResolver(ruleResolver), "com.facebook.base.Main", null, /* merge manifests */ true, null, /* blacklist */ ImmutableSet.<String>of(), new DefaultDirectoryTraverser(), ImmutableSetMultimap.<JavaLibrary, Path>of())); // Strip the trailing "." from the absolute path to the current directory. final String basePath = new File(".").getAbsolutePath().replaceFirst("\\.$", ""); // Each classpath entry is specified via its absolute path so that the executable command can be // run from a /tmp directory, if necessary. String expectedClasspath = basePath + javaBinary.getPathToOutput(); List<String> expectedCommand = ImmutableList.of("java", "-jar", expectedClasspath); assertEquals(expectedCommand, javaBinary.getExecutableCommand().getCommandPrefix(pathResolver)); assertFalse( "Library rules that are used exclusively by genrules should not be part of the classpath.", expectedClasspath.contains(PATH_TO_GENERATOR_JAR.toString())); }
private ImmutableList<SourcePath> generateCCompilation(ImmutableList<SourcePath> cInput) { ImmutableList.Builder<SourcePath> objects = ImmutableList.builder(); ImmutableList.Builder<String> cCompileFlags = ImmutableList.builder(); cCompileFlags.addAll(ocamlContext.getCCompileFlags()); cCompileFlags.addAll(ocamlContext.getCommonCFlags()); CxxPreprocessorInput cxxPreprocessorInput = ocamlContext.getCxxPreprocessorInput(); for (SourcePath cSrc : cInput) { String name = pathResolver.getAbsolutePath(cSrc).toFile().getName(); BuildTarget target = createCCompileBuildTarget(params.getBuildTarget(), name); BuildRuleParams cCompileParams = params.copyWithChanges( target, /* declaredDeps */ Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() // Depend on the rule that generates the sources and headers we're compiling. .addAll( pathResolver.filterBuildRuleInputs( ImmutableList.<SourcePath>builder() .add(cSrc) .addAll( cxxPreprocessorInput .getIncludes() .getNameToPathMap() .values()) .build())) // Also add in extra deps from the preprocessor input, such as the symlink // tree rules. .addAll( BuildRules.toBuildRulesFor( params.getBuildTarget(), resolver, cxxPreprocessorInput.getRules())) .addAll(params.getDeclaredDeps().get()) .build()), /* extraDeps */ params.getExtraDeps()); Path outputPath = ocamlContext.getCOutput(pathResolver.getRelativePath(cSrc)); OCamlCCompile compileRule = new OCamlCCompile( cCompileParams, pathResolver, new OCamlCCompileStep.Args( cCompiler.getEnvironment(pathResolver), cCompiler.getCommandPrefix(pathResolver), ocamlContext.getOcamlCompiler().get(), outputPath, cSrc, cCompileFlags.build(), ImmutableMap.copyOf(cxxPreprocessorInput.getIncludes().getNameToPathMap()))); resolver.addToIndex(compileRule); objects.add(new BuildTargetSourcePath(compileRule.getBuildTarget())); } return objects.build(); }
private BuildRule buildRuleAndAddToIndex( Buildable buildable, BuildRuleType buildRuleType, BuildTarget buildTarget, ImmutableSortedSet<BuildRule> deps) { BuildRule buildRule = Buildables.createRuleFromBuildable( buildable, buildRuleType, buildTarget, deps, buildRuleParams); ruleResolver.addToIndex(buildTarget, buildRule); return buildRule; }
@Test public void createBuildRuleForUnflavoredTargetCreateThriftLibrary() { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); BuildTarget unflavoredTarget = BuildTargetFactory.newInstance("//:thrift"); BuildRuleParams unflavoredParams = BuildRuleParamsFactory.createTrivialBuildRuleParams(unflavoredTarget); // Setup an empty thrift buck config, missing the compiler. FakeBuckConfig buckConfig = new FakeBuckConfig( ImmutableMap.<String, ImmutableMap<String, String>>of(), ImmutableMap.<String, String>of()); ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig); ThriftLibraryDescription desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Setup the thrift source. String sourceName = "test.thrift"; SourcePath source = new TestSourcePath(sourceName); // Create a dep and verify it gets attached. BuildTarget depTarget = BuildTargetFactory.newInstance("//:dep"); Path depIncludeRoot = desc.getIncludeRoot(depTarget); HeaderSymlinkTree depIncludeSymlinkTree = createFakeSymlinkTree(depTarget, pathResolver, depIncludeRoot); ThriftLibrary dep = new ThriftLibrary( BuildRuleParamsFactory.createTrivialBuildRuleParams(depTarget), pathResolver, ImmutableSortedSet.<ThriftLibrary>of(), depIncludeSymlinkTree, ImmutableMap.<Path, SourcePath>of()); resolver.addToIndex(dep); // Build up the constructor arg. ThriftConstructorArg arg = desc.createUnpopulatedConstructorArg(); arg.name = "thrift"; arg.srcs = ImmutableMap.of(source, ImmutableList.<String>of()); arg.deps = Optional.of(ImmutableSortedSet.of(dep.getBuildTarget())); arg.flags = Optional.absent(); // Build the thrift library rule and verify that it's setup correctly. BuildRule rule = desc.createBuildRule(TargetGraph.EMPTY, unflavoredParams, resolver, arg); assertTrue(rule instanceof ThriftLibrary); ThriftLibrary me = (ThriftLibrary) rule; assertEquals(ImmutableSortedSet.of(dep), me.getThriftDeps()); assertEquals(desc.getIncludeRoot(unflavoredTarget), me.getIncludeTreeRule().getIncludePath()); }
/** * Ensure that the build rule generated by the given {@link BuildRuleParams} had been generated by * it's corresponding {@link Description} and added to the {@link BuildRuleResolver}. If not, call * into it's associated {@link Description} to generate it's {@link BuildRule}. * * @return the {@link BuildRule} generated by the description corresponding to the supplied {@link * BuildRuleParams}. */ public static BuildRule requireBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver ruleResolver, Flavor... flavors) { BuildTarget target = BuildTarget.builder(params.getBuildTarget()).addFlavors(flavors).build(); Optional<BuildRule> rule = ruleResolver.getRuleOptional(target); if (!rule.isPresent()) { TargetNode<?> node = targetGraph.get(params.getBuildTarget()); Preconditions.checkNotNull( node, String.format("%s not in target graph", params.getBuildTarget())); rule = Optional.of(createBuildRule(targetGraph, params, ruleResolver, node, flavors)); ruleResolver.addToIndex(rule.get()); } return rule.get(); }
private BuildRule generateBytecodeLinking(ImmutableList<SourcePath> allInputs) { BuildRuleParams linkParams = params.copyWithChanges( addBytecodeFlavor(params.getBuildTarget()), Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(pathResolver.filterBuildRuleInputs(allInputs)) .addAll(ocamlContext.getBytecodeLinkDeps()) .addAll( FluentIterable.from(ocamlContext.getLinkableInput().getArgs()) .append(ocamlContext.getNativeLinkableInput().getArgs()) .transformAndConcat(Arg.getDepsFunction(pathResolver)) .filter(Predicates.not(Predicates.instanceOf(OCamlBuild.class)))) .build()), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); ImmutableList<String> linkerInputs = FluentIterable.from(allInputs) .transform(pathResolver.deprecatedPathFunction()) .transform(Functions.toStringFunction()) .toList(); ImmutableList.Builder<String> flags = ImmutableList.builder(); flags.addAll(ocamlContext.getFlags()); flags.addAll(ocamlContext.getCommonCLinkerFlags()); OCamlLink link = new OCamlLink( linkParams, pathResolver, allInputs, new OCamlLinkStep.Args( cxxCompiler.getEnvironment(pathResolver), cxxCompiler.getCommandPrefix(pathResolver), ocamlContext.getOcamlBytecodeCompiler().get(), ocamlContext.getBytecodeOutput(), ocamlContext.getLinkableInput().getArgs(), ocamlContext.getNativeLinkableInput().getArgs(), linkerInputs, flags.build(), ocamlContext.isLibrary(), /* isBytecode */ true)); resolver.addToIndex(link); return link; }
@Test public void shouldUseSpecifiedJavacJar() throws Exception { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); BuildRule rule = new FakeBuildRule("//:fake", pathResolver); resolver.addToIndex(rule); Path fakeJavacJar = Paths.get("ae036e57-77a7-4356-a79c-0f85b1a3290d", "fakeJavac.jar"); ExecutionContext executionContext = TestExecutionContext.newInstance(); MockClassLoader mockClassLoader = new MockClassLoader( ClassLoader.getSystemClassLoader(), ImmutableMap.<String, Class<?>>of( "com.sun.tools.javac.api.JavacTool", MockJavac.class)); executionContext .getClassLoaderCache() .injectClassLoader( ClassLoader.getSystemClassLoader(), ImmutableList.of(fakeJavacJar.toUri().toURL()), mockClassLoader); Jsr199Javac javac = createJavac(/* withSyntaxError */ false, Optional.of(fakeJavacJar)); boolean caught = false; try { javac.buildWithClasspath( executionContext, createProjectFilesystem(), PATH_RESOLVER, BuildTargetFactory.newInstance("//some:example"), ImmutableList.<String>of(), SOURCE_PATHS, Optional.of(pathToSrcsList), Optional.<Path>absent()); fail("Did not expect compilation to succeed"); } catch (UnsupportedOperationException ex) { if (ex.toString().contains("abcdef")) { caught = true; } } assertTrue("mock Java compiler should throw", caught); }
private BuildRule generateDebugLauncherRule() { BuildRuleParams debugParams = params.copyWithChanges( addDebugFlavor(params.getBuildTarget()), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); OCamlDebugLauncher debugLauncher = new OCamlDebugLauncher( debugParams, pathResolver, new OCamlDebugLauncherStep.Args( ocamlContext.getOcamlDebug().get(), ocamlContext.getBytecodeOutput(), ocamlContext.getOCamlInput(), ocamlContext.getBytecodeIncludeFlags())); resolver.addToIndex(debugLauncher); return debugLauncher; }
@Test public void testCreateWorkerToolWithBadExeValue() throws NoSuchBuildTargetException { BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildRule nonBinaryBuildRule = new FakeBuildRule( BuildTargetFactory.newInstance("//:fake"), new SourcePathResolver(resolver)); resolver.addToIndex(nonBinaryBuildRule); BuildTarget workerTarget = BuildTargetFactory.newInstance("//:worker_rule"); try { WorkerToolBuilder.newWorkerToolBuilder(workerTarget) .setExe(nonBinaryBuildRule.getBuildTarget()) .build(resolver); } catch (HumanReadableException e) { assertThat( e.getHumanReadableErrorMessage(), Matchers.containsString("needs to correspond to a binary rule")); } }
@Override public <A extends Arg> BuildRule createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) { BuildTarget libraryTarget = BuildTarget.builder(params.getBuildTarget()) .addFlavors(ImmutableFlavor.of("compile")) .build(); GoLibrary library = GoDescriptors.createGoLibraryRule( params.copyWithBuildTarget(libraryTarget), resolver, goBuckConfig, Paths.get("main"), args.srcs, args.compilerFlags.or(ImmutableList.<String>of())); resolver.addToIndex(library); BuildRuleParams binaryParams = params.copyWithDeps( Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(library)), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); GoSymlinkTree symlinkTree = GoDescriptors.requireTransitiveSymlinkTreeRule(binaryParams, resolver); return new GoBinary( params.copyWithDeps( Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(symlinkTree, library)), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), new SourcePathResolver(resolver), cxxPlatform.getLd(), symlinkTree, library, goBuckConfig.getGoLinker().get(), ImmutableList.<String>builder() .addAll(goBuckConfig.getLinkerFlags()) .addAll(args.linkerFlags.or(ImmutableList.<String>of())) .build()); }
public JavaTest build(BuildRuleResolver resolver) { BuildRuleParams params = new FakeBuildRuleParamsBuilder(target) .setType(JavaTestDescription.TYPE) .setDeps(deps.build()) .build(); JavaTest test = new JavaTest( params, srcs.build(), resources.build(), labels.build(), contacts.build(), proguardConfig, /* additionalClasspathEntries */ ImmutableSet.<Path>of(), JavacOptions.DEFAULTS, vmArgs, sourcesUnderTest.build(), Optional.<Path>absent()); resolver.addToIndex(test); return test; }
public static HeaderSymlinkTree requireHeaderSymlinkTree( BuildRuleParams params, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, CxxPlatform cxxPlatform, boolean includeLexYaccHeaders, ImmutableMap<String, SourcePath> lexSources, ImmutableMap<String, SourcePath> yaccSources, ImmutableMap<Path, SourcePath> headers, HeaderVisibility headerVisibility) { BuildTarget headerSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( params.getBuildTarget(), cxxPlatform.getFlavor(), headerVisibility); // Check the cache... Optional<BuildRule> rule = ruleResolver.getRuleOptional(headerSymlinkTreeTarget); if (rule.isPresent()) { Preconditions.checkState(rule.get() instanceof HeaderSymlinkTree); return (HeaderSymlinkTree) rule.get(); } HeaderSymlinkTree symlinkTree = createHeaderSymlinkTree( params, ruleResolver, pathResolver, cxxPlatform, includeLexYaccHeaders, lexSources, yaccSources, headers, headerVisibility); ruleResolver.addToIndex(symlinkTree); return symlinkTree; }
@Test public void createBuildRuleWithFlavoredTargetCallsEnhancerCorrectly() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); // Setup the default values returned by the language specific enhancer. String language = "fake"; Flavor flavor = ImmutableFlavor.of("fake"); final BuildRule implicitDep = createFakeBuildRule("//implicit:dep", pathResolver); resolver.addToIndex(implicitDep); filesystem.mkdirs(implicitDep.getBuildTarget().getBasePath()); filesystem.touch(implicitDep.getBuildTarget().getBasePath().resolve("BUCK")); ImmutableSet<BuildTarget> implicitDeps = ImmutableSet.of(implicitDep.getBuildTarget()); ImmutableSet<String> options = ImmutableSet.of(); // Create the build targets and params. BuildTarget unflavoredTarget = BuildTargetFactory.newInstance("//:thrift"); BuildRuleParams unflavoredParams = new FakeBuildRuleParamsBuilder(unflavoredTarget).setProjectFilesystem(filesystem).build(); BuildTarget flavoredTarget = BuildTargets.createFlavoredBuildTarget(unflavoredTarget.checkUnflavored(), flavor); BuildRuleParams flavoredParams = new FakeBuildRuleParamsBuilder(flavoredTarget).setProjectFilesystem(filesystem).build(); // Setup a thrift source file generated by a genrule. final String thriftSourceName1 = "foo.thrift"; BuildTarget genruleTarget = BuildTargetFactory.newInstance("//:genrule"); final Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(genruleTarget) .setOut(thriftSourceName1) .build(resolver); SourcePath thriftSource1 = new BuildTargetSourcePath(genrule.getBuildTarget()); final ImmutableList<String> thriftServices1 = ImmutableList.of(); // Setup a normal thrift source file. final String thriftSourceName2 = "bar.thrift"; SourcePath thriftSource2 = new TestSourcePath(thriftSourceName2); final ImmutableList<String> thriftServices2 = ImmutableList.of(); // Create a build rule that represents the thrift rule. final FakeBuildRule thriftRule = createFakeBuildRule("//thrift:target", pathResolver); resolver.addToIndex(thriftRule); filesystem.mkdirs(thriftRule.getBuildTarget().getBasePath()); filesystem.touch(thriftRule.getBuildTarget().getBasePath().resolve("BUCK")); // Setup a simple description with an empty config. FakeBuckConfig buckConfig = new FakeBuckConfig( ImmutableMap.of( "thrift", ImmutableMap.of("compiler", thriftRule.getBuildTarget().toString()))); ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig); ThriftLibraryDescription desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Setup the include rules. final BuildRule thriftIncludeSymlinkTree = createFakeBuildRule( desc.createThriftIncludeSymlinkTreeTarget(unflavoredTarget), pathResolver); // Setup our language enhancer FakeThriftLanguageSpecificEnhancer enhancer = new FakeThriftLanguageSpecificEnhancer(language, flavor, implicitDeps, options) { @Override public void checkCreateBuildRuleInputs( ImmutableMap<String, ThriftSource> sources, ImmutableSortedSet<BuildRule> deps) { // Verify both thrift sources are present in the list. assertEquals(2, sources.size()); ThriftSource src1 = sources.get(thriftSourceName1); assertNotNull(src1); ThriftSource src2 = sources.get(thriftSourceName2); assertNotNull(src2); // Verify the services are listed correctly for both sources. assertEquals(thriftServices1, src1.getServices()); assertEquals(thriftServices2, src2.getServices()); // Verify dependencies are setup correctly. assertEquals( ImmutableSortedSet.of(genrule, thriftRule, thriftIncludeSymlinkTree), src1.getCompileRule().getDeps()); assertEquals( ImmutableSortedSet.of(genrule, thriftRule, thriftIncludeSymlinkTree), src2.getCompileRule().getDeps()); // Verify the language specific implicit rules are added correctly. assertEquals( ImmutableSortedSet.<BuildRule>naturalOrder().add(implicitDep).build(), deps); } }; // Recreate the description with the enhancer we setup above. desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of(enhancer)); // Setup the internal structure indicating that the thrift target was set in the // buck config. // desc.setCompilerTarget(thriftRule.getBuildTarget()); // Setup the implicit deps for the flavored build target. // desc.setImplicitDeps(flavoredTarget, ImmutableList.of(implicitDep.getBuildTarget())); // Build up the constructor arg. ThriftConstructorArg arg = desc.createUnpopulatedConstructorArg(); arg.name = "thrift"; arg.srcs = ImmutableMap.of( thriftSource1, thriftServices1, thriftSource2, thriftServices2); arg.deps = Optional.absent(); arg.flags = Optional.absent(); // Setup the unflavored target, which should just produce a ThriftInclude, SymlinkTree, and // ThriftLibrary rule. BuildRule rule = desc.createBuildRule(TargetGraph.EMPTY, unflavoredParams, resolver, arg); resolver.addToIndex(rule); // Now attempt to create the flavored thrift library. desc.createBuildRule(TargetGraph.EMPTY, flavoredParams, resolver, arg); }
/** * Generate {@link Lex} and {@link Yacc} rules generating C/C++ sources from the given lex/yacc * sources. * * @return {@link CxxHeaderSourceSpec} containing the generated headers/sources */ public static CxxHeaderSourceSpec createLexYaccBuildRules( BuildRuleParams params, BuildRuleResolver resolver, CxxPlatform cxxPlatform, ImmutableList<String> lexFlags, ImmutableMap<String, SourcePath> lexSrcs, ImmutableList<String> yaccFlags, ImmutableMap<String, SourcePath> yaccSrcs) { if (!lexSrcs.isEmpty() && !cxxPlatform.getLex().isPresent()) { throw new HumanReadableException( "Platform %s must support lex to compile srcs %s", cxxPlatform, lexSrcs); } if (!yaccSrcs.isEmpty() && !cxxPlatform.getYacc().isPresent()) { throw new HumanReadableException( "Platform %s must support yacc to compile srcs %s", cxxPlatform, yaccSrcs); } SourcePathResolver pathResolver = new SourcePathResolver(resolver); ImmutableMap.Builder<String, CxxSource> lexYaccCxxSourcesBuilder = ImmutableMap.builder(); ImmutableMap.Builder<Path, SourcePath> lexYaccHeadersBuilder = ImmutableMap.builder(); // Loop over all lex sources, generating build rule for each one and adding the sources // and headers it generates to our bookkeeping maps. UnflavoredBuildTarget unflavoredBuildTarget = params.getBuildTarget().getUnflavoredBuildTarget(); for (ImmutableMap.Entry<String, SourcePath> ent : lexSrcs.entrySet()) { final String name = ent.getKey(); final SourcePath source = ent.getValue(); BuildTarget target = createLexBuildTarget(unflavoredBuildTarget, name); Path outputSource = getLexSourceOutputPath(unflavoredBuildTarget, name); Path outputHeader = getLexHeaderOutputPath(unflavoredBuildTarget, name); // Create the build rule to run lex on this source and add it to the resolver. Lex lex = new Lex( params.copyWithChanges( target, Suppliers.ofInstance( ImmutableSortedSet.copyOf( pathResolver.filterBuildRuleInputs(ImmutableList.of(source)))), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), pathResolver, cxxPlatform.getLex().get(), ImmutableList.<String>builder() .addAll(cxxPlatform.getLexFlags()) .addAll(lexFlags) .build(), outputSource, outputHeader, source); resolver.addToIndex(lex); // Record the output source and header as {@link BuildRuleSourcePath} objects. lexYaccCxxSourcesBuilder.put( name + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath(lex.getBuildTarget(), outputSource), ImmutableList.<String>of())); lexYaccHeadersBuilder.put( params.getBuildTarget().getBasePath().resolve(name + ".h"), new BuildTargetSourcePath(lex.getBuildTarget(), outputHeader)); } // Loop over all yaccc sources, generating build rule for each one and adding the sources // and headers it generates to our bookkeeping maps. for (ImmutableMap.Entry<String, SourcePath> ent : yaccSrcs.entrySet()) { final String name = ent.getKey(); final SourcePath source = ent.getValue(); BuildTarget target = createYaccBuildTarget(unflavoredBuildTarget, name); Path outputPrefix = getYaccOutputPrefix(unflavoredBuildTarget, Files.getNameWithoutExtension(name)); // Create the build rule to run yacc on this source and add it to the resolver. Yacc yacc = new Yacc( params.copyWithChanges( target, Suppliers.ofInstance( ImmutableSortedSet.copyOf( pathResolver.filterBuildRuleInputs(ImmutableList.of(source)))), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), pathResolver, cxxPlatform.getYacc().get(), ImmutableList.<String>builder() .addAll(cxxPlatform.getYaccFlags()) .addAll(yaccFlags) .build(), outputPrefix, source); resolver.addToIndex(yacc); // Record the output source and header as {@link BuildRuleSourcePath} objects. lexYaccCxxSourcesBuilder.put( name + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath( yacc.getBuildTarget(), Yacc.getSourceOutputPath(outputPrefix)), ImmutableList.<String>of())); lexYaccHeadersBuilder.put( params.getBuildTarget().getBasePath().resolve(name + ".h"), new BuildTargetSourcePath(yacc.getBuildTarget(), Yacc.getHeaderOutputPath(outputPrefix))); } return CxxHeaderSourceSpec.of(lexYaccHeadersBuilder.build(), lexYaccCxxSourcesBuilder.build()); }
@Test public void createThriftCompilerBuildRulesHasCorrectDeps() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); String language = "fake"; Flavor flavor = ImmutableFlavor.of("fake"); ImmutableSet<String> options = ImmutableSet.of(); // Setup the default values returned by the language specific enhancer. BuildTarget unflavoredTarget = BuildTargetFactory.newInstance("//:thrift"); BuildRuleParams unflavoredParams = new FakeBuildRuleParamsBuilder(BuildTarget.builder(unflavoredTarget).build()) .setProjectFilesystem(filesystem) .build(); // Setup a thrift source file generated by a genrule. BuildTarget flavoredTarget = BuildTargets.createFlavoredBuildTarget(unflavoredTarget.checkUnflavored(), flavor); BuildRuleParams flavoredParams = new FakeBuildRuleParamsBuilder(flavoredTarget).setProjectFilesystem(filesystem).build(); // Create a path for the thrift compiler. Path thriftPath = Paths.get("thrift_path"); filesystem.touch(thriftPath); // Setup an thrift buck config, with the path to the thrift compiler set. FakeBuckConfig buckConfig = new FakeBuckConfig( ImmutableMap.of("thrift", ImmutableMap.of("compiler", thriftPath.toString())), filesystem); ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig); ThriftLibraryDescription desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Setup a simple thrift source. String sourceName = "test.thrift"; SourcePath sourcePath = new TestSourcePath(sourceName); // Generate these rules using no deps. ImmutableMap<String, ThriftCompiler> rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule had no associated deps. assertSame(rules.size(), 1); ThriftCompiler rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(), rule.getDeps()); // Lets do this again, but pass in a ThriftLibrary deps, wrapping some includes we need. Path includeRoot = desc.getIncludeRoot(unflavoredTarget); HeaderSymlinkTree thriftIncludeSymlinkTree = createFakeSymlinkTree( desc.createThriftIncludeSymlinkTreeTarget(unflavoredTarget), pathResolver, includeRoot); ThriftLibrary lib = new ThriftLibrary( unflavoredParams, pathResolver, ImmutableSortedSet.<ThriftLibrary>of(), thriftIncludeSymlinkTree, ImmutableMap.<Path, SourcePath>of()); // Generate these rules using no deps. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.of(lib)); // Now verify that the generated rule has all the deps from the passed in thrift library. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(thriftIncludeSymlinkTree), rule.getDeps()); // Setup a simple genrule that creates the thrift source and verify its dep is propagated. Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule")) .setOut(sourceName) .build(resolver); SourcePath ruleSourcePath = new BuildTargetSourcePath(genrule.getBuildTarget()); // Generate these rules using no deps and the genrule generated source. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, ruleSourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule had no associated deps. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(genrule), rule.getDeps()); // Create a build rule that represents the thrift rule. FakeBuildRule thriftRule = createFakeBuildRule("//thrift:target", pathResolver); resolver.addToIndex(thriftRule); filesystem.mkdirs(thriftRule.getBuildTarget().getBasePath()); filesystem.touch(thriftRule.getBuildTarget().getBasePath().resolve("BUCK")); // Setup an empty thrift buck config, and set compiler target. buckConfig = new FakeBuckConfig( ImmutableMap.of( "thrift", ImmutableMap.of("compiler", thriftRule.getBuildTarget().toString())), filesystem); thriftBuckConfig = new ThriftBuckConfig(buckConfig); desc = new ThriftLibraryDescription( thriftBuckConfig, ImmutableList.<ThriftLanguageSpecificEnhancer>of()); // Generate these rules using no deps with a compiler target. rules = desc.createThriftCompilerBuildRules( flavoredParams, resolver, ThriftLibraryDescription.CompilerType.THRIFT, ImmutableList.<String>of(), language, options, ImmutableMap.of(sourceName, sourcePath), ImmutableSortedSet.<ThriftLibrary>of()); // Now verify that the generated rule only has deps from the compiler target. assertSame(rules.size(), 1); rule = rules.get(sourceName); assertNotNull(rule); assertEquals(ImmutableSortedSet.<BuildRule>of(thriftRule), rule.getDeps()); }
/** * Creates/finds the set of build rules that correspond to pre-dex'd artifacts that should be * merged to create the final classes.dex for the APK. * * <p>This method may modify {@code ruleResolver}, inserting new rules into its index. */ @VisibleForTesting PreDexMerge createPreDexMergeRule( AaptPackageResources aaptPackageResources, Iterable<DexProducedFromJavaLibrary> preDexRulesNotInThePackageableCollection, AndroidPackageableCollection packageableCollection) { ImmutableSortedSet.Builder<JavaLibrary> javaLibraryDepsBuilder = ImmutableSortedSet.naturalOrder(); ImmutableSet.Builder<DexProducedFromJavaLibrary> preDexDeps = ImmutableSet.builder(); preDexDeps.addAll(preDexRulesNotInThePackageableCollection); for (BuildTarget buildTarget : packageableCollection.getJavaLibrariesToDex()) { Preconditions.checkState( !buildTargetsToExcludeFromDex.contains(buildTarget), "JavaLibrary should have been excluded from target to dex: %s", buildTarget); BuildRule libraryRule = ruleResolver.getRule(buildTarget); // Skip uber R.java since AaptPackageResources takes care of dexing. if (libraryRule.equals(aaptPackageResources)) { continue; } Preconditions.checkState(libraryRule instanceof JavaLibrary); JavaLibrary javaLibrary = (JavaLibrary) libraryRule; // If the rule has no output file (which happens when a java_library has no srcs or // resources, but export_deps is true), then there will not be anything to dx. if (javaLibrary.getPathToOutput() == null) { continue; } // Take note of the rule so we add it to the enhanced deps. javaLibraryDepsBuilder.add(javaLibrary); // See whether the corresponding IntermediateDexRule has already been added to the // ruleResolver. BuildTarget originalTarget = javaLibrary.getBuildTarget(); BuildTarget preDexTarget = BuildTarget.builder(originalTarget).addFlavors(DEX_FLAVOR).build(); Optional<BuildRule> preDexRule = ruleResolver.getRuleOptional(preDexTarget); if (preDexRule.isPresent()) { preDexDeps.add((DexProducedFromJavaLibrary) preDexRule.get()); continue; } // Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps. BuildRuleParams paramsForPreDex = buildRuleParams.copyWithChanges( preDexTarget, Suppliers.ofInstance( ImmutableSortedSet.of(ruleResolver.getRule(javaLibrary.getBuildTarget()))), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); DexProducedFromJavaLibrary preDex = new DexProducedFromJavaLibrary(paramsForPreDex, pathResolver, javaLibrary); ruleResolver.addToIndex(preDex); preDexDeps.add(preDex); } ImmutableSet<DexProducedFromJavaLibrary> allPreDexDeps = preDexDeps.build(); BuildRuleParams paramsForPreDexMerge = buildRuleParams.copyWithChanges( createBuildTargetWithFlavor(DEX_MERGE_FLAVOR), Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(getDexMergeDeps(aaptPackageResources, allPreDexDeps)) .addAll(javaLibraryDepsBuilder.build()) .build()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); PreDexMerge preDexMerge = new PreDexMerge( paramsForPreDexMerge, pathResolver, primaryDexPath, dexSplitMode, allPreDexDeps, aaptPackageResources, dxExecutorService, xzCompressionLevel); ruleResolver.addToIndex(preDexMerge); return preDexMerge; }
@Override public <A extends Args> BuildRule createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) { SourcePathResolver pathResolver = new SourcePathResolver(resolver); ImmutableMap<String, SourcePath> nativeLibraries = JavaLibraryRules.getNativeLibraries(targetGraph, params.getDeps(), cxxPlatform); BuildRuleParams binaryParams = params; // If we're packaging native libraries, we'll build the binary JAR in a separate rule and // package it into the final fat JAR, so adjust it's params to use a flavored target. if (!nativeLibraries.isEmpty()) { binaryParams = params.copyWithChanges( BuildTarget.builder(params.getBuildTarget()) .addFlavors(FAT_JAR_INNER_JAR_FLAVOR) .build(), params.getDeclaredDeps(), params.getExtraDeps()); } // Construct the build rule to build the binary JAR. ImmutableSetMultimap<JavaLibrary, Path> transitiveClasspathEntries = Classpaths.getClasspathEntries(binaryParams.getDeps()); BuildRule rule = new JavaBinary( binaryParams.appendExtraDeps(transitiveClasspathEntries.keys()), pathResolver, args.mainClass.orNull(), args.manifestFile.orNull(), args.mergeManifests.or(true), args.metaInfDirectory.orNull(), args.blacklist.or(ImmutableSortedSet.<String>of()), new DefaultDirectoryTraverser(), transitiveClasspathEntries, javaBinOverride); // If we're packaging native libraries, construct the rule to build the fat JAR, which packages // up the original binary JAR and any required native libraries. if (!nativeLibraries.isEmpty()) { BuildRule innerJarRule = rule; resolver.addToIndex(innerJarRule); SourcePath innerJar = new BuildTargetSourcePath(innerJarRule.getBuildTarget()); rule = new JarFattener( params.appendExtraDeps( Suppliers.<Iterable<BuildRule>>ofInstance( pathResolver.filterBuildRuleInputs( ImmutableList.<SourcePath>builder() .add(innerJar) .addAll(nativeLibraries.values()) .build()))), pathResolver, javacOptions, innerJar, nativeLibraries, javaBinOverride); } return rule; }
private void generateSingleMLBytecodeCompilation( Map<Path, ImmutableSortedSet<BuildRule>> sourceToRule, ImmutableList.Builder<SourcePath> cmoFiles, Path mlSource, ImmutableMap<Path, ImmutableList<Path>> sources, ImmutableList<Path> cycleDetector) { ImmutableList<Path> newCycleDetector = ImmutableList.<Path>builder().addAll(cycleDetector).add(mlSource).build(); if (cycleDetector.contains(mlSource)) { throw new HumanReadableException( "Dependency cycle detected: %s", Joiner.on(" -> ").join(newCycleDetector)); } if (sourceToRule.containsKey(mlSource)) { return; } ImmutableSortedSet.Builder<BuildRule> depsBuilder = ImmutableSortedSet.naturalOrder(); if (sources.containsKey(mlSource)) { for (Path dep : checkNotNull(sources.get(mlSource))) { generateSingleMLBytecodeCompilation(sourceToRule, cmoFiles, dep, sources, newCycleDetector); depsBuilder.addAll(checkNotNull(sourceToRule.get(dep))); } } ImmutableSortedSet<BuildRule> deps = depsBuilder.build(); String name = mlSource.toFile().getName(); BuildTarget buildTarget = createMLBytecodeCompileBuildTarget(params.getBuildTarget(), name); BuildRuleParams compileParams = params.copyWithChanges( buildTarget, Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(params.getDeclaredDeps().get()) .addAll(deps) .addAll(ocamlContext.getBytecodeCompileDeps()) .build()), params.getExtraDeps()); String outputFileName = getMLBytecodeOutputName(name); Path outputPath = ocamlContext.getCompileBytecodeOutputDir().resolve(outputFileName); final ImmutableList<String> compileFlags = getCompileFlags(/* isBytecode */ true, /* excludeDeps */ false); BuildRule compileBytecode = new OCamlMLCompile( compileParams, pathResolver, new OCamlMLCompileStep.Args( cCompiler.getEnvironment(pathResolver), cCompiler.getCommandPrefix(pathResolver), ocamlContext.getOcamlBytecodeCompiler().get(), outputPath, mlSource, compileFlags)); resolver.addToIndex(compileBytecode); sourceToRule.put( mlSource, ImmutableSortedSet.<BuildRule>naturalOrder().add(compileBytecode).addAll(deps).build()); if (!outputFileName.endsWith(OCamlCompilables.OCAML_CMI)) { cmoFiles.add(new BuildTargetSourcePath(compileBytecode.getBuildTarget())); } }
/** * Creates a rooted DAG of build rules: * * <ul> * <li>{@code unzip_aar} depends on the deps specified to the original {@code android_aar} * <li>{@code prebuilt_jar} depends on {@code unzip_aar} * <li>{@code android_resource} depends on {@code unzip_aar} * <li>{@code android_library} depends on {@code android_resource}, {@code prebuilt_jar}, and * {@code unzip_aar} * </ul> * * Therefore, the return value is an {link AndroidLibrary} with no {@code srcs}. */ static BuildRule enhance( BuildRuleParams originalBuildRuleParams, SourcePath aarFile, BuildRuleResolver ruleResolver) { // unzip_aar BuildTarget originalBuildTarget = originalBuildRuleParams.getBuildTarget(); BuildRuleParams unzipAarParams = originalBuildRuleParams.copyWithChanges( UNZIP_AAR_TYPE, BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_UNZIP_FLAVOR), originalBuildRuleParams.getDeclaredDeps(), originalBuildRuleParams.getExtraDeps()); UnzipAar unzipAar = new UnzipAar(unzipAarParams, aarFile); ruleResolver.addToIndex(unzipAar); // unzip_aar#aar_classes_jar BuildRuleParams classesJarParams = originalBuildRuleParams.copyWithChanges( OutputOnlyBuildRule.TYPE, BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_CLASSES_JAR_FLAVOR), /* declaredDeps */ ImmutableSortedSet.<BuildRule>of(unzipAar), /* extraDeps */ ImmutableSortedSet.<BuildRule>of()); OutputOnlyBuildRule classesJar = new OutputOnlyBuildRule(classesJarParams, unzipAar.getPathToClassesJar()); ruleResolver.addToIndex(classesJar); // prebuilt_jar BuildRuleParams prebuiltJarParams = originalBuildRuleParams.copyWithChanges( PrebuiltJarDescription.TYPE, BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_PREBUILT_JAR_FLAVOR), /* declaredDeps */ ImmutableSortedSet.<BuildRule>of(unzipAar), /* extraDeps */ ImmutableSortedSet.<BuildRule>of()); PrebuiltJar prebuiltJar = new PrebuiltJar( /* params */ prebuiltJarParams, new BuildRuleSourcePath(classesJar), /* sourceJar */ Optional.<SourcePath>absent(), /* gwtJar */ Optional.<SourcePath>absent(), /* javadocUrl */ Optional.<String>absent()); ruleResolver.addToIndex(prebuiltJar); // unzip_aar#aar_manifest BuildRuleParams manifestParams = originalBuildRuleParams.copyWithChanges( OutputOnlyBuildRule.TYPE, BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_MANIFEST), /* declaredDeps */ ImmutableSortedSet.<BuildRule>of(unzipAar), /* extraDeps */ ImmutableSortedSet.<BuildRule>of()); OutputOnlyBuildRule manifest = new OutputOnlyBuildRule(manifestParams, unzipAar.getAndroidManifest()); ruleResolver.addToIndex(manifest); // android_resource BuildRuleParams androidResourceParams = originalBuildRuleParams.copyWithChanges( AndroidResourceDescription.TYPE, BuildTargets.createFlavoredBuildTarget( originalBuildTarget, AAR_ANDROID_RESOURCE_FLAVOR), /* declaredDeps */ ImmutableSortedSet.<BuildRule>of(manifest), /* extraDeps */ ImmutableSortedSet.<BuildRule>of()); // Because all resources and assets are generated files, we specify them as empty collections. ImmutableSortedSet<Path> resSrcs = ImmutableSortedSet.of(); ImmutableSortedSet<Path> assetsSrcs = ImmutableSortedSet.of(); AndroidResource androidResource = new AndroidResource( androidResourceParams, /* deps */ ImmutableSortedSet.<BuildRule>of(unzipAar), unzipAar.getResDirectory(), resSrcs, /* rDotJavaPackage */ null, /* assets */ unzipAar.getAssetsDirectory(), assetsSrcs, new BuildRuleSourcePath(manifest), /* hasWhitelistedStrings */ false); ruleResolver.addToIndex(androidResource); // android_library BuildRuleParams androidLibraryParams = originalBuildRuleParams.copyWithChanges( AndroidLibraryDescription.TYPE, BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ANDROID_LIBRARY_FLAVOR), /* declaredDeps */ ImmutableSortedSet.<BuildRule>of( androidResource, prebuiltJar, unzipAar), /* extraDeps */ ImmutableSortedSet.<BuildRule>of()); return new AndroidLibrary( androidLibraryParams, /* srcs */ ImmutableSortedSet.<SourcePath>of(), /* resources */ ImmutableSortedSet.<SourcePath>of(), Optional.of(unzipAar.getProguardConfig()), /* postprocessClassesCommands */ ImmutableList.<String>of(), /* exportedDeps */ ImmutableSortedSet.<BuildRule>of(prebuiltJar), /* providedDeps */ ImmutableSortedSet.<BuildRule>of(), /* additionalClasspathEntries */ ImmutableSet.<Path>of(), /* javacOptions */ JavacOptions.DEFAULTS, /* resourcesRoot */ Optional.<Path>absent(), /* manifestFile */ Optional.<SourcePath>absent(), /* isPrebuiltAar */ true); }
/** * If the user specified any android_build_config() rules, then we must add some build rules to * generate the production {@code BuildConfig.class} files and ensure that they are included in * the list of {@link AndroidPackageableCollection#getClasspathEntriesToDex}. */ private void addBuildConfigDeps( boolean shouldPreDex, AndroidPackageableCollection packageableCollection, ImmutableSortedSet.Builder<BuildRule> enhancedDeps, ImmutableList.Builder<DexProducedFromJavaLibrary> preDexRules, ImmutableList.Builder<Path> buildConfigJarFilesBuilder) { BuildConfigFields buildConfigConstants = BuildConfigFields.fromFields( ImmutableList.<BuildConfigFields.Field>of( BuildConfigFields.Field.of( "boolean", BuildConfigs.DEBUG_CONSTANT, String.valueOf(packageType != AndroidBinary.PackageType.RELEASE)), BuildConfigFields.Field.of( "boolean", BuildConfigs.IS_EXO_CONSTANT, String.valueOf(!exopackageModes.isEmpty())), BuildConfigFields.Field.of( "int", BuildConfigs.EXOPACKAGE_FLAGS, String.valueOf(ExopackageMode.toBitmask(exopackageModes))))); for (Map.Entry<String, BuildConfigFields> entry : packageableCollection.getBuildConfigs().entrySet()) { // Merge the user-defined constants with the APK-specific overrides. BuildConfigFields totalBuildConfigValues = BuildConfigFields.empty() .putAll(entry.getValue()) .putAll(buildConfigValues) .putAll(buildConfigConstants); // Each enhanced dep needs a unique build target, so we parameterize the build target by the // Java package. String javaPackage = entry.getKey(); Flavor flavor = ImmutableFlavor.of("buildconfig_" + javaPackage.replace('.', '_')); BuildRuleParams buildConfigParams = new BuildRuleParams( createBuildTargetWithFlavor(flavor), /* declaredDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()), buildRuleParams.getProjectFilesystem(), buildRuleParams.getRuleKeyBuilderFactory()); JavaLibrary buildConfigJavaLibrary = AndroidBuildConfigDescription.createBuildRule( buildConfigParams, javaPackage, totalBuildConfigValues, buildConfigValuesFile, /* useConstantExpressions */ true, javacOptions, ruleResolver); ruleResolver.addToIndex(buildConfigJavaLibrary); enhancedDeps.add(buildConfigJavaLibrary); Path buildConfigJar = buildConfigJavaLibrary.getPathToOutput(); Preconditions.checkNotNull( buildConfigJar, "%s must have an output file.", buildConfigJavaLibrary); buildConfigJarFilesBuilder.add(buildConfigJar); if (shouldPreDex) { DexProducedFromJavaLibrary buildConfigDex = new DexProducedFromJavaLibrary( buildConfigParams.copyWithChanges( createBuildTargetWithFlavor(ImmutableFlavor.of("dex_" + flavor.getName())), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(buildConfigJavaLibrary)), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), pathResolver, buildConfigJavaLibrary); ruleResolver.addToIndex(buildConfigDex); enhancedDeps.add(buildConfigDex); preDexRules.add(buildConfigDex); } } }
public static CxxLinkAndCompileRules createBuildRulesForCxxBinary( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, CxxPlatform cxxPlatform, ImmutableMap<String, CxxSource> srcs, ImmutableMap<Path, SourcePath> headers, ImmutableMap<String, SourcePath> lexSrcs, ImmutableMap<String, SourcePath> yaccSrcs, CxxPreprocessMode preprocessMode, Linker.LinkableDepType linkStyle, Optional<ImmutableList<String>> preprocessorFlags, Optional<PatternMatchedCollection<ImmutableList<String>>> platformPreprocessorFlags, Optional<ImmutableMap<CxxSource.Type, ImmutableList<String>>> langPreprocessorFlags, Optional<ImmutableSortedSet<FrameworkPath>> frameworks, Optional<ImmutableList<String>> compilerFlags, Optional<PatternMatchedCollection<ImmutableList<String>>> platformCompilerFlags, Optional<SourcePath> prefixHeader, Optional<ImmutableList<String>> linkerFlags, Optional<PatternMatchedCollection<ImmutableList<String>>> platformLinkerFlags, Optional<Linker.CxxRuntimeType> cxxRuntimeType) { SourcePathResolver sourcePathResolver = new SourcePathResolver(resolver); Path linkOutput = getLinkOutputPath(params.getBuildTarget()); ImmutableList.Builder<Arg> argsBuilder = ImmutableList.builder(); CommandTool.Builder executableBuilder = new CommandTool.Builder(); // Setup the rules to run lex/yacc. CxxHeaderSourceSpec lexYaccSources = requireLexYaccSources(params, resolver, sourcePathResolver, cxxPlatform, lexSrcs, yaccSrcs); // Setup the header symlink tree and combine all the preprocessor input from this rule // and all dependencies. HeaderSymlinkTree headerSymlinkTree = requireHeaderSymlinkTree( params, resolver, sourcePathResolver, cxxPlatform, /* includeLexYaccHeaders */ true, lexSrcs, yaccSrcs, headers, HeaderVisibility.PRIVATE); ImmutableList<CxxPreprocessorInput> cxxPreprocessorInput = collectCxxPreprocessorInput( targetGraph, params, cxxPlatform, CxxFlags.getLanguageFlags( preprocessorFlags, platformPreprocessorFlags, langPreprocessorFlags, cxxPlatform), ImmutableList.of(headerSymlinkTree), getFrameworkSearchPaths(frameworks, cxxPlatform, new SourcePathResolver(resolver)), CxxPreprocessables.getTransitiveCxxPreprocessorInput( targetGraph, cxxPlatform, FluentIterable.from(params.getDeps()) .filter(Predicates.instanceOf(CxxPreprocessorDep.class)))); // The complete list of input sources. ImmutableMap<String, CxxSource> sources = ImmutableMap.<String, CxxSource>builder() .putAll(srcs) .putAll(lexYaccSources.getCxxSources()) .build(); // Generate and add all the build rules to preprocess and compile the source to the // resolver and get the `SourcePath`s representing the generated object files. ImmutableMap<CxxPreprocessAndCompile, SourcePath> objects = CxxSourceRuleFactory.requirePreprocessAndCompileRules( params, resolver, sourcePathResolver, cxxPlatform, cxxPreprocessorInput, CxxFlags.getFlags(compilerFlags, platformCompilerFlags, cxxPlatform), prefixHeader, preprocessMode, sources, linkStyle == Linker.LinkableDepType.STATIC ? CxxSourceRuleFactory.PicType.PDC : CxxSourceRuleFactory.PicType.PIC); // Build up the linker flags, which support macro expansion. ImmutableList<String> resolvedLinkerFlags = CxxFlags.getFlags(linkerFlags, platformLinkerFlags, cxxPlatform); argsBuilder.addAll( FluentIterable.from(resolvedLinkerFlags) .transform( MacroArg.toMacroArgFunction( MACRO_HANDLER, params.getBuildTarget(), params.getCellRoots(), resolver, params.getProjectFilesystem()))); // Special handling for dynamically linked binaries. if (linkStyle == Linker.LinkableDepType.SHARED) { // Create a symlink tree with for all shared libraries needed by this binary. SymlinkTree sharedLibraries = resolver.addToIndex( createSharedLibrarySymlinkTree( targetGraph, params, sourcePathResolver, cxxPlatform, Predicates.instanceOf(NativeLinkable.class))); // Embed a origin-relative library path into the binary so it can find the shared libraries. argsBuilder.addAll( StringArg.from( Linkers.iXlinker( "-rpath", String.format( "%s/%s", cxxPlatform.getLd().origin(), linkOutput.getParent().relativize(sharedLibraries.getRoot()).toString())))); // Add all the shared libraries and the symlink tree as inputs to the tool that represents // this binary, so that users can attach the proper deps. executableBuilder.addDep(sharedLibraries); executableBuilder.addInputs(sharedLibraries.getLinks().values()); } // Add object files into the args. argsBuilder.addAll(SourcePathArg.from(sourcePathResolver, objects.values())); // Generate the final link rule. We use the top-level target as the link rule's // target, so that it corresponds to the actual binary we build. CxxLink cxxLink = CxxLinkableEnhancer.createCxxLinkableBuildRule( targetGraph, cxxPlatform, params, sourcePathResolver, createCxxLinkTarget(params.getBuildTarget()), Linker.LinkType.EXECUTABLE, Optional.<String>absent(), linkOutput, argsBuilder.build(), linkStyle, params.getDeps(), cxxRuntimeType, Optional.<SourcePath>absent(), ImmutableSet.<BuildTarget>of()); resolver.addToIndex(cxxLink); // Add the output of the link as the lone argument needed to invoke this binary as a tool. executableBuilder.addArg(new BuildTargetSourcePath(cxxLink.getBuildTarget())); return new CxxLinkAndCompileRules( cxxLink, ImmutableSortedSet.copyOf(objects.keySet()), executableBuilder.build()); }
@Override public <A extends Arg> BuildRule createBuildRule( TargetGraph targetGraph, BuildRuleParams originalBuildRuleParams, BuildRuleResolver resolver, A args) { UnflavoredBuildTarget originalBuildTarget = originalBuildRuleParams.getBuildTarget().checkUnflavored(); SourcePathResolver pathResolver = new SourcePathResolver(resolver); ImmutableList.Builder<BuildRule> aarExtraDepsBuilder = ImmutableList.<BuildRule>builder().addAll(originalBuildRuleParams.getExtraDeps().get()); /* android_manifest */ AndroidManifestDescription.Arg androidManifestArgs = androidManifestDescription.createUnpopulatedConstructorArg(); androidManifestArgs.skeleton = args.manifestSkeleton; androidManifestArgs.deps = args.deps; BuildRuleParams androidManifestParams = originalBuildRuleParams.copyWithChanges( BuildTargets.createFlavoredBuildTarget( originalBuildTarget, AAR_ANDROID_MANIFEST_FLAVOR), originalBuildRuleParams.getDeclaredDeps(), originalBuildRuleParams.getExtraDeps()); AndroidManifest manifest = androidManifestDescription.createBuildRule( targetGraph, androidManifestParams, resolver, androidManifestArgs); aarExtraDepsBuilder.add(resolver.addToIndex(manifest)); /* assemble dirs */ AndroidPackageableCollector collector = new AndroidPackageableCollector( originalBuildRuleParams.getBuildTarget(), /* buildTargetsToExcludeFromDex */ ImmutableSet.<BuildTarget>of(), /* resourcesToExclude */ ImmutableSet.<BuildTarget>of()); collector.addPackageables( AndroidPackageableCollector.getPackageableRules(originalBuildRuleParams.getDeps())); AndroidPackageableCollection packageableCollection = collector.build(); ImmutableSortedSet<BuildRule> androidResourceDeclaredDeps = AndroidResourceHelper.androidResOnly(originalBuildRuleParams.getDeclaredDeps().get()); ImmutableSortedSet<BuildRule> androidResourceExtraDeps = AndroidResourceHelper.androidResOnly(originalBuildRuleParams.getExtraDeps().get()); BuildRuleParams assembleAssetsParams = originalBuildRuleParams.copyWithChanges( BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ASSEMBLE_ASSETS_FLAVOR), Suppliers.ofInstance(androidResourceDeclaredDeps), Suppliers.ofInstance(androidResourceExtraDeps)); ImmutableCollection<SourcePath> assetsDirectories = packageableCollection.getAssetsDirectories(); AssembleDirectories assembleAssetsDirectories = new AssembleDirectories(assembleAssetsParams, pathResolver, assetsDirectories); aarExtraDepsBuilder.add(resolver.addToIndex(assembleAssetsDirectories)); BuildRuleParams assembleResourceParams = originalBuildRuleParams.copyWithChanges( BuildTargets.createFlavoredBuildTarget( originalBuildTarget, AAR_ASSEMBLE_RESOURCE_FLAVOR), Suppliers.ofInstance(androidResourceDeclaredDeps), Suppliers.ofInstance(androidResourceExtraDeps)); ImmutableCollection<SourcePath> resDirectories = packageableCollection.getResourceDetails().getResourceDirectories(); MergeAndroidResourceSources assembleResourceDirectories = new MergeAndroidResourceSources(assembleResourceParams, pathResolver, resDirectories); aarExtraDepsBuilder.add(resolver.addToIndex(assembleResourceDirectories)); /* android_resource */ BuildRuleParams androidResourceParams = originalBuildRuleParams.copyWithChanges( BuildTargets.createFlavoredBuildTarget( originalBuildTarget, AAR_ANDROID_RESOURCE_FLAVOR), Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>of( manifest, assembleAssetsDirectories, assembleResourceDirectories)), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); AndroidResource androidResource = new AndroidResource( androidResourceParams, pathResolver, /* deps */ ImmutableSortedSet.<BuildRule>naturalOrder() .add(assembleAssetsDirectories) .add(assembleResourceDirectories) .addAll(originalBuildRuleParams.getDeclaredDeps().get()) .build(), new BuildTargetSourcePath(assembleResourceDirectories.getBuildTarget()), /* resSrcs */ ImmutableSortedSet.<SourcePath>of(), Optional.<SourcePath>absent(), /* rDotJavaPackage */ null, new BuildTargetSourcePath(assembleAssetsDirectories.getBuildTarget()), /* assetsSrcs */ ImmutableSortedSet.<SourcePath>of(), Optional.<SourcePath>absent(), new BuildTargetSourcePath(manifest.getBuildTarget()), /* hasWhitelistedStrings */ false); aarExtraDepsBuilder.add(resolver.addToIndex(androidResource)); /* native_libraries */ AndroidNativeLibsPackageableGraphEnhancer packageableGraphEnhancer = new AndroidNativeLibsPackageableGraphEnhancer( resolver, originalBuildRuleParams, nativePlatforms, ImmutableSet.<NdkCxxPlatforms.TargetCpuType>of()); Optional<CopyNativeLibraries> nativeLibrariesOptional = packageableGraphEnhancer.getCopyNativeLibraries(targetGraph, packageableCollection); if (nativeLibrariesOptional.isPresent()) { aarExtraDepsBuilder.add(resolver.addToIndex(nativeLibrariesOptional.get())); } Optional<Path> assembledNativeLibsDir = nativeLibrariesOptional.transform( new Function<CopyNativeLibraries, Path>() { @Override public Path apply(CopyNativeLibraries input) { return input.getPathToNativeLibsDir(); } }); BuildRuleParams androidAarParams = originalBuildRuleParams.copyWithExtraDeps( Suppliers.ofInstance(ImmutableSortedSet.copyOf(aarExtraDepsBuilder.build()))); return new AndroidAar( androidAarParams, pathResolver, manifest, androidResource, assembleResourceDirectories.getPathToOutput(), assembleAssetsDirectories.getPathToOutput(), assembledNativeLibsDir, packageableCollection.getNativeLibAssetsDirectories()); }
AndroidGraphEnhancementResult createAdditionalBuildables() { ImmutableSortedSet.Builder<BuildRule> enhancedDeps = ImmutableSortedSet.naturalOrder(); enhancedDeps.addAll(originalDeps); AndroidPackageableCollector collector = new AndroidPackageableCollector( originalBuildTarget, buildTargetsToExcludeFromDex, resourcesToExclude); collector.addPackageables(AndroidPackageableCollector.getPackageableRules(originalDeps)); AndroidPackageableCollection packageableCollection = collector.build(); AndroidPackageableCollection.ResourceDetails resourceDetails = packageableCollection.getResourceDetails(); ImmutableSortedSet<BuildRule> resourceRules = getTargetsAsRules(resourceDetails.getResourcesWithNonEmptyResDir()); FilteredResourcesProvider filteredResourcesProvider; boolean needsResourceFiltering = resourceFilter.isEnabled() || resourceCompressionMode.isStoreStringsAsAssets() || !locales.isEmpty(); if (needsResourceFiltering) { BuildRuleParams paramsForResourcesFilter = buildRuleParams.copyWithChanges( createBuildTargetWithFlavor(RESOURCES_FILTER_FLAVOR), Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(resourceRules) .addAll( pathResolver.filterBuildRuleInputs( resourceDetails.getResourceDirectories())) .build()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); ResourcesFilter resourcesFilter = new ResourcesFilter( paramsForResourcesFilter, pathResolver, resourceDetails.getResourceDirectories(), ImmutableSet.copyOf(resourceDetails.getWhitelistedStringDirectories()), locales, resourceCompressionMode, resourceFilter); ruleResolver.addToIndex(resourcesFilter); filteredResourcesProvider = resourcesFilter; enhancedDeps.add(resourcesFilter); resourceRules = ImmutableSortedSet.<BuildRule>of(resourcesFilter); } else { filteredResourcesProvider = new IdentityResourcesProvider( pathResolver.getAllPaths(resourceDetails.getResourceDirectories())); } // Create the AaptPackageResourcesBuildable. BuildTarget buildTargetForAapt = createBuildTargetWithFlavor(AAPT_PACKAGE_FLAVOR); BuildRuleParams paramsForAaptPackageResources = buildRuleParams.copyWithChanges( buildTargetForAapt, Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() // Add all deps with non-empty res dirs, since we at least need the R.txt file // (even if we're filtering). .addAll(getTargetsAsRules(resourceDetails.getResourcesWithNonEmptyResDir())) .addAll( pathResolver.filterBuildRuleInputs( resourceDetails.getResourceDirectories())) .addAll( getAdditionalAaptDeps(pathResolver, resourceRules, packageableCollection)) .build()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); AaptPackageResources aaptPackageResources = new AaptPackageResources( paramsForAaptPackageResources, pathResolver, manifest, filteredResourcesProvider, getTargetsAsResourceDeps(resourceDetails.getResourcesWithNonEmptyResDir()), packageableCollection.getAssetsDirectories(), packageType, javacOptions, shouldPreDex, shouldBuildStringSourceMap, locales.isEmpty(), skipCrunchPngs); ruleResolver.addToIndex(aaptPackageResources); enhancedDeps.add(aaptPackageResources); Optional<PackageStringAssets> packageStringAssets = Optional.absent(); if (resourceCompressionMode.isStoreStringsAsAssets()) { BuildTarget buildTargetForPackageStringAssets = createBuildTargetWithFlavor(PACKAGE_STRING_ASSETS_FLAVOR); BuildRuleParams paramsForPackageStringAssets = buildRuleParams.copyWithChanges( buildTargetForPackageStringAssets, Suppliers.ofInstance( ImmutableSortedSet.<BuildRule>naturalOrder() .add(aaptPackageResources) // Model the dependency on the presence of res directories, which, in the case // of resource filtering, is cached by the `ResourcesFilter` rule. .addAll( Iterables.filter( ImmutableList.of(filteredResourcesProvider), BuildRule.class)) .build()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); packageStringAssets = Optional.of( new PackageStringAssets( paramsForPackageStringAssets, pathResolver, locales, filteredResourcesProvider, aaptPackageResources)); ruleResolver.addToIndex(packageStringAssets.get()); enhancedDeps.add(packageStringAssets.get()); } // TODO(natthu): Try to avoid re-building the collection by passing UberRDotJava directly. if (packageableCollection.getResourceDetails().hasResources()) { collector.addClasspathEntry( aaptPackageResources, new BuildTargetSourcePath( aaptPackageResources.getBuildTarget(), aaptPackageResources.getPathToCompiledRDotJavaFiles())); } // BuildConfig deps should not be added for instrumented APKs because BuildConfig.class has // already been added to the APK under test. ImmutableList<DexProducedFromJavaLibrary> preDexBuildConfigs; ImmutableList<Path> buildConfigJarFiles; if (packageType == PackageType.INSTRUMENTED) { preDexBuildConfigs = ImmutableList.of(); buildConfigJarFiles = ImmutableList.of(); } else { ImmutableList.Builder<DexProducedFromJavaLibrary> preDexBuildConfigsBuilder = ImmutableList.builder(); ImmutableList.Builder<Path> buildConfigJarFilesBuilder = ImmutableList.builder(); addBuildConfigDeps( shouldPreDex, packageableCollection, enhancedDeps, preDexBuildConfigsBuilder, buildConfigJarFilesBuilder); preDexBuildConfigs = preDexBuildConfigsBuilder.build(); buildConfigJarFiles = buildConfigJarFilesBuilder.build(); } packageableCollection = collector.build(); Optional<PreDexMerge> preDexMerge = Optional.absent(); if (shouldPreDex) { preDexMerge = Optional.of( createPreDexMergeRule( aaptPackageResources, preDexBuildConfigs, packageableCollection)); enhancedDeps.add(preDexMerge.get()); } else { enhancedDeps.addAll(getTargetsAsRules(packageableCollection.getJavaLibrariesToDex())); } // Add dependencies on all the build rules generating third-party JARs. This is mainly to // correctly capture deps when a prebuilt_jar forwards the output from another build rule. enhancedDeps.addAll( pathResolver.filterBuildRuleInputs(packageableCollection.getPathsToThirdPartyJars())); Optional<CopyNativeLibraries> copyNativeLibraries = nativeLibsEnhancer.getCopyNativeLibraries(targetGraph, packageableCollection); if (copyNativeLibraries.isPresent()) { ruleResolver.addToIndex(copyNativeLibraries.get()); enhancedDeps.add(copyNativeLibraries.get()); } Optional<ComputeExopackageDepsAbi> computeExopackageDepsAbi = Optional.absent(); if (!exopackageModes.isEmpty()) { BuildRuleParams paramsForComputeExopackageAbi = buildRuleParams.copyWithChanges( createBuildTargetWithFlavor(CALCULATE_ABI_FLAVOR), Suppliers.ofInstance(enhancedDeps.build()), /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())); computeExopackageDepsAbi = Optional.of( new ComputeExopackageDepsAbi( paramsForComputeExopackageAbi, pathResolver, exopackageModes, packageableCollection, aaptPackageResources, copyNativeLibraries, packageStringAssets, preDexMerge, keystore)); ruleResolver.addToIndex(computeExopackageDepsAbi.get()); enhancedDeps.add(computeExopackageDepsAbi.get()); } return AndroidGraphEnhancementResult.builder() .setPackageableCollection(packageableCollection) .setAaptPackageResources(aaptPackageResources) .setCopyNativeLibraries(copyNativeLibraries) .setPackageStringAssets(packageStringAssets) .setPreDexMerge(preDexMerge) .setComputeExopackageDepsAbi(computeExopackageDepsAbi) .setClasspathEntriesToDex( ImmutableSet.<Path>builder() .addAll(pathResolver.getAllPaths(packageableCollection.getClasspathEntriesToDex())) .addAll(buildConfigJarFiles) .build()) .setFinalDeps(enhancedDeps.build()) .build(); }