blob: da8e25fed5c146d7aadbf75164517baf4df004ff [file] [log] [blame]
/*
* Copyright 2013-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 com.facebook.buck.android.AndroidPackageable;
import com.facebook.buck.android.AndroidPackageableCollector;
import com.facebook.buck.model.Pair;
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.BuildRuleResolver;
import com.facebook.buck.rules.BuildTargetSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SymlinkTree;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* An action graph representation of a C/C++ library from the target graph, providing the
* various interfaces to make it consumable by C/C++ preprocessing and native linkable rules.
*/
public class CxxLibrary extends AbstractCxxLibrary {
private final BuildRuleParams params;
private final BuildRuleResolver ruleResolver;
private final ImmutableMultimap<CxxSource.Type, String> exportedPreprocessorFlags;
private final ImmutableList<String> linkerFlags;
private final ImmutableList<Pair<String, ImmutableList<String>>> platformLinkerFlags;
private final boolean linkWhole;
private final Optional<String> soname;
public CxxLibrary(
BuildRuleParams params,
BuildRuleResolver ruleResolver,
SourcePathResolver pathResolver,
ImmutableMultimap<CxxSource.Type, String> exportedPreprocessorFlags,
ImmutableList<String> linkerFlags,
ImmutableList<Pair<String, ImmutableList<String>>> platformLinkerFlags,
boolean linkWhole,
Optional<String> soname) {
super(params, pathResolver);
this.params = params;
this.ruleResolver = ruleResolver;
this.exportedPreprocessorFlags = exportedPreprocessorFlags;
this.linkerFlags = linkerFlags;
this.platformLinkerFlags = platformLinkerFlags;
this.linkWhole = linkWhole;
this.soname = soname;
}
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(CxxPlatform cxxPlatform) {
BuildRule rule = CxxDescriptionEnhancer.requireBuildRule(
params,
ruleResolver,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR);
Preconditions.checkState(rule instanceof SymlinkTree);
SymlinkTree symlinkTree = (SymlinkTree) rule;
return CxxPreprocessorInput.builder()
.addRules(symlinkTree.getBuildTarget())
.putAllPreprocessorFlags(exportedPreprocessorFlags)
.setIncludes(
ImmutableCxxHeaders.builder()
.putAllNameToPathMap(symlinkTree.getLinks())
.putAllFullNameToPathMap(symlinkTree.getFullLinks())
.build())
.addIncludeRoots(symlinkTree.getRoot())
.build();
}
@Override
public NativeLinkableInput getNativeLinkableInput(
CxxPlatform cxxPlatform,
Linker.LinkableDepType type) {
// Build up the arguments used to link this library. If we're linking the
// whole archive, wrap the library argument in the necessary "ld" flags.
final BuildRule libraryRule;
ImmutableList.Builder<String> linkerArgsBuilder = ImmutableList.builder();
linkerArgsBuilder.addAll(linkerFlags);
linkerArgsBuilder.addAll(
CxxDescriptionEnhancer.getPlatformFlags(
platformLinkerFlags,
cxxPlatform.getFlavor().toString()));
if (type == Linker.LinkableDepType.SHARED) {
Path sharedLibraryPath = CxxDescriptionEnhancer.getSharedLibraryPath(
getBuildTarget(),
cxxPlatform);
libraryRule = CxxDescriptionEnhancer.requireBuildRule(
params,
ruleResolver,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.SHARED_FLAVOR);
linkerArgsBuilder.add(sharedLibraryPath.toString());
} else {
libraryRule = CxxDescriptionEnhancer.requireBuildRule(
params,
ruleResolver,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.STATIC_FLAVOR);
Path staticLibraryPath = CxxDescriptionEnhancer.getStaticLibraryPath(
getBuildTarget(),
cxxPlatform.getFlavor());
if (linkWhole) {
Linker linker = cxxPlatform.getLd();
linkerArgsBuilder.addAll(linker.linkWhole(staticLibraryPath.toString()));
} else {
linkerArgsBuilder.add(staticLibraryPath.toString());
}
}
final ImmutableList<String> linkerArgs = linkerArgsBuilder.build();
return ImmutableNativeLinkableInput.of(
ImmutableList.<SourcePath>of(
new BuildTargetSourcePath(
libraryRule.getProjectFilesystem(),
libraryRule.getBuildTarget())),
linkerArgs);
}
@Override
public PythonPackageComponents getPythonPackageComponents(CxxPlatform cxxPlatform) {
String sharedLibrarySoname =
soname.or(CxxDescriptionEnhancer.getSharedLibrarySoname(getBuildTarget(), cxxPlatform));
BuildRule sharedLibraryBuildRule = CxxDescriptionEnhancer.requireBuildRule(
params,
ruleResolver,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.SHARED_FLAVOR);
return ImmutablePythonPackageComponents.of(
/* modules */ ImmutableMap.<Path, SourcePath>of(),
/* resources */ ImmutableMap.<Path, SourcePath>of(),
/* nativeLibraries */ ImmutableMap.<Path, SourcePath>of(
Paths.get(sharedLibrarySoname),
new BuildTargetSourcePath(
sharedLibraryBuildRule.getProjectFilesystem(),
sharedLibraryBuildRule.getBuildTarget())));
}
@Override
public Iterable<AndroidPackageable> getRequiredPackageables() {
return AndroidPackageableCollector.getPackageableRules(params.getDeps());
}
@Override
public void addToCollector(AndroidPackageableCollector collector) {
collector.addNativeLinkable(this);
}
@Override
public ImmutableMap<String, SourcePath> getSharedLibraries(CxxPlatform cxxPlatform) {
String sharedLibrarySoname =
soname.or(CxxDescriptionEnhancer.getSharedLibrarySoname(getBuildTarget(), cxxPlatform));
BuildRule sharedLibraryBuildRule = CxxDescriptionEnhancer.requireBuildRule(
params,
ruleResolver,
cxxPlatform.getFlavor(),
CxxDescriptionEnhancer.SHARED_FLAVOR);
return ImmutableMap.<String, SourcePath>of(
sharedLibrarySoname,
new BuildTargetSourcePath(
sharedLibraryBuildRule.getProjectFilesystem(),
sharedLibraryBuildRule.getBuildTarget()));
}
}