blob: d94575962a48584fd6e802b88a4eb77c06da8fff [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.assertTrue;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.python.ImmutablePythonPackageComponents;
import com.facebook.buck.python.PythonPackageComponents;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.PathSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.testutil.AllExistingProjectFilesystem;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.TargetGraphFactory;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PrebuiltCxxLibraryDescriptionTest {
private static final BuildTarget TARGET = BuildTargetFactory.newInstance("//:target");
private static final CxxPlatform CXX_PLATFORM = PrebuiltCxxLibraryBuilder.createDefaultPlatform();
private static Path getStaticLibraryPath(PrebuiltCxxLibraryDescription.Arg arg) {
String libDir = arg.libDir.or("lib");
String libName = arg.libName.or(TARGET.getShortName());
return TARGET.getBasePath().resolve(libDir).resolve(
String.format("lib%s.a", libName));
}
private static Path getSharedLibraryPath(PrebuiltCxxLibraryDescription.Arg arg) {
String libDir = arg.libDir.or("lib");
String libName = arg.libName.or(TARGET.getShortName());
return TARGET.getBasePath().resolve(libDir).resolve(
String.format("lib%s.so", libName));
}
private static String getSharedLibrarySoname(PrebuiltCxxLibraryDescription.Arg arg) {
String libName = arg.libName.or(TARGET.getShortName());
return arg.soname.or(String.format("lib%s.so", libName));
}
private static ImmutableList<Path> getIncludeDirs(PrebuiltCxxLibraryDescription.Arg arg) {
return FluentIterable
.from(arg.includeDirs.or(ImmutableList.of("include")))
.transform(
new Function<String, Path>() {
@Override
public Path apply(String input) {
return TARGET.getBasePath().resolve(input);
}
})
.toList();
}
@Test
public void createBuildRuleDefault() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(resolver, filesystem);
PrebuiltCxxLibraryDescription.Arg arg = libBuilder.build().getConstructorArg();
// Verify the preprocessable input is as expected.
CxxPreprocessorInput expectedCxxPreprocessorInput = CxxPreprocessorInput.builder()
.addAllSystemIncludeRoots(getIncludeDirs(arg))
.build();
assertEquals(
expectedCxxPreprocessorInput,
lib.getCxxPreprocessorInput(CXX_PLATFORM));
// Verify static native linkable input.
NativeLinkableInput expectedStaticLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getStaticLibraryPath(arg))),
ImmutableList.of(getStaticLibraryPath(arg).toString()));
assertEquals(
expectedStaticLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.STATIC));
// Verify shared native linkable input.
NativeLinkableInput expectedSharedLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getSharedLibraryPath(arg))),
ImmutableList.of(getSharedLibraryPath(arg).toString()));
assertEquals(
expectedSharedLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.SHARED));
// Verify the python packageable components are correct.
PythonPackageComponents expectedComponents = ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(
Paths.get(getSharedLibrarySoname(arg)),
new PathSourcePath(filesystem, getSharedLibraryPath(arg))));
assertEquals(
expectedComponents,
lib.getPythonPackageComponents(CXX_PLATFORM));
}
@Test
public void createBuildRuleHeaderOnly() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET)
.setHeaderOnly(true);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(resolver, filesystem);
PrebuiltCxxLibraryDescription.Arg arg = libBuilder.build().getConstructorArg();
// Verify the preprocessable input is as expected.
CxxPreprocessorInput expectedCxxPreprocessorInput = CxxPreprocessorInput.builder()
.addAllSystemIncludeRoots(getIncludeDirs(arg))
.build();
assertEquals(
expectedCxxPreprocessorInput,
lib.getCxxPreprocessorInput(CXX_PLATFORM));
// Verify static native linkable input.
NativeLinkableInput expectedStaticLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(),
ImmutableList.<String>of());
assertEquals(
expectedStaticLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.STATIC));
// Verify shared native linkable input.
NativeLinkableInput expectedSharedLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(),
ImmutableList.<String>of());
assertEquals(
expectedSharedLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.SHARED));
// Verify the python packageable components are correct.
PythonPackageComponents expectedComponents = ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of());
assertEquals(
expectedComponents,
lib.getPythonPackageComponents(CXX_PLATFORM));
}
@Test
public void createBuildRuleExternal() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET)
.setProvided(true);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(resolver, filesystem);
PrebuiltCxxLibraryDescription.Arg arg = libBuilder.build().getConstructorArg();
// Verify the preprocessable input is as expected.
CxxPreprocessorInput expectedCxxPreprocessorInput = CxxPreprocessorInput.builder()
.addAllSystemIncludeRoots(getIncludeDirs(arg))
.build();
assertEquals(
expectedCxxPreprocessorInput,
lib.getCxxPreprocessorInput(CXX_PLATFORM));
// Verify static native linkable input.
NativeLinkableInput expectedStaticLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getSharedLibraryPath(arg))),
ImmutableList.of(getSharedLibraryPath(arg).toString()));
assertEquals(
expectedStaticLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.STATIC));
// Verify shared native linkable input.
NativeLinkableInput expectedSharedLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getSharedLibraryPath(arg))),
ImmutableList.of(getSharedLibraryPath(arg).toString()));
assertEquals(
expectedSharedLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.SHARED));
// Verify the python packageable components are correct.
PythonPackageComponents expectedComponents = ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of());
assertEquals(
expectedComponents,
lib.getPythonPackageComponents(CXX_PLATFORM));
}
@Test
public void createBuildRuleIncludeDirs() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET)
.setIncludeDirs(ImmutableList.of("test"));
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(resolver, filesystem);
PrebuiltCxxLibraryDescription.Arg arg = libBuilder.build().getConstructorArg();
// Verify the preprocessable input is as expected.
CxxPreprocessorInput expectedCxxPreprocessorInput = CxxPreprocessorInput.builder()
.addAllSystemIncludeRoots(getIncludeDirs(arg))
.build();
assertEquals(
expectedCxxPreprocessorInput,
lib.getCxxPreprocessorInput(CXX_PLATFORM));
// Verify static native linkable input.
NativeLinkableInput expectedStaticLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getStaticLibraryPath(arg))),
ImmutableList.of(getStaticLibraryPath(arg).toString()));
assertEquals(
expectedStaticLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.STATIC));
// Verify shared native linkable input.
NativeLinkableInput expectedSharedLinkableInput = ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(new PathSourcePath(filesystem, getSharedLibraryPath(arg))),
ImmutableList.of(getSharedLibraryPath(arg).toString()));
assertEquals(
expectedSharedLinkableInput,
lib.getNativeLinkableInput(CXX_PLATFORM, Linker.LinkableDepType.SHARED));
// Verify the python packageable components are correct.
PythonPackageComponents expectedComponents = ImmutablePythonPackageComponents.of(
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(),
ImmutableMap.<Path, SourcePath>of(
Paths.get(getSharedLibrarySoname(arg)),
new PathSourcePath(filesystem, getSharedLibraryPath(arg))));
assertEquals(
expectedComponents,
lib.getPythonPackageComponents(CXX_PLATFORM));
}
@Test
public void missingSharedLibsAreAutoBuilt() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new FakeProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(
resolver,
filesystem,
TargetGraphFactory.newInstance(libBuilder.build()));
NativeLinkableInput nativeLinkableInput = lib.getNativeLinkableInput(
CXX_PLATFORM,
Linker.LinkableDepType.SHARED);
SourcePath input = nativeLinkableInput.getInputs().get(0);
assertTrue(input instanceof BuildTargetSourcePath);
assertTrue(new SourcePathResolver(resolver).getRule(input).get() instanceof CxxLink);
}
@Test
public void missingSharedLibsAreNotAutoBuiltForHeaderOnlyRules() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new FakeProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET)
.setHeaderOnly(true);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(
resolver,
filesystem,
TargetGraphFactory.newInstance(libBuilder.build()));
NativeLinkableInput nativeLinkableInput = lib.getNativeLinkableInput(
CXX_PLATFORM,
Linker.LinkableDepType.SHARED);
assertTrue(nativeLinkableInput.getInputs().isEmpty());
}
@Test
public void addsLibsToAndroidPackageableCollector() {
BuildRuleResolver resolver = new BuildRuleResolver();
ProjectFilesystem filesystem = new AllExistingProjectFilesystem();
PrebuiltCxxLibraryBuilder libBuilder = new PrebuiltCxxLibraryBuilder(TARGET);
PrebuiltCxxLibrary lib = (PrebuiltCxxLibrary) libBuilder.build(
resolver,
filesystem,
TargetGraphFactory.newInstance(libBuilder.build()));
PrebuiltCxxLibraryDescription.Arg arg = libBuilder.build().getConstructorArg();
assertEquals(
ImmutableMap.<String, SourcePath>of(
getSharedLibrarySoname(arg),
new PathSourcePath(filesystem, getSharedLibraryPath(arg))),
lib.getSharedLibraries(CXX_PLATFORM));
}
@Test
public void platformMacro() {
Optional<String> libDir = Optional.of("libs/$(platform)");
Optional<String> libName = Optional.of("test-$(platform)");
Optional<String> soname = Optional.absent();
CxxPlatform platform1 =
CxxPlatformUtils.DEFAULT_PLATFORM
.withFlavor(ImmutableFlavor.of("PLATFORM1"));
CxxPlatform platform2 =
CxxPlatformUtils.DEFAULT_PLATFORM
.withFlavor(ImmutableFlavor.of("PLATFORM2"));
assertEquals(
"libtest-PLATFORM1.so",
PrebuiltCxxLibraryDescription.getSoname(
TARGET,
platform1, soname, libName));
assertEquals(
"libtest-PLATFORM2.so",
PrebuiltCxxLibraryDescription.getSoname(
TARGET,
platform2, soname, libName));
assertEquals(
TARGET.getBasePath()
.resolve("libs/PLATFORM1/libtest-PLATFORM1.so"),
PrebuiltCxxLibraryDescription.getSharedLibraryPath(TARGET, platform1, libDir, libName));
assertEquals(
TARGET.getBasePath()
.resolve("libs/PLATFORM1/libtest-PLATFORM1.a"),
PrebuiltCxxLibraryDescription.getStaticLibraryPath(TARGET, platform1, libDir, libName));
assertEquals(
TARGET.getBasePath()
.resolve("libs/PLATFORM2/libtest-PLATFORM2.so"),
PrebuiltCxxLibraryDescription.getSharedLibraryPath(TARGET, platform2, libDir, libName));
assertEquals(
TARGET.getBasePath()
.resolve("libs/PLATFORM2/libtest-PLATFORM2.a"),
PrebuiltCxxLibraryDescription.getStaticLibraryPath(TARGET, platform2, libDir, libName));
}
}