aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-04-18 14:00:44 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-04-19 09:40:29 +0000
commit98aacfe14b7f5a79614efa26c30e3b7dea5fab91 (patch)
tree6fa402654ac5f14b1b53aea324e575da11e14c84 /src
parent812227f8733a2b6679cd9b06cea26fe238afb8dd (diff)
Add the option to have non-interface dependencies. This can greatly speed up
builds with C++ modules as modules can be built without waiting on dependencies that are only required for the module's implementation. -- MOS_MIGRATED_REVID=120119435
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java70
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompilationContext.java12
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java29
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java5
5 files changed, 89 insertions, 29 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()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
index b7bf3f48cc..41124222bb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
@@ -999,7 +999,7 @@ public class CcToolchainFeatures implements Serializable {
/**
* @return whether the given {@code feature} is enabled.
*/
- boolean isEnabled(String feature) {
+ public boolean isEnabled(String feature) {
return enabledFeatureNames.contains(feature);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompilationContext.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompilationContext.java
index 4afd941c0b..af3bbba851 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompilationContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompilationContext.java
@@ -614,7 +614,7 @@ public final class CppCompilationContext implements TransitiveInfoProvider {
* Builder class for {@link CppCompilationContext}.
*/
public static class Builder {
- private String purpose = "cpp_compilation_prerequisites";
+ private String purpose;
private final Set<Artifact> compilationPrerequisites = new LinkedHashSet<>();
private final Set<PathFragment> includeDirs = new LinkedHashSet<>();
private final Set<PathFragment> quoteIncludeDirs = new LinkedHashSet<>();
@@ -654,7 +654,17 @@ public final class CppCompilationContext implements TransitiveInfoProvider {
* Creates a new builder for a {@link CppCompilationContext} instance.
*/
public Builder(RuleContext ruleContext) {
+ this(ruleContext, /*forInterface=*/ false);
+ }
+
+ /**
+ * Creates a new builder for a {@link CppCompilationContext} instance.
+ *
+ * @param forInterface if true, this context is designated for the compilation of an interface.
+ */
+ public Builder(RuleContext ruleContext, boolean forInterface) {
this.ruleContext = ruleContext;
+ this.purpose = forInterface ? "cpp_interface_prerequisites" : "cpp_compilation_prerequisites";
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
index 0132191c30..579e8492d8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java
@@ -61,6 +61,7 @@ public final class CppModel {
// compile model
private CppCompilationContext context;
+ private CppCompilationContext interfaceContext;
private final List<Pair<Artifact, Label>> sourceFiles = new ArrayList<>();
private final List<String> copts = new ArrayList<>();
private final List<PathFragment> additionalIncludes = new ArrayList<>();
@@ -121,6 +122,15 @@ public final class CppModel {
this.context = context;
return this;
}
+
+ /**
+ * Sets the compilation context, i.e. include directories and allowed header files inclusions, for
+ * the compilation of this model's interface, e.g. header module.
+ */
+ public CppModel setInterfaceContext(CppCompilationContext context) {
+ this.interfaceContext = context;
+ return this;
+ }
/**
* Adds a single source file to be compiled. Note that this should only be called for primary
@@ -279,9 +289,10 @@ public final class CppModel {
* Returns a {@code CppCompileActionBuilder} with the common fields for a C++ compile action
* being initialized.
*/
- private CppCompileActionBuilder initializeCompileAction(Artifact sourceArtifact,
- Label sourceLabel) {
- CppCompileActionBuilder builder = createCompileActionBuilder(sourceArtifact, sourceLabel);
+ private CppCompileActionBuilder initializeCompileAction(
+ Artifact sourceArtifact, Label sourceLabel, boolean forInterface) {
+ CppCompileActionBuilder builder =
+ createCompileActionBuilder(sourceArtifact, sourceLabel, forInterface);
if (nocopts != null) {
builder.addNocopts(nocopts);
}
@@ -395,7 +406,8 @@ public final class CppModel {
Artifact moduleMapArtifact = context.getCppModuleMap().getArtifact();
Label moduleMapLabel = Label.parseAbsoluteUnchecked(context.getCppModuleMap().getName());
PathFragment outputName = getObjectOutputPath(moduleMapArtifact, objectDir);
- CppCompileActionBuilder builder = initializeCompileAction(moduleMapArtifact, moduleMapLabel);
+ CppCompileActionBuilder builder =
+ initializeCompileAction(moduleMapArtifact, moduleMapLabel, /*forInterface=*/ true);
// A header module compile action is just like a normal compile action, but:
// - the compiled source file is the module map
@@ -408,7 +420,8 @@ public final class CppModel {
Artifact sourceArtifact = source.getFirst();
Label sourceLabel = source.getSecond();
PathFragment outputName = getObjectOutputPath(sourceArtifact, objectDir);
- CppCompileActionBuilder builder = initializeCompileAction(sourceArtifact, sourceLabel);
+ CppCompileActionBuilder builder =
+ initializeCompileAction(sourceArtifact, sourceLabel, /*forInterface=*/ false);
if (CppFileTypes.CPP_HEADER.matches(source.first.getExecPath())) {
createHeaderAction(outputName, result, env, builder);
@@ -734,13 +747,11 @@ public final class CppModel {
* crosstool inputs, output and dotd file names, compilation context and copts.
*/
private CppCompileActionBuilder createCompileActionBuilder(
- Artifact source, Label label) {
+ Artifact source, Label label, boolean forInterface) {
CppCompileActionBuilder builder = new CppCompileActionBuilder(
ruleContext, source, label);
- builder
- .setContext(context)
- .addCopts(copts);
+ builder.setContext(forInterface ? interfaceContext : context).addCopts(copts);
return builder;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
index 77a9719923..2d71008e23 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
@@ -88,6 +88,11 @@ public class CppRuleClasses {
* A string constant for the preprocess_headers feature.
*/
public static final String PREPROCESS_HEADERS = "preprocess_headers";
+
+ /**
+ * A string constant for the disable_pbh feature.
+ */
+ public static final String DISABLE_PBH = "disable_pbh";
/**
* A string constant for the module_maps feature; this is a precondition to the layering_check and