@Test public void testUberCompilationDatabase() throws IOException { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp); workspace.setUp(); BuildTarget target = BuildTargetFactory.newInstance("//:test#default,uber-compilation-database"); ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName()); Path rootPath = tmp.getRoot(); assertEquals( BuildTargets.getGenPath( filesystem, target, "uber-compilation-database-%s/compile_commands.json"), rootPath.relativize(compilationDatabase)); Path binaryHeaderSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR), "%s"); Path binaryExportedHeaderSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR), "%s"); Map<String, CxxCompilationDatabaseEntry> fileToEntry = CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase); assertEquals(1, fileToEntry.size()); assertHasEntry( fileToEntry, "test.cpp", new ImmutableList.Builder<String>() .add(COMPILER_PATH) .add("-fPIC") .add("-fPIC") .add("-I") .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString()) .add("-I") .add(headerSymlinkTreePath(binaryExportedHeaderSymlinkTreeFolder).toString()) .addAll(getExtraFlagsForHeaderMaps(filesystem)) .addAll(COMPILER_SPECIFIC_FLAGS) .add("-x") .add("c++") .add("-c") .add("-o") .add( BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), ImmutableFlavor.of("compile-pic-" + sanitize("test.cpp.o"))), "%s/test.cpp.o") .toString()) .add(rootPath.resolve(Paths.get("test.cpp")).toRealPath().toString()) .build()); }
@Test public void testInferCxxBinaryDepsCaching() throws IOException { assumeTrue(Platform.detect() != Platform.WINDOWS); ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp); workspace.enableDirCache(); // enable the cache CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new CxxBuckConfig(new FakeBuckConfig())); BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:binary_with_deps"); String inputBuildTargetName = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName(); /* * Build the given target and check that it succeeds. */ workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); /* * Check that building after clean will use the cache */ workspace.runBuckCommand("clean").assertSuccess(); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); BuckBuildLog buildLog = workspace.getBuildLog(); for (BuildTarget buildTarget : buildLog.getAllTargets()) { buildLog.assertTargetWasFetchedFromCache(buildTarget.toString()); } /* * Check that if the file in the binary target changes, then all the deps will be fetched * from the cache */ String sourceName = "src_with_deps.c"; workspace.replaceFileContents("foo/" + sourceName, "10", "30"); workspace.runBuckCommand("clean").assertSuccess(); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); buildLog = workspace.getBuildLog(); CxxSourceRuleFactory cxxSourceRuleFactory = CxxSourceRuleFactoryHelper.of(inputBuildTarget, cxxPlatform); BuildTarget captureBuildTarget = cxxSourceRuleFactory.createInferCaptureBuildTarget(sourceName); // this is flavored, and denotes the analysis step (generates a local report) BuildTarget inferAnalysisTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER_ANALYZE); // this is the flavored version of the top level target (the one give in input to buck) BuildTarget inferReportTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER); String bt; for (BuildTarget buildTarget : buildLog.getAllTargets()) { bt = buildTarget.toString(); if (bt.equals(inferAnalysisTarget.toString()) || bt.equals(captureBuildTarget.toString()) || bt.equals(inferReportTarget.toString())) { buildLog.assertTargetBuiltLocally(bt); } else { buildLog.assertTargetWasFetchedFromCache(buildTarget.toString()); } } }
@Test public void compilationDatabaseFetchedFromCacheAlsoFetchesSymlinkTreeOrHeaderMap() throws IOException { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp); workspace.setUp(); ProjectFilesystem filesystem = new FakeProjectFilesystem(); // This test only fails if the directory cache is enabled and we don't update // the header map/symlink tree correctly when fetching from the cache. workspace.enableDirCache(); addLibraryHeaderFiles(workspace); BuildTarget target = BuildTargetFactory.newInstance("//:library_with_header#default,compilation-database"); // Populate the cache with the built rule workspace.buildAndReturnOutput(target.getFullyQualifiedName()); Path headerSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR), "%s"); Path exportedHeaderSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR), "%s"); // Validate the symlink tree/header maps verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h"); verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h"); // Delete the newly-added files and build again Files.delete(workspace.getPath("baz.h")); Files.delete(workspace.getPath("blech_private.h")); workspace.buildAndReturnOutput(target.getFullyQualifiedName()); verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h"); verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h"); // Restore the headers, build again, and check the symlink tree/header maps addLibraryHeaderFiles(workspace); workspace.buildAndReturnOutput(target.getFullyQualifiedName()); verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h"); verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h"); }
@Test public void testInferCxxBinaryWithCachedDepsGetsAllItsTransitiveDeps() throws IOException { assumeTrue(Platform.detect() != Platform.WINDOWS); ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp); workspace.enableDirCache(); // enable the cache BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:binary_with_chain_deps"); String inputBuildTargetName = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName(); /* * Build the given target and check that it succeeds. */ workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); /* * Check that building after clean will use the cache */ workspace.runBuckCommand("clean").assertSuccess(); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); BuckBuildLog buildLog = workspace.getBuildLog(); for (BuildTarget buildTarget : buildLog.getAllTargets()) { buildLog.assertTargetWasFetchedFromCache(buildTarget.toString()); } /* * Check that if the file in the top target changes, then all the transitive deps will be * fetched from the cache (even those that are not direct dependencies). * Make sure there's the specs file of the dependency that has distance 2 from * the binary target. */ String sourceName = "top_chain.c"; workspace.replaceFileContents("foo/" + sourceName, "*p += 1", "*p += 10"); workspace.runBuckCommand("clean").assertSuccess(); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); // Check all the buildrules were fetched from the cache (and there's the specs file) assertTrue( "Expected specs file for func_ret_null() in chain_dep_two.c not found", workspace .getPath( "buck-out/gen/foo/infer-analysis-chain_dep_two#default,infer-analyze/specs/" + "mockedSpec.specs") .toFile() .exists()); }
@Test public void testInferCxxBinaryMergesAllReportsOfDependencies() throws IOException { assumeTrue(Platform.detect() != Platform.WINDOWS); ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp); BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:binary_with_chain_deps"); String inputBuildTargetName = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName(); /* * Build the given target and check that it succeeds. */ workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); String reportPath = "buck-out/gen/foo/infer-binary_with_chain_deps#infer/report.json"; List<Object> bugs = InferHelper.loadInferReport(workspace, reportPath); // check that the merge step has merged a total of 3 bugs, one for each target // (chain_dep_two, chain_dep_one, binary_with_chain_deps) Assert.assertThat( "3 bugs expected in " + reportPath + " not found", bugs.size(), Matchers.equalTo(3)); }
@Test public void testAppleLibraryIsHermetic() throws IOException { assumeTrue(Platform.detect() == Platform.MACOS); ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_is_hermetic", tmp); workspace.setUp(); ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath()); BuildTarget target = BuildTargetFactory.newInstance( "//Libraries/TestLibrary:TestLibrary#static,iphonesimulator-x86_64"); ProjectWorkspace.ProcessResult first = workspace.runBuckCommand( workspace.getPath("first"), "build", target.getFullyQualifiedName()); first.assertSuccess(); ProjectWorkspace.ProcessResult second = workspace.runBuckCommand( workspace.getPath("second"), "build", target.getFullyQualifiedName()); second.assertSuccess(); Path objectPath = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("compile-" + sanitize("TestClass.m.o")), ImmutableFlavor.of("iphonesimulator-x86_64")), "%s") .resolve("TestClass.m.o"); MoreAsserts.assertContentsEqual( workspace.getPath(Paths.get("first").resolve(objectPath)), workspace.getPath(Paths.get("second").resolve(objectPath))); Path libraryPath = BuildTargets.getGenPath(filesystem, target, "%s").resolve("libTestLibrary.a"); MoreAsserts.assertContentsEqual( workspace.getPath(Paths.get("first").resolve(libraryPath)), workspace.getPath(Paths.get("second").resolve(libraryPath))); }
@Test public void testInferCxxBinaryWithDeps() throws IOException { assumeTrue(Platform.detect() != Platform.WINDOWS); ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp); CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new CxxBuckConfig(new FakeBuckConfig())); BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:binary_with_deps"); String inputBuildTargetName = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName(); /* * Build the given target and check that it succeeds. */ workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); /* * Check that all the required build targets have been generated. */ String sourceName = "src_with_deps.c"; CxxSourceRuleFactory cxxSourceRuleFactory = CxxSourceRuleFactoryHelper.of(inputBuildTarget, cxxPlatform); // 1. create the targets of binary_with_deps // this is unflavored, but bounded to the InferCapture build rule BuildTarget topCaptureBuildTarget = cxxSourceRuleFactory.createInferCaptureBuildTarget(sourceName); // this is unflavored, but necessary to run the compiler successfully BuildTarget topHeaderSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( inputBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PRIVATE); // this is flavored, and denotes the analysis step (generates a local report) BuildTarget topInferAnalysisTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER_ANALYZE); // this is flavored and corresponds to the top level target (the one give in input to buck) BuildTarget topInferReportTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER); // 2. create the targets of dep_one BuildTarget depOneBuildTarget = BuildTargetFactory.newInstance("//foo:dep_one"); String depOneSourceName = "dep_one.c"; String depOneSourceFull = "foo/" + depOneSourceName; CxxSourceRuleFactory depOneSourceRuleFactory = CxxSourceRuleFactoryHelper.of(depOneBuildTarget, cxxPlatform); BuildTarget depOneCaptureBuildTarget = depOneSourceRuleFactory.createInferCaptureBuildTarget(depOneSourceName); BuildTarget depOneHeaderSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( depOneBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PRIVATE); BuildTarget depOneExportedHeaderSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( depOneBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PUBLIC); BuildTarget depOneInferAnalysisTarget = depOneCaptureBuildTarget.withFlavors( cxxPlatform.getFlavor(), CxxInferEnhancer.INFER_ANALYZE); // 3. create the targets of dep_two BuildTarget depTwoBuildTarget = BuildTargetFactory.newInstance("//foo:dep_two"); CxxSourceRuleFactory depTwoSourceRuleFactory = CxxSourceRuleFactoryHelper.of(depTwoBuildTarget, cxxPlatform); BuildTarget depTwoCaptureBuildTarget = depTwoSourceRuleFactory.createInferCaptureBuildTarget("dep_two.c"); BuildTarget depTwoHeaderSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( depTwoBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PRIVATE); BuildTarget depTwoExportedHeaderSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( depTwoBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PUBLIC); BuildTarget depTwoInferAnalysisTarget = depTwoCaptureBuildTarget.withFlavors( cxxPlatform.getFlavor(), CxxInferEnhancer.INFER_ANALYZE); // Check all the targets are in the buildLog assertEquals( ImmutableSet.of( topCaptureBuildTarget, topHeaderSymlinkTreeTarget, topInferAnalysisTarget, topInferReportTarget, depOneCaptureBuildTarget, depOneHeaderSymlinkTreeTarget, depOneExportedHeaderSymlinkTreeTarget, depOneInferAnalysisTarget, depTwoCaptureBuildTarget, depTwoHeaderSymlinkTreeTarget, depTwoExportedHeaderSymlinkTreeTarget, depTwoInferAnalysisTarget), workspace.getBuildLog().getAllTargets()); /* * Check that running a build again results in no builds since nothing has changed. */ workspace.resetBuildLogFile(); // clear for new build workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); BuckBuildLog buildLog = workspace.getBuildLog(); assertEquals(ImmutableSet.of(topInferReportTarget), buildLog.getAllTargets()); buildLog.assertTargetHadMatchingRuleKey(topInferReportTarget.toString()); /* * Check that if a library source file changes then the capture/analysis rules run again on * the main target and on dep_one only. */ workspace.resetBuildLogFile(); workspace.replaceFileContents(depOneSourceFull, "flag > 0", "flag < 0"); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); buildLog = workspace.getBuildLog(); assertEquals( ImmutableSet.of( topInferAnalysisTarget, // analysis runs again topInferReportTarget, // report runs again topCaptureBuildTarget, // cached depTwoInferAnalysisTarget, // cached depOneCaptureBuildTarget, // capture of the changed file runs again depOneExportedHeaderSymlinkTreeTarget, // cached depOneHeaderSymlinkTreeTarget, // cached depOneInferAnalysisTarget), // analysis of the library runs again buildLog.getAllTargets()); buildLog.assertTargetBuiltLocally(topInferAnalysisTarget.toString()); buildLog.assertTargetBuiltLocally(topInferReportTarget.toString()); buildLog.assertTargetHadMatchingRuleKey(topCaptureBuildTarget.toString()); buildLog.assertTargetHadMatchingRuleKey(depTwoInferAnalysisTarget.toString()); buildLog.assertTargetBuiltLocally(depOneCaptureBuildTarget.toString()); buildLog.assertTargetHadMatchingRuleKey(depOneExportedHeaderSymlinkTreeTarget.toString()); buildLog.assertTargetHadMatchingRuleKey(depOneHeaderSymlinkTreeTarget.toString()); buildLog.assertTargetBuiltLocally(depOneInferAnalysisTarget.toString()); }
@Test public void testInferCxxBinaryWithoutDeps() throws IOException { assumeTrue(Platform.detect() != Platform.WINDOWS); ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp); CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new CxxBuckConfig(new FakeBuckConfig())); BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:simple"); String inputBuildTargetName = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName(); /* * Build the given target and check that it succeeds. */ workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); /* * Check that all the required build targets have been generated. */ String sourceName = "simple.cpp"; String sourceFull = "foo/" + sourceName; CxxSourceRuleFactory cxxSourceRuleFactory = CxxSourceRuleFactoryHelper.of(inputBuildTarget, cxxPlatform); // this is unflavored, but bounded to the InferCapture build rule BuildTarget captureBuildTarget = cxxSourceRuleFactory.createInferCaptureBuildTarget(sourceName); // this is unflavored, but necessary to run the compiler successfully BuildTarget headerSymlinkTreeTarget = CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget( inputBuildTarget, cxxPlatform.getFlavor(), HeaderVisibility.PRIVATE); // this is flavored, and denotes the analysis step (generates a local report) BuildTarget inferAnalysisTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER_ANALYZE); // this is flavored and corresponds to the top level target (the one give in input to buck) BuildTarget inferReportTarget = inputBuildTarget.withFlavors(CxxInferEnhancer.INFER); ImmutableSet<BuildTarget> expectedTargets = ImmutableSet.<BuildTarget>builder() .addAll( ImmutableSet.of( headerSymlinkTreeTarget, captureBuildTarget, inferAnalysisTarget, inferReportTarget)) .build(); BuckBuildLog buildLog = workspace.getBuildLog(); assertEquals(expectedTargets, buildLog.getAllTargets()); buildLog.assertTargetBuiltLocally(headerSymlinkTreeTarget.toString()); buildLog.assertTargetBuiltLocally(captureBuildTarget.toString()); buildLog.assertTargetBuiltLocally(inferAnalysisTarget.toString()); buildLog.assertTargetBuiltLocally(inferReportTarget.toString()); /* * Check that running a build again results in no builds since nothing has changed. */ workspace.resetBuildLogFile(); // clear for new build workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); buildLog = workspace.getBuildLog(); assertEquals(ImmutableSet.of(inferReportTarget), buildLog.getAllTargets()); buildLog.assertTargetHadMatchingRuleKey(inferReportTarget.toString()); /* * Check that changing the source file results in running the capture/analysis rules again. */ workspace.resetBuildLogFile(); workspace.replaceFileContents(sourceFull, "*s = 42;", ""); workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess(); buildLog = workspace.getBuildLog(); assertEquals(expectedTargets, buildLog.getAllTargets()); buildLog.assertTargetBuiltLocally(captureBuildTarget.toString()); buildLog.assertTargetBuiltLocally(inferAnalysisTarget.toString()); buildLog.assertTargetHadMatchingRuleKey(headerSymlinkTreeTarget.toString()); }
@Test public void binaryWithDependenciesCompilationDatabase() throws IOException { BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_dep#compilation-database"); Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName()); ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path rootPath = tmp.getRoot(); assertEquals( BuildTargets.getGenPath(filesystem, target, "__%s.json"), rootPath.relativize(compilationDatabase)); Path binaryHeaderSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR), "%s"); assertTrue(Files.exists(rootPath.resolve(binaryHeaderSymlinkTreeFolder))); BuildTarget libraryTarget = BuildTargetFactory.newInstance("//:library_with_header"); Path libraryExportedHeaderSymlinkTreeFolder = BuildTargets.getGenPath( filesystem, libraryTarget.withFlavors( ImmutableFlavor.of("default"), CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR), "%s"); // Verify that symlink folders for headers are created and header file is linked. assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder))); assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder + "/bar.h"))); Map<String, CxxCompilationDatabaseEntry> fileToEntry = CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase); assertEquals(1, fileToEntry.size()); assertHasEntry( fileToEntry, "foo.cpp", new ImmutableList.Builder<String>() .add(COMPILER_PATH) .add("-I") .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString()) .add("-I") .add(headerSymlinkTreePath(libraryExportedHeaderSymlinkTreeFolder).toString()) .addAll(getExtraFlagsForHeaderMaps(filesystem)) .addAll(COMPILER_SPECIFIC_FLAGS) .add("-x") .add("c++") .add("-c") .add("-o") .add( BuildTargets.getGenPath( filesystem, target.withFlavors( ImmutableFlavor.of("default"), ImmutableFlavor.of("compile-" + sanitize("foo.cpp.o"))), "%s/foo.cpp.o") .toString()) .add(rootPath.resolve(Paths.get("foo.cpp")).toRealPath().toString()) .build()); }
@Test public void shouldBeAbleToConstructACxxLibraryFromThrift() throws Exception { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "cxx", tmp); workspace.setUp(); BuckEventBus eventBus = BuckEventBusFactory.newInstance(); ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath()); Path compiler = new ExecutableFinder() .getExecutable(Paths.get("echo"), ImmutableMap.copyOf(System.getenv())); BuckConfig config = FakeBuckConfig.builder() .setFilesystem(filesystem) .setSections( "[thrift]", "compiler = " + compiler, "compiler2 = " + compiler, "cpp_library = //thrift:fake", "cpp_reflection_library = //thrift:fake") .build(); TypeCoercerFactory typeCoercerFactory = new DefaultTypeCoercerFactory(); Parser parser = new Parser( new ParserConfig(config), typeCoercerFactory, new ConstructorArgMarshaller(typeCoercerFactory)); Cell cell = Cell.createCell( filesystem, new TestConsole(), Watchman.NULL_WATCHMAN, config, new KnownBuildRuleTypesFactory( new ProcessExecutor(new TestConsole()), new FakeAndroidDirectoryResolver(), Optional.<Path>absent()), new FakeAndroidDirectoryResolver(), new DefaultClock()); BuildTarget target = BuildTargetFactory.newInstance(filesystem, "//thrift:exe"); TargetGraph targetGraph = parser.buildTargetGraph( eventBus, cell, false, Executors.newSingleThreadExecutor(), ImmutableSet.of(target)); TargetNodeToBuildRuleTransformer transformer = new BuildTargetNodeToBuildRuleTransformer(); // There was a case where the cxx library being generated wouldn't put the header into the tree // with the right flavour. This catches this case without us needing to stick a working thrift // compiler into buck's own source. Pair<ActionGraph, BuildRuleResolver> actionGraphAndResolver = new TargetGraphToActionGraph(eventBus, transformer).apply(targetGraph); // This is to cover the case where we weren't passing flavors around correctly, which ended // making the binary depend 'placeholder' BuildRules instead of real ones. This is the // regression test for that case. BuildRuleResolver ruleResolver = actionGraphAndResolver.getSecond(); BuildTarget binaryFlavor = target.withFlavors(ImmutableFlavor.of("binary")); ImmutableSortedSet<BuildRule> deps = ruleResolver.getRule(binaryFlavor).getDeps(); assertThat( FluentIterable.from(deps) .anyMatch( new Predicate<BuildRule>() { @Override public boolean apply(BuildRule input) { return input instanceof NoopBuildRule; } }), Matchers.is(false)); }