blob: 7cf230d357e8b0e39c0b8e8a8b169fab3aa8a9b6 [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.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.android.AndroidPackageable;
import com.facebook.buck.android.AndroidPackageableCollector;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.python.ImmutablePythonPackageComponents;
import com.facebook.buck.python.PythonPackageComponents;
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.PathSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.TestSourcePath;
import com.facebook.buck.rules.coercer.SourceWithFlags;
import com.facebook.buck.shell.GenruleBuilder;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.TargetGraphFactory;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class CxxLibraryDescriptionTest {
private static <T> void assertContains(List<T> container, Iterable<T> items) {
for (T item : items) {
assertThat(container, Matchers.hasItem(item));
}
}
private static <T> void assertNotContains(List<T> container, Iterable<T> items) {
for (T item : items) {
assertThat(container, Matchers.not(Matchers.hasItem(item)));
}
}
@Test
@SuppressWarnings("PMD.UseAssertTrueInsteadOfAssertEquals")
public void createBuildRule() {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
CxxPlatform cxxPlatform = CxxLibraryBuilder.createDefaultPlatform();
// Setup a genrule the generates a header we'll list.
String genHeaderName = "test/foo.h";
BuildTarget genHeaderTarget = BuildTargetFactory.newInstance("//:genHeader");
GenruleBuilder genHeaderBuilder = GenruleBuilder
.newGenruleBuilder(genHeaderTarget)
.setOut(genHeaderName);
genHeaderBuilder.build(resolver);
// Setup a genrule the generates a source we'll list.
String genSourceName = "test/foo.cpp";
BuildTarget genSourceTarget = BuildTargetFactory.newInstance("//:genSource");
GenruleBuilder genSourceBuilder = GenruleBuilder
.newGenruleBuilder(genSourceTarget)
.setOut(genSourceName);
genSourceBuilder.build(resolver);
// Setup a C/C++ library that we'll depend on form the C/C++ binary description.
final BuildRule header = new FakeBuildRule("//:header", pathResolver);
final BuildRule headerSymlinkTree = new FakeBuildRule("//:symlink", pathResolver);
final Path headerSymlinkTreeRoot = Paths.get("symlink/tree/root");
final BuildRule archive = new FakeBuildRule("//:archive", pathResolver);
final Path archiveOutput = Paths.get("output/path/lib.a");
BuildTarget depTarget = BuildTargetFactory.newInstance("//:dep");
BuildRuleParams depParams = BuildRuleParamsFactory.createTrivialBuildRuleParams(depTarget);
AbstractCxxLibrary dep = new AbstractCxxLibrary(depParams, pathResolver) {
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(CxxPlatform cxxPlatform) {
return CxxPreprocessorInput.builder()
.addRules(
header.getBuildTarget(),
headerSymlinkTree.getBuildTarget())
.addIncludeRoots(headerSymlinkTreeRoot)
.build();
}
@Override
public NativeLinkableInput getNativeLinkableInput(
CxxPlatform cxxPlatform,
Linker.LinkableDepType type) {
return ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(
new BuildTargetSourcePath(getProjectFilesystem(), archive.getBuildTarget())),
ImmutableList.of(archiveOutput.toString()));
}
@Override
public PythonPackageComponents getPythonPackageComponents(CxxPlatform cxxPlatform) {
return ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of());
}
@Override
public Iterable<AndroidPackageable> getRequiredPackageables() {
return ImmutableList.of();
}
@Override
public void addToCollector(AndroidPackageableCollector collector) {}
@Override
public ImmutableMap<String, SourcePath> getSharedLibraries(CxxPlatform cxxPlatform) {
return ImmutableMap.of();
}
};
resolver.addAllToIndex(ImmutableList.of(header, headerSymlinkTree, archive, dep));
// Setup the build params we'll pass to description when generating the build rules.
BuildTarget target = BuildTargetFactory.newInstance("//:rule");
String headerName = "test/bar.h";
CxxLibraryBuilder cxxLibraryBuilder = (CxxLibraryBuilder) new CxxLibraryBuilder(target)
.setExportedHeaders(
ImmutableList.<SourcePath>of(
new TestSourcePath(headerName),
new BuildTargetSourcePath(projectFilesystem, genHeaderTarget)))
.setSrcs(
ImmutableList.of(
SourceWithFlags.of(new TestSourcePath("test/bar.cpp")),
SourceWithFlags.of(new BuildTargetSourcePath(projectFilesystem, genSourceTarget))))
.setDeps(ImmutableSortedSet.of(dep.getBuildTarget()));
CxxLibrary rule = (CxxLibrary) cxxLibraryBuilder.build(
resolver,
new FakeProjectFilesystem(),
TargetGraphFactory.newInstance(
cxxLibraryBuilder.build(),
genSourceBuilder.build(),
genHeaderBuilder.build(),
GenruleBuilder.newGenruleBuilder(depTarget)
.build()));
Path headerRoot =
CxxDescriptionEnhancer.getHeaderSymlinkTreePath(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC);
assertEquals(
CxxPreprocessorInput.builder()
.addRules(
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC))
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get(headerName),
new TestSourcePath(headerName))
.putNameToPathMap(
Paths.get(genHeaderName),
new BuildTargetSourcePath(projectFilesystem, genHeaderTarget))
.putFullNameToPathMap(
headerRoot.resolve(headerName),
new TestSourcePath(headerName))
.putFullNameToPathMap(
headerRoot.resolve(genHeaderName),
new BuildTargetSourcePath(projectFilesystem, genHeaderTarget))
.build())
.addIncludeRoots(
CxxDescriptionEnhancer.getHeaderSymlinkTreePath(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC))
.build(),
rule.getCxxPreprocessorInput(cxxPlatform));
// Verify that the archive rule has the correct deps: the object files from our sources.
rule.getNativeLinkableInput(cxxPlatform, Linker.LinkableDepType.STATIC);
BuildRule archiveRule = resolver.getRule(
CxxDescriptionEnhancer.createStaticLibraryBuildTarget(target, cxxPlatform.getFlavor()));
assertNotNull(archiveRule);
assertEquals(
ImmutableSet.of(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ false),
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ false)),
FluentIterable.from(archiveRule.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the preprocess rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule preprocessRule1 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ false,
"test/bar.cpp"));
assertEquals(
ImmutableSet.of(
genHeaderTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(preprocessRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule compileRule1 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ false));
assertNotNull(compileRule1);
assertEquals(
ImmutableSet.of(
preprocessRule1.getBuildTarget()),
FluentIterable.from(compileRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the preprocess rule for our genrule-generated source has correct deps setup
// for the various header rules and the generating genrule.
BuildRule preprocessRule2 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ false,
genSourceName));
assertEquals(
ImmutableSet.of(
genHeaderTarget,
genSourceTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(preprocessRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our genrule-generated source has correct deps setup
// for the various header rules and the generating genrule.
BuildRule compileRule2 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ false));
assertNotNull(compileRule2);
assertEquals(
ImmutableSet.of(
preprocessRule2.getBuildTarget()),
FluentIterable.from(compileRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
}
@Test
public void overrideSoname() {
BuildRuleResolver resolver = new BuildRuleResolver();
FakeProjectFilesystem filesystem = new FakeProjectFilesystem();
CxxPlatform cxxPlatform = CxxLibraryBuilder.createDefaultPlatform();
String soname = "test_soname";
// Generate the C++ library rules.
BuildTarget target = BuildTargetFactory.newInstance("//:rule");
CxxLibraryBuilder ruleBuilder = new CxxLibraryBuilder(target)
.setSoname(soname);
CxxLibrary rule = (CxxLibrary) ruleBuilder.build(
resolver,
filesystem,
TargetGraphFactory.newInstance(ruleBuilder.build()));
Linker linker = cxxPlatform.getLd();
NativeLinkableInput input = rule.getNativeLinkableInput(
cxxPlatform,
Linker.LinkableDepType.SHARED);
ImmutableList<SourcePath> inputs = ImmutableList.copyOf(input.getInputs());
assertEquals(inputs.size(), 1);
SourcePath sourcePath = inputs.get(0);
assertTrue(sourcePath instanceof BuildTargetSourcePath);
BuildRule buildRule = new SourcePathResolver(resolver).getRule(sourcePath).get();
assertTrue(buildRule instanceof CxxLink);
CxxLink cxxLink = (CxxLink) buildRule;
ImmutableList<String> args = cxxLink.getArgs();
assertNotEquals(
-1,
Collections.indexOfSubList(
args,
ImmutableList.copyOf(CxxLinkableEnhancer.iXlinker(linker.soname(soname)))));
}
@Test
public void linkWhole() {
FakeProjectFilesystem filesystem = new FakeProjectFilesystem();
CxxPlatform cxxPlatform = CxxLibraryBuilder.createDefaultPlatform();
// Setup the target name and build params.
BuildTarget target = BuildTargetFactory.newInstance("//:test");
// Lookup the link whole flags.
Path staticLib = CxxDescriptionEnhancer.getStaticLibraryPath(target, cxxPlatform.getFlavor());
Linker linker = cxxPlatform.getLd();
Set<String> linkWholeFlags = Sets.newHashSet(linker.linkWhole(staticLib.toString()));
linkWholeFlags.remove(staticLib.toString());
// First, create a cxx library without using link whole.
CxxLibraryBuilder normalBuilder = new CxxLibraryBuilder(target);
CxxLibrary normal = (CxxLibrary) normalBuilder.build(
new BuildRuleResolver(),
filesystem,
TargetGraphFactory.newInstance(normalBuilder.build()));
// Verify that the linker args contains the link whole flags.
assertNotContains(
normal.getNativeLinkableInput(cxxPlatform, Linker.LinkableDepType.STATIC).getArgs(),
linkWholeFlags);
// Create a cxx library using link whole.
CxxLibraryBuilder linkWholeBuilder = new CxxLibraryBuilder(target)
.setLinkWhole(true);
CxxLibrary linkWhole = (CxxLibrary) linkWholeBuilder.build(
new BuildRuleResolver(),
filesystem,
TargetGraphFactory.newInstance(linkWholeBuilder.build()));
// Verify that the linker args contains the link whole flags.
assertContains(
linkWhole.getNativeLinkableInput(cxxPlatform, Linker.LinkableDepType.STATIC).getArgs(),
linkWholeFlags);
}
@Test
@SuppressWarnings("PMD.UseAssertTrueInsteadOfAssertEquals")
public void createCxxLibraryBuildRules() {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
CxxPlatform cxxPlatform = CxxLibraryBuilder.createDefaultPlatform();
// Setup a normal C++ source
String sourceName = "test/bar.cpp";
// Setup a genrule the generates a header we'll list.
String genHeaderName = "test/foo.h";
BuildTarget genHeaderTarget = BuildTargetFactory.newInstance("//:genHeader");
GenruleBuilder genHeaderBuilder = GenruleBuilder
.newGenruleBuilder(genHeaderTarget)
.setOut(genHeaderName);
genHeaderBuilder.build(resolver);
// Setup a genrule the generates a source we'll list.
String genSourceName = "test/foo.cpp";
BuildTarget genSourceTarget = BuildTargetFactory.newInstance("//:genSource");
GenruleBuilder genSourceBuilder = GenruleBuilder
.newGenruleBuilder(genSourceTarget)
.setOut(genSourceName);
genSourceBuilder.build(resolver);
// Setup a C/C++ library that we'll depend on form the C/C++ binary description.
final BuildRule header = new FakeBuildRule("//:header", pathResolver);
final BuildRule headerSymlinkTree = new FakeBuildRule("//:symlink", pathResolver);
final Path headerSymlinkTreeRoot = Paths.get("symlink/tree/root");
final BuildRule staticLibraryDep = new FakeBuildRule("//:static", pathResolver);
final Path staticLibraryOutput = Paths.get("output/path/lib.a");
final BuildRule sharedLibraryDep = new FakeBuildRule("//:shared", pathResolver);
final Path sharedLibraryOutput = Paths.get("output/path/lib.so");
final String sharedLibrarySoname = "soname";
BuildTarget depTarget = BuildTargetFactory.newInstance("//:dep");
BuildRuleParams depParams = BuildRuleParamsFactory.createTrivialBuildRuleParams(depTarget);
AbstractCxxLibrary dep = new AbstractCxxLibrary(depParams, pathResolver) {
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(CxxPlatform cxxPlatform) {
return CxxPreprocessorInput.builder()
.addRules(
header.getBuildTarget(),
headerSymlinkTree.getBuildTarget())
.addIncludeRoots(headerSymlinkTreeRoot)
.build();
}
@Override
public NativeLinkableInput getNativeLinkableInput(
CxxPlatform cxxPlatform,
Linker.LinkableDepType type) {
return type == Linker.LinkableDepType.STATIC ?
ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(
new BuildTargetSourcePath(
getProjectFilesystem(),
staticLibraryDep.getBuildTarget())),
ImmutableList.of(staticLibraryOutput.toString())) :
ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(
new BuildTargetSourcePath(
getProjectFilesystem(),
sharedLibraryDep.getBuildTarget())),
ImmutableList.of(sharedLibraryOutput.toString()));
}
@Override
public PythonPackageComponents getPythonPackageComponents(CxxPlatform cxxPlatform) {
return ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(
Paths.get(sharedLibrarySoname),
new PathSourcePath(getProjectFilesystem(), sharedLibraryOutput)));
}
@Override
public Iterable<AndroidPackageable> getRequiredPackageables() {
return ImmutableList.of();
}
@Override
public void addToCollector(AndroidPackageableCollector collector) {}
@Override
public ImmutableMap<String, SourcePath> getSharedLibraries(CxxPlatform cxxPlatform) {
return ImmutableMap.of();
}
};
resolver.addAllToIndex(
ImmutableList.of(
header,
headerSymlinkTree,
staticLibraryDep,
sharedLibraryDep,
dep));
// Setup the build params we'll pass to description when generating the build rules.
BuildTarget target = BuildTargetFactory.newInstance("//:rule");
CxxLibraryBuilder cxxLibraryBuilder = (CxxLibraryBuilder) new CxxLibraryBuilder(target)
.setExportedHeaders(
ImmutableMap.<String, SourcePath>of(
genHeaderName, new BuildTargetSourcePath(projectFilesystem, genHeaderTarget)))
.setSrcs(
ImmutableMap.of(
sourceName,
SourceWithFlags.of(new TestSourcePath(sourceName)),
genSourceName,
SourceWithFlags.of(new BuildTargetSourcePath(projectFilesystem, genSourceTarget))))
.setDeps(ImmutableSortedSet.of(dep.getBuildTarget()));
// Construct C/C++ library build rules.
CxxLibrary rule = (CxxLibrary) cxxLibraryBuilder.build(
resolver,
new FakeProjectFilesystem(),
TargetGraphFactory.newInstance(
cxxLibraryBuilder.build(),
genSourceBuilder.build(),
genHeaderBuilder.build(),
GenruleBuilder.newGenruleBuilder(depTarget)
.build()));
// Verify the C/C++ preprocessor input is setup correctly.
Path headerRoot =
CxxDescriptionEnhancer.getHeaderSymlinkTreePath(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC);
assertEquals(
CxxPreprocessorInput.builder()
.addRules(
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC))
.setIncludes(
ImmutableCxxHeaders.builder()
.putNameToPathMap(
Paths.get(genHeaderName),
new BuildTargetSourcePath(projectFilesystem, genHeaderTarget))
.putFullNameToPathMap(
headerRoot.resolve(genHeaderName),
new BuildTargetSourcePath(projectFilesystem, genHeaderTarget))
.build())
.addIncludeRoots(
CxxDescriptionEnhancer.getHeaderSymlinkTreePath(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC))
.build(),
rule.getCxxPreprocessorInput(cxxPlatform));
// Verify that the archive rule has the correct deps: the object files from our sources.
rule.getNativeLinkableInput(cxxPlatform, Linker.LinkableDepType.STATIC);
BuildRule staticRule = resolver.getRule(
CxxDescriptionEnhancer.createStaticLibraryBuildTarget(target, cxxPlatform.getFlavor()));
assertNotNull(staticRule);
assertEquals(
ImmutableSet.of(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ false),
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ false)),
FluentIterable.from(staticRule.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule staticPreprocessRule1 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ false,
"test/bar.cpp"));
assertNotNull(staticPreprocessRule1);
assertEquals(
ImmutableSet.of(
genHeaderTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(staticPreprocessRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule staticCompileRule1 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ false));
assertNotNull(staticCompileRule1);
assertEquals(
ImmutableSet.of(staticPreprocessRule1.getBuildTarget()),
FluentIterable.from(staticCompileRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our genrule-generated source has correct deps setup
// for the various header rules and the generating genrule.
BuildRule staticPreprocessRule2 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ false,
genSourceName));
assertNotNull(staticPreprocessRule2);
assertEquals(
ImmutableSet.of(
genHeaderTarget,
genSourceTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(staticPreprocessRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule staticCompileRule2 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ false));
assertNotNull(staticCompileRule2);
assertEquals(
ImmutableSet.of(staticPreprocessRule2.getBuildTarget()),
FluentIterable.from(staticCompileRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the archive rule has the correct deps: the object files from our sources.
rule.getNativeLinkableInput(cxxPlatform, Linker.LinkableDepType.SHARED);
BuildRule sharedRule = resolver.getRule(
CxxDescriptionEnhancer.createSharedLibraryBuildTarget(target, cxxPlatform.getFlavor()));
assertNotNull(sharedRule);
assertEquals(
ImmutableSet.of(
sharedLibraryDep.getBuildTarget(),
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ true),
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ true)),
FluentIterable.from(sharedRule.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule sharedPreprocessRule1 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ true,
"test/bar.cpp"));
assertNotNull(sharedPreprocessRule1);
assertEquals(
ImmutableSet.of(
genHeaderTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(sharedPreprocessRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule sharedCompileRule1 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ true));
assertNotNull(sharedCompileRule1);
assertEquals(
ImmutableSet.of(sharedPreprocessRule1.getBuildTarget()),
FluentIterable.from(sharedCompileRule1.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our genrule-generated source has correct deps setup
// for the various header rules and the generating genrule.
BuildRule sharedPreprocessRule2 = resolver.getRule(
CxxPreprocessables.createPreprocessBuildTarget(
target,
cxxPlatform.getFlavor(),
CxxSource.Type.CXX,
/* pic */ true,
genSourceName));
assertNotNull(sharedPreprocessRule2);
assertEquals(
ImmutableSet.of(
genHeaderTarget,
genSourceTarget,
headerSymlinkTree.getBuildTarget(),
header.getBuildTarget(),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PRIVATE),
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
target,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.HeaderVisibility.PUBLIC)),
FluentIterable.from(sharedPreprocessRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the compile rule for our user-provided source has correct deps setup
// for the various header rules.
BuildRule sharedCompileRule2 = resolver.getRule(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ true));
assertNotNull(sharedCompileRule2);
assertEquals(
ImmutableSet.of(sharedPreprocessRule2.getBuildTarget()),
FluentIterable.from(sharedCompileRule2.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Check the python interface returning by this C++ library.
PythonPackageComponents expectedPythonPackageComponents = ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(
Paths.get(CxxDescriptionEnhancer.getSharedLibrarySoname(target, cxxPlatform)),
new BuildTargetSourcePath(projectFilesystem, sharedRule.getBuildTarget())));
assertEquals(
expectedPythonPackageComponents,
rule.getPythonPackageComponents(cxxPlatform));
}
}