blob: 7f3b2198a3caa9fcde45e67ca2045985ae95ab2e [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.assertNotNull;
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.FakeBuildRuleParamsBuilder;
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.Genrule;
import com.facebook.buck.shell.GenruleBuilder;
import com.facebook.buck.testutil.FakeProjectFilesystem;
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 org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
public class CxxBinaryDescriptionTest {
private static FakeBuildRule createFakeBuildRule(
String target,
SourcePathResolver resolver,
BuildRule... deps) {
return new FakeBuildRule(
new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance(target))
.setDeps(ImmutableSortedSet.copyOf(deps))
.build(),
resolver);
}
@Test
@SuppressWarnings("PMD.UseAssertTrueInsteadOfAssertEquals")
public void createBuildRule() {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
BuildRuleResolver resolver = new BuildRuleResolver();
SourcePathResolver pathResolver = new SourcePathResolver(resolver);
CxxPlatform cxxPlatform = CxxBinaryBuilder.createDefaultPlatform();
// Setup a genrule the generates a header we'll list.
String genHeaderName = "test/foo.h";
BuildTarget genHeaderTarget = BuildTargetFactory.newInstance("//:genHeader");
Genrule genHeader = (Genrule) GenruleBuilder
.newGenruleBuilder(genHeaderTarget)
.setOut(genHeaderName)
.build(resolver);
// Setup a genrule the generates a source we'll list.
String genSourceName = "test/foo.cpp";
BuildTarget genSourceTarget = BuildTargetFactory.newInstance("//:genSource");
Genrule genSource = (Genrule) GenruleBuilder
.newGenruleBuilder(genSourceTarget)
.setOut(genSourceName)
.build(resolver);
// Setup a C/C++ library that we'll depend on form the C/C++ binary description.
final BuildRule header = createFakeBuildRule("//:header", pathResolver);
final BuildRule headerSymlinkTree = createFakeBuildRule("//:symlink", pathResolver);
final Path headerSymlinkTreeRoot = Paths.get("symlink/tree/root");
final BuildRule archive = createFakeBuildRule("//: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");
CxxBinary binRule = (CxxBinary) new CxxBinaryBuilder(target)
.setSrcs(
ImmutableList.of(
SourceWithFlags.of(new TestSourcePath("test/bar.cpp")),
SourceWithFlags.of(
new BuildTargetSourcePath(projectFilesystem, genSource.getBuildTarget()))))
.setHeaders(
ImmutableList.<SourcePath>of(
new TestSourcePath("test/bar.h"),
new BuildTargetSourcePath(projectFilesystem, genHeader.getBuildTarget())))
.setDeps(ImmutableSortedSet.of(dep.getBuildTarget()))
.build(resolver);
CxxLink rule = binRule.getRule();
// Check that link rule has the expected deps: the object files for our sources and the
// archive from the dependency.
assertEquals(
ImmutableSet.of(
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
"test/bar.cpp",
/* pic */ false),
CxxCompilableEnhancer.createCompileBuildTarget(
target,
cxxPlatform.getFlavor(),
genSourceName,
/* pic */ false),
archive.getBuildTarget()),
FluentIterable.from(rule.getDeps())
.transform(HasBuildTarget.TO_TARGET)
.toSet());
// Verify that the preproces 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)),
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 preproces rule for our user-provided source has correct deps setup
// for the various header rules.
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)),
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());
}
}