@Test public void usesCorrectCommandForPreprocess() { // Setup some dummy values for inputs to the CxxPreprocessAndCompile. SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); ProjectFilesystem filesystem = new FakeProjectFilesystem(); ImmutableList<String> platformFlags = ImmutableList.of("-Dtest=blah"); ImmutableList<String> ruleFlags = ImmutableList.of("-Dfoo=bar"); Path output = Paths.get("test.ii"); Path depFile = Paths.get("test.ii.dep"); Path input = Paths.get("test.cpp"); Path prefixHeader = Paths.get("prefix.pch"); CxxPreprocessAndCompile buildRule = CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, platformFlags, ruleFlags, ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>of(new FakeSourcePath(filesystem, prefixHeader.toString())), ImmutableList.of(CxxHeaders.builder().build())), output, new FakeSourcePath(input.toString()), DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); // Verify it uses the expected command. ImmutableList<String> expectedPreprocessCommand = ImmutableList.<String>builder() .add("preprocessor") .add("-Dtest=blah") .add("-Dfoo=bar") .add("-include") .add(filesystem.resolve(prefixHeader).toString()) .add("-x", "c++") .add("-E") .add("-MD") .add("-MF") .add(depFile.toString() + ".tmp") .add(input.toString()) .build(); ImmutableList<String> actualPreprocessCommand = buildRule.makeMainStep().getCommand(); assertEquals(expectedPreprocessCommand, actualPreprocessCommand); }
/** * @return adds a the header {@link SymlinkTree} for the given rule to the {@link * CxxPreprocessorInput}. */ public static CxxPreprocessorInput.Builder addHeaderSymlinkTree( CxxPreprocessorInput.Builder builder, BuildTarget target, BuildRuleResolver ruleResolver, Flavor flavor, HeaderVisibility headerVisibility, IncludeType includeType) throws NoSuchBuildTargetException { BuildRule rule = ruleResolver.requireRule( BuildTarget.builder(target) .addFlavors( flavor, CxxDescriptionEnhancer.getHeaderSymlinkTreeFlavor(headerVisibility)) .build()); Preconditions.checkState( rule instanceof HeaderSymlinkTree, "Attempt to add %s of type %s and class %s to %s", rule.getFullyQualifiedName(), rule.getType(), rule.getClass(), target); HeaderSymlinkTree symlinkTree = (HeaderSymlinkTree) rule; builder .addRules(symlinkTree.getBuildTarget()) .setIncludes( CxxHeaders.builder() .setNameToPathMap(ImmutableSortedMap.copyOf(symlinkTree.getLinks())) .setFullNameToPathMap(ImmutableSortedMap.copyOf(symlinkTree.getFullLinks())) .build()); switch (includeType) { case LOCAL: builder.addIncludeRoots(symlinkTree.getIncludePath()); builder.addAllHeaderMaps(symlinkTree.getHeaderMap().asSet()); break; case SYSTEM: builder.addSystemIncludeRoots(symlinkTree.getSystemIncludePath()); break; } return builder; }
public static ImmutableList<CxxPreprocessorInput> collectCxxPreprocessorInput( TargetGraph targetGraph, BuildRuleParams params, CxxPlatform cxxPlatform, ImmutableMultimap<CxxSource.Type, String> preprocessorFlags, ImmutableList<HeaderSymlinkTree> headerSymlinkTrees, ImmutableSet<Path> frameworkSearchPaths, Iterable<CxxPreprocessorInput> cxxPreprocessorInputFromDeps) { // Add the private includes of any rules which list this rule as a test. BuildTarget targetWithoutFlavor = BuildTarget.of(params.getBuildTarget().getUnflavoredBuildTarget()); ImmutableList.Builder<CxxPreprocessorInput> cxxPreprocessorInputFromTestedRulesBuilder = ImmutableList.builder(); for (BuildRule rule : params.getDeps()) { if (rule instanceof NativeTestable) { NativeTestable testable = (NativeTestable) rule; if (testable.isTestedBy(targetWithoutFlavor)) { LOG.debug( "Adding private includes of tested rule %s to testing rule %s", rule.getBuildTarget(), params.getBuildTarget()); cxxPreprocessorInputFromTestedRulesBuilder.add( testable.getCxxPreprocessorInput(targetGraph, cxxPlatform, HeaderVisibility.PRIVATE)); } } } ImmutableList<CxxPreprocessorInput> cxxPreprocessorInputFromTestedRules = cxxPreprocessorInputFromTestedRulesBuilder.build(); LOG.verbose( "Rules tested by target %s added private includes %s", params.getBuildTarget(), cxxPreprocessorInputFromTestedRules); ImmutableMap.Builder<Path, SourcePath> allLinks = ImmutableMap.builder(); ImmutableMap.Builder<Path, SourcePath> allFullLinks = ImmutableMap.builder(); ImmutableList.Builder<Path> allIncludeRoots = ImmutableList.builder(); ImmutableSet.Builder<Path> allHeaderMaps = ImmutableSet.builder(); for (HeaderSymlinkTree headerSymlinkTree : headerSymlinkTrees) { allLinks.putAll(headerSymlinkTree.getLinks()); allFullLinks.putAll(headerSymlinkTree.getFullLinks()); allIncludeRoots.add(headerSymlinkTree.getIncludePath()); allHeaderMaps.addAll(headerSymlinkTree.getHeaderMap().asSet()); } CxxPreprocessorInput localPreprocessorInput = CxxPreprocessorInput.builder() .addAllRules(Iterables.transform(headerSymlinkTrees, HasBuildTarget.TO_TARGET)) .putAllPreprocessorFlags(preprocessorFlags) .setIncludes( CxxHeaders.builder() .putAllNameToPathMap(allLinks.build()) .putAllFullNameToPathMap(allFullLinks.build()) .build()) .addAllIncludeRoots(allIncludeRoots.build()) .addAllHeaderMaps(allHeaderMaps.build()) .addAllFrameworkRoots(frameworkSearchPaths) .build(); return ImmutableList.<CxxPreprocessorInput>builder() .add(localPreprocessorInput) .addAll(cxxPreprocessorInputFromDeps) .addAll(cxxPreprocessorInputFromTestedRules) .build(); }
public class CxxPreprocessAndCompileTest { private static final Preprocessor DEFAULT_PREPROCESSOR = new DefaultPreprocessor(new HashedFileTool(Paths.get("preprocessor"))); private static final Compiler DEFAULT_COMPILER = new DefaultCompiler(new HashedFileTool(Paths.get("compiler"))); private static final ImmutableList<String> DEFAULT_PLATFORM_FLAGS = ImmutableList.of("-fsanitize=address"); private static final ImmutableList<String> DEFAULT_RULE_FLAGS = ImmutableList.of("-O3"); private static final ImmutableList<String> DEFAULT_PREPROCESSOR_PLATFORM_FLAGS = ImmutableList.of(); private static final ImmutableList<String> DEFAULT_PREPROCESOR_RULE_FLAGS = ImmutableList.of("-DTEST"); private static final Path DEFAULT_OUTPUT = Paths.get("test.o"); private static final SourcePath DEFAULT_INPUT = new FakeSourcePath("test.cpp"); private static final CxxSource.Type DEFAULT_INPUT_TYPE = CxxSource.Type.CXX; private static final ImmutableList<CxxHeaders> DEFAULT_INCLUDES = ImmutableList.of( CxxHeaders.builder() .putNameToPathMap(Paths.get("test.h"), new FakeSourcePath("foo/test.h")) .build()); private static final ImmutableSet<Path> DEFAULT_INCLUDE_ROOTS = ImmutableSet.of(Paths.get("foo/bar"), Paths.get("test")); private static final ImmutableSet<Path> DEFAULT_SYSTEM_INCLUDE_ROOTS = ImmutableSet.of(Paths.get("/usr/include"), Paths.get("/include")); private static final ImmutableSet<Path> DEFAULT_HEADER_MAPS = ImmutableSet.of(Paths.get("some/thing.hmap"), Paths.get("another/file.hmap")); private static final ImmutableSet<FrameworkPath> DEFAULT_FRAMEWORK_ROOTS = ImmutableSet.of(); private static final DebugPathSanitizer DEFAULT_SANITIZER = CxxPlatforms.DEFAULT_DEBUG_PATH_SANITIZER; private static final Path DEFAULT_WORKING_DIR = Paths.get(System.getProperty("user.dir")); private static final RuleKeyAppendableFunction<FrameworkPath, Path> DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION = new RuleKeyAppendableFunction<FrameworkPath, Path>() { @Override public RuleKeyBuilder appendToRuleKey(RuleKeyBuilder builder) { return builder; } @Override public Path apply(FrameworkPath input) { return Paths.get("test", "framework", "path", input.toString()); } }; @Test public void inputChangesCauseRuleKeyChangesForCompilation() { SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); FakeFileHashCache hashCache = FakeFileHashCache.createFromStrings( ImmutableMap.<String, String>builder() .put("preprocessor", Strings.repeat("a", 40)) .put("compiler", Strings.repeat("a", 40)) .put("test.o", Strings.repeat("b", 40)) .put("test.cpp", Strings.repeat("c", 40)) .put("different", Strings.repeat("d", 40)) .put("foo/test.h", Strings.repeat("e", 40)) .put("path/to/a/plugin.so", Strings.repeat("f", 40)) .put("path/to/a/different/plugin.so", Strings.repeat("a0", 40)) .build()); // Generate a rule key for the defaults. RuleKey defaultRuleKey = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.compile( params, pathResolver, DEFAULT_COMPILER, DEFAULT_PLATFORM_FLAGS, DEFAULT_RULE_FLAGS, DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); // Verify that changing the compiler causes a rulekey change. RuleKey compilerChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.compile( params, pathResolver, new DefaultCompiler(new HashedFileTool(Paths.get("different"))), DEFAULT_PLATFORM_FLAGS, DEFAULT_RULE_FLAGS, DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, compilerChange); // Verify that changing the operation causes a rulekey change. RuleKey operationChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PLATFORM_FLAGS, DEFAULT_RULE_FLAGS, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, operationChange); // Verify that changing the platform flags causes a rulekey change. RuleKey platformFlagsChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.compile( params, pathResolver, DEFAULT_COMPILER, ImmutableList.of("-different"), DEFAULT_RULE_FLAGS, DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, platformFlagsChange); // Verify that changing the rule flags causes a rulekey change. RuleKey ruleFlagsChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.compile( params, pathResolver, DEFAULT_COMPILER, DEFAULT_PLATFORM_FLAGS, ImmutableList.of("-other", "flags"), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, ruleFlagsChange); // Verify that changing the input causes a rulekey change. RuleKey inputChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.compile( params, pathResolver, DEFAULT_COMPILER, DEFAULT_PLATFORM_FLAGS, DEFAULT_RULE_FLAGS, DEFAULT_OUTPUT, new FakeSourcePath("different"), DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, inputChange); } @Test public void inputChangesCauseRuleKeyChangesForPreprocessing() { SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); FakeFileHashCache hashCache = FakeFileHashCache.createFromStrings( ImmutableMap.<String, String>builder() .put("preprocessor", Strings.repeat("a", 40)) .put("compiler", Strings.repeat("a", 40)) .put("test.o", Strings.repeat("b", 40)) .put("test.cpp", Strings.repeat("c", 40)) .put("different", Strings.repeat("d", 40)) .put("foo/test.h", Strings.repeat("e", 40)) .put("path/to/a/plugin.so", Strings.repeat("f", 40)) .put("path/to/a/different/plugin.so", Strings.repeat("a0", 40)) .build()); // Generate a rule key for the defaults. RuleKey defaultRuleKey = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PREPROCESSOR_PLATFORM_FLAGS, DEFAULT_PREPROCESOR_RULE_FLAGS, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); // Verify that changing the includes does *not* cause a rulekey change, since we use a // different mechanism to track header changes. RuleKey includesChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PREPROCESSOR_PLATFORM_FLAGS, DEFAULT_PREPROCESOR_RULE_FLAGS, ImmutableSet.of(Paths.get("different")), DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertEquals(defaultRuleKey, includesChange); // Verify that changing the system includes does *not* cause a rulekey change, since we use a // different mechanism to track header changes. RuleKey systemIncludesChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PREPROCESSOR_PLATFORM_FLAGS, DEFAULT_PREPROCESOR_RULE_FLAGS, DEFAULT_INCLUDE_ROOTS, ImmutableSet.of(Paths.get("different")), DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertEquals(defaultRuleKey, systemIncludesChange); // Verify that changing the header maps does *not* cause a rulekey change, since we use a // different mechanism to track header changes. RuleKey headerMapsChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PREPROCESSOR_PLATFORM_FLAGS, DEFAULT_PREPROCESOR_RULE_FLAGS, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, ImmutableSet.of(Paths.get("different")), DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertEquals(defaultRuleKey, headerMapsChange); // Verify that changing the framework roots causes a rulekey change. RuleKey frameworkRootsChange = new DefaultRuleKeyBuilderFactory(hashCache, pathResolver) .build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, DEFAULT_PREPROCESSOR_PLATFORM_FLAGS, DEFAULT_PREPROCESOR_RULE_FLAGS, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, ImmutableSet.of( FrameworkPath.ofSourcePath(new FakeSourcePath("different"))), DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER)); assertNotEquals(defaultRuleKey, frameworkRootsChange); } @Test public void sanitizedPathsInFlagsDoNotAffectRuleKey() { SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); RuleKeyBuilderFactory ruleKeyBuilderFactory = new DefaultRuleKeyBuilderFactory( FakeFileHashCache.createFromStrings( ImmutableMap.<String, String>builder() .put("preprocessor", Strings.repeat("a", 40)) .put("compiler", Strings.repeat("a", 40)) .put("test.o", Strings.repeat("b", 40)) .put("test.cpp", Strings.repeat("c", 40)) .put("different", Strings.repeat("d", 40)) .put("foo/test.h", Strings.repeat("e", 40)) .put("path/to/a/plugin.so", Strings.repeat("f", 40)) .put("path/to/a/different/plugin.so", Strings.repeat("a0", 40)) .build()), pathResolver); // Set up a map to sanitize the differences in the flags. int pathSize = 10; DebugPathSanitizer sanitizer1 = new DebugPathSanitizer( pathSize, File.separatorChar, Paths.get("PWD"), ImmutableBiMap.of(Paths.get("something"), Paths.get("A"))); DebugPathSanitizer sanitizer2 = new DebugPathSanitizer( pathSize, File.separatorChar, Paths.get("PWD"), ImmutableBiMap.of(Paths.get("different"), Paths.get("A"))); // Generate a rule key for the defaults. ImmutableList<String> platformFlags1 = ImmutableList.of("-Isomething/foo"); ImmutableList<String> ruleFlags1 = ImmutableList.of("-Isomething/bar"); RuleKey ruleKey1 = ruleKeyBuilderFactory.build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, sanitizer1, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, platformFlags1, ruleFlags1, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, sanitizer1)); // Generate a rule key for the defaults. ImmutableList<String> platformFlags2 = ImmutableList.of("-Idifferent/foo"); ImmutableList<String> ruleFlags2 = ImmutableList.of("-Idifferent/bar"); RuleKey ruleKey2 = ruleKeyBuilderFactory.build( CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, sanitizer2, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, platformFlags2, ruleFlags2, DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, sanitizer2)); assertEquals(ruleKey1, ruleKey2); } @Test public void usesCorrectCommandForCompile() { // Setup some dummy values for inputs to the CxxPreprocessAndCompile. SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); ImmutableList<String> platformFlags = ImmutableList.of("-ffunction-sections"); ImmutableList<String> ruleFlags = ImmutableList.of("-O3"); Path output = Paths.get("test.o"); Path depFile = Paths.get("test.o.dep"); Path input = Paths.get("test.ii"); CxxPreprocessAndCompile buildRule = CxxPreprocessAndCompile.compile( params, pathResolver, DEFAULT_COMPILER, platformFlags, ruleFlags, output, new FakeSourcePath(input.toString()), DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); ImmutableList<String> expectedCompileCommand = ImmutableList.<String>builder() .add("compiler") .add("-ffunction-sections") .add("-O3") .add("-x", "c++") .add("-c") .add("-MD") .add("-MF") .add(depFile.toString() + ".tmp") .add(input.toString()) .add("-o", output.toString()) .build(); ImmutableList<String> actualCompileCommand = buildRule.makeMainStep().getCommand(); assertEquals(expectedCompileCommand, actualCompileCommand); } @Test public void usesCorrectCommandForPreprocess() { // Setup some dummy values for inputs to the CxxPreprocessAndCompile. SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); ProjectFilesystem filesystem = new FakeProjectFilesystem(); ImmutableList<String> platformFlags = ImmutableList.of("-Dtest=blah"); ImmutableList<String> ruleFlags = ImmutableList.of("-Dfoo=bar"); Path output = Paths.get("test.ii"); Path depFile = Paths.get("test.ii.dep"); Path input = Paths.get("test.cpp"); Path prefixHeader = Paths.get("prefix.pch"); CxxPreprocessAndCompile buildRule = CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, platformFlags, ruleFlags, ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>of(new FakeSourcePath(filesystem, prefixHeader.toString())), ImmutableList.of(CxxHeaders.builder().build())), output, new FakeSourcePath(input.toString()), DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); // Verify it uses the expected command. ImmutableList<String> expectedPreprocessCommand = ImmutableList.<String>builder() .add("preprocessor") .add("-Dtest=blah") .add("-Dfoo=bar") .add("-include") .add(filesystem.resolve(prefixHeader).toString()) .add("-x", "c++") .add("-E") .add("-MD") .add("-MF") .add(depFile.toString() + ".tmp") .add(input.toString()) .build(); ImmutableList<String> actualPreprocessCommand = buildRule.makeMainStep().getCommand(); assertEquals(expectedPreprocessCommand, actualPreprocessCommand); } @Test public void compilerAndPreprocessorAreAlwaysReturnedFromGetInputsAfterBuildingLocally() throws IOException { ProjectFilesystem filesystem = new FakeProjectFilesystem(); SourcePath preprocessor = new PathSourcePath(filesystem, Paths.get("preprocessor")); Tool preprocessorTool = new CommandTool.Builder().addInput(preprocessor).build(); SourcePath compiler = new PathSourcePath(filesystem, Paths.get("compiler")); Tool compilerTool = new CommandTool.Builder().addInput(compiler).build(); SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); CxxPreprocessAndCompile cxxPreprocess = CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, new DefaultPreprocessor(preprocessorTool), ImmutableList.<String>of(), ImmutableList.<String>of(), DEFAULT_INCLUDE_ROOTS, DEFAULT_SYSTEM_INCLUDE_ROOTS, DEFAULT_HEADER_MAPS, DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>absent(), DEFAULT_INCLUDES), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); assertThat(cxxPreprocess.getInputsAfterBuildingLocally(), Matchers.hasItem(preprocessor)); CxxPreprocessAndCompile cxxCompile = CxxPreprocessAndCompile.compile( params, pathResolver, new DefaultCompiler(compilerTool), ImmutableList.<String>of(), ImmutableList.<String>of(), DEFAULT_OUTPUT, DEFAULT_INPUT, DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); assertThat(cxxCompile.getInputsAfterBuildingLocally(), Matchers.hasItem(compiler)); } }