blob: 0446e6133f240f63e1a0adc581b70c08c9c8fe6f [file] [log] [blame]
/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.cxx;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleParamsFactory;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.FakeBuildRule;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.PathSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SymlinkTree;
import com.facebook.buck.rules.TestSourcePath;
import com.facebook.buck.shell.Genrule;
import com.facebook.buck.shell.GenruleBuilder;
import com.facebook.buck.testutil.AllExistingProjectFilesystem;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class CxxPreprocessablesTest {
private static final ProjectFilesystem PROJECT_FILESYSTEM = new FakeProjectFilesystem();
private static final CxxPlatform CXX_PLATFORM = DefaultCxxPlatforms.build(
new FakeBuckConfig());
private static <T> void assertContains(ImmutableList<T> container, Iterable<T> items) {
for (T item : items) {
assertThat(container, Matchers.hasItem(item));
}
}
private static class FakeCxxPreprocessorDep extends FakeBuildRule
implements CxxPreprocessorDep {
private final CxxPreprocessorInput input;
public FakeCxxPreprocessorDep(
BuildRuleParams params,
SourcePathResolver resolver,
CxxPreprocessorInput input) {
super(params, resolver);
this.input = Preconditions.checkNotNull(input);
}
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(CxxPlatform cxxPlatform) {
return input;
}
}
private static FakeCxxPreprocessorDep createFakeCxxPreprocessorDep(
BuildTarget target,
SourcePathResolver resolver,
CxxPreprocessorInput input,
BuildRule... deps) {
return new FakeCxxPreprocessorDep(
new FakeBuildRuleParamsBuilder(target)
.setDeps(ImmutableSortedSet.copyOf(deps))
.build(),
resolver, input);
}
private static FakeCxxPreprocessorDep createFakeCxxPreprocessorDep(
String target,
SourcePathResolver resolver,
CxxPreprocessorInput input,
BuildRule... deps) {
return createFakeCxxPreprocessorDep(
BuildTargetFactory.newInstance(target),
resolver,
input,
deps);
}
private static FakeBuildRule createFakeBuildRule(
BuildTarget target,
SourcePathResolver resolver,
BuildRule... deps) {
return new FakeBuildRule(
new FakeBuildRuleParamsBuilder(target)
.setDeps(ImmutableSortedSet.copyOf(deps))
.build(),
resolver);
}
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void resolveHeaderMap() {
BuildTarget target = BuildTargetFactory.newInstance("//hello/world:test");
ImmutableMap<String, SourcePath> headerMap = ImmutableMap.<String, SourcePath>of(
"foo/bar.h", new TestSourcePath("header1.h"),
"foo/hello.h", new TestSourcePath("header2.h"));
// Verify that the resolveHeaderMap returns sane results.
ImmutableMap<Path, SourcePath> expected = ImmutableMap.<Path, SourcePath>of(
target.getBasePath().resolve("foo/bar.h"), new TestSourcePath("header1.h"),
target.getBasePath().resolve("foo/hello.h"), new TestSourcePath("header2.h"));
ImmutableMap<Path, SourcePath> actual = CxxPreprocessables.resolveHeaderMap(
target.getBasePath(), headerMap);
assertEquals(expected, actual);
}
@Test
public void getTransitiveCxxPreprocessorInput() throws Exception {
SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new FakeBuckConfig());
// Setup a simple CxxPreprocessorDep which contributes components to preprocessing.
BuildTarget cppDepTarget1 = BuildTargetFactory.newInstance("//:cpp1");
CxxPreprocessorInput input1 = CxxPreprocessorInput.builder()
.addRules(cppDepTarget1)
.putPreprocessorFlags(CxxSource.Type.C, "-Dtest=yes")
.putPreprocessorFlags(CxxSource.Type.CXX, "-Dtest=yes")
.addIncludeRoots(Paths.get("foo/bar"), Paths.get("hello"))
.addSystemIncludeRoots(Paths.get("/usr/include"))
.build();
BuildTarget depTarget1 = BuildTargetFactory.newInstance("//:dep1");
FakeCxxPreprocessorDep dep1 = createFakeCxxPreprocessorDep(depTarget1, pathResolver, input1);
// Setup another simple CxxPreprocessorDep which contributes components to preprocessing.
BuildTarget cppDepTarget2 = BuildTargetFactory.newInstance("//:cpp2");
CxxPreprocessorInput input2 = CxxPreprocessorInput.builder()
.addRules(cppDepTarget2)
.putPreprocessorFlags(CxxSource.Type.C, "-DBLAH")
.putPreprocessorFlags(CxxSource.Type.CXX, "-DBLAH")
.addIncludeRoots(Paths.get("goodbye"))
.addSystemIncludeRoots(Paths.get("test"))
.build();
BuildTarget depTarget2 = BuildTargetFactory.newInstance("//:dep2");
FakeCxxPreprocessorDep dep2 = createFakeCxxPreprocessorDep(depTarget2, pathResolver, input2);
// Create a normal dep which depends on the two CxxPreprocessorDep rules above.
BuildTarget depTarget3 = BuildTargetFactory.newInstance("//:dep3");
CxxPreprocessorInput nothing = CxxPreprocessorInput.EMPTY;
FakeCxxPreprocessorDep dep3 = createFakeCxxPreprocessorDep(depTarget3,
pathResolver,
nothing, dep1, dep2);
// Verify that getTransitiveCxxPreprocessorInput gets all CxxPreprocessorInput objects
// from the relevant rules above.
CxxPreprocessorInput expected = CxxPreprocessorInput.concat(
ImmutableList.of(input1, input2));
CxxPreprocessorInput actual = CxxPreprocessables.getTransitiveCxxPreprocessorInput(
cxxPlatform,
ImmutableList.<BuildRule>of(dep3));
assertEquals(expected, actual);
}
@Test
public void createHeaderSymlinkTreeBuildRuleHasNoDeps() {
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
// Setup up the main build target and build params, which some random dep. We'll make
// sure the dep doesn't get propagated to the symlink rule below.
FakeBuildRule dep = createFakeBuildRule(
BuildTargetFactory.newInstance("//random:dep"),
pathResolver);
BuildTarget target = BuildTargetFactory.newInstance("//foo:bar");
BuildRuleParams params = new FakeBuildRuleParamsBuilder(target)
.setDeps(ImmutableSortedSet.<BuildRule>of(dep))
.build();
Path root = Paths.get("root");
// Setup a simple genrule we can wrap in a BuildTargetSourcePath to model a input source
// that is built by another rule.
Genrule genrule = (Genrule) GenruleBuilder
.newGenruleBuilder(BuildTargetFactory.newInstance("//:genrule"))
.setOut("foo/bar.o")
.build(resolver);
// Setup the link map with both a regular path-based source path and one provided by
// another build rule.
ImmutableMap<Path, SourcePath> links = ImmutableMap.<Path, SourcePath>of(
Paths.get("link1"),
new TestSourcePath("hello"),
Paths.get("link2"),
new BuildTargetSourcePath(PROJECT_FILESYSTEM, genrule.getBuildTarget()));
// Build our symlink tree rule using the helper method.
SymlinkTree symlinkTree = CxxPreprocessables.createHeaderSymlinkTreeBuildRule(
pathResolver,
target,
params,
root,
links);
// Verify that the symlink tree has no deps. This is by design, since setting symlinks can
// be done completely independently from building the source that the links point to and
// independently from the original deps attached to the input build rule params.
assertTrue(symlinkTree.getDeps().isEmpty());
}
@Test
public void getTransitiveNativeLinkableInputDoesNotTraversePastNonNativeLinkables()
throws Exception {
SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new FakeBuckConfig());
// Create a native linkable that sits at the bottom of the dep chain.
String sentinal = "bottom";
CxxPreprocessorInput bottomInput = CxxPreprocessorInput.builder()
.putPreprocessorFlags(CxxSource.Type.C, sentinal)
.build();
BuildRule bottom = createFakeCxxPreprocessorDep("//:bottom", pathResolver, bottomInput);
// Create a non-native linkable that sits in the middle of the dep chain, preventing
// traversals to the bottom native linkable.
BuildRule middle = new FakeBuildRule("//:middle", pathResolver, bottom);
// Create a native linkable that sits at the top of the dep chain.
CxxPreprocessorInput topInput = CxxPreprocessorInput.EMPTY;
BuildRule top = createFakeCxxPreprocessorDep("//:top", pathResolver, topInput, middle);
// Now grab all input via traversing deps and verify that the middle rule prevents pulling
// in the bottom input.
CxxPreprocessorInput totalInput =
CxxPreprocessables.getTransitiveCxxPreprocessorInput(
cxxPlatform,
ImmutableList.of(top));
assertTrue(bottomInput.getPreprocessorFlags().get(CxxSource.Type.C).contains(sentinal));
assertFalse(totalInput.getPreprocessorFlags().get(CxxSource.Type.C).contains(sentinal));
}
@Test
public void createPreprocessBuildRulePropagatesCxxPreprocessorDeps() {
BuildTarget target = BuildTargetFactory.newInstance("//foo:bar");
BuildRuleParams params = BuildRuleParamsFactory.createTrivialBuildRuleParams(target);
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
FakeBuildRule dep = resolver.addToIndex(
new FakeBuildRule(
"//:dep1",
new SourcePathResolver(new BuildRuleResolver())));
CxxPreprocessorInput cxxPreprocessorInput =
CxxPreprocessorInput.builder()
.addRules(dep.getBuildTarget())
.build();
String name = "foo/bar.cpp";
SourcePath input = new PathSourcePath(PROJECT_FILESYSTEM, target.getBasePath().resolve(name));
CxxSource cxxSource = ImmutableCxxSource.of(
CxxSource.Type.CXX,
input,
ImmutableList.<String>of());
Map.Entry<String, CxxSource> entry =
CxxPreprocessables.createPreprocessBuildRule(
params,
resolver,
CXX_PLATFORM,
cxxPreprocessorInput,
/* pic */ false,
name,
cxxSource);
BuildRule cxxPreprocess = pathResolver.getRule(entry.getValue().getPath()).get();
assertEquals(ImmutableSortedSet.<BuildRule>of(dep), cxxPreprocess.getDeps());
}
@Test
public void preprocessFlagsFromPlatformArePropagated() {
BuildTarget target = BuildTargetFactory.newInstance("//foo:bar");
BuildRuleParams params = BuildRuleParamsFactory.createTrivialBuildRuleParams(target);
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
CxxPreprocessorInput cxxPreprocessorInput = CxxPreprocessorInput.EMPTY;
String name = "source.cpp";
CxxSource cxxSource = ImmutableCxxSource.of(
CxxSource.Type.CXX,
new TestSourcePath(name),
ImmutableList.<String>of());
ImmutableList<String> platformFlags = ImmutableList.of("-some", "-flags");
CxxPlatform platform = DefaultCxxPlatforms.build(
new FakeBuckConfig(
ImmutableMap.<String, Map<String, String>>of(
"cxx", ImmutableMap.of("cxxppflags", Joiner.on(" ").join(platformFlags)))));
// Verify that platform flags make it to the compile rule.
Map.Entry<String, CxxSource> output =
CxxPreprocessables.createPreprocessBuildRule(
params,
resolver,
platform,
cxxPreprocessorInput,
/* pic */ false,
name,
cxxSource);
CxxPreprocess cxxPreprocess =
(CxxPreprocess) pathResolver.getRule(output.getValue().getPath()).get();
assertNotEquals(
-1,
Collections.indexOfSubList(cxxPreprocess.getFlags(), platformFlags));
}
@Test
public void checkCorrectFlagsAreUsed() {
BuildRuleResolver buildRuleResolver = new BuildRuleResolver();
SourcePathResolver sourcePathResolver = new SourcePathResolver(buildRuleResolver);
BuildTarget target = BuildTargetFactory.newInstance("//:target");
BuildRuleParams params = BuildRuleParamsFactory.createTrivialBuildRuleParams(target);
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
Joiner space = Joiner.on(" ");
ImmutableList<String> explicitCppflags = ImmutableList.of("-explicit-cppflag");
ImmutableList<String> explicitCxxppflags = ImmutableList.of("-explicit-cxxppflag");
CxxPreprocessorInput cxxPreprocessorInput =
CxxPreprocessorInput.builder()
.putAllPreprocessorFlags(CxxSource.Type.C, explicitCppflags)
.putAllPreprocessorFlags(CxxSource.Type.CXX, explicitCxxppflags)
.build();
ImmutableList<String> asppflags = ImmutableList.of("-asppflag", "-asppflag");
SourcePath cpp = new TestSourcePath("cpp");
ImmutableList<String> cppflags = ImmutableList.of("-cppflag", "-cppflag");
SourcePath cxxpp = new TestSourcePath("cxxpp");
ImmutableList<String> cxxppflags = ImmutableList.of("-cxxppflag", "-cxxppflag");
FakeBuckConfig buckConfig = new FakeBuckConfig(
ImmutableMap.<String, Map<String, String>>of(
"cxx", ImmutableMap.<String, String>builder()
.put("asppflags", space.join(asppflags))
.put("cpp", sourcePathResolver.getPath(cpp).toString())
.put("cppflags", space.join(cppflags))
.put("cxxpp", sourcePathResolver.getPath(cxxpp).toString())
.put("cxxppflags", space.join(cxxppflags))
.build()),
filesystem);
CxxPlatform platform = DefaultCxxPlatforms.build(buckConfig);
String cSourceName = "test.c";
List<String> perFileFlagsForTestC =
ImmutableList.of("-per-file-flag-for-c-file", "-and-another-one");
CxxSource cSource = ImmutableCxxSource.of(
CxxSource.Type.C,
new TestSourcePath(cSourceName),
perFileFlagsForTestC);
Map.Entry<String, CxxSource> cPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
platform,
cxxPreprocessorInput,
/* pic */ false,
cSourceName,
cSource);
CxxPreprocess cPreprocess =
(CxxPreprocess) sourcePathResolver.getRule(cPreprocessEntry.getValue().getPath()).get();
assertContains(cPreprocess.getFlags(), explicitCppflags);
assertContains(cPreprocess.getFlags(), cppflags);
assertContains(cPreprocess.getFlags(), perFileFlagsForTestC);
String cxxSourceName = "test.cpp";
List<String> perFileFlagsForTestCpp =
ImmutableList.of("-per-file-flag-for-cpp-file");
CxxSource cxxSource = ImmutableCxxSource.of(
CxxSource.Type.CXX,
new TestSourcePath(cxxSourceName),
perFileFlagsForTestCpp);
Map.Entry<String, CxxSource> cxxPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
platform,
cxxPreprocessorInput,
/* pic */ false,
cxxSourceName,
cxxSource);
CxxPreprocess cxxPreprocess =
(CxxPreprocess) sourcePathResolver.getRule(cxxPreprocessEntry.getValue().getPath()).get();
assertContains(cxxPreprocess.getFlags(), explicitCxxppflags);
assertContains(cxxPreprocess.getFlags(), cxxppflags);
assertContains(cxxPreprocess.getFlags(), perFileFlagsForTestCpp);
String assemblerWithCppSourceName = "test.S";
List<String> perFileFlagsForTestS =
ImmutableList.of("-a-flag-for-s-file", "-another-one", "-one-more");
CxxSource assemblerWithCppSource = ImmutableCxxSource.of(
CxxSource.Type.ASSEMBLER_WITH_CPP,
new TestSourcePath(assemblerWithCppSourceName),
perFileFlagsForTestS);
Map.Entry<String, CxxSource> assemblerWithCppCompileEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
platform,
cxxPreprocessorInput,
/* pic */ false,
assemblerWithCppSourceName,
assemblerWithCppSource);
CxxPreprocess assemblerWithCppPreprocess =
(CxxPreprocess) sourcePathResolver.getRule(
assemblerWithCppCompileEntry.getValue().getPath()).get();
assertContains(assemblerWithCppPreprocess.getFlags(), asppflags);
assertContains(assemblerWithCppPreprocess.getFlags(), perFileFlagsForTestS);
}
@Test
public void languageFlagsArePassed() {
BuildRuleResolver buildRuleResolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(buildRuleResolver);
BuildTarget target = BuildTargetFactory.newInstance("//:target");
BuildRuleParams params = BuildRuleParamsFactory.createTrivialBuildRuleParams(target);
String name = "foo/bar.cpp";
SourcePath input = new PathSourcePath(PROJECT_FILESYSTEM, target.getBasePath().resolve(name));
CxxSource cxxSource = ImmutableCxxSource.of(
CxxSource.Type.CXX,
input,
ImmutableList.<String>of());
Map.Entry<String, CxxSource> cxxPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
CXX_PLATFORM,
CxxPreprocessorInput.EMPTY,
/* pic */ false,
name,
cxxSource);
CxxPreprocess cxxPreprocess =
(CxxPreprocess) pathResolver.getRule(
cxxPreprocessEntry.getValue().getPath()).get();
assertThat(cxxPreprocess.getFlags(), Matchers.contains("-x", "c++"));
name = "foo/bar.m";
input = new PathSourcePath(PROJECT_FILESYSTEM, target.getBasePath().resolve(name));
cxxSource = ImmutableCxxSource.of(
CxxSource.Type.OBJC,
input,
ImmutableList.<String>of());
cxxPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
CXX_PLATFORM,
CxxPreprocessorInput.EMPTY,
/* pic */ false,
name,
cxxSource);
cxxPreprocess =
(CxxPreprocess) pathResolver.getRule(
cxxPreprocessEntry.getValue().getPath()).get();
assertThat(cxxPreprocess.getFlags(), Matchers.contains("-x", "objective-c"));
name = "foo/bar.mm";
input = new PathSourcePath(PROJECT_FILESYSTEM, target.getBasePath().resolve(name));
cxxSource = ImmutableCxxSource.of(
CxxSource.Type.OBJCXX,
input,
ImmutableList.<String>of());
cxxPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
CXX_PLATFORM,
CxxPreprocessorInput.EMPTY,
/* pic */ false,
name,
cxxSource);
cxxPreprocess =
(CxxPreprocess) pathResolver.getRule(
cxxPreprocessEntry.getValue().getPath()).get();
assertThat(cxxPreprocess.getFlags(), Matchers.contains("-x", "objective-c++"));
name = "foo/bar.c";
input = new PathSourcePath(PROJECT_FILESYSTEM, target.getBasePath().resolve(name));
cxxSource = ImmutableCxxSource.of(
CxxSource.Type.C,
input,
ImmutableList.<String>of());
cxxPreprocessEntry =
CxxPreprocessables.createPreprocessBuildRule(
params,
buildRuleResolver,
CXX_PLATFORM,
CxxPreprocessorInput.EMPTY,
/* pic */ false,
name,
cxxSource);
cxxPreprocess =
(CxxPreprocess) pathResolver.getRule(
cxxPreprocessEntry.getValue().getPath()).get();
assertThat(cxxPreprocess.getFlags(), Matchers.contains("-x", "c"));
}
@Test
public void getTransitiveDependenciesThrowsForConflictingHeaders()
throws Exception {
SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new FakeBuckConfig());
CxxPreprocessorInput bottomInput = CxxPreprocessorInput.builder()
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get("prefix/file.h"),
new TestSourcePath("bottom/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something/prefix/file.h"),
new TestSourcePath("bottom/file.h"))
.build())
.build();
BuildRule bottom = createFakeCxxPreprocessorDep("//:bottom", pathResolver, bottomInput);
CxxPreprocessorInput topInput = CxxPreprocessorInput.builder()
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get("prefix/file.h"),
new TestSourcePath("top/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something-else/prefix/file.h"),
new TestSourcePath("top/file.h"))
.build())
.build();
BuildRule top = createFakeCxxPreprocessorDep("//:top", pathResolver, topInput, bottom);
exception.expect(CxxPreprocessorInput.ConflictingHeadersException.class);
exception.expectMessage("'prefix/file.h' maps to both [bottom/file.h, top/file.h].");
CxxPreprocessables.getTransitiveCxxPreprocessorInput(
cxxPlatform,
ImmutableList.of(top));
}
@Test
public void getTransitiveDependenciesDoesNotThrowsForCompatibleHeaders()
throws Exception {
SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
CxxPlatform cxxPlatform = DefaultCxxPlatforms.build(new FakeBuckConfig());
CxxPreprocessorInput bottomInput = CxxPreprocessorInput.builder()
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get("prefix/file.h"),
new TestSourcePath("common/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something/prefix/file.h"),
new TestSourcePath("common/file.h"))
.build())
.build();
BuildRule bottom = createFakeCxxPreprocessorDep("//:bottom", pathResolver, bottomInput);
CxxPreprocessorInput topInput = CxxPreprocessorInput.builder()
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get("prefix/file.h"),
new TestSourcePath("common/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something-else/prefix/file.h"),
new TestSourcePath("common/file.h"))
.build())
.build();
BuildRule top = createFakeCxxPreprocessorDep("//:top", pathResolver, topInput, bottom);
CxxPreprocessorInput expected = CxxPreprocessorInput.builder()
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get("prefix/file.h"),
new TestSourcePath("common/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something/prefix/file.h"),
new TestSourcePath("common/file.h"))
.putFullNameToPathMap(
Paths.get("buck-out/something-else/prefix/file.h"),
new TestSourcePath("common/file.h"))
.build())
.build();
assertEquals(
expected,
CxxPreprocessables.getTransitiveCxxPreprocessorInput(
cxxPlatform,
ImmutableList.of(top)));
}
}