@Test public void testCompilationDatabseWithSeperatedPreprocessAndCompileStrategy() { String root = "/Users/user/src"; final Path fakeRoot = Paths.get(root); ProjectFilesystem filesystem = new FakeProjectFilesystem() { @Override public Path getRootPath() { return fakeRoot; } @Override public Path resolve(Path relativePath) { return fakeRoot.resolve(relativePath); } }; BuildTarget testBuildTarget = BuildTarget.builder(BuildTargetFactory.newInstance("//foo:baz")) .addAllFlavors(ImmutableSet.of(CxxCompilationDatabase.COMPILATION_DATABASE)) .build(); BuildRuleParams testBuildRuleParams = new FakeBuildRuleParamsBuilder(testBuildTarget).setProjectFilesystem(filesystem).build(); BuildRuleResolver testBuildRuleResolver = new BuildRuleResolver(); SourcePathResolver testSourcePathResolver = new SourcePathResolver(testBuildRuleResolver); BuildTarget preprocessTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("preprocess-test.cpp")) .build(); BuildRuleParams preprocessBuildRuleParams = new FakeBuildRuleParamsBuilder(preprocessTarget).setProjectFilesystem(filesystem).build(); CxxPreprocessAndCompile testPreprocessRule = new CxxPreprocessAndCompile( preprocessBuildRuleParams, testSourcePathResolver, CxxPreprocessAndCompileStep.Operation.PREPROCESS, Optional.<Preprocessor>of( new DefaultPreprocessor(new HashedFileTool(Paths.get("compiler")))), Optional.of(ImmutableList.<String>of()), Optional.of(ImmutableList.<String>of()), Optional.<Compiler>absent(), Optional.<ImmutableList<String>>absent(), Optional.<ImmutableList<String>>absent(), Paths.get("test.ii"), new TestSourcePath("test.cpp"), CxxSource.Type.CXX_CPP_OUTPUT, ImmutableSet.of(Paths.get("foo/bar"), Paths.get("test")), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), Optional.<SourcePath>absent(), ImmutableList.<CxxHeaders>of(), CxxPlatforms.DEFAULT_DEBUG_PATH_SANITIZER); BuildTarget compileTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("compile-test.cpp")) .build(); BuildRuleParams compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget) .setProjectFilesystem(filesystem) .setDeclaredDeps(ImmutableSortedSet.<BuildRule>of(testPreprocessRule)) .build(); CxxPreprocessAndCompile testCompileRule = new CxxPreprocessAndCompile( compileBuildRuleParams, testSourcePathResolver, CxxPreprocessAndCompileStep.Operation.COMPILE, Optional.<Preprocessor>absent(), Optional.<ImmutableList<String>>absent(), Optional.<ImmutableList<String>>absent(), Optional.<Compiler>of(new DefaultCompiler(new HashedFileTool(Paths.get("compiler")))), Optional.of(ImmutableList.<String>of()), Optional.of(ImmutableList.<String>of()), Paths.get("test.o"), new TestSourcePath("test.ii"), CxxSource.Type.CXX_CPP_OUTPUT, ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), Optional.<SourcePath>absent(), ImmutableList.<CxxHeaders>of(), CxxPlatforms.DEFAULT_DEBUG_PATH_SANITIZER); CxxCompilationDatabase compilationDatabase = CxxCompilationDatabase.createCompilationDatabase( testBuildRuleParams, testSourcePathResolver, CxxPreprocessMode.SEPARATE, ImmutableSortedSet.of(testPreprocessRule, testCompileRule)); assertEquals( "getPathToOutput() should be a function of the build target.", Paths.get("buck-out/gen/foo/__baz#compilation-database.json"), compilationDatabase.getPathToOutput()); BuildContext buildContext = FakeBuildContext.NOOP_CONTEXT; BuildableContext buildableContext = new FakeBuildableContext(); List<Step> buildSteps = compilationDatabase.getPostBuildSteps(buildContext, buildableContext); assertEquals(2, buildSteps.size()); assertTrue(buildSteps.get(0) instanceof MkdirStep); assertTrue(buildSteps.get(1) instanceof CxxCompilationDatabase.GenerateCompilationCommandsJson); CxxCompilationDatabase.GenerateCompilationCommandsJson step = (CxxCompilationDatabase.GenerateCompilationCommandsJson) buildSteps.get(1); Iterable<CxxCompilationDatabaseEntry> observedEntries = step.createEntries(); Iterable<CxxCompilationDatabaseEntry> expectedEntries = ImmutableList.of( CxxCompilationDatabaseEntry.of( root, root + "/test.cpp", ImmutableList.of( "compiler", "-I", "foo/bar", "-I", "test", "-x", "c++-cpp-output", "-c", "-o", "test.o", "test.cpp"))); MoreAsserts.assertIterablesEquals(expectedEntries, observedEntries); }
private void runCombinedTest( CxxPreprocessMode strategy, ImmutableList<String> expectedArguments) { BuildTarget testBuildTarget = BuildTarget.builder(BuildTargetFactory.newInstance("//foo:baz")) .addAllFlavors(ImmutableSet.of(CxxCompilationDatabase.COMPILATION_DATABASE)) .build(); final String root = "/Users/user/src"; final Path fakeRoot = Paths.get(root); ProjectFilesystem filesystem = new FakeProjectFilesystem() { @Override public Path getRootPath() { return fakeRoot; } @Override public Path resolve(Path relativePath) { return fakeRoot.resolve(relativePath); } }; BuildRuleParams testBuildRuleParams = new FakeBuildRuleParamsBuilder(testBuildTarget).setProjectFilesystem(filesystem).build(); BuildRuleResolver testBuildRuleResolver = new BuildRuleResolver(); SourcePathResolver testSourcePathResolver = new SourcePathResolver(testBuildRuleResolver); BuildTarget preprocessTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("preprocess-test.cpp")) .build(); BuildTarget compileTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("compile-test.cpp")) .build(); ImmutableSortedSet.Builder<CxxPreprocessAndCompile> rules = ImmutableSortedSet.naturalOrder(); CxxPreprocessAndCompileStep.Operation operation; BuildRuleParams compileBuildRuleParams; switch (strategy) { case SEPARATE: operation = CxxPreprocessAndCompileStep.Operation.COMPILE; CxxPreprocessAndCompile preprocessRule = new CxxPreprocessAndCompile( new FakeBuildRuleParamsBuilder(preprocessTarget) .setProjectFilesystem(filesystem) .build(), testSourcePathResolver, operation, Optional.<Preprocessor>of( new DefaultPreprocessor(new HashedFileTool(Paths.get("preprocessor")))), Optional.of(ImmutableList.<String>of()), Optional.of(ImmutableList.<String>of()), Optional.<Compiler>absent(), Optional.<ImmutableList<String>>absent(), Optional.<ImmutableList<String>>absent(), Paths.get("test.o"), new TestSourcePath("test.cpp"), CxxSource.Type.CXX, ImmutableSet.of(Paths.get("foo/bar"), Paths.get("test")), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), Optional.<SourcePath>absent(), ImmutableList.<CxxHeaders>of(), CxxPlatforms.DEFAULT_DEBUG_PATH_SANITIZER); rules.add(preprocessRule); compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget) .setProjectFilesystem(filesystem) .setDeclaredDeps(ImmutableSortedSet.<BuildRule>of(preprocessRule)) .build(); break; case COMBINED: operation = CxxPreprocessAndCompileStep.Operation.COMPILE_MUNGE_DEBUGINFO; compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget).setProjectFilesystem(filesystem).build(); break; case PIPED: operation = CxxPreprocessAndCompileStep.Operation.PIPED_PREPROCESS_AND_COMPILE; compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget).setProjectFilesystem(filesystem).build(); break; default: throw new RuntimeException("Invalid strategy"); } rules.add( new CxxPreprocessAndCompile( compileBuildRuleParams, testSourcePathResolver, operation, Optional.<Preprocessor>of( new DefaultPreprocessor(new HashedFileTool(Paths.get("preprocessor")))), Optional.of(ImmutableList.<String>of()), Optional.of(ImmutableList.<String>of()), Optional.<Compiler>of(new DefaultCompiler(new HashedFileTool(Paths.get("compiler")))), Optional.of(ImmutableList.<String>of()), Optional.of(ImmutableList.<String>of()), Paths.get("test.o"), new TestSourcePath("test.cpp"), CxxSource.Type.CXX, ImmutableSet.of(Paths.get("foo/bar"), Paths.get("test")), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), Optional.<SourcePath>absent(), ImmutableList.<CxxHeaders>of(), CxxPlatforms.DEFAULT_DEBUG_PATH_SANITIZER)); CxxCompilationDatabase compilationDatabase = CxxCompilationDatabase.createCompilationDatabase( testBuildRuleParams, testSourcePathResolver, strategy, rules.build()); assertEquals( "getPathToOutput() should be a function of the build target.", Paths.get("buck-out/gen/foo/__baz#compilation-database.json"), compilationDatabase.getPathToOutput()); BuildContext buildContext = FakeBuildContext.NOOP_CONTEXT; BuildableContext buildableContext = new FakeBuildableContext(); List<Step> buildSteps = compilationDatabase.getPostBuildSteps(buildContext, buildableContext); assertEquals(2, buildSteps.size()); assertTrue(buildSteps.get(0) instanceof MkdirStep); assertTrue(buildSteps.get(1) instanceof CxxCompilationDatabase.GenerateCompilationCommandsJson); CxxCompilationDatabase.GenerateCompilationCommandsJson step = (CxxCompilationDatabase.GenerateCompilationCommandsJson) buildSteps.get(1); Iterable<CxxCompilationDatabaseEntry> observedEntries = step.createEntries(); Iterable<CxxCompilationDatabaseEntry> expectedEntries = ImmutableList.of( CxxCompilationDatabaseEntry.of(root, root + "/test.cpp", expectedArguments)); MoreAsserts.assertIterablesEquals(expectedEntries, observedEntries); }
private void runCombinedTest( CxxPreprocessMode strategy, ImmutableList<String> expectedArguments) { BuildTarget testBuildTarget = BuildTarget.builder(BuildTargetFactory.newInstance("//foo:baz")) .addAllFlavors(ImmutableSet.of(CxxCompilationDatabase.COMPILATION_DATABASE)) .build(); final String root = "/Users/user/src"; final Path fakeRoot = Paths.get(root); ProjectFilesystem filesystem = new FakeProjectFilesystem(fakeRoot); BuildRuleParams testBuildRuleParams = new FakeBuildRuleParamsBuilder(testBuildTarget).setProjectFilesystem(filesystem).build(); BuildRuleResolver testBuildRuleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver testSourcePathResolver = new SourcePathResolver(testBuildRuleResolver); BuildTarget preprocessTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("preprocess-test.cpp")) .build(); BuildTarget compileTarget = BuildTarget.builder(testBuildRuleParams.getBuildTarget().getUnflavoredBuildTarget()) .addFlavors(ImmutableFlavor.of("compile-test.cpp")) .build(); PreprocessorFlags preprocessorFlags = PreprocessorFlags.builder() .addSystemIncludePaths(filesystem.resolve("foo/bar"), filesystem.resolve("test")) .build(); ImmutableSortedSet.Builder<CxxPreprocessAndCompile> rules = ImmutableSortedSet.naturalOrder(); BuildRuleParams compileBuildRuleParams; switch (strategy) { case SEPARATE: CxxPreprocessAndCompile preprocessRule = CxxPreprocessAndCompile.preprocess( new FakeBuildRuleParamsBuilder(preprocessTarget) .setProjectFilesystem(filesystem) .build(), testSourcePathResolver, new PreprocessorDelegate( testSourcePathResolver, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, CxxPlatformUtils.DEFAULT_CONFIG.getHeaderVerification(), filesystem.getRootPath(), new DefaultPreprocessor(new HashedFileTool(Paths.get("compiler"))), preprocessorFlags, new RuleKeyAppendableFunction<FrameworkPath, Path>() { @Override public void appendToRuleKey(RuleKeyObjectSink sink) { // Do nothing. } @Override public Path apply(FrameworkPath input) { throw new UnsupportedOperationException("should not be called"); } }, ImmutableList.<CxxHeaders>of()), new CompilerDelegate( testSourcePathResolver, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, new GccCompiler(new HashedFileTool(Paths.get("compiler"))), CxxToolFlags.of()), Paths.get("test.ii"), new FakeSourcePath(filesystem, "test.cpp"), CxxSource.Type.CXX, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER); rules.add(preprocessRule); compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget) .setProjectFilesystem(filesystem) .setDeclaredDeps(ImmutableSortedSet.<BuildRule>of(preprocessRule)) .build(); rules.add( CxxPreprocessAndCompile.compile( compileBuildRuleParams, testSourcePathResolver, new CompilerDelegate( testSourcePathResolver, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, new GccCompiler(new HashedFileTool(Paths.get("compiler"))), CxxToolFlags.of()), Paths.get("test.o"), new FakeSourcePath(filesystem, "test.ii"), CxxSource.Type.CXX_CPP_OUTPUT, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER)); break; case COMBINED: case PIPED: compileBuildRuleParams = new FakeBuildRuleParamsBuilder(compileTarget).setProjectFilesystem(filesystem).build(); rules.add( CxxPreprocessAndCompile.preprocessAndCompile( compileBuildRuleParams, testSourcePathResolver, new PreprocessorDelegate( testSourcePathResolver, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, CxxPlatformUtils.DEFAULT_CONFIG.getHeaderVerification(), filesystem.getRootPath(), new DefaultPreprocessor(new HashedFileTool(Paths.get("preprocessor"))), preprocessorFlags, new RuleKeyAppendableFunction<FrameworkPath, Path>() { @Override public void appendToRuleKey(RuleKeyObjectSink sink) { // Do nothing. } @Override public Path apply(FrameworkPath input) { throw new UnsupportedOperationException("should not be called"); } }, ImmutableList.<CxxHeaders>of()), new CompilerDelegate( testSourcePathResolver, CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, new GccCompiler(new HashedFileTool(Paths.get("compiler"))), CxxToolFlags.of()), Paths.get("test.o"), new FakeSourcePath(filesystem, "test.cpp"), CxxSource.Type.CXX, Optional.<PrecompiledHeaderReference>absent(), CxxPlatformUtils.DEFAULT_DEBUG_PATH_SANITIZER, strategy)); break; default: throw new RuntimeException("Invalid strategy"); } HeaderSymlinkTree privateSymlinkTree = CxxDescriptionEnhancer.createHeaderSymlinkTree( testBuildRuleParams, testBuildRuleResolver, testSourcePathResolver, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableMap.<Path, SourcePath>of(), HeaderVisibility.PRIVATE); HeaderSymlinkTree exportedSymlinkTree = CxxDescriptionEnhancer.createHeaderSymlinkTree( testBuildRuleParams, testBuildRuleResolver, testSourcePathResolver, CxxPlatformUtils.DEFAULT_PLATFORM, ImmutableMap.<Path, SourcePath>of(), HeaderVisibility.PUBLIC); CxxCompilationDatabase compilationDatabase = CxxCompilationDatabase.createCompilationDatabase( testBuildRuleParams, testSourcePathResolver, strategy, rules.build(), ImmutableSortedSet.of(privateSymlinkTree, exportedSymlinkTree)); assertThat( compilationDatabase.getRuntimeDeps(), Matchers.<BuildRule>contains(exportedSymlinkTree, privateSymlinkTree)); assertEquals( "getPathToOutput() should be a function of the build target.", BuildTargets.getGenPath(filesystem, testBuildTarget, "__%s.json"), compilationDatabase.getPathToOutput()); BuildContext buildContext = FakeBuildContext.NOOP_CONTEXT; BuildableContext buildableContext = new FakeBuildableContext(); List<Step> buildSteps = compilationDatabase.getPostBuildSteps(buildContext, buildableContext); assertEquals(2, buildSteps.size()); assertTrue(buildSteps.get(0) instanceof MkdirStep); assertTrue(buildSteps.get(1) instanceof CxxCompilationDatabase.GenerateCompilationCommandsJson); CxxCompilationDatabase.GenerateCompilationCommandsJson step = (CxxCompilationDatabase.GenerateCompilationCommandsJson) buildSteps.get(1); Iterable<CxxCompilationDatabaseEntry> observedEntries = step.createEntries(); Iterable<CxxCompilationDatabaseEntry> expectedEntries = ImmutableList.of( CxxCompilationDatabaseEntry.of(root, root + "/test.cpp", expectedArguments)); MoreAsserts.assertIterablesEquals(expectedEntries, observedEntries); }