@Test public void testThatBuildTargetSourcePathDepsAndPathsArePropagated() { BuildRuleResolver resolver = new BuildRuleResolver(); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = BuildRuleParamsFactory.createTrivialBuildRuleParams(target); // Create a couple of genrules to generate inputs for an archive rule. Genrule genrule1 = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule")) .setOut("foo/bar.o") .build(resolver); Genrule genrule2 = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule2")) .setOut("foo/test.o") .build(resolver); // Build the archive using a normal input the outputs of the genrules above. Archive archive = Archives.createArchiveRule( new SourcePathResolver(resolver), target, params, DEFAULT_ARCHIVER, DEFAULT_OUTPUT, ImmutableList.<SourcePath>of( new TestSourcePath("simple.o"), new BuildTargetSourcePath(genrule1.getBuildTarget()), new BuildTargetSourcePath(genrule2.getBuildTarget()))); // Verify that the archive dependencies include the genrules providing the // SourcePath inputs. assertEquals(ImmutableSortedSet.<BuildRule>of(genrule1, genrule2), archive.getDeps()); }
@Test public void testThatBuildTargetSourcePathDepsAndPathsArePropagated() throws Exception { BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); // Create a couple of genrules to generate inputs for an archive rule. Genrule genrule1 = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule")) .setOut("foo/bar.o") .build(resolver); Genrule genrule2 = (Genrule) GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule2")) .setOut("foo/test.o") .build(resolver); // Build the archive using a normal input the outputs of the genrules above. Archive archive = Archive.from( target, params, new SourcePathResolver(resolver), DEFAULT_ARCHIVER, ImmutableList.of(), DEFAULT_RANLIB, ImmutableList.of(), Archive.Contents.NORMAL, DEFAULT_OUTPUT, ImmutableList.of( new FakeSourcePath("simple.o"), new BuildTargetSourcePath(genrule1.getBuildTarget()), new BuildTargetSourcePath(genrule2.getBuildTarget()))); // Verify that the archive dependencies include the genrules providing the // SourcePath inputs. assertEquals(ImmutableSortedSet.<BuildRule>of(genrule1, genrule2), archive.getDeps()); }
@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); }
@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()); }
@Test public void createLexYaccBuildRules() throws IOException { BuildRuleResolver resolver = new BuildRuleResolver(); // Setup our C++ buck config with the paths to the lex/yacc binaries. FakeProjectFilesystem filesystem = new FakeProjectFilesystem(); Path lexPath = Paths.get("lex"); filesystem.touch(lexPath); Path yaccPath = Paths.get("yacc"); filesystem.touch(yaccPath); BuckConfig buckConfig = FakeBuckConfig.builder() .setSections( ImmutableMap.of( "cxx", ImmutableMap.of( "lex", lexPath.toString(), "yacc", yaccPath.toString()))) .setFilesystem(filesystem) .build(); CxxPlatform cxxBuckConfig = DefaultCxxPlatforms.build(new CxxBuckConfig(buckConfig)); // Setup the target name and build params. UnflavoredBuildTarget target = BuildTargetFactory.newInstance("//:test").getUnflavoredBuildTarget(); BuildRuleParams params = new FakeBuildRuleParamsBuilder(BuildTarget.of(target)).build(); // Setup a genrule that generates our lex source. String lexSourceName = "test.ll"; BuildTarget genruleTarget = BuildTargetFactory.newInstance("//:genrule_lex"); Genrule genrule = (Genrule) GenruleBuilder.newGenruleBuilder(genruleTarget).setOut(lexSourceName).build(resolver); SourcePath lexSource = new BuildTargetSourcePath(genrule.getBuildTarget()); // Use a regular path for our yacc source. String yaccSourceName = "test.yy"; SourcePath yaccSource = new TestSourcePath(yaccSourceName); // Build the rules. CxxHeaderSourceSpec actual = CxxDescriptionEnhancer.createLexYaccBuildRules( params, resolver, cxxBuckConfig, ImmutableList.<String>of(), ImmutableMap.of(lexSourceName, lexSource), ImmutableList.<String>of(), ImmutableMap.of(yaccSourceName, yaccSource)); // Grab the generated lex rule and verify it has the genrule as a dep. Lex lex = (Lex) resolver.getRule(CxxDescriptionEnhancer.createLexBuildTarget(target, lexSourceName)); assertNotNull(lex); assertEquals(ImmutableSortedSet.<BuildRule>of(genrule), lex.getDeps()); // Grab the generated yacc rule and verify it has no deps. Yacc yacc = (Yacc) resolver.getRule(CxxDescriptionEnhancer.createYaccBuildTarget(target, yaccSourceName)); assertNotNull(yacc); assertEquals(ImmutableSortedSet.<BuildRule>of(), yacc.getDeps()); // Check the header/source spec is correct. Path lexOutputSource = CxxDescriptionEnhancer.getLexSourceOutputPath(target, lexSourceName); Path lexOutputHeader = CxxDescriptionEnhancer.getLexHeaderOutputPath(target, lexSourceName); Path yaccOutputPrefix = CxxDescriptionEnhancer.getYaccOutputPrefix( target, Files.getNameWithoutExtension(yaccSourceName)); Path yaccOutputSource = Yacc.getSourceOutputPath(yaccOutputPrefix); Path yaccOutputHeader = Yacc.getHeaderOutputPath(yaccOutputPrefix); CxxHeaderSourceSpec expected = CxxHeaderSourceSpec.of( ImmutableMap.<Path, SourcePath>of( target.getBasePath().resolve(lexSourceName + ".h"), new BuildTargetSourcePath(lex.getBuildTarget(), lexOutputHeader), target.getBasePath().resolve(yaccSourceName + ".h"), new BuildTargetSourcePath(yacc.getBuildTarget(), yaccOutputHeader)), ImmutableMap.of( lexSourceName + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath(lex.getBuildTarget(), lexOutputSource), ImmutableList.<String>of()), yaccSourceName + ".cc", CxxSource.of( CxxSource.Type.CXX, new BuildTargetSourcePath(yacc.getBuildTarget(), yaccOutputSource), ImmutableList.<String>of()))); assertEquals(expected, actual); }