aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar plf <plf@google.com>2018-02-08 01:42:23 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-08 01:44:21 -0800
commit8a96fe9bc1472656cecc420df881181340b82a40 (patch)
tree176a8d459dc3a8224fea3a5dc62975e0170b91b9 /src
parente7541262293977598ad96d9eb7a83b439eedd634 (diff)
C++: Split C++ library into two classes, compilation and linking
These will be separate calls in the Skylark API. RELNOTES:none PiperOrigin-RevId: 184961734
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java25
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java (renamed from src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java)902
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java26
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java30
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java706
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java52
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java274
10 files changed, 1091 insertions, 976 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index d72d44d015..61f6c2a18c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -48,7 +48,7 @@ import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.apple.ApplePlatform;
import com.google.devtools.build.lib.rules.cpp.CcCommon.CcFlagsSupplier;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.DynamicMode;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
@@ -212,14 +212,15 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
return null;
}
- CcLibraryHelper compilationHelper =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CcCompilationHelper compilationHelper =
+ new CcCompilationHelper(
+ ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
.fromCommon(common)
.addSources(common.getSources())
.addDeps(ImmutableList.of(CppHelper.mallocForTarget(ruleContext)))
.setFake(fake)
.addPrecompiledFiles(precompiledFiles);
- Info.CompilationInfo compilationInfo = compilationHelper.compile();
+ CompilationInfo compilationInfo = compilationHelper.compile();
CppCompilationContext cppCompilationContext = compilationInfo.getCppCompilationContext();
CcCompilationOutputs ccCompilationOutputs = compilationInfo.getCcCompilationOutputs();
@@ -232,11 +233,11 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
&& cppConfiguration.getLinkCompileOutputSeparately()
&& linkStaticness == LinkStaticness.DYNAMIC;
// When linking the object files directly into the resulting binary, we do not need
- // library-level link outputs; thus, we do not let CcLibraryHelper produce link outputs
+ // library-level link outputs; thus, we do not let CcCompilationHelper produce link outputs
// (either shared object files or archives) for a non-library link type [*], and add
// the object files explicitly in determineLinkerArguments.
//
- // When linking the object files into their own library, we want CcLibraryHelper to
+ // When linking the object files into their own library, we want CcCompilationHelper to
// take care of creating the library link outputs for us, so we need to set the link
// type to STATIC_LIBRARY.
//
@@ -245,8 +246,14 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
// output matching a shared object, for example cc_binary(name="foo.so", ...) on linux.
CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
if (linkCompileOutputSeparately) {
- CcLibraryHelper linkingHelper =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CcLinkingHelper linkingHelper =
+ new CcLinkingHelper(
+ ruleContext,
+ semantics,
+ featureConfiguration,
+ ccToolchain,
+ fdoSupport,
+ ruleContext.getConfiguration())
.fromCommon(common)
.addDeps(ImmutableList.of(CppHelper.mallocForTarget(ruleContext)))
.setFake(fake)
@@ -868,7 +875,7 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
instrumentedObjectFiles, !TargetUtils.isTestRule(ruleContext.getRule()) && !fake);
NestedSet<Artifact> headerTokens =
- CcLibraryHelper.collectHeaderTokens(ruleContext, ccCompilationOutputs);
+ CcCompilationHelper.collectHeaderTokens(ruleContext, ccCompilationOutputs);
NestedSet<Artifact> filesToCompile =
ccCompilationOutputs.getFilesToCompile(
cppConfiguration.isLipoContextCollector(),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index 07e2ca9408..8d599be1f1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -43,7 +43,7 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.rules.apple.ApplePlatform;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.SourceCategory;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.SourceCategory;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.CollidingProvidesException;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables;
@@ -60,6 +60,7 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.Nullable;
@@ -149,6 +150,31 @@ public final class CcCommon {
}
/**
+ * Merges a list of output groups into one. The sets for each entry with a given key are merged.
+ */
+ public static Map<String, NestedSet<Artifact>> mergeOutputGroups(
+ ImmutableList<Map<String, NestedSet<Artifact>>> outputGroups) {
+ Map<String, NestedSetBuilder<Artifact>> mergedOutputGroupsBuilder = new TreeMap<>();
+
+ for (Map<String, NestedSet<Artifact>> outputGroup : outputGroups) {
+ for (Map.Entry<String, NestedSet<Artifact>> entryOutputGroup : outputGroup.entrySet()) {
+ String key = entryOutputGroup.getKey();
+ mergedOutputGroupsBuilder.computeIfAbsent(
+ key, (String k) -> NestedSetBuilder.compileOrder());
+ mergedOutputGroupsBuilder.get(key).addTransitive(entryOutputGroup.getValue());
+ }
+ }
+
+ Map<String, NestedSet<Artifact>> mergedOutputGroups = new TreeMap<>();
+ for (Map.Entry<String, NestedSetBuilder<Artifact>> entryOutputGroupBuilder :
+ mergedOutputGroupsBuilder.entrySet()) {
+ mergedOutputGroups.put(
+ entryOutputGroupBuilder.getKey(), entryOutputGroupBuilder.getValue().build());
+ }
+ return mergedOutputGroups;
+ }
+
+ /**
* Returns our own linkopts from the rule attribute. This determines linker
* options to use when building this target and anything that depends on it.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java
index e898aa4820..d6464d1340 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.rules.cpp;
-import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toCollection;
import com.google.common.base.Function;
@@ -22,20 +21,13 @@ import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
-import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.LanguageDependentFragment;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.analysis.Runfiles;
-import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
@@ -52,9 +44,6 @@ import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode;
-import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
-import com.google.devtools.build.lib.rules.cpp.Link.Staticness;
-import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.Pair;
@@ -70,33 +59,24 @@ import java.util.TreeMap;
import javax.annotation.Nullable;
/**
- * A class to create C/C++ compile and link actions in a way that is consistent with cc_library.
- * Rules that generate source files and emulate cc_library on top of that should use this class
- * instead of the lower-level APIs in CppHelper and CppModel.
+ * A class to create C/C++ compile actions in a way that is consistent with cc_library. Rules that
+ * generate source files and emulate cc_library on top of that should use this class instead of the
+ * lower-level APIs in CppHelper and CppModel.
*
* <p>Rules that want to use this class are required to have implicit dependencies on the toolchain,
* the STL, the lipo context, and so on. Optionally, they can also have copts, and malloc
* attributes, but note that these require explicit calls to the corresponding setter methods.
- * TODO(plf): Split this class in two, one for compilation and other for linking.
*/
-public final class CcLibraryHelper {
- /**
- * Similar to {@code OutputGroupInfo.HIDDEN_TOP_LEVEL}, but specific to header token files.
- */
+public final class CcCompilationHelper {
+ /** Similar to {@code OutputGroupInfo.HIDDEN_TOP_LEVEL}, but specific to header token files. */
public static final String HIDDEN_HEADER_TOKENS =
OutputGroupInfo.HIDDEN_OUTPUT_GROUP_PREFIX
+ "hidden_header_tokens"
+ OutputGroupInfo.INTERNAL_SUFFIX;
- /** A string constant for the name of archive library(.a, .lo) output group. */
- public static final String ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME = "archive";
-
- /** A string constant for the name of dynamic library output group. */
- public static final String DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME = "dynamic_library";
-
/**
- * A group of source file types and action names for builds controlled by CcLibraryHelper.
- * Determines what file types CcLibraryHelper considers sources and what action configs are
+ * A group of source file types and action names for builds controlled by CcCompilationHelper.
+ * Determines what file types CcCompilationHelper considers sources and what action configs are
* configured in the CROSSTOOL.
*/
public enum SourceCategory {
@@ -124,150 +104,42 @@ public final class CcLibraryHelper {
this.sourceTypeSet = sourceTypeSet;
}
- /**
- * Returns the set of file types that are valid for this category.
- */
+ /** Returns the set of file types that are valid for this category. */
public FileTypeSet getSourceTypes() {
return sourceTypeSet;
}
}
/** Function for extracting module maps from CppCompilationDependencies. */
- public static final Function<TransitiveInfoCollection, CppModuleMap> CPP_DEPS_TO_MODULES =
+ private static final Function<TransitiveInfoCollection, CppModuleMap> CPP_DEPS_TO_MODULES =
dep -> {
CppCompilationContext context = dep.getProvider(CppCompilationContext.class);
return context == null ? null : context.getCppModuleMap();
};
- /**
- * Contains the providers as well as the compilation and linking outputs, and the compilation
- * context. TODO(plf): Remove outer class Info.
- */
- public static final class Info {
- private final TransitiveInfoProviderMapBuilder providers;
- private final ImmutableMap<String, NestedSet<Artifact>> outputGroups;
+ /** Contains the providers as well as the compilation outputs, and the compilation context. */
+ public static final class CompilationInfo {
+ private final TransitiveInfoProviderMap providers;
+ private final Map<String, NestedSet<Artifact>> outputGroups;
private final CcCompilationOutputs compilationOutputs;
- private final CcLinkingOutputs linkingOutputsExcludingPrecompiledLibraries;
private final CppCompilationContext context;
- /** Contains the providers as well as the compilation outputs, and the compilation context. */
- public static final class CompilationInfo {
- private final TransitiveInfoProviderMap providers;
- private final Map<String, NestedSet<Artifact>> outputGroups;
- private final CcCompilationOutputs compilationOutputs;
- private final CppCompilationContext context;
-
- private CompilationInfo(
- TransitiveInfoProviderMap providers,
- Map<String, NestedSet<Artifact>> outputGroups,
- CcCompilationOutputs compilationOutputs,
- CppCompilationContext context) {
- this.providers = providers;
- this.outputGroups = outputGroups;
- this.compilationOutputs = compilationOutputs;
- this.context = context;
- }
-
- public TransitiveInfoProviderMap getProviders() {
- return providers;
- }
-
- public Map<String, NestedSet<Artifact>> getOutputGroups() {
- return outputGroups;
- }
-
- public CcCompilationOutputs getCcCompilationOutputs() {
- return compilationOutputs;
- }
-
- public CppCompilationContext getCppCompilationContext() {
- return context;
- }
- }
-
- /** Contains the providers as well as the linking outputs. */
- public static final class LinkingInfo {
- private final TransitiveInfoProviderMap providers;
- private final Map<String, NestedSet<Artifact>> outputGroups;
- private final CcLinkingOutputs linkingOutputs;
- private final CcLinkingOutputs linkingOutputsExcludingPrecompiledLibraries;
-
- private LinkingInfo(
- TransitiveInfoProviderMap providers,
- Map<String, NestedSet<Artifact>> outputGroups,
- CcLinkingOutputs linkingOutputs,
- CcLinkingOutputs linkingOutputsExcludingPrecompiledLibraries) {
- this.providers = providers;
- this.outputGroups = outputGroups;
- this.linkingOutputs = linkingOutputs;
- this.linkingOutputsExcludingPrecompiledLibraries =
- linkingOutputsExcludingPrecompiledLibraries;
- }
-
- public TransitiveInfoProviderMap getProviders() {
- return providers;
- }
-
- public Map<String, NestedSet<Artifact>> getOutputGroups() {
- return outputGroups;
- }
-
- public CcLinkingOutputs getCcLinkingOutputs() {
- return linkingOutputs;
- }
-
- /**
- * Returns the linking outputs before adding the pre-compiled libraries. Avoid using this -
- * pre-compiled and locally compiled libraries should be treated identically. This method only
- * exists for backwards compatibility.
- */
- public CcLinkingOutputs getCcLinkingOutputsExcludingPrecompiledLibraries() {
- return linkingOutputsExcludingPrecompiledLibraries;
- }
-
- /**
- * Adds the static, pic-static libraries to the given builder. If addDynamicLibraries
- * parameter is true, it also adds dynamic(both compile-time and execution-time) libraries.
- */
- public void addLinkingOutputsTo(
- NestedSetBuilder<Artifact> filesBuilder, boolean addDynamicLibraries) {
- filesBuilder
- .addAll(LinkerInputs.toLibraryArtifacts(linkingOutputs.getStaticLibraries()))
- .addAll(LinkerInputs.toLibraryArtifacts(linkingOutputs.getPicStaticLibraries()));
- if (addDynamicLibraries) {
- filesBuilder
- .addAll(LinkerInputs.toNonSolibArtifacts(linkingOutputs.getDynamicLibraries()))
- .addAll(
- LinkerInputs.toNonSolibArtifacts(linkingOutputs.getExecutionDynamicLibraries()));
- }
- }
-
- public void addLinkingOutputsTo(NestedSetBuilder<Artifact> filesBuilder) {
- addLinkingOutputsTo(filesBuilder, true);
- }
- }
-
- public Info(CompilationInfo compilationInfo, LinkingInfo linkingInfo) {
- this.providers =
- new TransitiveInfoProviderMapBuilder()
- .addAll(compilationInfo.getProviders())
- .addAll(linkingInfo.getProviders());
- this.outputGroups =
- ImmutableMap.copyOf(
- Iterables.concat(
- compilationInfo.getOutputGroups().entrySet(),
- linkingInfo.getOutputGroups().entrySet()));
- this.compilationOutputs = compilationInfo.getCcCompilationOutputs();
- this.linkingOutputsExcludingPrecompiledLibraries =
- linkingInfo.getCcLinkingOutputsExcludingPrecompiledLibraries();
- this.context = compilationInfo.getCppCompilationContext();
+ private CompilationInfo(
+ TransitiveInfoProviderMap providers,
+ Map<String, NestedSet<Artifact>> outputGroups,
+ CcCompilationOutputs compilationOutputs,
+ CppCompilationContext context) {
+ this.providers = providers;
+ this.outputGroups = outputGroups;
+ this.compilationOutputs = compilationOutputs;
+ this.context = context;
}
public TransitiveInfoProviderMap getProviders() {
- return providers.build();
+ return providers;
}
- public ImmutableMap<String, NestedSet<Artifact>> getOutputGroups() {
+ public Map<String, NestedSet<Artifact>> getOutputGroups() {
return outputGroups;
}
@@ -275,43 +147,9 @@ public final class CcLibraryHelper {
return compilationOutputs;
}
- /**
- * Returns the linking outputs before adding the pre-compiled libraries. Avoid using this -
- * pre-compiled and locally compiled libraries should be treated identically. This method only
- * exists for backwards compatibility.
- */
- public CcLinkingOutputs getCcLinkingOutputsExcludingPrecompiledLibraries() {
- return linkingOutputsExcludingPrecompiledLibraries;
- }
-
public CppCompilationContext getCppCompilationContext() {
return context;
}
-
- /**
- * Merges a list of output groups into one. The sets for each entry with a given key are merged.
- */
- public static Map<String, NestedSet<Artifact>> mergeOutputGroups(
- Map<String, NestedSet<Artifact>>... outputGroups) {
- Map<String, NestedSetBuilder<Artifact>> mergedOutputGroupsBuilder = new TreeMap<>();
-
- for (Map<String, NestedSet<Artifact>> outputGroup : outputGroups) {
- for (Map.Entry<String, NestedSet<Artifact>> entryOutputGroup : outputGroup.entrySet()) {
- String key = entryOutputGroup.getKey();
- mergedOutputGroupsBuilder.computeIfAbsent(
- key, (String k) -> NestedSetBuilder.compileOrder());
- mergedOutputGroupsBuilder.get(key).addTransitive(entryOutputGroup.getValue());
- }
- }
-
- Map<String, NestedSet<Artifact>> mergedOutputGroups = new TreeMap<>();
- for (Map.Entry<String, NestedSetBuilder<Artifact>> entryOutputGroupBuilder :
- mergedOutputGroupsBuilder.entrySet()) {
- mergedOutputGroups.put(
- entryOutputGroupBuilder.getKey(), entryOutputGroupBuilder.getValue().build());
- }
- return mergedOutputGroups;
- }
}
private final RuleContext ruleContext;
@@ -330,86 +168,72 @@ public final class CcLibraryHelper {
private final Set<CppSource> compilationUnitSources = new LinkedHashSet<>();
private final List<Artifact> objectFiles = new ArrayList<>();
private final List<Artifact> picObjectFiles = new ArrayList<>();
- private final List<Artifact> nonCodeLinkerInputs = new ArrayList<>();
private ImmutableList<String> copts = ImmutableList.of();
- private final List<String> linkopts = new ArrayList<>();
private CoptsFilter coptsFilter = CoptsFilter.alwaysPasses();
private final Set<String> defines = new LinkedHashSet<>();
private final List<TransitiveInfoCollection> deps = new ArrayList<>();
private final List<CppCompilationContext> depContexts = new ArrayList<>();
- private final NestedSetBuilder<Artifact> linkstamps = NestedSetBuilder.stableOrder();
private final List<PathFragment> looseIncludeDirs = new ArrayList<>();
private final List<PathFragment> systemIncludeDirs = new ArrayList<>();
private final List<PathFragment> includeDirs = new ArrayList<>();
- private final List<Artifact> linkActionInputs = new ArrayList<>();
- @Nullable private Artifact dynamicLibrary;
- private LinkTargetType linkType = LinkTargetType.STATIC_LIBRARY;
private HeadersCheckingMode headersCheckingMode = HeadersCheckingMode.LOOSE;
- private boolean neverlink;
private boolean fake;
- private final List<LibraryToLink> staticLibraries = new ArrayList<>();
- private final List<LibraryToLink> picStaticLibraries = new ArrayList<>();
- private final List<LibraryToLink> dynamicLibraries = new ArrayList<>();
- private final List<LibraryToLink> executionDynamicLibraries = new ArrayList<>();
-
- private boolean emitLinkActions = true;
- private boolean emitLinkActionsIfEmpty;
- private boolean emitCcNativeLibrariesProvider;
- private boolean emitCcSpecificLinkParamsProvider;
- private boolean emitInterfaceSharedObjects;
- private boolean createDynamicLibrary = true;
- private boolean createStaticLibraries = true;
private boolean checkDepsGenerateCpp = true;
private boolean emitCompileProviders;
private final SourceCategory sourceCategory;
- private List<VariablesExtension> variablesExtensions = new ArrayList<>();
+ private final List<VariablesExtension> variablesExtensions = new ArrayList<>();
@Nullable private CppModuleMap cppModuleMap;
private boolean propagateModuleMapToCompileAction = true;
private final FeatureConfiguration featureConfiguration;
- private CcToolchainProvider ccToolchain;
+ private final CcToolchainProvider ccToolchain;
private final FdoSupportProvider fdoSupport;
- private String linkedArtifactNameSuffix = "";
private boolean useDeps = true;
private boolean generateModuleMap = true;
private String purpose = null;
private boolean generateNoPic = true;
/**
- * Creates a CcLibraryHelper.
+ * Creates a CcCompilationHelper.
*
- * @param ruleContext the RuleContext for the rule being built
- * @param semantics CppSemantics for the build
- * @param featureConfiguration activated features and action configs for the build
- * @param sourceCatagory the candidate source types for the build
+ * @param ruleContext the RuleContext for the rule being built
+ * @param semantics CppSemantics for the build
+ * @param featureConfiguration activated features and action configs for the build
+ * @param sourceCatagory the candidate source types for the build
* @param ccToolchain the C++ toolchain provider for the build
* @param fdoSupport the C++ FDO optimization support provider for the build
*/
- public CcLibraryHelper(
+ public CcCompilationHelper(
RuleContext ruleContext,
CppSemantics semantics,
FeatureConfiguration featureConfiguration,
SourceCategory sourceCatagory,
CcToolchainProvider ccToolchain,
FdoSupportProvider fdoSupport) {
- this(ruleContext, semantics, featureConfiguration, sourceCatagory, ccToolchain, fdoSupport,
+ this(
+ ruleContext,
+ semantics,
+ featureConfiguration,
+ sourceCatagory,
+ ccToolchain,
+ fdoSupport,
ruleContext.getConfiguration());
}
/**
- * Creates a CcLibraryHelper that outputs artifacts in a given configuration.
+ * Creates a CcCompilationHelper that outputs artifacts in a given configuration.
*
- * @param ruleContext the RuleContext for the rule being built
- * @param semantics CppSemantics for the build
- * @param featureConfiguration activated features and action configs for the build
- * @param sourceCatagory the candidate source types for the build
+ * @param ruleContext the RuleContext for the rule being built
+ * @param semantics CppSemantics for the build
+ * @param featureConfiguration activated features and action configs for the build
+ * @param sourceCatagory the candidate source types for the build
* @param ccToolchain the C++ toolchain provider for the build
* @param fdoSupport the C++ FDO optimization support provider for the build
* @param configuration the configuration that gives the directory of output artifacts
*/
- public CcLibraryHelper(
+ public CcCompilationHelper(
RuleContext ruleContext,
CppSemantics semantics,
FeatureConfiguration featureConfiguration,
@@ -427,7 +251,7 @@ public final class CcLibraryHelper {
}
/**
- * Creates a CcLibraryHelper for cpp source files.
+ * Creates a CcCompilationHelper for cpp source files.
*
* @param ruleContext the RuleContext for the rule being built
* @param semantics CppSemantics for the build
@@ -435,19 +259,21 @@ public final class CcLibraryHelper {
* @param ccToolchain the C++ toolchain provider for the build
* @param fdoSupport the C++ FDO optimization support provider for the build
*/
- public CcLibraryHelper(
- RuleContext ruleContext, CppSemantics semantics, FeatureConfiguration featureConfiguration,
- CcToolchainProvider ccToolchain, FdoSupportProvider fdoSupport) {
+ public CcCompilationHelper(
+ RuleContext ruleContext,
+ CppSemantics semantics,
+ FeatureConfiguration featureConfiguration,
+ CcToolchainProvider ccToolchain,
+ FdoSupportProvider fdoSupport) {
this(ruleContext, semantics, featureConfiguration, SourceCategory.CC, ccToolchain, fdoSupport);
}
/** Sets fields that overlap for cc_library and cc_binary rules. */
- public CcLibraryHelper fromCommon(CcCommon common) {
+ public CcCompilationHelper fromCommon(CcCommon common) {
setCopts(common.getCopts());
addDefines(common.getDefines());
addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET));
addLooseIncludeDirs(common.getLooseIncludeDirs());
- addNonCodeLinkerInputs(common.getLinkerScripts());
addSystemIncludeDirs(common.getSystemIncludeDirs());
setCoptsFilter(common.getCoptsFilter());
setHeadersCheckingMode(semantics.determineHeadersCheckingMode(ruleContext));
@@ -459,7 +285,7 @@ public final class CcLibraryHelper {
* rules. They may be parsed/preprocessed or compiled into a header module depending on the
* configuration.
*/
- public CcLibraryHelper addPublicHeaders(Collection<Artifact> headers) {
+ public CcCompilationHelper addPublicHeaders(Collection<Artifact> headers) {
for (Artifact header : headers) {
addHeader(header, ruleContext.getLabel());
}
@@ -471,7 +297,7 @@ public final class CcLibraryHelper {
* rules. They may be parsed/preprocessed or compiled into a header module depending on the
* configuration.
*/
- public CcLibraryHelper addPublicHeaders(Artifact... headers) {
+ public CcCompilationHelper addPublicHeaders(Artifact... headers) {
addPublicHeaders(Arrays.asList(headers));
return this;
}
@@ -481,7 +307,7 @@ public final class CcLibraryHelper {
* rules. They may be parsed/preprocessed or compiled into a header module depending on the
* configuration.
*/
- public CcLibraryHelper addPublicHeaders(Iterable<Pair<Artifact, Label>> headers) {
+ public CcCompilationHelper addPublicHeaders(Iterable<Pair<Artifact, Label>> headers) {
for (Pair<Artifact, Label> header : headers) {
addHeader(header.first, header.second);
}
@@ -492,7 +318,7 @@ public final class CcLibraryHelper {
* Add the corresponding files as public header files, i.e., these files will not be compiled, but
* are made visible as includes to dependent rules in module maps.
*/
- public CcLibraryHelper addAdditionalExportedHeaders(
+ public CcCompilationHelper addAdditionalExportedHeaders(
Iterable<PathFragment> additionalExportedHeaders) {
Iterables.addAll(this.additionalExportedHeaders, additionalExportedHeaders);
return this;
@@ -502,7 +328,7 @@ public final class CcLibraryHelper {
* Add the corresponding files as public textual header files. These files will not be compiled
* into a target's header module, but will be made visible as textual includes to dependent rules.
*/
- public CcLibraryHelper addPublicTextualHeaders(Iterable<Artifact> textualHeaders) {
+ public CcCompilationHelper addPublicTextualHeaders(Iterable<Artifact> textualHeaders) {
Iterables.addAll(this.publicTextualHeaders, textualHeaders);
for (Artifact header : textualHeaders) {
this.additionalExportedHeaders.add(header.getExecPath());
@@ -515,7 +341,7 @@ public final class CcLibraryHelper {
* will not be compiled, but also not made visible as includes to dependent rules. The given build
* variables will be added to those used for compiling this source.
*/
- public CcLibraryHelper addSources(Collection<Artifact> sources) {
+ public CcCompilationHelper addSources(Collection<Artifact> sources) {
for (Artifact source : sources) {
addSource(source, ruleContext.getLabel());
}
@@ -526,7 +352,7 @@ public final class CcLibraryHelper {
* Add the corresponding files as source files. These may also be header files, in which case they
* will not be compiled, but also not made visible as includes to dependent rules.
*/
- public CcLibraryHelper addSources(Iterable<Pair<Artifact, Label>> sources) {
+ public CcCompilationHelper addSources(Iterable<Pair<Artifact, Label>> sources) {
for (Pair<Artifact, Label> source : sources) {
addSource(source.first, source.second);
}
@@ -537,12 +363,12 @@ public final class CcLibraryHelper {
* Add the corresponding files as source files. These may also be header files, in which case they
* will not be compiled, but also not made visible as includes to dependent rules.
*/
- public CcLibraryHelper addSources(Artifact... sources) {
+ public CcCompilationHelper addSources(Artifact... sources) {
return addSources(Arrays.asList(sources));
}
/** Add the corresponding files as non-header, non-source input files. */
- public CcLibraryHelper addAdditionalInputs(Collection<Artifact> inputs) {
+ public CcCompilationHelper addAdditionalInputs(Collection<Artifact> inputs) {
Iterables.addAll(additionalInputs, inputs);
return this;
}
@@ -564,7 +390,7 @@ public final class CcLibraryHelper {
}
/** Adds a header to {@code publicHeaders}, but not to this target's module map. */
- public CcLibraryHelper addNonModuleMapHeader(Artifact header) {
+ public CcCompilationHelper addNonModuleMapHeader(Artifact header) {
Preconditions.checkNotNull(header);
nonModuleMapHeaders.add(header);
return this;
@@ -574,7 +400,7 @@ public final class CcLibraryHelper {
* Adds a source to {@code compilationUnitSources} if it is a compiled file type (including
* parsed/preprocessed header) and to {@code privateHeaders} if it is a header.
*/
- private CcLibraryHelper addSource(Artifact source, Label label) {
+ private void addSource(Artifact source, Label label) {
Preconditions.checkNotNull(featureConfiguration);
boolean isHeader = CppFileTypes.CPP_HEADER.matches(source.getExecPath());
boolean isTextualInclude = CppFileTypes.CPP_TEXTUAL_INCLUDE.matches(source.getExecPath());
@@ -586,7 +412,7 @@ public final class CcLibraryHelper {
privateHeaders.add(source);
}
if (isTextualInclude || !isCompiledSource || (isHeader && !shouldProcessHeaders())) {
- return this;
+ return;
}
boolean isClifInputProto = CppFileTypes.CLIF_INPUT_PROTO.matches(source.getExecPathString());
CppSource.Type type;
@@ -598,7 +424,6 @@ public final class CcLibraryHelper {
type = CppSource.Type.SOURCE;
}
compilationUnitSources.add(CppSource.create(source, label, type));
- return this;
}
private boolean shouldProcessHeaders() {
@@ -626,7 +451,7 @@ public final class CcLibraryHelper {
* here, if {@code --start_end_lib} is enabled, but instead at any binary that transitively
* depends on the current rule.
*/
- public CcLibraryHelper addObjectFiles(Iterable<Artifact> objectFiles) {
+ public CcCompilationHelper addObjectFiles(Iterable<Artifact> objectFiles) {
for (Artifact objectFile : objectFiles) {
Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(objectFile.getFilename()));
}
@@ -640,7 +465,7 @@ public final class CcLibraryHelper {
* here, if {@code --start_end_lib} is enabled, but instead at any binary that transitively
* depends on the current rule.
*/
- public CcLibraryHelper addPicObjectFiles(Iterable<Artifact> picObjectFiles) {
+ public CcCompilationHelper addPicObjectFiles(Iterable<Artifact> picObjectFiles) {
for (Artifact objectFile : objectFiles) {
Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(objectFile.getFilename()));
}
@@ -648,115 +473,44 @@ public final class CcLibraryHelper {
return this;
}
- /**
- * Adds the corresponding non-code files as linker inputs.
- */
- public CcLibraryHelper addNonCodeLinkerInputs(Iterable<Artifact> nonCodeLinkerInputs) {
- for (Artifact nonCodeLinkerInput : nonCodeLinkerInputs) {
- String basename = nonCodeLinkerInput.getFilename();
- Preconditions.checkArgument(!Link.OBJECT_FILETYPES.matches(basename));
- Preconditions.checkArgument(!Link.ARCHIVE_LIBRARY_FILETYPES.matches(basename));
- Preconditions.checkArgument(!Link.SHARED_LIBRARY_FILETYPES.matches(basename));
- this.nonCodeLinkerInputs.add(nonCodeLinkerInput);
- }
-
- return this;
- }
-
- /**
- * Add the corresponding files as static libraries into the linker outputs (i.e., after the linker
- * action) - this makes them available for linking to binary rules that depend on this rule.
- */
- public CcLibraryHelper addStaticLibraries(Iterable<LibraryToLink> libraries) {
- Iterables.addAll(staticLibraries, libraries);
- return this;
- }
-
- /**
- * Add the corresponding files as static libraries into the linker outputs (i.e., after the linker
- * action) - this makes them available for linking to binary rules that depend on this rule.
- */
- public CcLibraryHelper addPicStaticLibraries(Iterable<LibraryToLink> libraries) {
- Iterables.addAll(picStaticLibraries, libraries);
- return this;
- }
-
- /**
- * Add the corresponding files as dynamic libraries into the linker outputs (i.e., after the
- * linker action) - this makes them available for linking to binary rules that depend on this
- * rule.
- */
- public CcLibraryHelper addDynamicLibraries(Iterable<LibraryToLink> libraries) {
- Iterables.addAll(dynamicLibraries, libraries);
- return this;
- }
-
- /** Add the corresponding files as dynamic libraries required at runtime */
- public CcLibraryHelper addExecutionDynamicLibraries(Iterable<LibraryToLink> libraries) {
- Iterables.addAll(executionDynamicLibraries, libraries);
- return this;
- }
-
- public CcLibraryHelper setCopts(ImmutableList<String> copts) {
+ public CcCompilationHelper setCopts(ImmutableList<String> copts) {
this.copts = Preconditions.checkNotNull(copts);
return this;
}
/** Sets a pattern that is used to filter copts; set to {@code null} for no filtering. */
- public CcLibraryHelper setCoptsFilter(CoptsFilter coptsFilter) {
+ private void setCoptsFilter(CoptsFilter coptsFilter) {
this.coptsFilter = Preconditions.checkNotNull(coptsFilter);
- return this;
}
- /**
- * Adds the given options as linker options to the link command.
- */
- public CcLibraryHelper addLinkopts(Iterable<String> linkopts) {
- Iterables.addAll(this.linkopts, linkopts);
- return this;
- }
-
- /**
- * Adds the given defines to the compiler command line.
- */
- public CcLibraryHelper addDefines(Iterable<String> defines) {
+ /** Adds the given defines to the compiler command line. */
+ public CcCompilationHelper addDefines(Iterable<String> defines) {
Iterables.addAll(this.defines, defines);
return this;
}
/**
- * Adds the given targets as dependencies - this can include explicit dependencies on other
- * rules (like from a "deps" attribute) and also implicit dependencies on runtime libraries.
+ * Adds the given targets as dependencies - this can include explicit dependencies on other rules
+ * (like from a "deps" attribute) and also implicit dependencies on runtime libraries.
*/
- public CcLibraryHelper addDeps(Iterable<? extends TransitiveInfoCollection> deps) {
+ public CcCompilationHelper addDeps(Iterable<? extends TransitiveInfoCollection> deps) {
for (TransitiveInfoCollection dep : deps) {
this.deps.add(dep);
}
return this;
}
- public CcLibraryHelper addDepContext(CppCompilationContext dep) {
+ public CcCompilationHelper addDepContext(CppCompilationContext dep) {
this.depContexts.add(Preconditions.checkNotNull(dep));
return this;
}
/**
- * Adds the given linkstamps. Note that linkstamps are usually not compiled at the library level,
- * but only in the dependent binary rules.
- */
- public CcLibraryHelper addLinkstamps(Iterable<? extends TransitiveInfoCollection> linkstamps) {
- for (TransitiveInfoCollection linkstamp : linkstamps) {
- this.linkstamps.addTransitive(linkstamp.getProvider(FileProvider.class).getFilesToBuild());
- }
- return this;
- }
-
- /**
* Adds the given precompiled files to this helper. Shared and static libraries are added as
* compilation prerequisites, and object files are added as pic or non-pic object files
* respectively.
*/
- public CcLibraryHelper addPrecompiledFiles(PrecompiledFiles precompiledFiles) {
+ public CcCompilationHelper addPrecompiledFiles(PrecompiledFiles precompiledFiles) {
addObjectFiles(precompiledFiles.getObjectFiles(false));
addPicObjectFiles(precompiledFiles.getObjectFiles(true));
return this;
@@ -767,112 +521,50 @@ public final class CcLibraryHelper {
* referenced when headers checking is {@link HeadersCheckingMode#LOOSE} or {@link
* HeadersCheckingMode#WARN}.
*/
- public CcLibraryHelper addLooseIncludeDirs(Iterable<PathFragment> looseIncludeDirs) {
+ private void addLooseIncludeDirs(Iterable<PathFragment> looseIncludeDirs) {
Iterables.addAll(this.looseIncludeDirs, looseIncludeDirs);
- return this;
}
/**
* Adds the given directories to the system include directories (they are passed with {@code
* "-isystem"} to the compiler); these are also passed to dependent rules.
*/
- public CcLibraryHelper addSystemIncludeDirs(Iterable<PathFragment> systemIncludeDirs) {
+ public CcCompilationHelper addSystemIncludeDirs(Iterable<PathFragment> systemIncludeDirs) {
Iterables.addAll(this.systemIncludeDirs, systemIncludeDirs);
return this;
}
/**
- * Adds the given directories to the include directories (they are passed with {@code "-I"} to
- * the compiler); these are also passed to dependent rules.
+ * Adds the given directories to the include directories (they are passed with {@code "-I"} to the
+ * compiler); these are also passed to dependent rules.
*/
- public CcLibraryHelper addIncludeDirs(Iterable<PathFragment> includeDirs) {
+ public CcCompilationHelper addIncludeDirs(Iterable<PathFragment> includeDirs) {
Iterables.addAll(this.includeDirs, includeDirs);
return this;
}
- /** Adds the given artifact to the input of any generated link actions. */
- public CcLibraryHelper addLinkActionInput(Artifact input) {
- Preconditions.checkNotNull(input);
- this.linkActionInputs.add(input);
- return this;
- }
-
- /**
- * Adds a variableExtension to template the crosstool.
- */
- public CcLibraryHelper addVariableExtension(VariablesExtension variableExtension) {
+ /** Adds a variableExtension to template the crosstool. */
+ public CcCompilationHelper addVariableExtension(VariablesExtension variableExtension) {
Preconditions.checkNotNull(variableExtension);
this.variablesExtensions.add(variableExtension);
return this;
}
- /**
- * Sets a module map artifact for this build.
- */
- public CcLibraryHelper setCppModuleMap(CppModuleMap cppModuleMap) {
+ /** Sets a module map artifact for this build. */
+ public CcCompilationHelper setCppModuleMap(CppModuleMap cppModuleMap) {
Preconditions.checkNotNull(cppModuleMap);
this.cppModuleMap = cppModuleMap;
return this;
}
- /**
- * Signals that this target's module map should not be an input to c++ compile actions.
- */
- public CcLibraryHelper setPropagateModuleMapToCompileAction(boolean propagatesModuleMap) {
+ /** Signals that this target's module map should not be an input to c++ compile actions. */
+ public CcCompilationHelper setPropagateModuleMapToCompileAction(boolean propagatesModuleMap) {
this.propagateModuleMapToCompileAction = propagatesModuleMap;
return this;
}
- /**
- * Overrides the path for the generated dynamic library - this should only be called if the
- * dynamic library is an implicit or explicit output of the rule, i.e., if it is accessible by
- * name from other rules in the same package. Set to {@code null} to use the default computation.
- */
- public CcLibraryHelper setDynamicLibrary(@Nullable Artifact dynamicLibrary) {
- this.dynamicLibrary = dynamicLibrary;
- return this;
- }
-
- /**
- * Marks the output of this rule as alwayslink, i.e., the corresponding symbols will be retained
- * by the linker even if they are not otherwise used. This is useful for libraries that register
- * themselves somewhere during initialization.
- *
- * <p>This only sets the link type (see {@link #setStaticLinkType}), either to a static library or
- * to an alwayslink static library (blaze uses a different file extension to signal alwayslink to
- * downstream code).
- */
- public CcLibraryHelper setAlwayslink(boolean alwayslink) {
- linkType = alwayslink
- ? LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY
- : LinkTargetType.STATIC_LIBRARY;
- return this;
- }
-
- /**
- * Directly set the link type. This can be used instead of {@link #setAlwayslink}. Setting
- * anything other than a static link causes this class to skip the link action creation.
- */
- public CcLibraryHelper setStaticLinkType(LinkTargetType linkType) {
- Preconditions.checkNotNull(linkType);
- Preconditions.checkState(linkType.staticness() == Staticness.STATIC);
- this.linkType = linkType;
- return this;
- }
-
- /**
- * Marks the resulting code as neverlink, i.e., the code will not be linked into dependent
- * libraries or binaries - the header files are still available.
- */
- public CcLibraryHelper setNeverLink(boolean neverlink) {
- this.neverlink = neverlink;
- return this;
- }
-
- /**
- * Sets the given headers checking mode. The default is {@link HeadersCheckingMode#LOOSE}.
- */
- public CcLibraryHelper setHeadersCheckingMode(HeadersCheckingMode headersCheckingMode) {
+ /** Sets the given headers checking mode. The default is {@link HeadersCheckingMode#LOOSE}. */
+ public CcCompilationHelper setHeadersCheckingMode(HeadersCheckingMode headersCheckingMode) {
this.headersCheckingMode = Preconditions.checkNotNull(headersCheckingMode);
return this;
}
@@ -883,125 +575,48 @@ public final class CcLibraryHelper {
* used for non-compilation tests. Unfortunately, the design is problematic, so please don't add
* any further uses.
*/
- public CcLibraryHelper setFake(boolean fake) {
+ public CcCompilationHelper setFake(boolean fake) {
this.fake = fake;
return this;
}
- /*
- * Adds a suffix for paths of linked artifacts. Normally their paths are derived solely from rule
- * labels. In the case of multiple callers (e.g., aspects) acting on a single rule, they may
- * generate the same linked artifact and therefore lead to artifact conflicts. This method
- * provides a way to avoid this artifact conflict by allowing different callers acting on the same
- * rule to provide a suffix that will be used to scope their own linked artifacts.
- */
- public CcLibraryHelper setLinkedArtifactNameSuffix(String suffix) {
- this.linkedArtifactNameSuffix = Preconditions.checkNotNull(suffix);
- return this;
- }
-
- /**
- * This adds the {@link CcNativeLibraryProvider} to the providers created by this class.
- */
- public CcLibraryHelper enableCcNativeLibrariesProvider() {
- this.emitCcNativeLibrariesProvider = true;
- return this;
- }
-
- /**
- * This adds the {@link CcSpecificLinkParamsProvider} to the providers created by this class.
- * Otherwise the result will contain an instance of {@link CcLinkParamsInfo}.
- */
- public CcLibraryHelper enableCcSpecificLinkParamsProvider() {
- this.emitCcSpecificLinkParamsProvider = true;
- return this;
- }
-
- public CcLibraryHelper setEmitLinkActions(boolean emitLinkActions) {
- this.emitLinkActions = emitLinkActions;
- return this;
- }
-
- /**
- * Enables or disables generation of link actions if there are no object files. Some rules declare
- * a <code>.a</code> or <code>.so</code> implicit output, which requires that these files are
- * created even if there are no object files, so be careful when calling this.
- *
- * <p>This is disabled by default.
- */
- public CcLibraryHelper setGenerateLinkActionsIfEmpty(boolean emitLinkActionsIfEmpty) {
- this.emitLinkActionsIfEmpty = emitLinkActionsIfEmpty;
- return this;
- }
-
- /**
- * Enables the optional generation of interface dynamic libraries - this is only used when the
- * linker generates a dynamic library, and only if the crosstool supports it. The default is not
- * to generate interface dynamic libraries.
- */
- public CcLibraryHelper enableInterfaceSharedObjects() {
- this.emitInterfaceSharedObjects = true;
- return this;
- }
-
- /**
- * This enables or disables the generation of a dynamic library link action. The default is to
- * generate a dynamic library. Note that the selection between dynamic or static linking is
- * performed at the binary rule level.
- */
- public CcLibraryHelper setCreateDynamicLibrary(boolean emitDynamicLibrary) {
- this.createDynamicLibrary = emitDynamicLibrary;
- return this;
- }
-
- /** When createStaticLibraries is true, there are no actions created for static libraries. */
- public CcLibraryHelper setCreateStaticLibraries(boolean emitStaticLibraries) {
- this.createStaticLibraries = emitStaticLibraries;
- return this;
- }
-
- public CcLibraryHelper setNeverlink(boolean neverlink) {
- this.neverlink = neverlink;
- return this;
- }
-
/**
* Disables checking that the deps actually are C++ rules. By default, the {@link #compile} method
* uses {@link LanguageDependentFragment.Checker#depSupportsLanguage} to check that all deps
* provide C++ providers.
*/
- public CcLibraryHelper setCheckDepsGenerateCpp(boolean checkDepsGenerateCpp) {
+ public CcCompilationHelper setCheckDepsGenerateCpp(boolean checkDepsGenerateCpp) {
this.checkDepsGenerateCpp = checkDepsGenerateCpp;
return this;
}
/**
- * Enables the output of the {@code files_to_compile} and {@code compilation_prerequisites}
- * output groups.
+ * Enables the output of the {@code files_to_compile} and {@code compilation_prerequisites} output
+ * groups.
*/
// TODO(bazel-team): We probably need to adjust this for the multi-language rules.
- public CcLibraryHelper enableCompileProviders() {
+ public CcCompilationHelper enableCompileProviders() {
this.emitCompileProviders = true;
return this;
}
/**
- * Causes actions generated from this CcLibraryHelper not to use build semantics (includes,
+ * Causes actions generated from this CcCompilationHelper not to use build semantics (includes,
* headers, srcs) from dependencies.
*/
- public CcLibraryHelper doNotUseDeps() {
+ public CcCompilationHelper doNotUseDeps() {
this.useDeps = false;
return this;
}
/** non-PIC actions won't be generated. */
- public CcLibraryHelper setGenerateNoPic(boolean generateNoPic) {
+ public CcCompilationHelper setGenerateNoPic(boolean generateNoPic) {
this.generateNoPic = generateNoPic;
return this;
}
/** Adds mandatory inputs for the compilation action. */
- public CcLibraryHelper addCompilationMandatoryInputs(
+ public CcCompilationHelper addCompilationMandatoryInputs(
Collection<Artifact> compilationMandatoryInputs) {
this.compilationMandatoryInputs.addAll(compilationMandatoryInputs);
return this;
@@ -1010,7 +625,7 @@ public final class CcLibraryHelper {
/** Adds additional includes to be scanned. */
// TODO(plf): This is only needed for CLIF. Investigate whether this is strictly necessary or
// there is a way to avoid include scanning for CLIF rules.
- public CcLibraryHelper addAditionalIncludeScanningRoots(
+ public CcCompilationHelper addAditionalIncludeScanningRoots(
Collection<Artifact> additionalIncludeScanningRoots) {
this.additionalIncludeScanningRoots.addAll(additionalIncludeScanningRoots);
return this;
@@ -1021,7 +636,7 @@ public final class CcLibraryHelper {
*
* @throws RuleErrorException
*/
- public Info.CompilationInfo compile() throws RuleErrorException {
+ public CompilationInfo compile() throws RuleErrorException {
if (checkDepsGenerateCpp) {
for (LanguageDependentFragment dep :
AnalysisUtils.getProviders(deps, LanguageDependentFragment.class)) {
@@ -1085,223 +700,23 @@ public final class CcLibraryHelper {
CcCommon.collectCompilationPrerequisites(ruleContext, cppCompilationContext));
}
- return new Info.CompilationInfo(
- providers.build(), outputGroups, ccOutputs, cppCompilationContext);
+ return new CompilationInfo(providers.build(), outputGroups, ccOutputs, cppCompilationContext);
}
- /**
- * Create the C++ link actions, and the corresponding linking related providers.
- *
- * @throws RuleErrorException
- */
- public Info.LinkingInfo link(
- CcCompilationOutputs ccOutputs, CppCompilationContext cppCompilationContext)
- throws RuleErrorException, InterruptedException {
- Preconditions.checkNotNull(ccOutputs);
- Preconditions.checkNotNull(cppCompilationContext);
-
- if (checkDepsGenerateCpp) {
- for (LanguageDependentFragment dep :
- AnalysisUtils.getProviders(deps, LanguageDependentFragment.class)) {
- LanguageDependentFragment.Checker.depSupportsLanguage(
- ruleContext, dep, CppRuleClasses.LANGUAGE, "deps");
- }
- }
-
- CppModel model = initializeCppModel();
- model.setContext(cppCompilationContext);
-
- // Create link actions (only if there are object files or if explicitly requested).
- CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
- if (emitLinkActions && (emitLinkActionsIfEmpty || !ccOutputs.isEmpty())) {
- // On some systems, the linker gives an error message if there are no input files. Even with
- // the check above, this can still happen if there is a .nopic.o or .o files in srcs, but no
- // other files. To fix that, we'd have to check for each link action individually.
- //
- // An additional pre-existing issue is that the header check tokens are dropped if we don't
- // generate any link actions, effectively disabling header checking in some cases.
- if (linkType.staticness() == Staticness.STATIC) {
- // TODO(bazel-team): This can't create the link action for a cc_binary yet.
- ccLinkingOutputs = model.createCcLinkActions(ccOutputs, nonCodeLinkerInputs);
- }
- }
- CcLinkingOutputs originalLinkingOutputs = ccLinkingOutputs;
- if (!(staticLibraries.isEmpty()
- && picStaticLibraries.isEmpty()
- && dynamicLibraries.isEmpty()
- && executionDynamicLibraries.isEmpty())) {
-
- CcLinkingOutputs.Builder newOutputsBuilder = new CcLinkingOutputs.Builder();
- if (!ccOutputs.isEmpty()) {
- // Add the linked outputs of this rule iff we had anything to put in them, but then
- // make sure we're not colliding with some library added from the inputs.
- newOutputsBuilder.merge(originalLinkingOutputs);
- ImmutableSetMultimap<String, LibraryToLink> precompiledLibraryMap =
- CcLinkingOutputs.getLibrariesByIdentifier(
- Iterables.concat(
- staticLibraries, picStaticLibraries,
- dynamicLibraries, executionDynamicLibraries));
- ImmutableSetMultimap<String, LibraryToLink> linkedLibraryMap =
- originalLinkingOutputs.getLibrariesByIdentifier();
- for (String matchingIdentifier :
- Sets.intersection(precompiledLibraryMap.keySet(), linkedLibraryMap.keySet())) {
- Iterable<Artifact> matchingInputLibs =
- LinkerInputs.toNonSolibArtifacts(precompiledLibraryMap.get(matchingIdentifier));
- Iterable<Artifact> matchingOutputLibs =
- LinkerInputs.toNonSolibArtifacts(linkedLibraryMap.get(matchingIdentifier));
- ruleContext.ruleError(
- "Can't put "
- + Streams.stream(matchingInputLibs)
- .map(Artifact::getFilename)
- .collect(joining(", "))
- + " into the srcs of a "
- + ruleContext.getRuleClassNameForLogging()
- + " with the same name ("
- + ruleContext.getRule().getName()
- + ") which also contains other code or objects to link; it shares a name with "
- + Streams.stream(matchingOutputLibs)
- .map(Artifact::getFilename)
- .collect(joining(", "))
- + " (output compiled and linked from the non-library sources of this rule), "
- + "which could cause confusion");
- }
- }
-
- // Merge the pre-compiled libraries (static & dynamic) into the linker outputs.
- ccLinkingOutputs =
- newOutputsBuilder
- .addStaticLibraries(staticLibraries)
- .addPicStaticLibraries(picStaticLibraries)
- .addDynamicLibraries(dynamicLibraries)
- .addExecutionDynamicLibraries(executionDynamicLibraries)
- .build();
- }
-
- Runfiles cppStaticRunfiles = collectCppRunfiles(ccLinkingOutputs, true);
- Runfiles cppSharedRunfiles = collectCppRunfiles(ccLinkingOutputs, false);
-
- // By very careful when adding new providers here - it can potentially affect a lot of rules.
- // We should consider merging most of these providers into a single provider.
- TransitiveInfoProviderMapBuilder providers =
- new TransitiveInfoProviderMapBuilder()
- .add(new CppRunfilesProvider(cppStaticRunfiles, cppSharedRunfiles));
-
- Map<String, NestedSet<Artifact>> outputGroups = new TreeMap<>();
-
- if (shouldAddLinkerOutputArtifacts(ruleContext, ccOutputs)) {
- addLinkerOutputArtifacts(outputGroups, ccOutputs);
- }
-
- // TODO(bazel-team): Maybe we can infer these from other data at the places where they are
- // used.
- if (emitCcNativeLibrariesProvider) {
- providers.add(new CcNativeLibraryProvider(collectNativeCcLibraries(ccLinkingOutputs)));
- }
- providers.put(
- CcExecutionDynamicLibrariesProvider.class,
- collectExecutionDynamicLibraryArtifacts(ccLinkingOutputs.getExecutionDynamicLibraries()));
-
- CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
- boolean forcePic = cppConfiguration.forcePic();
- if (emitCcSpecificLinkParamsProvider) {
- providers.add(
- new CcSpecificLinkParamsProvider(
- createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic)));
- } else {
- providers.put(
- new CcLinkParamsInfo(
- createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic)));
- }
- return new Info.LinkingInfo(
- providers.build(), outputGroups, ccLinkingOutputs, originalLinkingOutputs);
- }
-
- /**
- * Returns true if the appropriate attributes for linker output artifacts are defined, and either
- * the compile action produces object files or the build is configured to produce an archive or
- * dynamic library even in the absence of object files.
- */
- private boolean shouldAddLinkerOutputArtifacts(
- RuleContext ruleContext, CcCompilationOutputs ccOutputs) {
- return (ruleContext.attributes().has("alwayslink", Type.BOOLEAN)
- && ruleContext.attributes().has("linkstatic", Type.BOOLEAN)
- && (emitLinkActionsIfEmpty || !ccOutputs.isEmpty()));
- }
-
- /**
- * Adds linker output artifacts to the given map, to be registered on the configured target as
- * output groups.
- */
- private void addLinkerOutputArtifacts(Map<String, NestedSet<Artifact>> outputGroups,
- CcCompilationOutputs ccOutputs) {
- NestedSetBuilder<Artifact> archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER);
- NestedSetBuilder<Artifact> dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER);
-
- if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) {
- archiveFile.add(
- CppHelper.getLinuxLinkedArtifact(
- ruleContext,
- configuration,
- Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY,
- linkedArtifactNameSuffix));
- } else {
- archiveFile.add(
- CppHelper.getLinuxLinkedArtifact(
- ruleContext,
- configuration,
- Link.LinkTargetType.STATIC_LIBRARY,
- linkedArtifactNameSuffix));
- }
-
- if (!ruleContext.attributes().get("linkstatic", Type.BOOLEAN)
- && !ccOutputs.isEmpty()) {
- dynamicLibrary.add(
- CppHelper.getLinuxLinkedArtifact(
- ruleContext,
- configuration,
- Link.LinkTargetType.DYNAMIC_LIBRARY,
- linkedArtifactNameSuffix));
-
- if (CppHelper.useInterfaceSharedObjects(ccToolchain.getCppConfiguration(), ccToolchain)
- && emitInterfaceSharedObjects) {
- dynamicLibrary.add(
- CppHelper.getLinuxLinkedArtifact(
- ruleContext,
- configuration,
- LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
- linkedArtifactNameSuffix));
- }
- }
-
- outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
- outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
- }
-
- /**
- * Creates the C/C++ compilation action creator.
- */
+ /** Creates the C/C++ compilation action creator. */
private CppModel initializeCppModel() {
return new CppModel(
ruleContext, semantics, ccToolchain, fdoSupport, configuration, copts, coptsFilter)
.addCompilationUnitSources(compilationUnitSources)
- .setLinkTargetType(linkType)
- .setNeverLink(neverlink)
- .addLinkActionInputs(linkActionInputs)
.addCompilationMandatoryInputs(compilationMandatoryInputs)
.addAdditionalIncludeScanningRoots(additionalIncludeScanningRoots)
.setFake(fake)
.setGenerateNoPic(generateNoPic)
- .setAllowInterfaceSharedObjects(emitInterfaceSharedObjects)
- .setCreateDynamicLibrary(createDynamicLibrary)
- .setCreateStaticLibraries(createStaticLibraries)
// Note: this doesn't actually save the temps, it just makes the CppModel use the
// configurations --save_temps setting to decide whether to actually save the temps.
.setSaveTemps(true)
- .setDynamicLibrary(dynamicLibrary)
- .addLinkopts(linkopts)
.setFeatureConfiguration(featureConfiguration)
- .addVariablesExtension(variablesExtensions)
- .setLinkedArtifactNameSuffix(linkedArtifactNameSuffix);
+ .addVariablesExtension(variablesExtensions);
}
@Immutable
@@ -1319,16 +734,16 @@ public final class CcLibraryHelper {
this.virtualIncludePath = virtualIncludePath;
}
- public ImmutableList<Artifact> getHeaders() {
+ private ImmutableList<Artifact> getHeaders() {
return headers;
}
- public ImmutableList<Artifact> getModuleMapHeaders() {
+ private ImmutableList<Artifact> getModuleMapHeaders() {
return moduleMapHeaders;
}
@Nullable
- public PathFragment getVirtualIncludePath() {
+ private PathFragment getVirtualIncludePath() {
return virtualIncludePath;
}
}
@@ -1352,8 +767,13 @@ public final class CcLibraryHelper {
stripPrefix =
PathFragment.create(ruleContext.attributes().get("strip_include_prefix", Type.STRING));
if (stripPrefix.isAbsolute()) {
- stripPrefix = ruleContext.getLabel().getPackageIdentifier().getRepository().getSourceRoot()
- .getRelative(stripPrefix.toRelative());
+ stripPrefix =
+ ruleContext
+ .getLabel()
+ .getPackageIdentifier()
+ .getRepository()
+ .getSourceRoot()
+ .getRelative(stripPrefix.toRelative());
} else {
stripPrefix = ruleContext.getPackageDirectory().getRelative(stripPrefix);
}
@@ -1372,8 +792,7 @@ public final class CcLibraryHelper {
}
if (stripPrefix.containsUplevelReferences()) {
- ruleContext.attributeError("strip_include_prefix",
- "should not contain uplevel references");
+ ruleContext.attributeError("strip_include_prefix", "should not contain uplevel references");
}
if (prefix != null && prefix.containsUplevelReferences()) {
@@ -1392,9 +811,10 @@ public final class CcLibraryHelper {
for (Artifact originalHeader : publicHeaders) {
if (!originalHeader.getRootRelativePath().startsWith(stripPrefix)) {
- ruleContext.ruleError(String.format(
- "header '%s' is not under the specified strip prefix '%s'",
- originalHeader.getExecPathString(), stripPrefix.getPathString()));
+ ruleContext.ruleError(
+ String.format(
+ "header '%s' is not under the specified strip prefix '%s'",
+ originalHeader.getExecPathString(), stripPrefix.getPathString()));
continue;
}
@@ -1443,7 +863,7 @@ public final class CcLibraryHelper {
/**
* Create context for cc compile action from generated inputs.
*
- * TODO(plf): Try to pull out CppCompilationContext building out of this class.
+ * <p>TODO(plf): Try to pull out CppCompilationContext building out of this class.
*/
private CppCompilationContext initializeCppCompilationContext(CppModel model) {
CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext);
@@ -1568,8 +988,8 @@ public final class CcLibraryHelper {
return contextBuilder.build();
}
- private UmbrellaHeaderAction createUmbrellaHeaderAction(Artifact umbrellaHeader,
- PublicHeaders publicHeaders) {
+ private UmbrellaHeaderAction createUmbrellaHeaderAction(
+ Artifact umbrellaHeader, PublicHeaders publicHeaders) {
return new UmbrellaHeaderAction(
ruleContext.getActionOwner(),
umbrellaHeader,
@@ -1627,9 +1047,8 @@ public final class CcLibraryHelper {
RuleContext ruleContext, CcCompilationOutputs ccCompilationOutputs) {
NestedSetBuilder<Artifact> headerTokens = NestedSetBuilder.stableOrder();
for (OutputGroupInfo dep :
- ruleContext.getPrerequisites(
- "deps", Mode.TARGET, OutputGroupInfo.SKYLARK_CONSTRUCTOR)) {
- headerTokens.addTransitive(dep.getOutputGroup(CcLibraryHelper.HIDDEN_HEADER_TOKENS));
+ ruleContext.getPrerequisites("deps", Mode.TARGET, OutputGroupInfo.SKYLARK_CONSTRUCTOR)) {
+ headerTokens.addTransitive(dep.getOutputGroup(CcCompilationHelper.HIDDEN_HEADER_TOKENS));
}
if (ruleContext.getFragment(CppConfiguration.class).processHeadersInDependencies()) {
headerTokens.addAll(ccCompilationOutputs.getHeaderTokenFiles());
@@ -1663,73 +1082,6 @@ public final class CcLibraryHelper {
return new TransitiveLipoInfoProvider(scannableBuilder.build());
}
- private Runfiles collectCppRunfiles(
- CcLinkingOutputs ccLinkingOutputs, boolean linkingStatically) {
- Runfiles.Builder builder = new Runfiles.Builder(
- ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles());
- builder.addTargets(deps, RunfilesProvider.DEFAULT_RUNFILES);
- builder.addTargets(deps, CppRunfilesProvider.runfilesFunction(linkingStatically));
- // Add the shared libraries to the runfiles.
- builder.addArtifacts(ccLinkingOutputs.getLibrariesForRunfiles(linkingStatically));
- return builder.build();
- }
-
- private CcLinkParamsStore createCcLinkParamsStore(
- final CcLinkingOutputs ccLinkingOutputs, final CppCompilationContext cppCompilationContext,
- final boolean forcePic) {
- return new CcLinkParamsStore() {
- @Override
- protected void collect(
- CcLinkParams.Builder builder, boolean linkingStatically, boolean linkShared) {
- builder.addLinkstamps(linkstamps.build(), cppCompilationContext);
- builder.addTransitiveTargets(
- deps, CcLinkParamsInfo.TO_LINK_PARAMS, CcSpecificLinkParamsProvider.TO_LINK_PARAMS);
- if (!neverlink) {
- builder.addLibraries(
- ccLinkingOutputs.getPreferredLibraries(
- linkingStatically, /*preferPic=*/ linkShared || forcePic));
- if (!linkingStatically
- || (ccLinkingOutputs.getStaticLibraries().isEmpty()
- && ccLinkingOutputs.getPicStaticLibraries().isEmpty())) {
- builder.addExecutionDynamicLibraries(
- LinkerInputs.toLibraryArtifacts(ccLinkingOutputs.getExecutionDynamicLibraries()));
- }
- builder.addLinkOpts(linkopts);
- builder.addNonCodeInputs(nonCodeLinkerInputs);
- }
- }
- };
- }
-
- private NestedSet<LinkerInput> collectNativeCcLibraries(CcLinkingOutputs ccLinkingOutputs) {
- NestedSetBuilder<LinkerInput> result = NestedSetBuilder.linkOrder();
- result.addAll(ccLinkingOutputs.getDynamicLibraries());
- for (CcNativeLibraryProvider dep :
- AnalysisUtils.getProviders(deps, CcNativeLibraryProvider.class)) {
- result.addTransitive(dep.getTransitiveCcNativeLibraries());
- }
-
- return result.build();
- }
-
- private CcExecutionDynamicLibrariesProvider collectExecutionDynamicLibraryArtifacts(
- List<LibraryToLink> executionDynamicLibraries) {
- Iterable<Artifact> artifacts = LinkerInputs.toLibraryArtifacts(executionDynamicLibraries);
- if (!Iterables.isEmpty(artifacts)) {
- return new CcExecutionDynamicLibrariesProvider(
- NestedSetBuilder.wrap(Order.STABLE_ORDER, artifacts));
- }
-
- NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
- for (CcExecutionDynamicLibrariesProvider dep :
- AnalysisUtils.getProviders(deps, CcExecutionDynamicLibrariesProvider.class)) {
- builder.addTransitive(dep.getExecutionDynamicLibraryArtifacts());
- }
- return builder.isEmpty()
- ? CcExecutionDynamicLibrariesProvider.EMPTY
- : new CcExecutionDynamicLibrariesProvider(builder.build());
- }
-
private NestedSet<Artifact> getTemps(CcCompilationOutputs compilationOutputs) {
return ruleContext.getFragment(CppConfiguration.class).isLipoContextCollector()
? NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)
@@ -1740,10 +1092,8 @@ public final class CcLibraryHelper {
this.additionalCppModuleMaps.add(Preconditions.checkNotNull(cppModuleMap));
}
- /**
- * Don't generate a module map for this target if a custom module map is provided.
- */
- public CcLibraryHelper doNotGenerateModuleMap() {
+ /** Don't generate a module map for this target if a custom module map is provided. */
+ public CcCompilationHelper doNotGenerateModuleMap() {
generateModuleMap = false;
return this;
}
@@ -1755,7 +1105,7 @@ public final class CcLibraryHelper {
* @param purpose must be a string which is suitable for use as a filename. A single rule may have
* many middlemen with distinct purposes.
*/
- public CcLibraryHelper setPurpose(@Nullable String purpose) {
+ public CcCompilationHelper setPurpose(@Nullable String purpose) {
this.purpose = purpose;
return this;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
index f5e9f9dea5..b70ace4aea 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcImport.java
@@ -23,7 +23,8 @@ import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper.LinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
@@ -62,7 +63,7 @@ public abstract class CcImport implements RuleConfiguredTargetFactory {
"'shared_library' should be specified when 'system_provided' is false");
}
- // Create CcLibraryHelper
+ // Create CcCompilationHelper
CcToolchainProvider ccToolchain =
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
FeatureConfiguration featureConfiguration =
@@ -72,8 +73,9 @@ public abstract class CcImport implements RuleConfiguredTargetFactory {
// Add headers to compilation step.
final CcCommon common = new CcCommon(ruleContext);
- Info.CompilationInfo compilationInfo =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CompilationInfo compilationInfo =
+ new CcCompilationHelper(
+ ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
.addPublicHeaders(common.getHeaders())
.setHeadersCheckingMode(HeadersCheckingMode.STRICT)
.compile();
@@ -90,8 +92,14 @@ public abstract class CcImport implements RuleConfiguredTargetFactory {
.getRelative(labelName.replaceName("lib" + labelName.getBaseName()))
.getPathString();
- CcLibraryHelper linkingHelper =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport);
+ CcLinkingHelper linkingHelper =
+ new CcLinkingHelper(
+ ruleContext,
+ semantics,
+ featureConfiguration,
+ ccToolchain,
+ fdoSupport,
+ ruleContext.getConfiguration());
if (staticLibrary != null) {
if (CppFileTypes.PIC_ARCHIVE.matches(staticLibrary.getPath())) {
@@ -159,7 +167,7 @@ public abstract class CcImport implements RuleConfiguredTargetFactory {
linkingHelper.addDynamicLibraries(dynamicLibraryList);
}
- Info.LinkingInfo linkingInfo =
+ LinkingInfo linkingInfo =
linkingHelper.link(
compilationInfo.getCcCompilationOutputs(), compilationInfo.getCppCompilationContext());
@@ -168,8 +176,8 @@ public abstract class CcImport implements RuleConfiguredTargetFactory {
.addProviders(linkingInfo.getProviders())
.addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider())
.addOutputGroups(
- Info.mergeOutputGroups(
- compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups()))
+ CcCommon.mergeOutputGroups(
+ ImmutableList.of(compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups())))
.addProvider(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY))
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
index ad05f41707..a844ef6375 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcIncLibrary.java
@@ -26,7 +26,8 @@ import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper.LinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.Path;
@@ -130,14 +131,21 @@ public abstract class CcIncLibrary implements RuleConfiguredTargetFactory {
new CreateIncSymlinkAction(ruleContext.getActionOwner(), virtualArtifactMap, includeRoot));
FdoSupportProvider fdoSupport =
CppHelper.getFdoSupportUsingDefaultCcToolchainAttribute(ruleContext);
- Info.CompilationInfo compilationInfo =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CompilationInfo compilationInfo =
+ new CcCompilationHelper(
+ ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
.addIncludeDirs(Arrays.asList(includePath))
.addPublicHeaders(virtualArtifactMap.keySet())
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
.compile();
- Info.LinkingInfo linkingInfo =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ LinkingInfo linkingInfo =
+ new CcLinkingHelper(
+ ruleContext,
+ semantics,
+ featureConfiguration,
+ ccToolchain,
+ fdoSupport,
+ ruleContext.getConfiguration())
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
.link(
compilationInfo.getCcCompilationOutputs(),
@@ -154,8 +162,8 @@ public abstract class CcIncLibrary implements RuleConfiguredTargetFactory {
.addProviders(linkingInfo.getProviders())
.addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider())
.addOutputGroups(
- Info.mergeOutputGroups(
- compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups()))
+ CcCommon.mergeOutputGroups(
+ ImmutableList.of(compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups())))
.add(InstrumentedFilesProvider.class, instrumentedFilesProvider)
.add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY))
.build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index 963414ae86..d07dd05769 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -37,7 +37,8 @@ import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.rules.cpp.CcCommon.CcFlagsSupplier;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper.LinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
@@ -132,16 +133,23 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
return;
}
- CcLibraryHelper compilationHelper =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CcCompilationHelper compilationHelper =
+ new CcCompilationHelper(
+ ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
.fromCommon(common)
.addSources(common.getSources())
.addPublicHeaders(common.getHeaders())
.enableCompileProviders()
.addPrecompiledFiles(precompiledFiles);
- CcLibraryHelper linkingHelper =
- new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport)
+ CcLinkingHelper linkingHelper =
+ new CcLinkingHelper(
+ ruleContext,
+ semantics,
+ featureConfiguration,
+ ccToolchain,
+ fdoSupport,
+ ruleContext.getConfiguration())
.fromCommon(common)
.addLinkopts(common.getLinkopts())
.enableCcNativeLibrariesProvider()
@@ -272,8 +280,8 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
linkingHelper.addDynamicLibraries(dynamicLibraries);
linkingHelper.addExecutionDynamicLibraries(dynamicLibraries);
- Info.CompilationInfo compilationInfo = compilationHelper.compile();
- Info.LinkingInfo linkingInfo =
+ CompilationInfo compilationInfo = compilationHelper.compile();
+ LinkingInfo linkingInfo =
linkingHelper.link(
compilationInfo.getCcCompilationOutputs(), compilationInfo.getCppCompilationContext());
@@ -322,8 +330,8 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
.addProviders(linkingInfo.getProviders())
.addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider())
.addOutputGroups(
- Info.mergeOutputGroups(
- compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups()))
+ CcCommon.mergeOutputGroups(
+ ImmutableList.of(compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups())))
.addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider)
.addProvider(
RunfilesProvider.class, RunfilesProvider.withData(staticRunfiles, sharedRunfiles))
@@ -335,8 +343,8 @@ public abstract class CcLibrary implements RuleConfiguredTargetFactory {
collectHiddenTopLevelArtifacts(
ruleContext, ccToolchain, compilationInfo.getCcCompilationOutputs()))
.addOutputGroup(
- CcLibraryHelper.HIDDEN_HEADER_TOKENS,
- CcLibraryHelper.collectHeaderTokens(
+ CcCompilationHelper.HIDDEN_HEADER_TOKENS,
+ CcCompilationHelper.collectHeaderTokens(
ruleContext, compilationInfo.getCcCompilationOutputs()));
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
new file mode 100644
index 0000000000..77dc80f562
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
@@ -0,0 +1,706 @@
+// Copyright 2014 The Bazel Authors. All rights reserved.
+//
+// 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.google.devtools.build.lib.rules.cpp;
+
+import static java.util.stream.Collectors.joining;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Streams;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.AnalysisUtils;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.LanguageDependentFragment;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.Runfiles;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
+import com.google.devtools.build.lib.rules.cpp.CcCommon.CoptsFilter;
+import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
+import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension;
+import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
+import com.google.devtools.build.lib.rules.cpp.Link.Staticness;
+import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
+import com.google.devtools.build.lib.syntax.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.annotation.Nullable;
+
+/**
+ * A class to create C/C++ link actions in a way that is consistent with cc_library. Rules that
+ * generate source files and emulate cc_library on top of that should use this class instead of the
+ * lower-level APIs in CppHelper and CppModel.
+ *
+ * <p>Rules that want to use this class are required to have implicit dependencies on the toolchain,
+ * the STL, the lipo context, and so on. Optionally, they can also have copts, and malloc
+ * attributes, but note that these require explicit calls to the corresponding setter methods.
+ */
+public final class CcLinkingHelper {
+
+ /** A string constant for the name of archive library(.a, .lo) output group. */
+ public static final String ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME = "archive";
+
+ /** A string constant for the name of dynamic library output group. */
+ public static final String DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME = "dynamic_library";
+
+ /** Contains the providers as well as the linking outputs. */
+ public static final class LinkingInfo {
+ private final TransitiveInfoProviderMap providers;
+ private final Map<String, NestedSet<Artifact>> outputGroups;
+ private final CcLinkingOutputs linkingOutputs;
+ private final CcLinkingOutputs linkingOutputsExcludingPrecompiledLibraries;
+
+ private LinkingInfo(
+ TransitiveInfoProviderMap providers,
+ Map<String, NestedSet<Artifact>> outputGroups,
+ CcLinkingOutputs linkingOutputs,
+ CcLinkingOutputs linkingOutputsExcludingPrecompiledLibraries) {
+ this.providers = providers;
+ this.outputGroups = outputGroups;
+ this.linkingOutputs = linkingOutputs;
+ this.linkingOutputsExcludingPrecompiledLibraries =
+ linkingOutputsExcludingPrecompiledLibraries;
+ }
+
+ public TransitiveInfoProviderMap getProviders() {
+ return providers;
+ }
+
+ public Map<String, NestedSet<Artifact>> getOutputGroups() {
+ return outputGroups;
+ }
+
+ public CcLinkingOutputs getCcLinkingOutputs() {
+ return linkingOutputs;
+ }
+
+ /**
+ * Returns the linking outputs before adding the pre-compiled libraries. Avoid using this -
+ * pre-compiled and locally compiled libraries should be treated identically. This method only
+ * exists for backwards compatibility.
+ */
+ public CcLinkingOutputs getCcLinkingOutputsExcludingPrecompiledLibraries() {
+ return linkingOutputsExcludingPrecompiledLibraries;
+ }
+
+ /**
+ * Adds the static, pic-static libraries to the given builder. If addDynamicLibraries parameter
+ * is true, it also adds dynamic(both compile-time and execution-time) libraries.
+ */
+ public void addLinkingOutputsTo(
+ NestedSetBuilder<Artifact> filesBuilder, boolean addDynamicLibraries) {
+ filesBuilder
+ .addAll(LinkerInputs.toLibraryArtifacts(linkingOutputs.getStaticLibraries()))
+ .addAll(LinkerInputs.toLibraryArtifacts(linkingOutputs.getPicStaticLibraries()));
+ if (addDynamicLibraries) {
+ filesBuilder
+ .addAll(LinkerInputs.toNonSolibArtifacts(linkingOutputs.getDynamicLibraries()))
+ .addAll(
+ LinkerInputs.toNonSolibArtifacts(linkingOutputs.getExecutionDynamicLibraries()));
+ }
+ }
+
+ public void addLinkingOutputsTo(NestedSetBuilder<Artifact> filesBuilder) {
+ addLinkingOutputsTo(filesBuilder, true);
+ }
+ }
+
+ private final RuleContext ruleContext;
+ private final CppSemantics semantics;
+ private final BuildConfiguration configuration;
+
+ private final List<Artifact> nonCodeLinkerInputs = new ArrayList<>();
+ private final List<String> linkopts = new ArrayList<>();
+ private final List<TransitiveInfoCollection> deps = new ArrayList<>();
+ private final NestedSetBuilder<Artifact> linkstamps = NestedSetBuilder.stableOrder();
+ private final List<Artifact> linkActionInputs = new ArrayList<>();
+
+ @Nullable private Artifact dynamicLibrary;
+ private LinkTargetType linkType = LinkTargetType.STATIC_LIBRARY;
+ private boolean neverlink;
+ private boolean fake;
+
+ private final List<LibraryToLink> staticLibraries = new ArrayList<>();
+ private final List<LibraryToLink> picStaticLibraries = new ArrayList<>();
+ private final List<LibraryToLink> dynamicLibraries = new ArrayList<>();
+ private final List<LibraryToLink> executionDynamicLibraries = new ArrayList<>();
+
+ private boolean checkDepsGenerateCpp = true;
+ private boolean emitLinkActionsIfEmpty;
+ private boolean emitCcNativeLibrariesProvider;
+ private boolean emitCcSpecificLinkParamsProvider;
+ private boolean emitInterfaceSharedObjects;
+ private boolean createDynamicLibrary = true;
+ private boolean createStaticLibraries = true;
+ private final List<VariablesExtension> variablesExtensions = new ArrayList<>();
+
+ private final FeatureConfiguration featureConfiguration;
+ private final CcToolchainProvider ccToolchain;
+ private final FdoSupportProvider fdoSupport;
+ private String linkedArtifactNameSuffix = "";
+
+ /**
+ * Creates a CcLinkingHelper that outputs artifacts in a given configuration.
+ *
+ * @param ruleContext the RuleContext for the rule being built
+ * @param semantics CppSemantics for the build
+ * @param featureConfiguration activated features and action configs for the build
+ * @param ccToolchain the C++ toolchain provider for the build
+ * @param fdoSupport the C++ FDO optimization support provider for the build
+ * @param configuration the configuration that gives the directory of output artifacts
+ */
+ public CcLinkingHelper(
+ RuleContext ruleContext,
+ CppSemantics semantics,
+ FeatureConfiguration featureConfiguration,
+ CcToolchainProvider ccToolchain,
+ FdoSupportProvider fdoSupport,
+ BuildConfiguration configuration) {
+ this.ruleContext = Preconditions.checkNotNull(ruleContext);
+ this.semantics = Preconditions.checkNotNull(semantics);
+ this.featureConfiguration = Preconditions.checkNotNull(featureConfiguration);
+ this.ccToolchain = Preconditions.checkNotNull(ccToolchain);
+ this.fdoSupport = Preconditions.checkNotNull(fdoSupport);
+ this.configuration = Preconditions.checkNotNull(configuration);
+ }
+
+ /** Sets fields that overlap for cc_library and cc_binary rules. */
+ public CcLinkingHelper fromCommon(CcCommon common) {
+ addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET));
+ addNonCodeLinkerInputs(common.getLinkerScripts());
+ return this;
+ }
+
+ /** Adds the corresponding non-code files as linker inputs. */
+ public void addNonCodeLinkerInputs(Iterable<Artifact> nonCodeLinkerInputs) {
+ for (Artifact nonCodeLinkerInput : nonCodeLinkerInputs) {
+ String basename = nonCodeLinkerInput.getFilename();
+ Preconditions.checkArgument(!Link.OBJECT_FILETYPES.matches(basename));
+ Preconditions.checkArgument(!Link.ARCHIVE_LIBRARY_FILETYPES.matches(basename));
+ Preconditions.checkArgument(!Link.SHARED_LIBRARY_FILETYPES.matches(basename));
+ this.nonCodeLinkerInputs.add(nonCodeLinkerInput);
+ }
+ }
+
+ /**
+ * Add the corresponding files as static libraries into the linker outputs (i.e., after the linker
+ * action) - this makes them available for linking to binary rules that depend on this rule.
+ */
+ public CcLinkingHelper addStaticLibraries(Iterable<LibraryToLink> libraries) {
+ Iterables.addAll(staticLibraries, libraries);
+ return this;
+ }
+
+ /**
+ * Add the corresponding files as static libraries into the linker outputs (i.e., after the linker
+ * action) - this makes them available for linking to binary rules that depend on this rule.
+ */
+ public CcLinkingHelper addPicStaticLibraries(Iterable<LibraryToLink> libraries) {
+ Iterables.addAll(picStaticLibraries, libraries);
+ return this;
+ }
+
+ /**
+ * Add the corresponding files as dynamic libraries into the linker outputs (i.e., after the
+ * linker action) - this makes them available for linking to binary rules that depend on this
+ * rule.
+ */
+ public CcLinkingHelper addDynamicLibraries(Iterable<LibraryToLink> libraries) {
+ Iterables.addAll(dynamicLibraries, libraries);
+ return this;
+ }
+
+ /** Add the corresponding files as dynamic libraries required at runtime */
+ public CcLinkingHelper addExecutionDynamicLibraries(Iterable<LibraryToLink> libraries) {
+ Iterables.addAll(executionDynamicLibraries, libraries);
+ return this;
+ }
+
+ /** Adds the given options as linker options to the link command. */
+ public CcLinkingHelper addLinkopts(Iterable<String> linkopts) {
+ Iterables.addAll(this.linkopts, linkopts);
+ return this;
+ }
+
+ /**
+ * Adds the given targets as dependencies - this can include explicit dependencies on other rules
+ * (like from a "deps" attribute) and also implicit dependencies on runtime libraries.
+ */
+ public CcLinkingHelper addDeps(Iterable<? extends TransitiveInfoCollection> deps) {
+ for (TransitiveInfoCollection dep : deps) {
+ this.deps.add(dep);
+ }
+ return this;
+ }
+
+ /**
+ * Adds the given linkstamps. Note that linkstamps are usually not compiled at the library level,
+ * but only in the dependent binary rules.
+ */
+ public CcLinkingHelper addLinkstamps(Iterable<? extends TransitiveInfoCollection> linkstamps) {
+ for (TransitiveInfoCollection linkstamp : linkstamps) {
+ this.linkstamps.addTransitive(linkstamp.getProvider(FileProvider.class).getFilesToBuild());
+ }
+ return this;
+ }
+
+ /** Adds the given artifact to the input of any generated link actions. */
+ public CcLinkingHelper addLinkActionInput(Artifact input) {
+ Preconditions.checkNotNull(input);
+ this.linkActionInputs.add(input);
+ return this;
+ }
+
+ /** Adds a variableExtension to template the crosstool. */
+ public CcLinkingHelper addVariableExtension(VariablesExtension variableExtension) {
+ Preconditions.checkNotNull(variableExtension);
+ this.variablesExtensions.add(variableExtension);
+ return this;
+ }
+
+ /**
+ * Overrides the path for the generated dynamic library - this should only be called if the
+ * dynamic library is an implicit or explicit output of the rule, i.e., if it is accessible by
+ * name from other rules in the same package. Set to {@code null} to use the default computation.
+ */
+ public CcLinkingHelper setDynamicLibrary(@Nullable Artifact dynamicLibrary) {
+ this.dynamicLibrary = dynamicLibrary;
+ return this;
+ }
+
+ /**
+ * Marks the output of this rule as alwayslink, i.e., the corresponding symbols will be retained
+ * by the linker even if they are not otherwise used. This is useful for libraries that register
+ * themselves somewhere during initialization.
+ *
+ * <p>This only sets the link type (see {@link #setStaticLinkType}), either to a static library or
+ * to an alwayslink static library (blaze uses a different file extension to signal alwayslink to
+ * downstream code).
+ */
+ public CcLinkingHelper setAlwayslink(boolean alwayslink) {
+ linkType =
+ alwayslink ? LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY : LinkTargetType.STATIC_LIBRARY;
+ return this;
+ }
+
+ /**
+ * Directly set the link type. This can be used instead of {@link #setAlwayslink}. Setting
+ * anything other than a static link causes this class to skip the link action creation.
+ */
+ public CcLinkingHelper setStaticLinkType(LinkTargetType linkType) {
+ Preconditions.checkNotNull(linkType);
+ Preconditions.checkState(linkType.staticness() == Staticness.STATIC);
+ this.linkType = linkType;
+ return this;
+ }
+
+ /**
+ * Marks the resulting code as neverlink, i.e., the code will not be linked into dependent
+ * libraries or binaries - the header files are still available.
+ */
+ public CcLinkingHelper setNeverLink(boolean neverlink) {
+ this.neverlink = neverlink;
+ return this;
+ }
+
+ /**
+ * Disables checking that the deps actually are C++ rules. By default, the {@link #link} method
+ * uses {@link LanguageDependentFragment.Checker#depSupportsLanguage} to check that all deps
+ * provide C++ providers.
+ */
+ public CcLinkingHelper setCheckDepsGenerateCpp(boolean checkDepsGenerateCpp) {
+ this.checkDepsGenerateCpp = checkDepsGenerateCpp;
+ return this;
+ }
+
+ /**
+ * Marks the resulting code as fake, i.e., the code will not actually be compiled or linked, but
+ * instead, the compile command is written to a file and added to the runfiles. This is currently
+ * used for non-compilation tests. Unfortunately, the design is problematic, so please don't add
+ * any further uses.
+ */
+ public CcLinkingHelper setFake(boolean fake) {
+ this.fake = fake;
+ return this;
+ }
+
+ /*
+ * Adds a suffix for paths of linked artifacts. Normally their paths are derived solely from rule
+ * labels. In the case of multiple callers (e.g., aspects) acting on a single rule, they may
+ * generate the same linked artifact and therefore lead to artifact conflicts. This method
+ * provides a way to avoid this artifact conflict by allowing different callers acting on the same
+ * rule to provide a suffix that will be used to scope their own linked artifacts.
+ */
+ public CcLinkingHelper setLinkedArtifactNameSuffix(String suffix) {
+ this.linkedArtifactNameSuffix = Preconditions.checkNotNull(suffix);
+ return this;
+ }
+
+ /** This adds the {@link CcNativeLibraryProvider} to the providers created by this class. */
+ public CcLinkingHelper enableCcNativeLibrariesProvider() {
+ this.emitCcNativeLibrariesProvider = true;
+ return this;
+ }
+
+ /**
+ * This adds the {@link CcSpecificLinkParamsProvider} to the providers created by this class.
+ * Otherwise the result will contain an instance of {@link CcLinkParamsInfo}.
+ */
+ public CcLinkingHelper enableCcSpecificLinkParamsProvider() {
+ this.emitCcSpecificLinkParamsProvider = true;
+ return this;
+ }
+
+ /**
+ * Enables or disables generation of link actions if there are no object files. Some rules declare
+ * a <code>.a</code> or <code>.so</code> implicit output, which requires that these files are
+ * created even if there are no object files, so be careful when calling this.
+ *
+ * <p>This is disabled by default.
+ */
+ public CcLinkingHelper setGenerateLinkActionsIfEmpty(boolean emitLinkActionsIfEmpty) {
+ this.emitLinkActionsIfEmpty = emitLinkActionsIfEmpty;
+ return this;
+ }
+
+ /**
+ * Enables the optional generation of interface dynamic libraries - this is only used when the
+ * linker generates a dynamic library, and only if the crosstool supports it. The default is not
+ * to generate interface dynamic libraries.
+ */
+ public CcLinkingHelper enableInterfaceSharedObjects() {
+ this.emitInterfaceSharedObjects = true;
+ return this;
+ }
+
+ /**
+ * This enables or disables the generation of a dynamic library link action. The default is to
+ * generate a dynamic library. Note that the selection between dynamic or static linking is
+ * performed at the binary rule level.
+ */
+ public CcLinkingHelper setCreateDynamicLibrary(boolean emitDynamicLibrary) {
+ this.createDynamicLibrary = emitDynamicLibrary;
+ return this;
+ }
+
+ /** When createStaticLibraries is true, there are no actions created for static libraries. */
+ public CcLinkingHelper setCreateStaticLibraries(boolean emitStaticLibraries) {
+ this.createStaticLibraries = emitStaticLibraries;
+ return this;
+ }
+
+ public CcLinkingHelper setNeverlink(boolean neverlink) {
+ this.neverlink = neverlink;
+ return this;
+ }
+
+ /**
+ * Create the C++ link actions, and the corresponding linking related providers.
+ *
+ * @throws RuleErrorException
+ */
+ public LinkingInfo link(
+ CcCompilationOutputs ccOutputs, CppCompilationContext cppCompilationContext)
+ throws RuleErrorException, InterruptedException {
+ Preconditions.checkNotNull(ccOutputs);
+ Preconditions.checkNotNull(cppCompilationContext);
+
+ if (checkDepsGenerateCpp) {
+ for (LanguageDependentFragment dep :
+ AnalysisUtils.getProviders(deps, LanguageDependentFragment.class)) {
+ LanguageDependentFragment.Checker.depSupportsLanguage(
+ ruleContext, dep, CppRuleClasses.LANGUAGE, "deps");
+ }
+ }
+
+ CppModel model = initializeCppModel();
+ model.setContext(cppCompilationContext);
+
+ // Create link actions (only if there are object files or if explicitly requested).
+ CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
+ if (emitLinkActionsIfEmpty || !ccOutputs.isEmpty()) {
+ // On some systems, the linker gives an error message if there are no input files. Even with
+ // the check above, this can still happen if there is a .nopic.o or .o files in srcs, but no
+ // other files. To fix that, we'd have to check for each link action individually.
+ //
+ // An additional pre-existing issue is that the header check tokens are dropped if we don't
+ // generate any link actions, effectively disabling header checking in some cases.
+ if (linkType.staticness() == Staticness.STATIC) {
+ // TODO(bazel-team): This can't create the link action for a cc_binary yet.
+ ccLinkingOutputs = model.createCcLinkActions(ccOutputs, nonCodeLinkerInputs);
+ }
+ }
+ CcLinkingOutputs originalLinkingOutputs = ccLinkingOutputs;
+ if (!(staticLibraries.isEmpty()
+ && picStaticLibraries.isEmpty()
+ && dynamicLibraries.isEmpty()
+ && executionDynamicLibraries.isEmpty())) {
+
+ CcLinkingOutputs.Builder newOutputsBuilder = new CcLinkingOutputs.Builder();
+ if (!ccOutputs.isEmpty()) {
+ // Add the linked outputs of this rule iff we had anything to put in them, but then
+ // make sure we're not colliding with some library added from the inputs.
+ newOutputsBuilder.merge(originalLinkingOutputs);
+ ImmutableSetMultimap<String, LibraryToLink> precompiledLibraryMap =
+ CcLinkingOutputs.getLibrariesByIdentifier(
+ Iterables.concat(
+ staticLibraries, picStaticLibraries,
+ dynamicLibraries, executionDynamicLibraries));
+ ImmutableSetMultimap<String, LibraryToLink> linkedLibraryMap =
+ originalLinkingOutputs.getLibrariesByIdentifier();
+ for (String matchingIdentifier :
+ Sets.intersection(precompiledLibraryMap.keySet(), linkedLibraryMap.keySet())) {
+ Iterable<Artifact> matchingInputLibs =
+ LinkerInputs.toNonSolibArtifacts(precompiledLibraryMap.get(matchingIdentifier));
+ Iterable<Artifact> matchingOutputLibs =
+ LinkerInputs.toNonSolibArtifacts(linkedLibraryMap.get(matchingIdentifier));
+ ruleContext.ruleError(
+ "Can't put "
+ + Streams.stream(matchingInputLibs)
+ .map(Artifact::getFilename)
+ .collect(joining(", "))
+ + " into the srcs of a "
+ + ruleContext.getRuleClassNameForLogging()
+ + " with the same name ("
+ + ruleContext.getRule().getName()
+ + ") which also contains other code or objects to link; it shares a name with "
+ + Streams.stream(matchingOutputLibs)
+ .map(Artifact::getFilename)
+ .collect(joining(", "))
+ + " (output compiled and linked from the non-library sources of this rule), "
+ + "which could cause confusion");
+ }
+ }
+
+ // Merge the pre-compiled libraries (static & dynamic) into the linker outputs.
+ ccLinkingOutputs =
+ newOutputsBuilder
+ .addStaticLibraries(staticLibraries)
+ .addPicStaticLibraries(picStaticLibraries)
+ .addDynamicLibraries(dynamicLibraries)
+ .addExecutionDynamicLibraries(executionDynamicLibraries)
+ .build();
+ }
+
+ Runfiles cppStaticRunfiles = collectCppRunfiles(ccLinkingOutputs, true);
+ Runfiles cppSharedRunfiles = collectCppRunfiles(ccLinkingOutputs, false);
+
+ // By very careful when adding new providers here - it can potentially affect a lot of rules.
+ // We should consider merging most of these providers into a single provider.
+ TransitiveInfoProviderMapBuilder providers =
+ new TransitiveInfoProviderMapBuilder()
+ .add(new CppRunfilesProvider(cppStaticRunfiles, cppSharedRunfiles));
+
+ Map<String, NestedSet<Artifact>> outputGroups = new TreeMap<>();
+
+ if (shouldAddLinkerOutputArtifacts(ruleContext, ccOutputs)) {
+ addLinkerOutputArtifacts(outputGroups, ccOutputs);
+ }
+
+ // TODO(bazel-team): Maybe we can infer these from other data at the places where they are
+ // used.
+ if (emitCcNativeLibrariesProvider) {
+ providers.add(new CcNativeLibraryProvider(collectNativeCcLibraries(ccLinkingOutputs)));
+ }
+ providers.put(
+ CcExecutionDynamicLibrariesProvider.class,
+ collectExecutionDynamicLibraryArtifacts(ccLinkingOutputs.getExecutionDynamicLibraries()));
+
+ CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
+ boolean forcePic = cppConfiguration.forcePic();
+ if (emitCcSpecificLinkParamsProvider) {
+ providers.add(
+ new CcSpecificLinkParamsProvider(
+ createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic)));
+ } else {
+ providers.put(
+ new CcLinkParamsInfo(
+ createCcLinkParamsStore(ccLinkingOutputs, cppCompilationContext, forcePic)));
+ }
+ return new LinkingInfo(
+ providers.build(), outputGroups, ccLinkingOutputs, originalLinkingOutputs);
+ }
+
+ /**
+ * Returns true if the appropriate attributes for linker output artifacts are defined, and either
+ * the compile action produces object files or the build is configured to produce an archive or
+ * dynamic library even in the absence of object files.
+ */
+ private boolean shouldAddLinkerOutputArtifacts(
+ RuleContext ruleContext, CcCompilationOutputs ccOutputs) {
+ return (ruleContext.attributes().has("alwayslink", Type.BOOLEAN)
+ && ruleContext.attributes().has("linkstatic", Type.BOOLEAN)
+ && (emitLinkActionsIfEmpty || !ccOutputs.isEmpty()));
+ }
+
+ /**
+ * Adds linker output artifacts to the given map, to be registered on the configured target as
+ * output groups.
+ */
+ private void addLinkerOutputArtifacts(
+ Map<String, NestedSet<Artifact>> outputGroups, CcCompilationOutputs ccOutputs) {
+ NestedSetBuilder<Artifact> archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER);
+ NestedSetBuilder<Artifact> dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER);
+
+ if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) {
+ archiveFile.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext,
+ configuration,
+ Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY,
+ linkedArtifactNameSuffix));
+ } else {
+ archiveFile.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext,
+ configuration,
+ Link.LinkTargetType.STATIC_LIBRARY,
+ linkedArtifactNameSuffix));
+ }
+
+ if (!ruleContext.attributes().get("linkstatic", Type.BOOLEAN) && !ccOutputs.isEmpty()) {
+ dynamicLibrary.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext,
+ configuration,
+ Link.LinkTargetType.DYNAMIC_LIBRARY,
+ linkedArtifactNameSuffix));
+
+ if (CppHelper.useInterfaceSharedObjects(ccToolchain.getCppConfiguration(), ccToolchain)
+ && emitInterfaceSharedObjects) {
+ dynamicLibrary.add(
+ CppHelper.getLinuxLinkedArtifact(
+ ruleContext,
+ configuration,
+ LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
+ linkedArtifactNameSuffix));
+ }
+ }
+
+ outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
+ outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
+ }
+
+ /** Creates the C/C++ compilation action creator. */
+ private CppModel initializeCppModel() {
+ // TODO(plf): Split CppModel into compilation and linking and stop passing last two arguments.
+ return new CppModel(
+ ruleContext,
+ semantics,
+ ccToolchain,
+ fdoSupport,
+ configuration,
+ ImmutableList.of(),
+ CoptsFilter.alwaysPasses())
+ .setLinkTargetType(linkType)
+ .setNeverLink(neverlink)
+ .addLinkActionInputs(linkActionInputs)
+ .setFake(fake)
+ .setAllowInterfaceSharedObjects(emitInterfaceSharedObjects)
+ .setCreateDynamicLibrary(createDynamicLibrary)
+ .setCreateStaticLibraries(createStaticLibraries)
+ // Note: this doesn't actually save the temps, it just makes the CppModel use the
+ // configurations --save_temps setting to decide whether to actually save the temps.
+ .setSaveTemps(true)
+ .setDynamicLibrary(dynamicLibrary)
+ .addLinkopts(linkopts)
+ .setFeatureConfiguration(featureConfiguration)
+ .addVariablesExtension(variablesExtensions)
+ .setLinkedArtifactNameSuffix(linkedArtifactNameSuffix);
+ }
+
+ private Runfiles collectCppRunfiles(
+ CcLinkingOutputs ccLinkingOutputs, boolean linkingStatically) {
+ Runfiles.Builder builder =
+ new Runfiles.Builder(
+ ruleContext.getWorkspaceName(),
+ ruleContext.getConfiguration().legacyExternalRunfiles());
+ builder.addTargets(deps, RunfilesProvider.DEFAULT_RUNFILES);
+ builder.addTargets(deps, CppRunfilesProvider.runfilesFunction(linkingStatically));
+ // Add the shared libraries to the runfiles.
+ builder.addArtifacts(ccLinkingOutputs.getLibrariesForRunfiles(linkingStatically));
+ return builder.build();
+ }
+
+ private CcLinkParamsStore createCcLinkParamsStore(
+ final CcLinkingOutputs ccLinkingOutputs,
+ final CppCompilationContext cppCompilationContext,
+ final boolean forcePic) {
+ return new CcLinkParamsStore() {
+ @Override
+ protected void collect(
+ CcLinkParams.Builder builder, boolean linkingStatically, boolean linkShared) {
+ builder.addLinkstamps(linkstamps.build(), cppCompilationContext);
+ builder.addTransitiveTargets(
+ deps, CcLinkParamsInfo.TO_LINK_PARAMS, CcSpecificLinkParamsProvider.TO_LINK_PARAMS);
+ if (!neverlink) {
+ builder.addLibraries(
+ ccLinkingOutputs.getPreferredLibraries(
+ linkingStatically, /*preferPic=*/ linkShared || forcePic));
+ if (!linkingStatically
+ || (ccLinkingOutputs.getStaticLibraries().isEmpty()
+ && ccLinkingOutputs.getPicStaticLibraries().isEmpty())) {
+ builder.addExecutionDynamicLibraries(
+ LinkerInputs.toLibraryArtifacts(ccLinkingOutputs.getExecutionDynamicLibraries()));
+ }
+ builder.addLinkOpts(linkopts);
+ builder.addNonCodeInputs(nonCodeLinkerInputs);
+ }
+ }
+ };
+ }
+
+ private NestedSet<LinkerInput> collectNativeCcLibraries(CcLinkingOutputs ccLinkingOutputs) {
+ NestedSetBuilder<LinkerInput> result = NestedSetBuilder.linkOrder();
+ result.addAll(ccLinkingOutputs.getDynamicLibraries());
+ for (CcNativeLibraryProvider dep :
+ AnalysisUtils.getProviders(deps, CcNativeLibraryProvider.class)) {
+ result.addTransitive(dep.getTransitiveCcNativeLibraries());
+ }
+
+ return result.build();
+ }
+
+ private CcExecutionDynamicLibrariesProvider collectExecutionDynamicLibraryArtifacts(
+ List<LibraryToLink> executionDynamicLibraries) {
+ Iterable<Artifact> artifacts = LinkerInputs.toLibraryArtifacts(executionDynamicLibraries);
+ if (!Iterables.isEmpty(artifacts)) {
+ return new CcExecutionDynamicLibrariesProvider(
+ NestedSetBuilder.wrap(Order.STABLE_ORDER, artifacts));
+ }
+
+ NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
+ for (CcExecutionDynamicLibrariesProvider dep :
+ AnalysisUtils.getProviders(deps, CcExecutionDynamicLibrariesProvider.class)) {
+ builder.addTransitive(dep.getExecutionDynamicLibraryArtifacts());
+ }
+ return builder.isEmpty()
+ ? CcExecutionDynamicLibrariesProvider.EMPTY
+ : new CcExecutionDynamicLibrariesProvider(builder.build());
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
index d3037ff265..247d3ef91f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
@@ -261,7 +261,7 @@ public class CppCompileActionBuilder {
} else if (CppFileTypes.CPP_MODULE.matches(sourcePath)) {
return CppCompileAction.CPP_MODULE_CODEGEN;
}
- // CcLibraryHelper ensures CppCompileAction only gets instantiated for supported file types.
+ // CcCompilationHelper ensures CppCompileAction only gets instantiated for supported file types.
throw new IllegalStateException();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
index a3cc7bfacb..2f4e7807e8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/proto/CcProtoAspect.java
@@ -28,7 +28,6 @@ import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
-import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
import com.google.devtools.build.lib.cmdline.Label;
@@ -41,8 +40,10 @@ import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.cpp.AspectLegalCppSemantics;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper.LinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
@@ -114,9 +115,7 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
.requireProviders(ProtoSupportDataProvider.class)
.add(
attr(PROTO_TOOLCHAIN_ATTR, LABEL)
- .mandatoryNativeProviders(
- ImmutableList.<Class<? extends TransitiveInfoProvider>>of(
- ProtoLangToolchainProvider.class))
+ .mandatoryNativeProviders(ImmutableList.of(ProtoLangToolchainProvider.class))
.value(PROTO_TOOLCHAIN_LABEL))
.add(
attr(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, LABEL)
@@ -149,7 +148,7 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
FeatureConfiguration featureConfiguration = getFeatureConfiguration(supportData);
ProtoConfiguration protoConfiguration = ruleContext.getFragment(ProtoConfiguration.class);
- CcLibraryHelper compilationHelper = initializeCompilationHelper(featureConfiguration);
+ CcCompilationHelper compilationHelper = initializeCompilationHelper(featureConfiguration);
// Compute and register files generated by this proto library.
Collection<Artifact> outputs = new ArrayList<>();
@@ -190,8 +189,8 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
filesBuilder.addAll(outputs);
createProtoCompileAction(supportData, outputs);
- Info.CompilationInfo compilationInfo = compilationHelper.compile();
- Info.LinkingInfo linkingInfo =
+ CompilationInfo compilationInfo = compilationHelper.compile();
+ LinkingInfo linkingInfo =
initializeLinkingHelper(featureConfiguration)
.link(
compilationInfo.getCcCompilationOutputs(),
@@ -204,8 +203,9 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
.build();
outputGroups =
ImmutableMap.copyOf(
- Info.mergeOutputGroups(
- compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups()));
+ CcCommon.mergeOutputGroups(
+ ImmutableList.of(
+ compilationInfo.getOutputGroups(), linkingInfo.getOutputGroups())));
// On Windows, dynamic library is not built by default, so don't add them to filesToBuild.
linkingInfo.addLinkingOutputsTo(
filesBuilder, !featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS));
@@ -236,9 +236,10 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
return featureConfiguration;
}
- private CcLibraryHelper initializeCcLibraryHelper(FeatureConfiguration featureConfiguration) {
- CcLibraryHelper helper =
- new CcLibraryHelper(
+ private CcCompilationHelper initializeCompilationHelper(
+ FeatureConfiguration featureConfiguration) {
+ CcCompilationHelper helper =
+ new CcCompilationHelper(
ruleContext,
cppSemantics,
featureConfiguration,
@@ -253,15 +254,22 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
return helper;
}
- private CcLibraryHelper initializeCompilationHelper(FeatureConfiguration featureConfiguration) {
- return initializeCcLibraryHelper(featureConfiguration);
- }
-
- private CcLibraryHelper initializeLinkingHelper(FeatureConfiguration featureConfiguration) {
- CcLibraryHelper helper =
- initializeCcLibraryHelper(featureConfiguration)
+ private CcLinkingHelper initializeLinkingHelper(FeatureConfiguration featureConfiguration) {
+ CcLinkingHelper helper =
+ new CcLinkingHelper(
+ ruleContext,
+ cppSemantics,
+ featureConfiguration,
+ ccToolchain(ruleContext),
+ CppHelper.getFdoSupportUsingDefaultCcToolchainAttribute(ruleContext),
+ ruleContext.getConfiguration())
.enableCcSpecificLinkParamsProvider()
.enableCcNativeLibrariesProvider();
+ TransitiveInfoCollection runtime = getProtoToolchainProvider().runtime();
+ if (runtime != null) {
+ helper.addDeps(ImmutableList.of(runtime));
+ }
+ helper.addDeps(ruleContext.getPrerequisites("deps", TARGET));
// TODO(dougk): Configure output artifact with action_config
// once proto compile action is configurable from the crosstool.
if (!ccToolchain(ruleContext).supportsDynamicLinker()) {
@@ -287,7 +295,7 @@ public abstract class CcProtoAspect extends NativeAspectClass implements Configu
return result.build();
}
- private void registerBlacklistedSrcs(SupportData supportData, CcLibraryHelper helper) {
+ private void registerBlacklistedSrcs(SupportData supportData, CcCompilationHelper helper) {
// Hack: This is a proto_library for descriptor.proto or similar.
//
// The headers of those libraries are precomputed . They are also explicitly part of normal
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
index 6f574abe67..f768eda0f5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
@@ -88,9 +88,12 @@ import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType;
import com.google.devtools.build.lib.rules.apple.AppleToolchain;
import com.google.devtools.build.lib.rules.apple.XcodeConfig;
import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider;
+import com.google.devtools.build.lib.rules.cpp.CcCommon;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper;
+import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper;
-import com.google.devtools.build.lib.rules.cpp.CcLibraryHelper.Info;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper;
+import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper.LinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.CollidingProvidesException;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
@@ -301,7 +304,7 @@ public class CompilationSupport {
}
}
- private Info.CompilationInfo compile(
+ private CompilationInfo compile(
ObjcProvider objcProvider,
VariablesExtension extension,
ExtraCompileArgs extraCompileArgs,
@@ -318,12 +321,12 @@ public class CompilationSupport {
ObjcCppSemantics semantics,
String purpose)
throws RuleErrorException, InterruptedException {
- CcLibraryHelper result =
- new CcLibraryHelper(
+ CcCompilationHelper result =
+ new CcCompilationHelper(
ruleContext,
semantics,
getFeatureConfiguration(ruleContext, ccToolchain, buildConfiguration, objcProvider),
- CcLibraryHelper.SourceCategory.CC_AND_OBJC,
+ CcCompilationHelper.SourceCategory.CC_AND_OBJC,
ccToolchain,
fdoSupport,
buildConfiguration)
@@ -398,7 +401,7 @@ public class CompilationSupport {
String purpose = String.format("%s_objc_arc", semantics.getPurpose());
extensionBuilder.setArcEnabled(true);
- Info.CompilationInfo objcArcCompilationInfo =
+ CompilationInfo objcArcCompilationInfo =
compile(
objcProvider,
extensionBuilder.build(),
@@ -417,7 +420,7 @@ public class CompilationSupport {
purpose = String.format("%s_non_objc_arc", semantics.getPurpose());
extensionBuilder.setArcEnabled(false);
- Info.CompilationInfo nonObjcArcCompilationInfo =
+ CompilationInfo nonObjcArcCompilationInfo =
compile(
objcProvider,
extensionBuilder.build(),
@@ -434,23 +437,18 @@ public class CompilationSupport {
semantics,
purpose);
- CcLibraryHelper resultLink =
- new CcLibraryHelper(
+ CcLinkingHelper resultLink =
+ new CcLinkingHelper(
ruleContext,
semantics,
getFeatureConfiguration(ruleContext, ccToolchain, buildConfiguration, objcProvider),
- CcLibraryHelper.SourceCategory.CC_AND_OBJC,
ccToolchain,
fdoSupport,
buildConfiguration)
- .addPrecompiledFiles(precompiledFiles)
.addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET))
- // Not all our dependencies need to export cpp information.
- // For example, objc_proto_library can depend on a proto_library rule that does not
- // generate C++ protos.
- .setCheckDepsGenerateCpp(false)
.setLinkedArtifactNameSuffix(intermediateArtifacts.archiveFileNameSuffix())
.setNeverLink(true)
+ .setCheckDepsGenerateCpp(false)
.addVariableExtension(extensionBuilder.build());
if (linkType != null) {
@@ -475,15 +473,15 @@ public class CompilationSupport {
compilationOutputsBuilder.merge(objcArcCompilationInfo.getCcCompilationOutputs());
compilationOutputsBuilder.merge(nonObjcArcCompilationInfo.getCcCompilationOutputs());
- Info.LinkingInfo linkingInfo =
- resultLink.link(
- compilationOutputsBuilder.build(), compilationContextBuilder.build());
+ LinkingInfo linkingInfo =
+ resultLink.link(compilationOutputsBuilder.build(), compilationContextBuilder.build());
Map<String, NestedSet<Artifact>> mergedOutputGroups =
- Info.mergeOutputGroups(
- objcArcCompilationInfo.getOutputGroups(),
- nonObjcArcCompilationInfo.getOutputGroups(),
- linkingInfo.getOutputGroups());
+ CcCommon.mergeOutputGroups(
+ ImmutableList.of(
+ objcArcCompilationInfo.getOutputGroups(),
+ nonObjcArcCompilationInfo.getOutputGroups(),
+ linkingInfo.getOutputGroups()));
return new Pair<>(compilationOutputsBuilder.build(), ImmutableMap.copyOf(mergedOutputGroups));
}
@@ -572,36 +570,6 @@ public class CompilationSupport {
}
}
- private void registerHeaderScanningActions(
- CcCompilationOutputs ccCompilationOutputs,
- ObjcProvider objcProvider,
- CompilationArtifacts compilationArtifacts) {
- // PIC is not used for Obj-C builds, if that changes this method will need to change
- if (!isHeaderThinningEnabled() || ccCompilationOutputs.getObjectFiles(false).isEmpty()) {
- return;
- }
-
- ImmutableList.Builder<ObjcHeaderThinningInfo> headerThinningInfos = ImmutableList.builder();
- AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
- for (Artifact objectFile : ccCompilationOutputs.getObjectFiles(false)) {
- ActionAnalysisMetadata generatingAction =
- analysisEnvironment.getLocalGeneratingAction(objectFile);
- if (generatingAction instanceof CppCompileAction) {
- CppCompileAction action = (CppCompileAction) generatingAction;
- Artifact sourceFile = action.getSourceFile();
- if (!sourceFile.isTreeArtifact()
- && SOURCES_FOR_HEADER_THINNING.matches(sourceFile.getFilename())) {
- headerThinningInfos.add(
- new ObjcHeaderThinningInfo(
- sourceFile,
- intermediateArtifacts.headersListFile(sourceFile),
- action.getCompilerOptions()));
- }
- }
- }
- registerHeaderScanningActions(headerThinningInfos.build(), objcProvider, compilationArtifacts);
- }
-
/**
* Iterable wrapper providing strong type safety for arguments to binary linking.
*/
@@ -890,72 +858,6 @@ public class CompilationSupport {
}
/**
- * Registers all actions necessary to compile this rule's sources and archive them.
- *
- * @param compilationArtifacts collection of artifacts required for the compilation
- * @param objcProvider provides all compiling and linking information to register these actions
- * @param toolchain the toolchain to be used in determining command lines
- * @return this compilation support
- * @throws RuleErrorException for invalid crosstool files
- */
- CompilationSupport registerCompileAndArchiveActions(
- CompilationArtifacts compilationArtifacts,
- ObjcProvider objcProvider,
- CcToolchainProvider toolchain)
- throws RuleErrorException, InterruptedException {
- return registerCompileAndArchiveActions(
- compilationArtifacts,
- objcProvider,
- ExtraCompileArgs.NONE,
- ImmutableList.<PathFragment>of(),
- toolchain,
- maybeGetFdoSupport());
- }
-
- /**
- * Registers all actions necessary to compile this rule's sources and archive them.
- *
- * @param common common information about this rule and its dependencies
- * @return this compilation support
- * @throws RuleErrorException for invalid crosstool files
- */
- CompilationSupport registerCompileAndArchiveActions(ObjcCommon common)
- throws RuleErrorException, InterruptedException {
- return registerCompileAndArchiveActions(
- common, ExtraCompileArgs.NONE, ImmutableList.<PathFragment>of());
- }
-
- /**
- * Registers all actions necessary to compile this rule's sources and archive them.
- *
- * @param common common information about this rule and its dependencies
- * @param priorityHeaders priority headers to be included before the dependency headers
- * @return this compilation support
- * @throws RuleErrorException for invalid crosstool files
- */
- CompilationSupport registerCompileAndArchiveActions(
- ObjcCommon common, Iterable<PathFragment> priorityHeaders)
- throws RuleErrorException, InterruptedException {
- return registerCompileAndArchiveActions(common, ExtraCompileArgs.NONE, priorityHeaders);
- }
-
- /**
- * Registers an action to create an archive artifact by fully (statically) linking all transitive
- * dependencies of this rule.
- *
- * @param objcProvider provides all compiling and linking information to create this artifact
- * @param outputArchive the output artifact for this action
- */
- public CompilationSupport registerFullyLinkAction(
- ObjcProvider objcProvider, Artifact outputArchive) throws InterruptedException {
- return registerFullyLinkAction(
- objcProvider,
- outputArchive,
- toolchain,
- maybeGetFdoSupport());
- }
-
- /**
* Returns a provider that collects this target's instrumented sources as well as those of its
* dependencies.
*
@@ -984,27 +886,6 @@ public class CompilationSupport {
}
/**
- * Registers an action that will generate a clang module map for this target, using the hdrs
- * attribute of this rule.
- */
- CompilationSupport registerGenerateModuleMapAction(CompilationArtifacts compilationArtifacts) {
- // TODO(bazel-team): Include textual headers in the module map when Xcode 6 support is
- // dropped.
- // TODO(b/32225593): Include private headers in the module map.
- Iterable<Artifact> publicHeaders = attributes.hdrs();
- publicHeaders = Iterables.concat(publicHeaders, compilationArtifacts.getAdditionalHdrs());
- CppModuleMap moduleMap = intermediateArtifacts.moduleMap();
- registerGenerateModuleMapAction(moduleMap, publicHeaders);
-
- Optional<Artifact> umbrellaHeader = moduleMap.getUmbrellaHeader();
- if (umbrellaHeader.isPresent()) {
- registerGenerateUmbrellaHeaderAction(umbrellaHeader.get(), publicHeaders);
- }
-
- return this;
- }
-
- /**
* Validates compilation-related attributes on this rule.
*
* @return this compilation support
@@ -1049,6 +930,56 @@ public class CompilationSupport {
*
* @param compilationArtifacts collection of artifacts required for the compilation
* @param objcProvider provides all compiling and linking information to register these actions
+ * @param toolchain the toolchain to be used in determining command lines
+ * @return this compilation support
+ * @throws RuleErrorException for invalid crosstool files
+ */
+ CompilationSupport registerCompileAndArchiveActions(
+ CompilationArtifacts compilationArtifacts,
+ ObjcProvider objcProvider,
+ CcToolchainProvider toolchain)
+ throws RuleErrorException, InterruptedException {
+ return registerCompileAndArchiveActions(
+ compilationArtifacts,
+ objcProvider,
+ ExtraCompileArgs.NONE,
+ ImmutableList.<PathFragment>of(),
+ toolchain,
+ maybeGetFdoSupport());
+ }
+
+ /**
+ * Registers all actions necessary to compile this rule's sources and archive them.
+ *
+ * @param common common information about this rule and its dependencies
+ * @return this compilation support
+ * @throws RuleErrorException for invalid crosstool files
+ */
+ CompilationSupport registerCompileAndArchiveActions(ObjcCommon common)
+ throws RuleErrorException, InterruptedException {
+ return registerCompileAndArchiveActions(
+ common, ExtraCompileArgs.NONE, ImmutableList.<PathFragment>of());
+ }
+
+ /**
+ * Registers all actions necessary to compile this rule's sources and archive them.
+ *
+ * @param common common information about this rule and its dependencies
+ * @param priorityHeaders priority headers to be included before the dependency headers
+ * @return this compilation support
+ * @throws RuleErrorException for invalid crosstool files
+ */
+ CompilationSupport registerCompileAndArchiveActions(
+ ObjcCommon common, Iterable<PathFragment> priorityHeaders)
+ throws RuleErrorException, InterruptedException {
+ return registerCompileAndArchiveActions(common, ExtraCompileArgs.NONE, priorityHeaders);
+ }
+
+ /**
+ * Registers all actions necessary to compile this rule's sources and archive them.
+ *
+ * @param compilationArtifacts collection of artifacts required for the compilation
+ * @param objcProvider provides all compiling and linking information to register these actions
* @param extraCompileArgs args to be added to compile actions
* @param priorityHeaders priority headers to be included before the dependency headers
* @param ccToolchain the cpp toolchain provider, may be null
@@ -1381,6 +1312,18 @@ public class CompilationSupport {
*
* @param objcProvider provides all compiling and linking information to create this artifact
* @param outputArchive the output artifact for this action
+ */
+ public CompilationSupport registerFullyLinkAction(
+ ObjcProvider objcProvider, Artifact outputArchive) throws InterruptedException {
+ return registerFullyLinkAction(objcProvider, outputArchive, toolchain, maybeGetFdoSupport());
+ }
+
+ /**
+ * Registers an action to create an archive artifact by fully (statically) linking all transitive
+ * dependencies of this rule.
+ *
+ * @param objcProvider provides all compiling and linking information to create this artifact
+ * @param outputArchive the output artifact for this action
* @param ccToolchain the cpp toolchain provider, may be null
* @param fdoSupport the cpp FDO support provider, may be null
* @return this {@link CompilationSupport} instance
@@ -1745,6 +1688,27 @@ public class CompilationSupport {
}
/**
+ * Registers an action that will generate a clang module map for this target, using the hdrs
+ * attribute of this rule.
+ */
+ CompilationSupport registerGenerateModuleMapAction(CompilationArtifacts compilationArtifacts) {
+ // TODO(bazel-team): Include textual headers in the module map when Xcode 6 support is
+ // dropped.
+ // TODO(b/32225593): Include private headers in the module map.
+ Iterable<Artifact> publicHeaders = attributes.hdrs();
+ publicHeaders = Iterables.concat(publicHeaders, compilationArtifacts.getAdditionalHdrs());
+ CppModuleMap moduleMap = intermediateArtifacts.moduleMap();
+ registerGenerateModuleMapAction(moduleMap, publicHeaders);
+
+ Optional<Artifact> umbrellaHeader = moduleMap.getUmbrellaHeader();
+ if (umbrellaHeader.isPresent()) {
+ registerGenerateUmbrellaHeaderAction(umbrellaHeader.get(), publicHeaders);
+ }
+
+ return this;
+ }
+
+ /**
* Registers an action that will generate a clang module map.
* @param moduleMap the module map to generate
* @param publicHeaders the headers that should be directly accessible by dependers
@@ -1840,6 +1804,36 @@ public class CompilationSupport {
.getProvider(FilesToRunProvider.class);
}
+ private void registerHeaderScanningActions(
+ CcCompilationOutputs ccCompilationOutputs,
+ ObjcProvider objcProvider,
+ CompilationArtifacts compilationArtifacts) {
+ // PIC is not used for Obj-C builds, if that changes this method will need to change
+ if (!isHeaderThinningEnabled() || ccCompilationOutputs.getObjectFiles(false).isEmpty()) {
+ return;
+ }
+
+ ImmutableList.Builder<ObjcHeaderThinningInfo> headerThinningInfos = ImmutableList.builder();
+ AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
+ for (Artifact objectFile : ccCompilationOutputs.getObjectFiles(false)) {
+ ActionAnalysisMetadata generatingAction =
+ analysisEnvironment.getLocalGeneratingAction(objectFile);
+ if (generatingAction instanceof CppCompileAction) {
+ CppCompileAction action = (CppCompileAction) generatingAction;
+ Artifact sourceFile = action.getSourceFile();
+ if (!sourceFile.isTreeArtifact()
+ && SOURCES_FOR_HEADER_THINNING.matches(sourceFile.getFilename())) {
+ headerThinningInfos.add(
+ new ObjcHeaderThinningInfo(
+ sourceFile,
+ intermediateArtifacts.headersListFile(sourceFile),
+ action.getCompilerOptions()));
+ }
+ }
+ }
+ registerHeaderScanningActions(headerThinningInfos.build(), objcProvider, compilationArtifacts);
+ }
+
/**
* Creates and registers ObjcHeaderScanning {@link SpawnAction}. Groups all the actions by their
* compilation command line arguments and creates a ObjcHeaderScanning action for each unique one.