aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java70
1 files changed, 52 insertions, 18 deletions
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/CcLibraryHelper.java
index 9f8f98d46c..dc7f035353 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/CcLibraryHelper.java
@@ -201,7 +201,8 @@ public final class CcLibraryHelper {
@Nullable private Pattern nocopts;
private final List<String> linkopts = new ArrayList<>();
private final Set<String> defines = new LinkedHashSet<>();
- private final List<TransitiveInfoCollection> deps = new ArrayList<>();
+ private final List<TransitiveInfoCollection> implementationDeps = new ArrayList<>();
+ private final List<TransitiveInfoCollection> interfaceDeps = new ArrayList<>();
private final List<Artifact> linkstamps = new ArrayList<>();
private final List<Artifact> prerequisites = new ArrayList<>();
private final List<PathFragment> looseIncludeDirs = new ArrayList<>();
@@ -513,7 +514,26 @@ public final class CcLibraryHelper {
Preconditions.checkArgument(dep.getConfiguration() == null
|| configuration.equalsOrIsSupersetOf(dep.getConfiguration()),
"dep " + dep.getLabel() + " has a different config than " + ruleContext.getLabel());
- this.deps.add(dep);
+ this.implementationDeps.add(dep);
+ this.interfaceDeps.add(dep);
+ }
+ return this;
+ }
+
+ /**
+ * Similar to @{link addDeps}, but adds the given targets as implementation dependencies.
+ * Implementation dependencies are required to actually build a target, but are not required to
+ * build the target's interface, e.g. header module. Thus, implementation dependencies are always
+ * a superset of interface dependencies. Whatever is required to build the interface is also
+ * required to build the implementation.
+ */
+ public CcLibraryHelper addImplementationDeps(Iterable<? extends TransitiveInfoCollection> deps) {
+ for (TransitiveInfoCollection dep : deps) {
+ Preconditions.checkArgument(
+ dep.getConfiguration() == null
+ || configuration.equalsOrIsSupersetOf(dep.getConfiguration()),
+ "dep " + dep.getLabel() + " has a different config than " + ruleContext.getLabel());
+ this.implementationDeps.add(dep);
}
return this;
}
@@ -727,15 +747,26 @@ public final class CcLibraryHelper {
if (checkDepsGenerateCpp) {
for (LanguageDependentFragment dep :
- AnalysisUtils.getProviders(deps, LanguageDependentFragment.class)) {
+ AnalysisUtils.getProviders(implementationDeps, LanguageDependentFragment.class)) {
LanguageDependentFragment.Checker.depSupportsLanguage(
ruleContext, dep, CppRuleClasses.LANGUAGE);
}
}
CppModel model = initializeCppModel();
- CppCompilationContext cppCompilationContext = initializeCppCompilationContext(model);
+ CppCompilationContext cppCompilationContext =
+ initializeCppCompilationContext(model, /*forInterface=*/ false);
model.setContext(cppCompilationContext);
+
+ // If we actually have different interface deps, we need a separate compilation context
+ // for the interface. Otherwise, we can just re-use the normal cppCompilationContext.
+ CppCompilationContext interfaceCompilationContext = cppCompilationContext;
+ // As implemenationDeps is a superset of interfaceDeps, comparing the size proves equality.
+ if (implementationDeps.size() != interfaceDeps.size()) {
+ interfaceCompilationContext = initializeCppCompilationContext(model, /*forInterface=*/ true);
+ }
+ model.setInterfaceContext(interfaceCompilationContext);
+
boolean compileHeaderModules = featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULES);
Preconditions.checkState(
!compileHeaderModules || cppCompilationContext.getCppModuleMap() != null,
@@ -781,7 +812,8 @@ public final class CcLibraryHelper {
.build();
}
- DwoArtifactsCollector dwoArtifacts = DwoArtifactsCollector.transitiveCollector(ccOutputs, deps);
+ DwoArtifactsCollector dwoArtifacts =
+ DwoArtifactsCollector.transitiveCollector(ccOutputs, implementationDeps);
Runfiles cppStaticRunfiles = collectCppRunfiles(ccLinkingOutputs, true);
Runfiles cppSharedRunfiles = collectCppRunfiles(ccLinkingOutputs, false);
@@ -791,7 +823,7 @@ public final class CcLibraryHelper {
new LinkedHashMap<>();
providers.put(CppRunfilesProvider.class,
new CppRunfilesProvider(cppStaticRunfiles, cppSharedRunfiles));
- providers.put(CppCompilationContext.class, cppCompilationContext);
+ providers.put(CppCompilationContext.class, interfaceCompilationContext);
providers.put(CppDebugFileProvider.class, new CppDebugFileProvider(
dwoArtifacts.getDwoArtifacts(), dwoArtifacts.getPicDwoArtifacts()));
providers.put(TransitiveLipoInfoProvider.class, collectTransitiveLipoInfo(ccOutputs));
@@ -855,9 +887,10 @@ public final class CcLibraryHelper {
/**
* Create context for cc compile action from generated inputs.
*/
- private CppCompilationContext initializeCppCompilationContext(CppModel model) {
+ private CppCompilationContext initializeCppCompilationContext(
+ CppModel model, boolean forInterface) {
CppCompilationContext.Builder contextBuilder =
- new CppCompilationContext.Builder(ruleContext);
+ new CppCompilationContext.Builder(ruleContext, forInterface);
// Setup the include path; local include directories come before those inherited from deps or
// from the toolchain; in case of aliasing (same include file found on different entries),
@@ -881,7 +914,8 @@ public final class CcLibraryHelper {
}
contextBuilder.mergeDependentContexts(
- AnalysisUtils.getProviders(deps, CppCompilationContext.class));
+ AnalysisUtils.getProviders(
+ forInterface ? interfaceDeps : implementationDeps, CppCompilationContext.class));
CppHelper.mergeToolchainDependentContext(ruleContext, contextBuilder);
// But defines come after those inherited from deps.
@@ -952,13 +986,13 @@ public final class CcLibraryHelper {
* Creates context for cc compile action from generated inputs.
*/
public CppCompilationContext initializeCppCompilationContext() {
- return initializeCppCompilationContext(initializeCppModel());
+ return initializeCppCompilationContext(initializeCppModel(), /*forInterface=*/ false);
}
private Iterable<CppModuleMap> collectModuleMaps() {
// Cpp module maps may be null for some rules. We filter the nulls out at the end.
List<CppModuleMap> result = new ArrayList<>();
- Iterables.addAll(result, Iterables.transform(deps, CPP_DEPS_TO_MODULES));
+ Iterables.addAll(result, Iterables.transform(interfaceDeps, CPP_DEPS_TO_MODULES));
if (ruleContext.getRule().getAttributeDefinition(":stl") != null) {
CppCompilationContext stl =
ruleContext.getPrerequisite(":stl", Mode.TARGET, CppCompilationContext.class);
@@ -990,7 +1024,7 @@ public final class CcLibraryHelper {
}
for (TransitiveLipoInfoProvider dep :
- AnalysisUtils.getProviders(deps, TransitiveLipoInfoProvider.class)) {
+ AnalysisUtils.getProviders(implementationDeps, TransitiveLipoInfoProvider.class)) {
scannableBuilder.addTransitive(dep.getTransitiveIncludeScannables());
}
@@ -1004,8 +1038,8 @@ public final class CcLibraryHelper {
private Runfiles collectCppRunfiles(
CcLinkingOutputs ccLinkingOutputs, boolean linkingStatically) {
Runfiles.Builder builder = new Runfiles.Builder(ruleContext.getWorkspaceName());
- builder.addTargets(deps, RunfilesProvider.DEFAULT_RUNFILES);
- builder.addTargets(deps, CppRunfilesProvider.runfilesFunction(linkingStatically));
+ builder.addTargets(implementationDeps, RunfilesProvider.DEFAULT_RUNFILES);
+ builder.addTargets(implementationDeps, CppRunfilesProvider.runfilesFunction(linkingStatically));
// Add the shared libraries to the runfiles.
builder.addArtifacts(ccLinkingOutputs.getLibrariesForRunfiles(linkingStatically));
return builder.build();
@@ -1019,7 +1053,7 @@ public final class CcLibraryHelper {
protected void collect(CcLinkParams.Builder builder, boolean linkingStatically,
boolean linkShared) {
builder.addLinkstamps(linkstamps, cppCompilationContext);
- builder.addTransitiveTargets(deps,
+ builder.addTransitiveTargets(implementationDeps,
CcLinkParamsProvider.TO_LINK_PARAMS, CcSpecificLinkParamsProvider.TO_LINK_PARAMS);
if (!neverlink) {
builder.addLibraries(ccLinkingOutputs.getPreferredLibraries(linkingStatically,
@@ -1033,8 +1067,8 @@ public final class CcLibraryHelper {
private NestedSet<LinkerInput> collectNativeCcLibraries(CcLinkingOutputs ccLinkingOutputs) {
NestedSetBuilder<LinkerInput> result = NestedSetBuilder.linkOrder();
result.addAll(ccLinkingOutputs.getDynamicLibraries());
- for (CcNativeLibraryProvider dep : AnalysisUtils.getProviders(
- deps, CcNativeLibraryProvider.class)) {
+ for (CcNativeLibraryProvider dep :
+ AnalysisUtils.getProviders(implementationDeps, CcNativeLibraryProvider.class)) {
result.addTransitive(dep.getTransitiveCcNativeLibraries());
}
@@ -1051,7 +1085,7 @@ public final class CcLibraryHelper {
NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
for (CcExecutionDynamicLibrariesProvider dep :
- AnalysisUtils.getProviders(deps, CcExecutionDynamicLibrariesProvider.class)) {
+ AnalysisUtils.getProviders(implementationDeps, CcExecutionDynamicLibrariesProvider.class)) {
builder.addTransitive(dep.getExecutionDynamicLibraryArtifacts());
}
return builder.isEmpty()