aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules
diff options
context:
space:
mode:
authorGravatar Rumou Duan <rduan@google.com>2017-02-10 17:24:03 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2017-02-10 18:19:31 +0000
commit5490757be5e527df82eee5094a0f59c86a5de766 (patch)
tree6d75800e0348de7e3472dd37de75d467a65fb468 /src/main/java/com/google/devtools/build/lib/rules
parent762576e5e7a3ee0da39dbb24134cb8530cbb911e (diff)
Introduce CppCompileActionTemplate, which expands into a list of CppCompileActions that to be executed at execution time.
-- PiperOrigin-RevId: 147163077 MOS_MIGRATED_REVID=147163077
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java95
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java233
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java200
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppModel.java154
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppSource.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java5
13 files changed, 590 insertions, 220 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
index f601913dc2..f70a4ed28b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationOutputs.java
@@ -200,7 +200,10 @@ public class CcCompilationOutputs {
* Adds an .o file.
*/
public Builder addObjectFile(Artifact artifact) {
- Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(artifact.getFilename()));
+ // We skip file extension checks for TreeArtifacts because they represent directory artifacts
+ // without a file extension.
+ Preconditions.checkArgument(
+ artifact.isTreeArtifact() || Link.OBJECT_FILETYPES.matches(artifact.getFilename()));
objectFiles.add(artifact);
return this;
}
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 355d01b00b..9d5295764e 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
@@ -451,13 +451,16 @@ public final class CcLibraryHelper {
* file type also to compilationUnitSources.
*/
private void addHeader(Artifact header, Label label) {
- boolean isHeader = CppFileTypes.CPP_HEADER.matches(header.getExecPath());
+ // We assume TreeArtifacts passed in are directories containing proper headers.
+ boolean isHeader =
+ CppFileTypes.CPP_HEADER.matches(header.getExecPath()) || header.isTreeArtifact();
boolean isTextualInclude = CppFileTypes.CPP_TEXTUAL_INCLUDE.matches(header.getExecPath());
publicHeaders.add(header);
if (isTextualInclude || !isHeader || !shouldProcessHeaders()) {
return;
}
- compilationUnitSources.add(CppSource.create(header, label, ImmutableMap.<String, String>of()));
+ compilationUnitSources.add(
+ CppSource.create(header, label, ImmutableMap.<String, String>of(), CppSource.Type.HEADER));
}
/** Adds a header to {@code publicHeaders}, but not to this target's module map. */
@@ -476,14 +479,26 @@ public final class CcLibraryHelper {
Preconditions.checkNotNull(featureConfiguration);
boolean isHeader = CppFileTypes.CPP_HEADER.matches(source.getExecPath());
boolean isTextualInclude = CppFileTypes.CPP_TEXTUAL_INCLUDE.matches(source.getExecPath());
- boolean isCompiledSource = sourceCategory.getSourceTypes().matches(source.getExecPathString());
+ // We assume TreeArtifacts passed in are directories containing proper sources for compilation.
+ boolean isCompiledSource =
+ sourceCategory.getSourceTypes().matches(source.getExecPathString())
+ || source.isTreeArtifact();
if (isHeader || isTextualInclude) {
privateHeaders.add(source);
}
if (isTextualInclude || !isCompiledSource || (isHeader && !shouldProcessHeaders())) {
return;
}
- compilationUnitSources.add(CppSource.create(source, label, buildVariables));
+ boolean isClifInputProto = CppFileTypes.CLIF_INPUT_PROTO.matches(source.getExecPathString());
+ CppSource.Type type;
+ if (isHeader) {
+ type = CppSource.Type.HEADER;
+ } else if (isClifInputProto) {
+ type = CppSource.Type.CLIF_INPUT_PROTO;
+ } else {
+ type = CppSource.Type.SOURCE;
+ }
+ compilationUnitSources.add(CppSource.create(source, label, buildVariables, type));
}
private boolean shouldProcessHeaders() {
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 f9295c684a..3d03ece32d 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
@@ -1407,6 +1407,13 @@ public class CcToolchainFeatures implements Serializable {
private final Map<String, VariableValue> variablesMap = new LinkedHashMap<>();
private final Map<String, String> stringVariablesMap = new LinkedHashMap<>();
+ public Builder() {};
+
+ public Builder(Variables variables) {
+ variablesMap.putAll(variables.variablesMap);
+ stringVariablesMap.putAll(variables.stringVariablesMap);
+ }
+
/** Add a variable that expands {@code name} to {@code value}. */
public Builder addStringVariable(String name, String value) {
Preconditions.checkArgument(
@@ -1419,6 +1426,14 @@ public class CcToolchainFeatures implements Serializable {
return this;
}
+ /** Overrides a variable to expands {@code name} to {@code value} instead. */
+ public Builder overrideStringVariable(String name, String value) {
+ Preconditions.checkNotNull(
+ value, "Cannot set null as a value for variable '%s'", name);
+ stringVariablesMap.put(name, value);
+ return this;
+ }
+
/**
* Add a sequence variable that expands {@code name} to {@code values}.
*
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index 6d73265772..c51edff2f9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -36,7 +36,6 @@ import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.extra.CppCompileInfo;
import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
-import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.config.PerLabelOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.CollectionUtils;
@@ -236,6 +235,7 @@ public class CppCompileAction extends AbstractAction
* Creates a new action to compile C/C++ source files.
*
* @param owner the owner of the action, usually the configured target that emitted it
+ * @param allInputs the list of all action inputs.
* @param features TODO(bazel-team): Add parameter description.
* @param featureConfiguration TODO(bazel-team): Add parameter description.
* @param variables TODO(bazel-team): Add parameter description.
@@ -266,14 +266,15 @@ public class CppCompileAction extends AbstractAction
* @param executionRequirements out-of-band hints to be passed to the execution backend to signal
* platform requirements
* @param environment TODO(bazel-team): Add parameter description
+ * @param builtinIncludeFiles List of include files that may be included even if they are not
+ * mentioned in the source file or any of the headers included by it
* @param actionName a string giving the name of this action for the purpose of toolchain
* evaluation
- * @param ruleContext The rule-context that produced this action
* @param cppSemantics C++ compilation semantics
- * @param ccToolchain C++ toolchain provider
*/
protected CppCompileAction(
ActionOwner owner,
+ NestedSet<Artifact> allInputs,
// TODO(bazel-team): Eventually we will remove 'features'; all functionality in 'features'
// will be provided by 'featureConfiguration'.
ImmutableList<String> features,
@@ -306,18 +307,11 @@ public class CppCompileAction extends AbstractAction
ImmutableMap<String, String> executionInfo,
ImmutableMap<String, String> environment,
String actionName,
- RuleContext ruleContext,
- CppSemantics cppSemantics,
- CcToolchainProvider ccToolchain) {
+ Iterable<Artifact> builtinIncludeFiles,
+ CppSemantics cppSemantics) {
super(
owner,
- createInputs(
- ruleContext,
- ccToolchain,
- mandatoryInputs,
- context.getTransitiveCompilationPrerequisites(),
- optionalSourceFile,
- lipoScannables),
+ allInputs,
CollectionUtils.asListWithoutNulls(
outputFile, (dotdFile == null ? null : dotdFile.artifact()), gcnoFile, dwoFile));
this.localShellEnvironment = localShellEnvironment;
@@ -351,81 +345,12 @@ public class CppCompileAction extends AbstractAction
// artifact and will definitely exist prior to this action execution.
this.mandatoryInputs = mandatoryInputs;
this.prunableInputs = prunableInputs;
- this.builtinIncludeFiles = ccToolchain.getBuiltinIncludeFiles();
+ this.builtinIncludeFiles = ImmutableList.copyOf(builtinIncludeFiles);
this.cppSemantics = cppSemantics;
- if (cppSemantics.needsIncludeValidation()) {
- verifyIncludePaths(ruleContext);
- }
this.additionalIncludeScannables = ImmutableList.copyOf(additionalIncludeScannables);
}
/**
- * Verifies that the include paths of this action are within the limits of the execution root.
- */
- private void verifyIncludePaths(RuleContext ruleContext) {
- if (ruleContext == null) {
- return;
- }
-
- Iterable<PathFragment> ignoredDirs = getValidationIgnoredDirs();
-
- // We currently do not check the output of:
- // - getQuoteIncludeDirs(): those only come from includes attributes, and are checked in
- // CcCommon.getIncludeDirsFromIncludesAttribute().
- // - getBuiltinIncludeDirs(): while in practice this doesn't happen, bazel can be configured
- // to use an absolute system root, in which case the builtin include dirs might be absolute.
- for (PathFragment include : Iterables.concat(getIncludeDirs(), getSystemIncludeDirs())) {
-
- // Ignore headers from built-in include directories.
- if (FileSystemUtils.startsWithAny(include, ignoredDirs)) {
- continue;
- }
-
- // One starting ../ is okay for getting to a sibling repository.
- if (include.startsWith(new PathFragment(Label.EXTERNAL_PATH_PREFIX))) {
- include = include.relativeTo(Label.EXTERNAL_PATH_PREFIX);
- }
-
- if (include.isAbsolute()
- || !PathFragment.EMPTY_FRAGMENT.getRelative(include).normalize().isNormalized()) {
- ruleContext.ruleError(
- "The include path '" + include + "' references a path outside of the execution root.");
- }
- }
- }
-
- private static NestedSet<Artifact> createInputs(
- RuleContext ruleContext,
- CcToolchainProvider ccToolchain,
- NestedSet<Artifact> mandatoryInputs,
- Set<Artifact> prerequisites,
- Artifact optionalSourceFile,
- Iterable<IncludeScannable> lipoScannables) {
- NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
- if (optionalSourceFile != null) {
- builder.add(optionalSourceFile);
- }
- builder.addAll(prerequisites);
- builder.addAll(ccToolchain.getBuiltinIncludeFiles());
- builder.addTransitive(mandatoryInputs);
- if (lipoScannables != null && lipoScannables.iterator().hasNext()) {
- // We need to add "legal generated scanner files" coming through LIPO scannables here. These
- // usually contain pre-grepped source files, i.e. files just containing the #include lines
- // extracted from generated files. With LIPO, some of these files can be accessed, even though
- // there is no direct dependency on them. Adding the artifacts as inputs to this compile
- // action ensures that the action generating them is actually executed.
- for (IncludeScannable lipoScannable : lipoScannables) {
- for (Artifact value : lipoScannable.getLegalGeneratedScannerFileMap().values()) {
- if (value != null) {
- builder.add(value);
- }
- }
- }
- }
- return builder.build();
- }
-
- /**
* Whether we should do "include scanning". Note that this does *not* mean whether we should parse
* the .d files to determine which include files were used during compilation. Instead, this means
* whether we should a) run the pre-execution include scanner (see {@code IncludeScanningContext})
@@ -959,7 +884,7 @@ public class CppCompileAction extends AbstractAction
errors.assertProblemFree(this, getSourceFile());
}
- private Iterable<PathFragment> getValidationIgnoredDirs() {
+ Iterable<PathFragment> getValidationIgnoredDirs() {
List<PathFragment> cxxSystemIncludeDirs = cppConfiguration.getBuiltInIncludeDirectories();
return Iterables.concat(
cxxSystemIncludeDirs, context.getSystemIncludeDirs());
@@ -1383,7 +1308,7 @@ public class CppCompileAction extends AbstractAction
CcToolchainFeatures.Variables variables,
String actionName) {
this.sourceFile = Preconditions.checkNotNull(sourceFile);
- this.dotdFile = CppFileTypes.mustProduceDotdFile(sourceFile.getPath().toString())
+ this.dotdFile = CppFileTypes.mustProduceDotdFile(sourceFile)
? Preconditions.checkNotNull(dotdFile) : null;
this.copts = Preconditions.checkNotNull(copts);
this.coptsFilter = coptsFilter;
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 ee606bc14b..39e7ff95b3 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
@@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -34,12 +33,14 @@ import com.google.devtools.build.lib.rules.cpp.CppCompileAction.DotdFile;
import com.google.devtools.build.lib.rules.cpp.CppCompileAction.SpecialInputsHandler;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Preconditions;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -53,7 +54,7 @@ public class CppCompileActionBuilder {
private final List<String> features = new ArrayList<>();
private CcToolchainFeatures.FeatureConfiguration featureConfiguration;
private CcToolchainFeatures.Variables variables;
- private final Artifact sourceFile;
+ private Artifact sourceFile;
private final Label sourceLabel;
private final NestedSetBuilder<Artifact> mandatoryInputsBuilder;
private Artifact optionalSourceFile;
@@ -62,12 +63,10 @@ public class CppCompileActionBuilder {
private PathFragment tempOutputFile;
private DotdFile dotdFile;
private Artifact gcnoFile;
- private final BuildConfiguration configuration;
private CppCompilationContext context = CppCompilationContext.EMPTY;
private final List<String> copts = new ArrayList<>();
private final List<String> pluginOpts = new ArrayList<>();
private final List<Pattern> nocopts = new ArrayList<>();
- private AnalysisEnvironment analysisEnvironment;
private ImmutableList<PathFragment> extraSystemIncludePrefixes = ImmutableList.of();
private boolean usePic;
private boolean allowUsingHeaderModules;
@@ -78,34 +77,50 @@ public class CppCompileActionBuilder {
private ImmutableMap<Artifact, IncludeScannable> lipoScannableMap;
private final ImmutableList.Builder<Artifact> additionalIncludeFiles =
new ImmutableList.Builder<>();
- private RuleContext ruleContext = null;
private Boolean shouldScanIncludes;
private Map<String, String> executionInfo = new LinkedHashMap<>();
private Map<String, String> environment = new LinkedHashMap<>();
private CppSemantics cppSemantics;
private CcToolchainProvider ccToolchain;
+ private final ImmutableMap<String, String> localShellEnvironment;
+ private final boolean codeCoverageEnabled;
// New fields need to be added to the copy constructor.
/**
* Creates a builder from a rule. This also uses the configuration and
* artifact factory from the rule.
*/
- public CppCompileActionBuilder(RuleContext ruleContext, Artifact sourceFile, Label sourceLabel,
+ public CppCompileActionBuilder(RuleContext ruleContext, Label sourceLabel,
CcToolchainProvider ccToolchain) {
- this.owner = ruleContext.getActionOwner();
- this.actionContext = CppCompileActionContext.class;
- this.cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
- this.analysisEnvironment = ruleContext.getAnalysisEnvironment();
- this.sourceFile = sourceFile;
+ this(
+ ruleContext.getActionOwner(),
+ sourceLabel,
+ ruleContext.getFragment(CppConfiguration.class),
+ ruleContext.getConfiguration(),
+ getLipoScannableMap(ruleContext),
+ ruleContext.getFeatures(),
+ ccToolchain);
+ }
+
+ private CppCompileActionBuilder(
+ ActionOwner actionOwner,
+ Label sourceLabel,
+ CppConfiguration cppConfiguration,
+ BuildConfiguration configuration,
+ Map<Artifact, IncludeScannable> lipoScannableMap,
+ Set<String> features,
+ CcToolchainProvider ccToolchain) {
+ this.owner = actionOwner;
this.sourceLabel = sourceLabel;
- this.configuration = ruleContext.getConfiguration();
+ this.cppConfiguration = cppConfiguration;
+ this.lipoScannableMap = ImmutableMap.copyOf(lipoScannableMap);
+ this.features.addAll(features);
this.mandatoryInputsBuilder = NestedSetBuilder.stableOrder();
- this.lipoScannableMap = getLipoScannableMap(ruleContext);
- this.ruleContext = ruleContext;
this.allowUsingHeaderModules = true;
+ this.localShellEnvironment = configuration.getLocalShellEnvironment();
+ this.codeCoverageEnabled = configuration.isCodeCoverageEnabled();
+ this.actionContext = CppCompileActionContext.class;
this.ccToolchain = ccToolchain;
-
- features.addAll(ruleContext.getFeatures());
}
private static ImmutableMap<Artifact, IncludeScannable> getLipoScannableMap(
@@ -115,7 +130,7 @@ public class CppCompileActionBuilder {
// contain headers, will still create CppCompileActions without providing a
// lipo_context_collector.
|| ruleContext.attributes().getAttributeDefinition(":lipo_context_collector") == null) {
- return null;
+ return ImmutableMap.<Artifact, IncludeScannable>of();
}
LipoContextProvider provider = ruleContext.getPrerequisite(
":lipo_context_collector", Mode.DONT_CHECK, LipoContextProvider.class);
@@ -129,6 +144,7 @@ public class CppCompileActionBuilder {
this.owner = other.owner;
this.features.addAll(other.features);
this.featureConfiguration = other.featureConfiguration;
+ this.variables = other.variables;
this.sourceFile = other.sourceFile;
this.sourceLabel = other.sourceLabel;
this.mandatoryInputsBuilder = NestedSetBuilder.<Artifact>stableOrder()
@@ -139,12 +155,10 @@ public class CppCompileActionBuilder {
this.tempOutputFile = other.tempOutputFile;
this.dotdFile = other.dotdFile;
this.gcnoFile = other.gcnoFile;
- this.configuration = other.configuration;
this.context = other.context;
this.copts.addAll(other.copts);
this.pluginOpts.addAll(other.pluginOpts);
this.nocopts.addAll(other.nocopts);
- this.analysisEnvironment = other.analysisEnvironment;
this.extraSystemIncludePrefixes = ImmutableList.copyOf(other.extraSystemIncludePrefixes);
this.specialInputsHandler = other.specialInputsHandler;
this.actionClassId = other.actionClassId;
@@ -153,10 +167,11 @@ public class CppCompileActionBuilder {
this.usePic = other.usePic;
this.allowUsingHeaderModules = other.allowUsingHeaderModules;
this.lipoScannableMap = other.lipoScannableMap;
- this.ruleContext = other.ruleContext;
this.shouldScanIncludes = other.shouldScanIncludes;
this.executionInfo = new LinkedHashMap<>(other.executionInfo);
this.environment = new LinkedHashMap<>(other.environment);
+ this.localShellEnvironment = other.localShellEnvironment;
+ this.codeCoverageEnabled = other.codeCoverageEnabled;
this.cppSemantics = other.cppSemantics;
this.ccToolchain = other.ccToolchain;
}
@@ -165,6 +180,11 @@ public class CppCompileActionBuilder {
return tempOutputFile;
}
+ public CppCompileActionBuilder setSourceFile(Artifact sourceFile) {
+ this.sourceFile = sourceFile;
+ return this;
+ }
+
public Artifact getSourceFile() {
return sourceFile;
}
@@ -198,16 +218,21 @@ public class CppCompileActionBuilder {
}
private Iterable<IncludeScannable> getLipoScannables(NestedSet<Artifact> realMandatoryInputs) {
- return lipoScannableMap == null ? ImmutableList.<IncludeScannable>of() : Iterables.filter(
- Iterables.transform(
- Iterables.filter(
- FileType.filter(
- realMandatoryInputs,
- CppFileTypes.C_SOURCE, CppFileTypes.CPP_SOURCE,
- CppFileTypes.ASSEMBLER_WITH_C_PREPROCESSOR),
- Predicates.not(Predicates.equalTo(getSourceFile()))),
- Functions.forMap(lipoScannableMap, null)),
- Predicates.notNull());
+ boolean fake = tempOutputFile != null;
+
+ return lipoScannableMap == null || fake
+ ? ImmutableList.<IncludeScannable>of()
+ : Iterables.filter(
+ Iterables.transform(
+ Iterables.filter(
+ FileType.filter(
+ realMandatoryInputs,
+ CppFileTypes.C_SOURCE,
+ CppFileTypes.CPP_SOURCE,
+ CppFileTypes.ASSEMBLER_WITH_C_PREPROCESSOR),
+ Predicates.not(Predicates.equalTo(getSourceFile()))),
+ Functions.forMap(lipoScannableMap, null)),
+ Predicates.notNull());
}
private String getActionName() {
@@ -248,7 +273,23 @@ public class CppCompileActionBuilder {
}
/**
- * Builds the Action as configured and returns the to be generated Artifact.
+ * Builds the action and performs some validations on the action.
+ *
+ * <p>This method may be called multiple times to create multiple compile
+ * actions (usually after calling some setters to modify the generated
+ * action).
+ */
+ public CppCompileAction buildAndValidate(RuleContext ruleContext) {
+ CppCompileAction action = build();
+ if (cppSemantics.needsIncludeValidation()) {
+ verifyActionIncludePaths(action, ruleContext);
+ }
+ return action;
+ }
+
+ /**
+ * Builds the Action as configured without validations. Users may want to call
+ * {@link #buildAndValidate} instead.
*
* <p>This method may be called multiple times to create multiple compile
* actions (usually after calling some setters to modify the generated
@@ -262,19 +303,6 @@ public class CppCompileActionBuilder {
allowUsingHeaderModules
&& featureConfiguration.isEnabled(CppRuleClasses.USE_HEADER_MODULES);
- boolean fake = tempOutputFile != null;
- // Configuration can be null in tests.
- NestedSetBuilder<Artifact> realMandatoryInputsBuilder = NestedSetBuilder.compileOrder();
- realMandatoryInputsBuilder.addTransitive(mandatoryInputsBuilder.build());
- boolean shouldPruneModules =
- cppConfiguration.getPruneCppModules() && shouldScanIncludes && useHeaderModules;
- if (useHeaderModules && !shouldPruneModules) {
- realMandatoryInputsBuilder.addTransitive(context.getTransitiveModules(usePic));
- }
- realMandatoryInputsBuilder.addTransitive(context.getAdditionalInputs());
-
- realMandatoryInputsBuilder.add(sourceFile);
-
// If the crosstool uses action_configs to configure cc compilation, collect execution info
// from there, otherwise, use no execution info.
// TODO(b/27903698): Assert that the crosstool has an action_config for this action.
@@ -285,7 +313,8 @@ public class CppCompileActionBuilder {
}
}
- NestedSet<Artifact> realMandatoryInputs = realMandatoryInputsBuilder.build();
+ NestedSet<Artifact> realMandatoryInputs = buildMandatoryInputs();
+ NestedSet<Artifact> allInputs = buildAllInputs();
NestedSetBuilder<Artifact> prunableInputBuilder = NestedSetBuilder.stableOrder();
prunableInputBuilder.addTransitive(context.getDeclaredIncludeSrcs());
@@ -294,15 +323,17 @@ public class CppCompileActionBuilder {
NestedSet<Artifact> prunableInputs = prunableInputBuilder.build();
// Copying the collections is needed to make the builder reusable.
+ boolean fake = tempOutputFile != null;
if (fake) {
return new FakeCppCompileAction(
owner,
+ allInputs,
ImmutableList.copyOf(features),
featureConfiguration,
variables,
sourceFile,
shouldScanIncludes,
- shouldPruneModules,
+ shouldPruneModules(),
usePic,
useHeaderModules,
sourceLabel,
@@ -311,25 +342,27 @@ public class CppCompileActionBuilder {
outputFile,
tempOutputFile,
dotdFile,
- configuration,
+ localShellEnvironment,
+ codeCoverageEnabled,
cppConfiguration,
context,
actionContext,
ImmutableList.copyOf(copts),
getNocoptPredicate(nocopts),
- ruleContext,
+ getLipoScannables(realMandatoryInputs),
+ ccToolchain.getBuiltinIncludeFiles(),
cppSemantics,
- ccToolchain,
ImmutableMap.copyOf(executionInfo));
} else {
return new CppCompileAction(
owner,
+ allInputs,
ImmutableList.copyOf(features),
featureConfiguration,
variables,
sourceFile,
shouldScanIncludes,
- shouldPruneModules,
+ shouldPruneModules(),
usePic,
useHeaderModules,
sourceLabel,
@@ -340,8 +373,8 @@ public class CppCompileActionBuilder {
gcnoFile,
dwoFile,
optionalSourceFile,
- configuration.getLocalShellEnvironment(),
- configuration.isCodeCoverageEnabled(),
+ localShellEnvironment,
+ codeCoverageEnabled,
cppConfiguration,
context,
actionContext,
@@ -354,9 +387,84 @@ public class CppCompileActionBuilder {
ImmutableMap.copyOf(executionInfo),
ImmutableMap.copyOf(environment),
getActionName(),
- ruleContext,
- cppSemantics,
- ccToolchain);
+ ccToolchain.getBuiltinIncludeFiles(),
+ cppSemantics);
+ }
+ }
+
+ /**
+ * Returns the list of mandatory inputs for the {@link CppCompileAction} as configured.
+ */
+ NestedSet<Artifact> buildMandatoryInputs() {
+ NestedSetBuilder<Artifact> realMandatoryInputsBuilder = NestedSetBuilder.compileOrder();
+ realMandatoryInputsBuilder.addTransitive(mandatoryInputsBuilder.build());
+ if (useHeaderModules() && !shouldPruneModules()) {
+ realMandatoryInputsBuilder.addTransitive(context.getTransitiveModules(usePic));
+ }
+ realMandatoryInputsBuilder.addTransitive(context.getAdditionalInputs());
+ realMandatoryInputsBuilder.add(Preconditions.checkNotNull(sourceFile));
+ return realMandatoryInputsBuilder.build();
+ }
+
+ /**
+ * Returns the list of all inputs for the {@link CppCompileAction} as configured.
+ */
+ NestedSet<Artifact> buildAllInputs() {
+ NestedSet<Artifact> mandatoryInputs = buildMandatoryInputs();
+ NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder();
+ if (optionalSourceFile != null) {
+ builder.add(optionalSourceFile);
+ }
+ builder.addAll(context.getTransitiveCompilationPrerequisites());
+ builder.addAll(ccToolchain.getBuiltinIncludeFiles());
+ builder.addTransitive(mandatoryInputs);
+ Iterable<IncludeScannable> lipoScannables = getLipoScannables(mandatoryInputs);
+ // We need to add "legal generated scanner files" coming through LIPO scannables here. These
+ // usually contain pre-grepped source files, i.e. files just containing the #include lines
+ // extracted from generated files. With LIPO, some of these files can be accessed, even though
+ // there is no direct dependency on them. Adding the artifacts as inputs to this compile
+ // action ensures that the action generating them is actually executed.
+ for (IncludeScannable lipoScannable : lipoScannables) {
+ for (Artifact value : lipoScannable.getLegalGeneratedScannerFileMap().values()) {
+ if (value != null) {
+ builder.add(value);
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ private boolean useHeaderModules() {
+ return allowUsingHeaderModules
+ && featureConfiguration.isEnabled(CppRuleClasses.USE_HEADER_MODULES);
+ }
+
+ private boolean shouldPruneModules() {
+ return cppConfiguration.getPruneCppModules() && shouldScanIncludes && useHeaderModules();
+ }
+
+ private static void verifyActionIncludePaths(CppCompileAction action, RuleContext ruleContext) {
+ Iterable<PathFragment> ignoredDirs = action.getValidationIgnoredDirs();
+ // We currently do not check the output of:
+ // - getQuoteIncludeDirs(): those only come from includes attributes, and are checked in
+ // CcCommon.getIncludeDirsFromIncludesAttribute().
+ // - getBuiltinIncludeDirs(): while in practice this doesn't happen, bazel can be configured
+ // to use an absolute system root, in which case the builtin include dirs might be absolute.
+ for (PathFragment include :
+ Iterables.concat(action.getIncludeDirs(), action.getSystemIncludeDirs())) {
+ // Ignore headers from built-in include directories.
+ if (FileSystemUtils.startsWithAny(include, ignoredDirs)) {
+ continue;
+ }
+ // One starting ../ is okay for getting to a sibling repository.
+ if (include.startsWith(new PathFragment(Label.EXTERNAL_PATH_PREFIX))) {
+ include = include.relativeTo(Label.EXTERNAL_PATH_PREFIX);
+ }
+ if (include.isAbsolute()
+ || !PathFragment.EMPTY_FRAGMENT.getRelative(include).normalize().isNormalized()) {
+ ruleContext.ruleError(
+ "The include path '" + include + "' references a path outside of the execution root.");
+ }
}
}
@@ -377,6 +485,13 @@ public class CppCompileActionBuilder {
return this;
}
+ /**
+ * Returns the build variables to be used for the action.
+ */
+ CcToolchainFeatures.Variables getVariables() {
+ return variables;
+ }
+
public CppCompileActionBuilder addEnvironment(Map<String, String> environment) {
this.environment.putAll(environment);
return this;
@@ -435,22 +550,24 @@ public class CppCompileActionBuilder {
return this;
}
- public CppCompileActionBuilder setOutputsForTesting(Artifact outputFile, Artifact dotdFile) {
+ public CppCompileActionBuilder setOutputs(Artifact outputFile, Artifact dotdFile) {
this.outputFile = outputFile;
this.dotdFile = dotdFile == null ? null : new DotdFile(dotdFile);
return this;
}
public CppCompileActionBuilder setOutputs(
- ArtifactCategory outputCategory, String outputName, boolean generateDotd) {
+ RuleContext ruleContext, ArtifactCategory outputCategory, String outputName,
+ boolean generateDotd) {
this.outputFile = CppHelper.getCompileOutputArtifact(
ruleContext,
CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, outputCategory, outputName));
if (generateDotd) {
String dotdFileName =
CppHelper.getDotdFileName(ruleContext, ccToolchain, outputCategory, outputName);
- if (configuration.getFragment(CppConfiguration.class).getInmemoryDotdFiles()) {
+ if (cppConfiguration.getInmemoryDotdFiles()) {
// Just set the path, no artifact is constructed
+ BuildConfiguration configuration = ruleContext.getConfiguration();
dotdFile = new DotdFile(
configuration.getBinDirectory(ruleContext.getRule().getRepository()).getExecPath()
.getRelative(CppHelper.getObjDirectory(ruleContext.getLabel()))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
new file mode 100644
index 0000000000..21abea8474
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
@@ -0,0 +1,200 @@
+// Copyright 2017 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 com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
+import com.google.devtools.build.lib.actions.ActionInputHelper;
+import com.google.devtools.build.lib.actions.ActionOwner;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
+import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.analysis.actions.ActionTemplate;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+/**
+ * An {@link ActionTemplate} that expands into {@link CppCompileAction}s at execution time.
+ */
+public final class CppCompileActionTemplate implements ActionTemplate<CppCompileAction> {
+ private final CppCompileActionBuilder cppCompileActionBuilder;
+ private final Artifact sourceTreeArtifact;
+ private final Artifact outputTreeArtifact;
+ private final CppConfiguration cppConfiguration;
+ private final Iterable<ArtifactCategory> categories;
+ private final ActionOwner actionOwner;
+ private final NestedSet<Artifact> mandatoryInputs;
+ private final NestedSet<Artifact> allInputs;
+
+ /**
+ * Creates an CppCompileActionTemplate.
+ * @param sourceTreeArtifact the TreeArtifact that contains source files to compile.
+ * @param outputTreeArtifact the TreeArtifact that contains compilation outputs.
+ * @param cppCompileActionBuilder An almost completely configured {@link CppCompileActionBuilder}
+ * without the input and output files set. It is used as a template to instantiate expanded
+ * {CppCompileAction}s.
+ * @param cppConfiguration configuration for cpp.
+ * @param categories A list of {@link ArtifactCategory} used to calculate output file name from
+ * a source file name.
+ * @param actionOwner the owner of this {@link ActionTemplate}.
+ */
+ CppCompileActionTemplate(
+ Artifact sourceTreeArtifact,
+ Artifact outputTreeArtifact,
+ CppCompileActionBuilder cppCompileActionBuilder,
+ CppConfiguration cppConfiguration,
+ Iterable<ArtifactCategory> categories,
+ ActionOwner actionOwner) {
+ this.cppCompileActionBuilder = cppCompileActionBuilder;
+ this.sourceTreeArtifact = sourceTreeArtifact;
+ this.outputTreeArtifact = outputTreeArtifact;
+ this.cppConfiguration = cppConfiguration;
+ this.categories = categories;
+ this.actionOwner = actionOwner;
+ this.mandatoryInputs = cppCompileActionBuilder.buildMandatoryInputs();
+ this.allInputs = cppCompileActionBuilder.buildAllInputs();
+ }
+
+ @Override
+ public Iterable<CppCompileAction> generateActionForInputArtifacts(
+ Iterable<TreeFileArtifact> inputTreeFileArtifacts, ArtifactOwner artifactOwner) {
+ ImmutableList.Builder<CppCompileAction> expandedActions = new ImmutableList.Builder<>();
+ for (TreeFileArtifact inputTreeFileArtifact : inputTreeFileArtifacts) {
+ String outputName = outputTreeFileArtifactName(inputTreeFileArtifact);
+ TreeFileArtifact outputTreeFileArtifact = ActionInputHelper.treeFileArtifact(
+ outputTreeArtifact,
+ new PathFragment(outputName),
+ artifactOwner);
+
+ expandedActions.add(createAction(inputTreeFileArtifact, outputTreeFileArtifact));
+ }
+
+ return expandedActions.build();
+ }
+
+ private CppCompileAction createAction(
+ Artifact sourceTreeFileArtifact, Artifact outputTreeFileArtifact) {
+ CppCompileActionBuilder builder = new CppCompileActionBuilder(cppCompileActionBuilder);
+ builder.setSourceFile(sourceTreeFileArtifact);
+ builder.setOutputs(outputTreeFileArtifact, null);
+
+ CcToolchainFeatures.Variables.Builder buildVariables =
+ new CcToolchainFeatures.Variables.Builder(builder.getVariables());
+ buildVariables.overrideStringVariable(
+ "source_file", sourceTreeFileArtifact.getExecPathString());
+ buildVariables.overrideStringVariable(
+ "output_file", outputTreeFileArtifact.getExecPathString());
+ buildVariables.overrideStringVariable(
+ "output_object_file", outputTreeFileArtifact.getExecPathString());
+
+ builder.setVariables(buildVariables.build());
+
+ return builder.build();
+ }
+
+ private String outputTreeFileArtifactName(TreeFileArtifact inputTreeFileArtifact) {
+ String outputName = FileSystemUtils.removeExtension(
+ inputTreeFileArtifact.getParentRelativePath().getPathString());
+ for (ArtifactCategory category : categories) {
+ outputName = cppConfiguration.getFeatures().getArtifactNameForCategory(category, outputName);
+ }
+ return outputName;
+ }
+
+ @Override
+ public Artifact getInputTreeArtifact() {
+ return sourceTreeArtifact;
+ }
+
+ @Override
+ public Artifact getOutputTreeArtifact() {
+ return outputTreeArtifact;
+ }
+
+ @Override
+ public ActionOwner getOwner() {
+ return actionOwner;
+ }
+
+ @Override
+ public final String getMnemonic() {
+ return "CppCompileActionTemplate";
+ }
+
+ @Override
+ public Iterable<Artifact> getMandatoryInputs() {
+ return NestedSetBuilder.<Artifact>compileOrder()
+ .add(sourceTreeArtifact)
+ .addTransitive(mandatoryInputs)
+ .build();
+ }
+
+ @Override
+ public ImmutableSet<Artifact> getMandatoryOutputs() {
+ return ImmutableSet.<Artifact>of();
+ }
+
+ @Override
+ public Iterable<Artifact> getTools() {
+ return ImmutableList.<Artifact>of();
+ }
+
+ @Override
+ public Iterable<Artifact> getInputs() {
+ return NestedSetBuilder.<Artifact>stableOrder()
+ .add(sourceTreeArtifact)
+ .addTransitive(allInputs)
+ .build();
+ }
+
+ @Override
+ public ImmutableSet<Artifact> getOutputs() {
+ return ImmutableSet.of(outputTreeArtifact);
+ }
+
+ @Override
+ public Iterable<String> getClientEnvironmentVariables() {
+ return ImmutableList.<String>of();
+ }
+
+ @Override
+ public Artifact getPrimaryInput() {
+ return sourceTreeArtifact;
+ }
+
+ @Override
+ public Artifact getPrimaryOutput() {
+ return outputTreeArtifact;
+ }
+
+ @Override
+ public boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action) {
+ return this != action;
+ }
+
+ @Override
+ public MiddlemanType getActionType() {
+ return MiddlemanType.NORMAL;
+ }
+
+ @Override
+ public String prettyPrint() {
+ return String.format(
+ "CppCompileActionTemplate compiling " + sourceTreeArtifact.getExecPathString());
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java
index 2ad342dd67..dc174850db 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppFileTypes.java
@@ -183,10 +183,16 @@ public final class CppFileTypes {
}
};
- public static final boolean mustProduceDotdFile(String source) {
- return !ASSEMBLER.matches(source)
- && !PIC_ASSEMBLER.matches(source)
- && !CLIF_INPUT_PROTO.matches(source);
+ public static final boolean mustProduceDotdFile(Artifact source) {
+ // Sources from TreeArtifacts and TreeFileArtifacts will not generate dotd file.
+ if (source.isTreeArtifact() || source.hasParent()) {
+ return false;
+ }
+
+ String fileName = source.getFilename();
+ return !ASSEMBLER.matches(fileName)
+ && !PIC_ASSEMBLER.matches(fileName)
+ && !CLIF_INPUT_PROTO.matches(fileName);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
index e4b19dcb2b..5228588d91 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
@@ -584,9 +584,19 @@ public class CppHelper {
ruleContext.getConfiguration().getBinDirectory(ruleContext.getRule().getRepository()));
}
- static String getArtifactNameForCategory(
- RuleContext ruleContext, CcToolchainProvider toolchain, ArtifactCategory category,
- String outputName) {
+ /**
+ * Returns the corresponding compiled TreeArtifact given the source TreeArtifact.
+ */
+ public static Artifact getCompileOutputTreeArtifact(
+ RuleContext ruleContext, Artifact sourceTreeArtifact) {
+ PathFragment objectDir = getObjDirectory(ruleContext.getLabel());
+ PathFragment rootRelativePath = sourceTreeArtifact.getRootRelativePath();
+ return ruleContext.getTreeArtifact(
+ objectDir.getRelative(rootRelativePath), sourceTreeArtifact.getRoot());
+ }
+
+ static String getArtifactNameForCategory(RuleContext ruleContext, CcToolchainProvider toolchain,
+ ArtifactCategory category, String outputName) {
return toolchain.getFeatures().getArtifactNameForCategory(category, outputName);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index b22e989734..ffe579062a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -954,8 +954,11 @@ public class CppLinkActionBuilder {
}
private void addObjectFile(LinkerInput input) {
+ // We skip file extension checks for TreeArtifacts because they represent directory artifacts
+ // without a file extension.
String name = input.getArtifact().getFilename();
- Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(name), name);
+ Preconditions.checkArgument(
+ input.getArtifact().isTreeArtifact() || Link.OBJECT_FILETYPES.matches(name), name);
this.objectFiles.add(input);
}
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 1e186294aa..7960baca9d 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
@@ -144,9 +144,10 @@ public final class CppModel {
* units, including module files or headers to be parsed or preprocessed.
*/
public CppModel addCompilationUnitSources(
- Iterable<Artifact> sourceFiles, Label sourceLabel, Map<String, String> buildVariables) {
+ Iterable<Artifact> sourceFiles, Label sourceLabel, Map<String, String> buildVariables,
+ CppSource.Type type) {
for (Artifact sourceFile : sourceFiles) {
- this.sourceFiles.add(CppSource.create(sourceFile, sourceLabel, buildVariables));
+ this.sourceFiles.add(CppSource.create(sourceFile, sourceLabel, buildVariables, type));
}
return this;
}
@@ -380,7 +381,7 @@ public final class CppModel {
buildVariables.addStringVariable("output_object_file", realOutputFilePath);
}
- DotdFile dotdFile = CppFileTypes.mustProduceDotdFile(sourceFile.getPath().toString())
+ DotdFile dotdFile = CppFileTypes.mustProduceDotdFile(sourceFile)
? Preconditions.checkNotNull(builder.getDotdFile()) : null;
// Set dependency_file to enable <object>.d file generation.
if (dotdFile != null) {
@@ -485,33 +486,61 @@ public final class CppModel {
CppCompileActionBuilder builder = initializeCompileAction(sourceArtifact, sourceLabel);
builder.setSemantics(semantics);
-
- if (CppFileTypes.CPP_HEADER.matches(source.getSource().getExecPath())) {
- createHeaderAction(outputName, result, env, builder,
- CppFileTypes.mustProduceDotdFile(sourceArtifact.getFilename()));
- } else if (CppFileTypes.CLIF_INPUT_PROTO.matches(source.getSource().getExecPath())) {
- createClifMatchAction(outputName, result, env, builder);
+
+ if (!sourceArtifact.isTreeArtifact()) {
+ switch (source.getType()) {
+ case HEADER:
+ createHeaderAction(outputName, result, env, builder,
+ CppFileTypes.mustProduceDotdFile(sourceArtifact));
+ break;
+ case CLIF_INPUT_PROTO:
+ createClifMatchAction(outputName, result, env, builder);
+ break;
+ default:
+ boolean bitcodeOutput =
+ featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)
+ && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename());
+ createSourceAction(
+ outputName,
+ result,
+ env,
+ sourceArtifact,
+ builder,
+ ArtifactCategory.OBJECT_FILE,
+ context.getCppModuleMap(),
+ /*addObject=*/ true,
+ isCodeCoverageEnabled(),
+ // The source action does not generate dwo when it has bitcode
+ // output (since it isn't generating a native object with debug
+ // info). In that case the LTOBackendAction will generate the dwo.
+ /*generateDwo=*/ cppConfiguration.useFission() && !bitcodeOutput,
+ CppFileTypes.mustProduceDotdFile(sourceArtifact),
+ source.getBuildVariables(), /*addHeaderTokenFile=*/
+ false);
+ break;
+ }
} else {
- boolean bitcodeOutput =
- featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)
- && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename());
- createSourceAction(
- outputName,
- result,
- env,
- sourceArtifact,
- builder,
- ArtifactCategory.OBJECT_FILE,
- context.getCppModuleMap(),
- /*addObject=*/ true,
- isCodeCoverageEnabled(),
- // The source action does not generate dwo when it has bitcode
- // output (since it isn't generating a native object with debug
- // info). In that case the LTOBackendAction will generate the dwo.
- /*generateDwo=*/ cppConfiguration.useFission() && !bitcodeOutput,
- CppFileTypes.mustProduceDotdFile(sourceArtifact.getFilename()),
- source.getBuildVariables(), /*addHeaderTokenFile=*/
- false);
+ switch (source.getType()) {
+ case HEADER:
+ Artifact headerTokenFile =
+ createCompileActionTemplate(
+ env,
+ source,
+ builder,
+ ImmutableList.of(
+ ArtifactCategory.GENERATED_HEADER, ArtifactCategory.PROCESSED_HEADER));
+ result.addHeaderTokenFile(headerTokenFile);
+ break;
+ case SOURCE:
+ Artifact objectFile =
+ createCompileActionTemplate(
+ env, source, builder, ImmutableList.of(ArtifactCategory.OBJECT_FILE));
+ result.addObjectFile(objectFile);
+ break;
+ default:
+ throw new IllegalStateException(
+ "Encountered invalid source types when creating CppCompileActionTemplates");
+ }
}
}
@@ -525,7 +554,7 @@ public final class CppModel {
ruleContext, ccToolchain, ArtifactCategory.GENERATED_HEADER, outputName);
builder
- .setOutputs(ArtifactCategory.PROCESSED_HEADER, outputNameBase, generateDotd)
+ .setOutputs(ruleContext, ArtifactCategory.PROCESSED_HEADER, outputNameBase, generateDotd)
// If we generate pic actions, we prefer the header actions to use the pic artifacts.
.setPicMode(this.getGeneratePicActions());
setupCompileBuildVariables(
@@ -538,7 +567,7 @@ public final class CppModel {
builder.getContext().getCppModuleMap(),
ImmutableMap.<String, String>of());
semantics.finalizeCompileActionBuilder(ruleContext, builder);
- CppCompileAction compileAction = builder.build();
+ CppCompileAction compileAction = builder.buildAndValidate(ruleContext);
env.registerAction(compileAction);
Artifact tokenFile = compileAction.getOutputFile();
result.addHeaderTokenFile(tokenFile);
@@ -568,7 +597,7 @@ public final class CppModel {
/*addObject=*/ false,
/*enableCoverage=*/ false,
/*generateDwo=*/ false,
- CppFileTypes.mustProduceDotdFile(moduleMapArtifact.getFilename()),
+ CppFileTypes.mustProduceDotdFile(moduleMapArtifact),
ImmutableMap.<String, String>of(), /*addHeaderTokenFile=*/
addHeaderTokenFiles);
}
@@ -576,7 +605,7 @@ public final class CppModel {
private void createClifMatchAction(
String outputName, Builder result, AnalysisEnvironment env, CppCompileActionBuilder builder) {
builder
- .setOutputs(ArtifactCategory.CLIF_OUTPUT_PROTO, outputName, false)
+ .setOutputs(ruleContext, ArtifactCategory.CLIF_OUTPUT_PROTO, outputName, false)
.setPicMode(false)
// The additional headers in a clif action are both mandatory inputs and
// need to be include-scanned.
@@ -592,7 +621,7 @@ public final class CppModel {
builder.getContext().getCppModuleMap(),
/*sourceSpecificBuildVariables=*/ ImmutableMap.<String, String>of());
semantics.finalizeCompileActionBuilder(ruleContext, builder);
- CppCompileAction compileAction = builder.build();
+ CppCompileAction compileAction = builder.buildAndValidate(ruleContext);
env.registerAction(compileAction);
Artifact tokenFile = compileAction.getOutputFile();
result.addHeaderTokenFile(tokenFile);
@@ -663,7 +692,7 @@ public final class CppModel {
picBuilder.setDwoFile(dwoFile);
semantics.finalizeCompileActionBuilder(ruleContext, picBuilder);
- CppCompileAction picAction = picBuilder.build();
+ CppCompileAction picAction = picBuilder.buildAndValidate(ruleContext);
env.registerAction(picAction);
if (addHeaderTokenFiles) {
result.addHeaderTokenFile(picAction.getOutputFile());
@@ -690,7 +719,7 @@ public final class CppModel {
ruleContext,
CppHelper.getArtifactNameForCategory(
ruleContext, ccToolchain, outputCategory, outputName));
- builder.setOutputs(outputCategory, outputName, generateDotd);
+ builder.setOutputs(ruleContext, outputCategory, outputName, generateDotd);
String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext,
ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, outputName);
@@ -727,7 +756,7 @@ public final class CppModel {
builder.setDwoFile(noPicDwoFile);
semantics.finalizeCompileActionBuilder(ruleContext, builder);
- CppCompileAction compileAction = builder.build();
+ CppCompileAction compileAction = builder.buildAndValidate(ruleContext);
env.registerAction(compileAction);
Artifact objectFile = compileAction.getOutputFile();
if (addHeaderTokenFiles) {
@@ -751,6 +780,35 @@ public final class CppModel {
}
}
+ private Artifact createCompileActionTemplate(AnalysisEnvironment env,
+ CppSource source, CppCompileActionBuilder builder,
+ Iterable<ArtifactCategory> outputCategories) {
+ Artifact sourceArtifact = source.getSource();
+ Artifact outputFiles = CppHelper.getCompileOutputTreeArtifact(ruleContext, sourceArtifact);
+ // TODO(rduan): Dotd file output is not supported yet.
+ builder.setOutputs(outputFiles, null);
+ setupCompileBuildVariables(
+ builder,
+ /* usePic=*/ false,
+ /*ccRelativeName=*/ null,
+ /*autoFdoImportPath=*/ null,
+ /*gcnoFile=*/ null,
+ /*dwoFile=*/ null,
+ builder.getContext().getCppModuleMap(),
+ source.getBuildVariables());
+ semantics.finalizeCompileActionBuilder(ruleContext, builder);
+ CppCompileActionTemplate actionTemplate = new CppCompileActionTemplate(
+ sourceArtifact,
+ outputFiles,
+ builder,
+ cppConfiguration,
+ outputCategories,
+ ruleContext.getActionOwner());
+ env.registerAction(actionTemplate);
+
+ return outputFiles;
+ }
+
String getOutputNameBaseWith(String base, boolean usePic) {
return usePic
? CppHelper.getArtifactNameForCategory(
@@ -771,7 +829,7 @@ public final class CppModel {
.getPathString();
builder
.setPicMode(usePic)
- .setOutputs(outputCategory, outputNameBase, generateDotd)
+ .setOutputs(ruleContext, outputCategory, outputNameBase, generateDotd)
.setTempOutputFile(new PathFragment(tempOutputName));
setupCompileBuildVariables(
@@ -784,7 +842,7 @@ public final class CppModel {
builder.getContext().getCppModuleMap(),
ImmutableMap.<String, String>of());
semantics.finalizeCompileActionBuilder(ruleContext, builder);
- CppCompileAction action = builder.build();
+ CppCompileAction action = builder.buildAndValidate(ruleContext);
env.registerAction(action);
if (addObject) {
if (usePic) {
@@ -818,7 +876,6 @@ public final class CppModel {
maybePicName = CppHelper.getArtifactNameForCategory(
ruleContext, ccToolchain, ArtifactCategory.PIC_FILE, maybePicName);
}
-
String linkedName = CppHelper.getArtifactNameForCategory(
ruleContext, ccToolchain, linkTargetType.getLinkerOutput(), maybePicName);
PathFragment artifactFragment = new PathFragment(ruleContext.getLabel().getName())
@@ -923,7 +980,6 @@ public final class CppModel {
// If the crosstool is configured to select an output artifact, we use that selection.
// Otherwise, we use linux defaults.
Artifact picArtifact = getLinkedArtifact(picLinkType);
-
CppLinkAction picAction =
newLinkActionBuilder(picArtifact)
.addObjectFiles(ccOutputs.getObjectFiles(true))
@@ -1062,9 +1118,8 @@ public final class CppModel {
* inputs, output and dotd file names, compilation context and copts.
*/
private CppCompileActionBuilder createCompileActionBuilder(Artifact source, Label label) {
- CppCompileActionBuilder builder = new CppCompileActionBuilder(
- ruleContext, source, label, ccToolchain);
-
+ CppCompileActionBuilder builder = new CppCompileActionBuilder(ruleContext, label, ccToolchain);
+ builder.setSourceFile(source);
builder.setContext(context).addCopts(copts);
builder.addEnvironment(ccToolchain.getEnvironment());
return builder;
@@ -1080,7 +1135,7 @@ public final class CppModel {
CppCompileActionBuilder picBuilder = new CppCompileActionBuilder(builder);
picBuilder
.setPicMode(true)
- .setOutputs(outputCategory, outputName, generateDotd);
+ .setOutputs(ruleContext, outputCategory, outputName, generateDotd);
return picBuilder;
}
@@ -1109,7 +1164,7 @@ public final class CppModel {
String outputArtifactNameBase = getOutputNameBaseWith(outputName, usePic);
CppCompileActionBuilder dBuilder = new CppCompileActionBuilder(builder);
- dBuilder.setOutputs(category, outputArtifactNameBase, generateDotd);
+ dBuilder.setOutputs(ruleContext, category, outputArtifactNameBase, generateDotd);
setupCompileBuildVariables(
dBuilder,
usePic,
@@ -1120,11 +1175,12 @@ public final class CppModel {
builder.getContext().getCppModuleMap(),
ImmutableMap.<String, String>of());
semantics.finalizeCompileActionBuilder(ruleContext, dBuilder);
- CppCompileAction dAction = dBuilder.build();
+ CppCompileAction dAction = dBuilder.buildAndValidate(ruleContext);
ruleContext.registerAction(dAction);
CppCompileActionBuilder sdBuilder = new CppCompileActionBuilder(builder);
- sdBuilder.setOutputs(ArtifactCategory.GENERATED_ASSEMBLY, outputArtifactNameBase, generateDotd);
+ sdBuilder.setOutputs(
+ ruleContext, ArtifactCategory.GENERATED_ASSEMBLY, outputArtifactNameBase, generateDotd);
setupCompileBuildVariables(
sdBuilder,
usePic,
@@ -1135,7 +1191,7 @@ public final class CppModel {
builder.getContext().getCppModuleMap(),
ImmutableMap.<String, String>of());
semantics.finalizeCompileActionBuilder(ruleContext, sdBuilder);
- CppCompileAction sdAction = sdBuilder.build();
+ CppCompileAction sdAction = sdBuilder.buildAndValidate(ruleContext);
ruleContext.registerAction(sdAction);
return ImmutableList.of(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSource.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSource.java
index 17ec8d0372..bc6ff4b6ac 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSource.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSource.java
@@ -22,7 +22,17 @@ import java.util.Map;
/** A source file that is an input to a c++ compilation. */
@AutoValue
-abstract class CppSource {
+public abstract class CppSource {
+
+ /**
+ * Types of sources.
+ */
+ public enum Type {
+ SOURCE,
+ HEADER,
+ CLIF_INPUT_PROTO,
+ }
+
/**
* Creates a {@code CppSource}.
*
@@ -30,9 +40,11 @@ abstract class CppSource {
* @param label the label from which this source arises in the build graph
* @param buildVariables build variables that should be used specifically in the compilation
* of this source
+ * @param type type of the source file.
*/
- static CppSource create(Artifact source, Label label, Map<String, String> buildVariables) {
- return new AutoValue_CppSource(source, label, buildVariables);
+ static CppSource create(Artifact source, Label label, Map<String, String> buildVariables,
+ Type type) {
+ return new AutoValue_CppSource(source, label, buildVariables, type);
}
/**
@@ -49,4 +61,9 @@ abstract class CppSource {
* Returns build variables to be used specifically in the compilation of this source.
*/
abstract Map<String, String> getBuildVariables();
+
+ /**
+ * Returns the type of this source.
+ */
+ abstract Type getType();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
index dc42ddd235..cf57fd67d3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
@@ -29,8 +29,6 @@ import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.ResourceSet;
-import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -61,6 +59,7 @@ public class FakeCppCompileAction extends CppCompileAction {
FakeCppCompileAction(
ActionOwner owner,
+ NestedSet<Artifact> allInputs,
ImmutableList<String> features,
FeatureConfiguration featureConfiguration,
CcToolchainFeatures.Variables variables,
@@ -75,18 +74,20 @@ public class FakeCppCompileAction extends CppCompileAction {
Artifact outputFile,
PathFragment tempOutputFile,
DotdFile dotdFile,
- BuildConfiguration configuration,
+ ImmutableMap<String, String> localShellEnvironment,
+ boolean codeCoverageEnabled,
CppConfiguration cppConfiguration,
CppCompilationContext context,
Class<? extends CppCompileActionContext> actionContext,
ImmutableList<String> copts,
Predicate<String> nocopts,
- RuleContext ruleContext,
+ Iterable<IncludeScannable> lipoScannables,
+ Iterable<Artifact> builtinIncludeFiles,
CppSemantics cppSemantics,
- CcToolchainProvider ccToolchain,
ImmutableMap<String, String> executionInfo) {
super(
owner,
+ allInputs,
features,
featureConfiguration,
variables,
@@ -103,8 +104,8 @@ public class FakeCppCompileAction extends CppCompileAction {
null,
null,
null,
- configuration.getLocalShellEnvironment(),
- configuration.isCodeCoverageEnabled(),
+ localShellEnvironment,
+ codeCoverageEnabled,
cppConfiguration,
// We only allow inclusion of header files explicitly declared in
// "srcs", so we only use declaredIncludeSrcs, not declaredIncludeDirs.
@@ -118,15 +119,14 @@ public class FakeCppCompileAction extends CppCompileAction {
copts,
nocopts,
VOID_SPECIAL_INPUTS_HANDLER,
- ImmutableList.<IncludeScannable>of(),
+ lipoScannables,
ImmutableList.<Artifact>of(),
GUID,
executionInfo,
ImmutableMap.<String, String>of(),
CppCompileAction.CPP_COMPILE,
- ruleContext,
- cppSemantics,
- ccToolchain);
+ builtinIncludeFiles,
+ cppSemantics);
this.tempOutputFile = Preconditions.checkNotNull(tempOutputFile);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
index d4346a39e1..bb65c34002 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
@@ -47,7 +47,10 @@ public abstract class LinkerInputs {
break;
case OBJECT_FILE:
- Preconditions.checkState(Link.OBJECT_FILETYPES.matches(basename));
+ // We skip file extension checks for TreeArtifacts because they represent directory
+ // artifacts without a file extension.
+ Preconditions.checkState(
+ artifact.isTreeArtifact() || Link.OBJECT_FILETYPES.matches(basename));
break;
default: