aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar Cal Peyser <cpeyser@google.com>2016-04-25 13:25:40 +0000
committerGravatar Yun Peng <pcloudy@google.com>2016-04-25 17:46:48 +0000
commit83b2123d5671a579cb63eff8aefcc60de8355516 (patch)
treedabccb1a9bd89f6f3f6e082efe1ff4a8d06151cc /src/main/java/com
parentc78052c7ae8176d9266e3e277009d5b24763a0a2 (diff)
Add mechanism to crosstool language to specify action-specific execution requirements. Uses this mechanism to configure c/c++ compilation and linking for darwin execution from the crosstool.
-- MOS_MIGRATED_REVID=120701108
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutionInfoSpecifier.java34
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java71
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java68
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java45
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java50
-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/FakeCppCompileAction.java3
9 files changed, 235 insertions, 69 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutionInfoSpecifier.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutionInfoSpecifier.java
new file mode 100644
index 0000000000..d6d37e05c9
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/ExecutionInfoSpecifier.java
@@ -0,0 +1,34 @@
+// Copyright 2016 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.analysis.actions;
+
+import java.util.Map;
+
+/**
+ * An action that specifies requirements for its execution.
+ */
+public interface ExecutionInfoSpecifier {
+
+ /**
+ * Returns execution data for this action. This is used to signal hardware requirements to the
+ * execution (ex. "requires-darwin"). This is a workaround to allow execution on platforms other
+ * than that specified by the host configuration. The ability to choose seperate platforms by
+ * action can provide a performance advantage.
+ *
+ * <p>Restrictions are mapped to arbitrary values (typically "") so as to be consistent with
+ * {@link com.google.devtools.build.lib.actions.Spawn#getExecutionInfo()}.
+ */
+ Map<String, String> getExecutionInfo();
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
index b9d86748e7..e364d9e535 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java
@@ -64,7 +64,7 @@ import javax.annotation.CheckReturnValue;
/**
* An Action representing an arbitrary subprocess to be forked and exec'd.
*/
-public class SpawnAction extends AbstractAction {
+public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifier {
private static class ExtraActionInfoSupplier<T> {
private final GeneratedExtension<ExtraActionInfo, T> extension;
private final T value;
@@ -364,6 +364,7 @@ public class SpawnAction extends AbstractAction {
/**
* Returns the out-of-band execution data for this action.
*/
+ @Override
public Map<String, String> getExecutionInfo() {
return executionInfo;
}
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 184fcc4175..6b6b5cc042 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
@@ -221,6 +221,7 @@ public abstract class CcBinary implements RuleConfiguredTargetFactory {
linkActionBuilder.setLinkType(linkType);
linkActionBuilder.setLinkStaticness(linkStaticness);
linkActionBuilder.setFake(fake);
+ linkActionBuilder.setFeatureConfiguration(featureConfiguration);
if (CppLinkAction.enableSymbolsCounts(cppConfiguration, fake, linkType)) {
linkActionBuilder.setSymbolCountsOutput(ruleContext.getPackageRelativeArtifact(
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 41124222bb..b6d9e10c94 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
@@ -520,6 +520,7 @@ public class CcToolchainFeatures implements Serializable {
flagSetBuilder.add(new FlagSet(flagSet));
}
this.flagSets = flagSetBuilder.build();
+
ImmutableList.Builder<EnvSet> envSetBuilder = ImmutableList.builder();
for (CToolchain.EnvSet flagSet : feature.getEnvSetList()) {
envSetBuilder.add(new EnvSet(flagSet));
@@ -532,8 +533,11 @@ public class CcToolchainFeatures implements Serializable {
return name;
}
- private void expandEnvironment(String action, Variables variables,
- ImmutableMap.Builder<String, String> envBuilder) {
+ /**
+ * Adds environment variables for the given action to the provided builder.
+ */
+ private void expandEnvironment(
+ String action, Variables variables, ImmutableMap.Builder<String, String> envBuilder) {
for (EnvSet envSet : envSets) {
envSet.expandEnvironment(action, variables, envBuilder);
}
@@ -551,6 +555,42 @@ public class CcToolchainFeatures implements Serializable {
}
/**
+ * An executable to be invoked by a blaze action. Can carry information on its platform
+ * restrictions.
+ */
+ @Immutable
+ static class Tool {
+ private final String toolPathString;
+ private final ImmutableSet<String> executionRequirements;
+
+ private Tool(CToolchain.Tool tool) {
+ toolPathString = tool.getToolPath();
+ executionRequirements = ImmutableSet.copyOf(tool.getExecutionRequirementList());
+ }
+
+ @VisibleForTesting
+ public Tool(String toolPathString, ImmutableSet<String> executionRequirements) {
+ this.toolPathString = toolPathString;
+ this.executionRequirements = executionRequirements;
+ }
+
+ /**
+ * Returns the path to this action's tool relative to the provided crosstool path.
+ */
+ PathFragment getToolPath(PathFragment crosstoolTopPathFragment) {
+ return crosstoolTopPathFragment.getRelative(toolPathString);
+ }
+
+ /**
+ * Returns a list of requirement hints that apply to the execution of this tool.
+ */
+ ImmutableSet<String> getExecutionRequirements() {
+ return executionRequirements;
+ }
+ }
+
+
+ /**
* A container for information on a particular blaze action.
*
* <p>An ActionConfig can select a tool for its blaze action based on the set of active
@@ -597,9 +637,8 @@ public class CcToolchainFeatures implements Serializable {
* Returns the path to this action's tool relative to the provided crosstool path given a set
* of enabled features.
*/
- private PathFragment getTool(
- PathFragment crosstoolTopPathFragment, final Set<String> enabledFeatureNames) {
- Optional<Tool> tool =
+ private Tool getTool(final Set<String> enabledFeatureNames) {
+ Optional<CToolchain.Tool> tool =
Iterables.tryFind(
tools,
new Predicate<CToolchain.Tool>() {
@@ -612,7 +651,7 @@ public class CcToolchainFeatures implements Serializable {
}
});
if (tool.isPresent()) {
- return crosstoolTopPathFragment.getRelative(tool.get().getToolPath());
+ return new Tool(tool.get());
} else {
throw new IllegalArgumentException(
"Matching tool for action "
@@ -968,7 +1007,7 @@ public class CcToolchainFeatures implements Serializable {
public static class FeatureConfiguration {
private final ImmutableSet<String> enabledFeatureNames;
private final Iterable<Feature> enabledFeatures;
-
+
private final ImmutableMap<String, ActionConfig> actionConfigByActionName;
public FeatureConfiguration() {
@@ -983,6 +1022,7 @@ public class CcToolchainFeatures implements Serializable {
Iterable<ActionConfig> enabledActionConfigs,
ImmutableMap<String, ActionConfig> actionConfigByActionName) {
this.enabledFeatures = enabledFeatures;
+
this.actionConfigByActionName = actionConfigByActionName;
ImmutableSet.Builder<String> featureBuilder = ImmutableSet.builder();
for (Feature feature : enabledFeatures) {
@@ -1004,6 +1044,13 @@ public class CcToolchainFeatures implements Serializable {
}
/**
+ * @return whether an action config for the blaze action with the given name is enabled.
+ */
+ boolean actionIsConfigured(String actionName) {
+ return actionConfigByActionName.containsKey(actionName);
+ }
+
+ /**
* @return the command line for the given {@code action}.
*/
List<String> getCommandLine(String action, Variables variables) {
@@ -1024,19 +1071,17 @@ public class CcToolchainFeatures implements Serializable {
}
return envBuilder.build();
}
-
+
/**
- * Returns the path to the given action's tool under this FeatureConfiguration relative to the
- * crosstool.
+ * Returns a given action's tool under this FeatureConfiguration.
*/
- PathFragment getToolPathFragmentForAction(
- final String actionName, PathFragment crosstoolTopPathFragment) {
+ Tool getToolForAction(String actionName) {
Preconditions.checkArgument(
actionConfigByActionName.containsKey(actionName),
"Action %s does not have an enabled configuration in the toolchain.",
actionName);
ActionConfig actionConfig = actionConfigByActionName.get(actionName);
- return actionConfig.getTool(crosstoolTopPathFragment, enabledFeatureNames);
+ return actionConfig.getTool(enabledFeatureNames);
}
}
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 97bd13f10e..76dd500c17 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
@@ -37,6 +37,7 @@ 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.actions.ExecutionInfoSpecifier;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.PerLabelOptions;
import com.google.devtools.build.lib.cmdline.Label;
@@ -84,7 +85,8 @@ import javax.annotation.concurrent.GuardedBy;
* Action that represents some kind of C++ compilation step.
*/
@ThreadCompatible
-public class CppCompileAction extends AbstractAction implements IncludeScannable {
+public class CppCompileAction extends AbstractAction
+ implements IncludeScannable, ExecutionInfoSpecifier {
/**
* Represents logic that determines if an artifact is a special input, meaning that it may require
* additional inputs when it is compiled or may not be available to other actions.
@@ -171,6 +173,7 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
private final ImmutableList<Artifact> builtinIncludeFiles;
@VisibleForTesting public final CppCompileCommandLine cppCompileCommandLine;
private final boolean usePic;
+ private final ImmutableSet<String> executionRequirements;
@VisibleForTesting
final CppConfiguration cppConfiguration;
@@ -222,6 +225,10 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
* @param context the compilation context
* @param copts options for the compiler
* @param coptsFilter regular expression to remove options from {@code copts}
+ * @param executionRequirements out-of-band hints to be passed to the execution backend to signal
+ * platform requirements
+ * @param actionName a string giving the name of this action for the purpose of toolchain
+ * evaluation
*/
protected CppCompileAction(
ActionOwner owner,
@@ -252,6 +259,8 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
Iterable<IncludeScannable> lipoScannables,
UUID actionClassId,
boolean usePic,
+ ImmutableSet<String> executionRequirements,
+ String actionName,
RuleContext ruleContext) {
super(
owner,
@@ -288,11 +297,13 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
features,
featureConfiguration,
variables,
- fdoBuildStamp);
+ fdoBuildStamp,
+ actionName);
this.actionContext = actionContext;
this.lipoScannables = lipoScannables;
this.actionClassId = actionClassId;
this.usePic = usePic;
+ this.executionRequirements = executionRequirements;
// We do not need to include the middleman artifact since it is a generated
// artifact and will definitely exist prior to this action execution.
@@ -704,6 +715,15 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
return cppCompileCommandLine.getCompilerOptions();
}
+ @Override
+ public Map<String, String> getExecutionInfo() {
+ ImmutableMap.Builder<String, String> result = ImmutableMap.<String, String>builder();
+ for (String requirement : executionRequirements) {
+ result.put(requirement, "");
+ }
+ return result.build();
+ }
+
/**
* Enforce that the includes actually visited during the compile were properly
* declared in the rules.
@@ -1125,6 +1145,7 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
f.addUUID(actionClassId);
f.addStringMap(getEnvironment());
f.addStrings(getArgv());
+ f.addStrings(executionRequirements);
/*
* getArgv() above captures all changes which affect the compilation
@@ -1273,6 +1294,7 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
private final Collection<String> features;
private final FeatureConfiguration featureConfiguration;
@VisibleForTesting public final CcToolchainFeatures.Variables variables;
+ private final String actionName;
// The value of the BUILD_FDO_TYPE macro to be defined on command line
@Nullable private final String fdoBuildStamp;
@@ -1287,7 +1309,8 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
Collection<String> features,
FeatureConfiguration featureConfiguration,
CcToolchainFeatures.Variables variables,
- @Nullable String fdoBuildStamp) {
+ @Nullable String fdoBuildStamp,
+ String actionName) {
this.sourceFile = Preconditions.checkNotNull(sourceFile);
this.dotdFile = CppFileTypes.mustProduceDotdFile(sourceFile.getPath().toString())
? Preconditions.checkNotNull(dotdFile) : null;
@@ -1299,13 +1322,14 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
this.featureConfiguration = featureConfiguration;
this.variables = variables;
this.fdoBuildStamp = fdoBuildStamp;
+ this.actionName = actionName;
}
/**
* Returns the environment variables that should be set for C++ compile actions.
*/
protected Map<String, String> getEnvironment() {
- return featureConfiguration.getEnvironmentVariables(getActionName(), variables);
+ return featureConfiguration.getEnvironmentVariables(actionName, variables);
}
protected List<String> getArgv(PathFragment outputFile) {
@@ -1328,39 +1352,6 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
return commandLine;
}
- private String getActionName() {
- PathFragment sourcePath = sourceFile.getExecPath();
- if (CppFileTypes.CPP_MODULE_MAP.matches(sourcePath)) {
- return CPP_MODULE_COMPILE;
- } else if (CppFileTypes.CPP_HEADER.matches(sourcePath)) {
- // TODO(bazel-team): Handle C headers that probably don't work in C++ mode.
- if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_HEADERS)) {
- return CPP_HEADER_PARSING;
- } else if (featureConfiguration.isEnabled(CppRuleClasses.PREPROCESS_HEADERS)) {
- return CPP_HEADER_PREPROCESSING;
- } else {
- // CcCommon.collectCAndCppSources() ensures we do not add headers to
- // the compilation artifacts unless either 'parse_headers' or
- // 'preprocess_headers' is set.
- throw new IllegalStateException();
- }
- } else if (CppFileTypes.C_SOURCE.matches(sourcePath)) {
- return C_COMPILE;
- } else if (CppFileTypes.CPP_SOURCE.matches(sourcePath)) {
- return CPP_COMPILE;
- } else if (CppFileTypes.OBJC_SOURCE.matches(sourcePath)) {
- return OBJC_COMPILE;
- } else if (CppFileTypes.OBJCPP_SOURCE.matches(sourcePath)) {
- return OBJCPP_COMPILE;
- } else if (CppFileTypes.ASSEMBLER.matches(sourcePath)) {
- return ASSEMBLE;
- } else if (CppFileTypes.ASSEMBLER_WITH_C_PREPROCESSOR.matches(sourcePath)) {
- return PREPROCESS_ASSEMBLE;
- }
- // CcLibraryHelper ensures CppCompileAction only gets instantiated for supported file types.
- throw new IllegalStateException();
- }
-
public List<String> getCompilerOptions() {
List<String> options = new ArrayList<>();
CppConfiguration toolchain = cppConfiguration;
@@ -1396,8 +1387,7 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable
// unfiltered compiler options to inject include paths, which is superseded by the feature
// configuration; on the other hand toolchains switch off warnings for the layering check
// that will be re-added by the feature flags.
- addFilteredOptions(options,
- featureConfiguration.getCommandLine(getActionName(), variables));
+ addFilteredOptions(options, featureConfiguration.getCommandLine(actionName, variables));
// TODO(bazel-team): Move this into a feature; more specifically, create a feature for both
// the amount of debug information requested, and whether the debug info is written in a
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 1cdcf26c93..81ae9144ad 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
@@ -20,6 +20,7 @@ import com.google.common.base.Predicate;
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.Iterables;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
@@ -242,6 +243,39 @@ public class CppCompileActionBuilder {
Predicates.notNull());
}
+ private String getActionName() {
+ PathFragment sourcePath = sourceFile.getExecPath();
+ if (CppFileTypes.CPP_MODULE_MAP.matches(sourcePath)) {
+ return CppCompileAction.CPP_MODULE_COMPILE;
+ } else if (CppFileTypes.CPP_HEADER.matches(sourcePath)) {
+ // TODO(bazel-team): Handle C headers that probably don't work in C++ mode.
+ if (featureConfiguration.isEnabled(CppRuleClasses.PARSE_HEADERS)) {
+ return CppCompileAction.CPP_HEADER_PARSING;
+ } else if (featureConfiguration.isEnabled(CppRuleClasses.PREPROCESS_HEADERS)) {
+ return CppCompileAction.CPP_HEADER_PREPROCESSING;
+ } else {
+ // CcCommon.collectCAndCppSources() ensures we do not add headers to
+ // the compilation artifacts unless either 'parse_headers' or
+ // 'preprocess_headers' is set.
+ throw new IllegalStateException();
+ }
+ } else if (CppFileTypes.C_SOURCE.matches(sourcePath)) {
+ return CppCompileAction.C_COMPILE;
+ } else if (CppFileTypes.CPP_SOURCE.matches(sourcePath)) {
+ return CppCompileAction.CPP_COMPILE;
+ } else if (CppFileTypes.OBJC_SOURCE.matches(sourcePath)) {
+ return CppCompileAction.OBJC_COMPILE;
+ } else if (CppFileTypes.OBJCPP_SOURCE.matches(sourcePath)) {
+ return CppCompileAction.OBJCPP_COMPILE;
+ } else if (CppFileTypes.ASSEMBLER.matches(sourcePath)) {
+ return CppCompileAction.ASSEMBLE;
+ } else if (CppFileTypes.ASSEMBLER_WITH_C_PREPROCESSOR.matches(sourcePath)) {
+ return CppCompileAction.PREPROCESS_ASSEMBLE;
+ }
+ // CcLibraryHelper ensures CppCompileAction only gets instantiated for supported file types.
+ throw new IllegalStateException();
+ }
+
/**
* Builds the Action as configured and returns the to be generated Artifact.
*
@@ -266,6 +300,15 @@ public class CppCompileActionBuilder {
realMandatoryInputsBuilder.add(sourceFile);
boolean fake = tempOutputFile != null;
+ // 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.
+ ImmutableSet<String> executionRequirements = ImmutableSet.of();
+ if (featureConfiguration.actionIsConfigured(getActionName())) {
+ executionRequirements =
+ featureConfiguration.getToolForAction(getActionName()).getExecutionRequirements();
+ }
+
// Copying the collections is needed to make the builder reusable.
if (fake) {
return new FakeCppCompileAction(owner, ImmutableList.copyOf(features), featureConfiguration,
@@ -305,6 +348,8 @@ public class CppCompileActionBuilder {
getLipoScannables(realMandatoryInputs),
actionClassId,
usePic,
+ executionRequirements,
+ getActionName(),
ruleContext);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
index b0a1b7d825..154ecf6f75 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
@@ -38,6 +38,7 @@ import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.analysis.actions.ExecutionInfoSpecifier;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.collect.CollectionUtils;
@@ -50,6 +51,7 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.packages.RuleErrorConsumer;
+import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.Link.LinkStaticness;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
@@ -76,7 +78,7 @@ import javax.annotation.Nullable;
* Action that represents a linking step.
*/
@ThreadCompatible
-public final class CppLinkAction extends AbstractAction {
+public final class CppLinkAction extends AbstractAction implements ExecutionInfoSpecifier {
/**
* An abstraction for creating intermediate and output artifacts for C++ linking.
*
@@ -107,10 +109,16 @@ public final class CppLinkAction extends AbstractAction {
private static final String LINK_GUID = "58ec78bd-1176-4e36-8143-439f656b181d";
private static final String FAKE_LINK_GUID = "da36f819-5a15-43a9-8a45-e01b60e10c8b";
+ /**
+ * The name of this action for the purpose of crosstool features/action_configs
+ */
+ private static final String ACTION_NAME = "cpp-link";
+
private final CppConfiguration cppConfiguration;
private final LibraryToLink outputLibrary;
private final LibraryToLink interfaceOutputLibrary;
-
+ private final ImmutableSet<String> executionRequirements;
+
private final LinkCommandLine linkCommandLine;
/** True for cc_fake_binary targets. */
@@ -155,7 +163,8 @@ public final class CppLinkAction extends AbstractAction {
boolean fake,
boolean isLTOIndexing,
Iterable<LTOBackendArtifacts> allLTOBackendArtifacts,
- LinkCommandLine linkCommandLine) {
+ LinkCommandLine linkCommandLine,
+ ImmutableSet<String> executionRequirements) {
super(owner, inputs, outputs);
this.mandatoryInputs = inputs;
this.cppConfiguration = cppConfiguration;
@@ -165,6 +174,7 @@ public final class CppLinkAction extends AbstractAction {
this.isLTOIndexing = isLTOIndexing;
this.allLTOBackendArtifacts = allLTOBackendArtifacts;
this.linkCommandLine = linkCommandLine;
+ this.executionRequirements = executionRequirements;
}
private static Iterable<LinkerInput> filterLinkerInputs(Iterable<LinkerInput> inputs) {
@@ -243,6 +253,15 @@ public final class CppLinkAction extends AbstractAction {
return outputLibrary.getArtifact().getPath();
}
+ @Override
+ public Map<String, String> getExecutionInfo() {
+ ImmutableMap.Builder<String, String> result = ImmutableMap.<String, String>builder();
+ for (String requirement : executionRequirements) {
+ result.put(requirement, "");
+ }
+ return result.build();
+ }
+
@VisibleForTesting
public List<String> getRawLinkArgv() {
return linkCommandLine.getRawLinkArgv();
@@ -405,6 +424,8 @@ public final class CppLinkAction extends AbstractAction {
f.addString(fake ? FAKE_LINK_GUID : LINK_GUID);
f.addString(getCppConfiguration().getLdExecutable().getPathString());
f.addStrings(linkCommandLine.arguments());
+ f.addStrings(executionRequirements);
+
// TODO(bazel-team): For correctness, we need to ensure the invariant that all values accessed
// during the execution phase are also covered by the key. Above, we add the argv to the key,
// which covers most cases. Unfortunately, the extra action and fake support methods above also
@@ -518,6 +539,7 @@ public final class CppLinkAction extends AbstractAction {
private PathFragment runtimeSolibDir;
protected final BuildConfiguration configuration;
private final CppConfiguration cppConfiguration;
+ private FeatureConfiguration featureConfiguration;
// Morally equivalent with {@link Context}, except these are mutable.
// Keep these in sync with {@link Context}.
@@ -870,6 +892,17 @@ public final class CppLinkAction extends AbstractAction {
analysisEnvironment.registerAction(parameterFileWriteAction);
}
+ // 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.
+ ImmutableSet<String> executionRequirements = ImmutableSet.of();
+ if (featureConfiguration != null) {
+ if (featureConfiguration.actionIsConfigured(ACTION_NAME)) {
+ executionRequirements =
+ featureConfiguration.getToolForAction(ACTION_NAME).getExecutionRequirements();
+ }
+ }
+
return new CppLinkAction(
getOwner(),
inputsBuilder.deduplicate().build(),
@@ -880,7 +913,8 @@ public final class CppLinkAction extends AbstractAction {
fake,
isLTOIndexing,
allLTOArtifacts,
- linkCommandLine);
+ linkCommandLine,
+ executionRequirements);
}
/**
@@ -954,6 +988,14 @@ public final class CppLinkAction extends AbstractAction {
this.crosstoolInputs = inputs;
return this;
}
+
+ /**
+ * Sets the feature configuration for the action.
+ */
+ public Builder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
+ this.featureConfiguration = featureConfiguration;
+ return this;
+ }
/**
* This is the LTO indexing step, rather than the real link.
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 865a3d8758..34e7b3a1ab 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
@@ -305,6 +305,7 @@ public final class CppModel {
builder.setExtraSystemIncludePrefixes(additionalIncludes);
builder.setFdoBuildStamp(CppHelper.getFdoBuildStamp(ruleContext));
builder.setFeatureConfiguration(featureConfiguration);
+
return builder;
}
@@ -646,6 +647,7 @@ public final class CppModel {
.addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles())
.setLinkType(linkType)
.setLinkStaticness(LinkStaticness.FULLY_STATIC)
+ .setFeatureConfiguration(featureConfiguration)
.build();
env.registerAction(maybePicAction);
result.addStaticLibrary(maybePicAction.getOutputLibrary());
@@ -666,6 +668,7 @@ public final class CppModel {
.addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles())
.setLinkType(picLinkType)
.setLinkStaticness(LinkStaticness.FULLY_STATIC)
+ .setFeatureConfiguration(featureConfiguration)
.build();
env.registerAction(picAction);
result.addPicStaticLibrary(picAction.getOutputLibrary());
@@ -694,18 +697,20 @@ public final class CppModel {
// Should we also link in any libraries that this library depends on?
// That is required on some systems...
- CppLinkAction action = newLinkActionBuilder(soImpl)
- .setInterfaceOutput(soInterface)
- .addNonLibraryInputs(ccOutputs.getObjectFiles(usePicForSharedLibs))
- .addNonLibraryInputs(ccOutputs.getHeaderTokenFiles())
- .setLinkType(LinkTargetType.DYNAMIC_LIBRARY)
- .setLinkStaticness(LinkStaticness.DYNAMIC)
- .addLinkopts(linkopts)
- .addLinkopts(sonameLinkopts)
- .setRuntimeInputs(
- CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkMiddleman(),
- CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkInputs())
- .build();
+ CppLinkAction action =
+ newLinkActionBuilder(soImpl)
+ .setInterfaceOutput(soInterface)
+ .addNonLibraryInputs(ccOutputs.getObjectFiles(usePicForSharedLibs))
+ .addNonLibraryInputs(ccOutputs.getHeaderTokenFiles())
+ .setLinkType(LinkTargetType.DYNAMIC_LIBRARY)
+ .setLinkStaticness(LinkStaticness.DYNAMIC)
+ .addLinkopts(linkopts)
+ .addLinkopts(sonameLinkopts)
+ .setRuntimeInputs(
+ CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkMiddleman(),
+ CppHelper.getToolchain(ruleContext).getDynamicRuntimeLinkInputs())
+ .setFeatureConfiguration(featureConfiguration)
+ .build();
env.registerAction(action);
LibraryToLink dynamicLibrary = action.getOutputLibrary();
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 dc5b22dad8..75638eed25 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
@@ -20,6 +20,7 @@ import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
@@ -116,6 +117,8 @@ public class FakeCppCompileAction extends CppCompileAction {
ImmutableList.<IncludeScannable>of(),
GUID,
usePic,
+ ImmutableSet.<String>of(),
+ CppCompileAction.CPP_COMPILE,
ruleContext);
this.tempOutputFile = Preconditions.checkNotNull(tempOutputFile);
}