Create a new ExecGroupCollection container to manage exec group inheritance and exec property parsing.
Fixes #13459.
PiperOrigin-RevId: 373388266
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 7942efc..ea2c124 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -29,7 +29,6 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
@@ -45,6 +44,7 @@
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.analysis.AliasProvider.TargetMode;
+import com.google.devtools.build.lib.analysis.ExecGroupCollection.InvalidExecGroupException;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoKey;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -98,12 +98,7 @@
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.LabelClass;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
-import com.google.devtools.build.lib.server.FailureDetails.Analysis;
-import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code;
-import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
-import com.google.devtools.build.lib.skyframe.SaneAnalysisException;
-import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
@@ -217,10 +212,10 @@
private final FragmentClassSet universalFragments;
private final RuleErrorConsumer reporter;
@Nullable private final ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
+ private final ExecGroupCollection execGroupCollection;
private final ConstraintSemantics<RuleContext> constraintSemantics;
private final ImmutableSet<String> requiredConfigFragments;
private final List<Expander> makeVariableExpanders = new ArrayList<>();
- private final ImmutableTable<String, String, String> execProperties;
/** Map of exec group names to ActionOwners. */
private final Map<String, ActionOwner> actionOwners = new HashMap<>();
@@ -264,6 +259,7 @@
ActionLookupKey actionLookupKey,
ImmutableMap<String, Attribute> aspectAttributes,
@Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
+ ExecGroupCollection execGroupCollection,
ConstraintSemantics<RuleContext> constraintSemantics,
ImmutableSet<String> requiredConfigFragments,
String toolsRepository,
@@ -300,7 +296,7 @@
this.actionOwnerSymbolGenerator = new SymbolGenerator<>(actionLookupKey);
reporter = builder.reporter;
this.toolchainContexts = toolchainContexts;
- this.execProperties = parseExecProperties(builder.rawExecProperties);
+ this.execGroupCollection = execGroupCollection;
this.constraintSemantics = constraintSemantics;
this.requiredConfigFragments = requiredConfigFragments;
this.starlarkSemantics = starlarkSemantics;
@@ -517,9 +513,8 @@
rule,
aspectDescriptors,
getConfiguration(),
- getExecProperties(execGroup, execProperties),
- getExecutionPlatform(execGroup),
- ImmutableSet.of(execGroup));
+ getExecGroups().getExecProperties(execGroup),
+ getExecutionPlatform(execGroup));
actionOwners.put(execGroup, actionOwner);
return actionOwner;
}
@@ -626,47 +621,13 @@
AnalysisUtils.isStampingEnabled(this, getConfiguration()), key, getConfiguration());
}
- /**
- * Computes a map of exec properties given the execution platform, taking only properties in exec
- * groups that are applicable to this action. Properties for specific exec groups take precedence
- * over properties that don't specify an exec group.
- */
- private static ImmutableMap<String, String> computeExecProperties(
- Map<String, String> targetExecProperties,
- @Nullable PlatformInfo executionPlatform,
- Set<String> execGroups) {
- Map<String, String> execProperties = new HashMap<>();
-
- if (executionPlatform != null) {
- ImmutableTable<String, String, String> execPropertiesPerGroup =
- parseExecGroups(executionPlatform.execProperties());
-
- if (execPropertiesPerGroup.containsRow(DEFAULT_EXEC_GROUP_NAME)) {
- execProperties.putAll(execPropertiesPerGroup.row(DEFAULT_EXEC_GROUP_NAME));
- }
-
- for (String execGroup : execPropertiesPerGroup.rowKeySet()) {
- if (execGroups.contains(execGroup)) {
- execProperties.putAll(execPropertiesPerGroup.row(execGroup));
- }
- }
- }
-
- // If the same key occurs both in the platform and in target-specific properties, the
- // value is taken from target-specific properties (effectively overriding the platform
- // properties).
- execProperties.putAll(targetExecProperties);
- return ImmutableMap.copyOf(execProperties);
- }
-
@VisibleForTesting
public static ActionOwner createActionOwner(
Rule rule,
ImmutableList<AspectDescriptor> aspectDescriptors,
BuildConfiguration configuration,
- Map<String, String> targetExecProperties,
- @Nullable PlatformInfo executionPlatform,
- Set<String> execGroups) {
+ ImmutableMap<String, String> execProperties,
+ @Nullable PlatformInfo executionPlatform) {
return ActionOwner.create(
rule.getLabel(),
aspectDescriptors,
@@ -676,7 +637,7 @@
configuration.checksum(),
configuration.toBuildEvent(),
configuration.isHostConfiguration() ? HOST_CONFIGURATION_PROGRESS_TAG : null,
- computeExecProperties(targetExecProperties, executionPlatform, execGroups),
+ execProperties,
executionPlatform);
}
@@ -1374,6 +1335,10 @@
return toolchainContexts;
}
+ public ExecGroupCollection getExecGroups() {
+ return execGroupCollection;
+ }
+
public boolean targetPlatformHasConstraint(ConstraintValueInfo constraintValue) {
if (toolchainContexts == null || toolchainContexts.getTargetPlatform() == null) {
return false;
@@ -1408,101 +1373,6 @@
return ans.build();
}
- private ImmutableTable<String, String, String> parseExecProperties(
- Map<String, String> execProperties) throws InvalidExecGroupException {
- if (execProperties.isEmpty()) {
- return ImmutableTable.of();
- } else {
- return parseExecProperties(
- execProperties, toolchainContexts == null ? null : toolchainContexts.getExecGroupNames());
- }
- }
-
- /**
- * Parse raw exec properties attribute value into a map of exec group names to their properties.
- * The raw map can have keys of two forms: (1) 'property' and (2) 'exec_group_name.property'. The
- * former get parsed into the default exec group, the latter get parsed into their relevant exec
- * groups.
- */
- private static ImmutableTable<String, String, String> parseExecGroups(
- Map<String, String> rawExecProperties) {
- ImmutableTable.Builder<String, String, String> execProperties = ImmutableTable.builder();
- for (Map.Entry<String, String> execProperty : rawExecProperties.entrySet()) {
- String rawProperty = execProperty.getKey();
- int delimiterIndex = rawProperty.indexOf('.');
- if (delimiterIndex == -1) {
- execProperties.put(DEFAULT_EXEC_GROUP_NAME, rawProperty, execProperty.getValue());
- } else {
- String execGroup = rawProperty.substring(0, delimiterIndex);
- String property = rawProperty.substring(delimiterIndex + 1);
- execProperties.put(execGroup, property, execProperty.getValue());
- }
- }
- return execProperties.build();
- }
-
- /**
- * Parse raw exec properties attribute value into a map of exec group names to their properties.
- * If given a set of exec groups, validates all the exec groups in the map are applicable to the
- * action.
- */
- private static ImmutableTable<String, String, String> parseExecProperties(
- Map<String, String> rawExecProperties, @Nullable Set<String> execGroups)
- throws InvalidExecGroupException {
- ImmutableTable<String, String, String> consolidatedProperties =
- parseExecGroups(rawExecProperties);
- if (execGroups != null) {
- for (String execGroupName : consolidatedProperties.rowKeySet()) {
- if (!execGroupName.equals(DEFAULT_EXEC_GROUP_NAME) && !execGroups.contains(execGroupName)) {
- throw new InvalidExecGroupException(
- String.format(
- "Tried to set properties for non-existent exec group '%s'.", execGroupName));
- }
- }
- }
-
- return consolidatedProperties;
- }
-
- /**
- * Gets the combined exec properties of the given exec group and the target's exec properties. If
- * a property is set in both, the exec group properties take precedence. If a non-existent exec
- * group is passed in, just returns the target's exec properties.
- *
- * @param execGroup group whose properties to retrieve
- * @param execProperties Map of exec group name to map of properties and values
- */
- private static ImmutableMap<String, String> getExecProperties(
- String execGroup, ImmutableTable<String, String, String> execProperties) {
- if (!execProperties.containsRow(execGroup) || execGroup.equals(DEFAULT_EXEC_GROUP_NAME)) {
- return execProperties.row(DEFAULT_EXEC_GROUP_NAME);
- }
-
- // Use a HashMap to build here because we expect duplicate keys to happen
- // (and rewrite previous entries).
- Map<String, String> targetAndGroupProperties =
- new HashMap<>(execProperties.row(DEFAULT_EXEC_GROUP_NAME));
- targetAndGroupProperties.putAll(execProperties.row(execGroup));
- return ImmutableMap.copyOf(targetAndGroupProperties);
- }
-
- /** An error for when the user tries to access an non-existent exec group */
- public static final class InvalidExecGroupException extends Exception
- implements SaneAnalysisException {
- InvalidExecGroupException(String message) {
- super(message);
- }
-
- @Override
- public DetailedExitCode getDetailedExitCode() {
- return DetailedExitCode.of(
- FailureDetail.newBuilder()
- .setMessage(getMessage())
- .setAnalysis(Analysis.newBuilder().setCode(Code.EXEC_GROUP_MISSING))
- .build());
- }
- }
-
private void checkAttributeIsDependency(String attributeName) {
Attribute attributeDefinition = attributes.getAttributeDefinition(attributeName);
if (attributeDefinition == null) {
@@ -1876,6 +1746,7 @@
private ImmutableMap<String, Attribute> aspectAttributes;
private ImmutableList<Aspect> aspects;
private ToolchainCollection<ResolvedToolchainContext> toolchainContexts;
+ private ExecGroupCollection.Builder execGroupCollectionBuilder;
private ImmutableMap<String, String> rawExecProperties;
private ConstraintSemantics<RuleContext> constraintSemantics;
private ImmutableSet<String> requiredConfigFragments = ImmutableSet.of();
@@ -1933,14 +1804,7 @@
}
ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap =
createFilesetEntryMap(target.getAssociatedRule(), configConditions.asProviders());
- if (rawExecProperties == null) {
- if (!attributes.has(RuleClass.EXEC_PROPERTIES, Type.STRING_DICT)) {
- rawExecProperties = ImmutableMap.of();
- } else {
- rawExecProperties =
- ImmutableMap.copyOf(attributes.get(RuleClass.EXEC_PROPERTIES, Type.STRING_DICT));
- }
- }
+
return new RuleContext(
this,
attributes,
@@ -1952,6 +1816,7 @@
actionOwnerSymbol,
firstNonNull(aspectAttributes, ImmutableMap.of()),
toolchainContexts,
+ createExecGroupCollection(execGroupCollectionBuilder, attributes),
constraintSemantics,
requiredConfigFragments,
toolsRepository,
@@ -1959,6 +1824,21 @@
mutability);
}
+ private ExecGroupCollection createExecGroupCollection(
+ ExecGroupCollection.Builder execGroupCollectionBuilder, AttributeMap attributes)
+ throws InvalidExecGroupException {
+ if (rawExecProperties == null) {
+ if (!attributes.has(RuleClass.EXEC_PROPERTIES, Type.STRING_DICT)) {
+ rawExecProperties = ImmutableMap.of();
+ } else {
+ rawExecProperties =
+ ImmutableMap.copyOf(attributes.get(RuleClass.EXEC_PROPERTIES, Type.STRING_DICT));
+ }
+ }
+
+ return execGroupCollectionBuilder.build(toolchainContexts, rawExecProperties);
+ }
+
private void checkAttributesNonEmpty(AttributeMap attributes) {
for (String attributeName : attributes.getAttributeNames()) {
Attribute attr = attributes.getAttributeDefinition(attributeName);
@@ -2062,6 +1942,12 @@
return this;
}
+ public Builder setExecGroupCollectionBuilder(
+ ExecGroupCollection.Builder execGroupCollectionBuilder) {
+ this.execGroupCollectionBuilder = execGroupCollectionBuilder;
+ return this;
+ }
+
/**
* Warning: if you set the exec properties using this method any exec_properties attribute value
* will be ignored in favor of this value.