diff options
Diffstat (limited to 'src')
4 files changed, 46 insertions, 23 deletions
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/attributes/common/features.html b/src/main/java/com/google/devtools/build/docgen/templates/attributes/common/features.html new file mode 100644 index 0000000000..ba4bbb46d7 --- /dev/null +++ b/src/main/java/com/google/devtools/build/docgen/templates/attributes/common/features.html @@ -0,0 +1,7 @@ +List of <i>features</i>. Default is the empty list.<br/> +<i>Features</i> on a rule modify the <i>features</i> currently enabled on +the <a href="#package">package</a> level via the <i>features</i> attribute.<br/> +For example, if the features ['a', 'b'] are enabled on the package level, +and a rule <i>features</i> attribute contains ['-a', 'c'], the features +enabled for the rule will be 'b' and 'c'. +</p> diff --git a/src/main/java/com/google/devtools/build/lib/Constants.java b/src/main/java/com/google/devtools/build/lib/Constants.java index ac4c9d2708..ee32c59f31 100644 --- a/src/main/java/com/google/devtools/build/lib/Constants.java +++ b/src/main/java/com/google/devtools/build/lib/Constants.java @@ -44,6 +44,7 @@ public class Constants { "templates/attributes/common/deprecation.html", "templates/attributes/common/deps.html", "templates/attributes/common/distribs.html", + "templates/attributes/common/features.html", "templates/attributes/common/licenses.html", "templates/attributes/common/tags.html", "templates/attributes/common/testonly.html", diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java index 4b7015f648..dcec485bd7 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java @@ -196,6 +196,7 @@ public class BaseRuleClasses { .add(attr("generator_function", STRING).undocumented("internal")) .add(attr("testonly", BOOLEAN).value(testonlyDefault) .nonconfigurable("policy decision: rules testability should be consistent")) + .add(attr("features", STRING_LIST).orderIndependent()) .add(attr(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST) .allowedRuleClasses(EnvironmentRule.RULE_NAME) .cfg(Attribute.ConfigurationTransition.HOST) 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 8e30ff47e2..932bc2b672 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 @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimaps; @@ -140,8 +141,7 @@ public final class RuleContext extends TargetContext private RuleContext(Builder builder, ListMultimap<String, ConfiguredTarget> targetMap, ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap, - Set<ConfigMatchingProvider> configConditions, ImmutableSet<String> features, - Map<String, Attribute> attributeMap) { + Set<ConfigMatchingProvider> configConditions, Map<String, Attribute> attributeMap) { super(builder.env, builder.rule, builder.configuration, builder.prerequisiteMap.get(null), builder.visibility); this.rule = builder.rule; @@ -150,10 +150,43 @@ public final class RuleContext extends TargetContext this.configConditions = configConditions; this.attributes = ConfiguredAttributeMapper.of(builder.rule, configConditions); - this.features = features; + this.features = getEnabledFeatures(); this.attributeMap = attributeMap; } + private ImmutableSet<String> getEnabledFeatures() { + Set<String> globallyEnabled = new HashSet<>(); + Set<String> globallyDisabled = new HashSet<>(); + parseFeatures(getConfiguration().getDefaultFeatures(), globallyEnabled, globallyDisabled); + Set<String> packageEnabled = new HashSet<>(); + Set<String> packageDisabled = new HashSet<>(); + parseFeatures(getRule().getPackage().getFeatures(), packageEnabled, packageDisabled); + Set<String> packageFeatures = + Sets.difference(Sets.union(globallyEnabled, packageEnabled), packageDisabled); + Set<String> ruleFeatures = packageFeatures; + if (attributes().has("features", Type.STRING_LIST)) { + Set<String> ruleEnabled = new HashSet<>(); + Set<String> ruleDisabled = new HashSet<>(); + parseFeatures(attributes().get("features", Type.STRING_LIST), ruleEnabled, ruleDisabled); + ruleFeatures = Sets.difference(Sets.union(packageFeatures, ruleEnabled), ruleDisabled); + } + return ImmutableSortedSet.copyOf(Sets.difference(ruleFeatures, globallyDisabled)); + } + + private void parseFeatures(Iterable<String> features, Set<String> enabled, Set<String> disabled) { + for (String feature : features) { + if (feature.startsWith("-")) { + disabled.add(feature.substring(1)); + } else if (feature.equals("no_layering_check")) { + // TODO(bazel-team): Remove once we do not have BUILD files left that contain + // 'no_layering_check'. + disabled.add(feature.substring(3)); + } else { + enabled.add(feature); + } + } + } + @Override public Rule getRule() { return rule; @@ -1125,26 +1158,7 @@ public final class RuleContext extends TargetContext } attributeMap.put(attribute.getName(), attribute); } - return new RuleContext(this, targetMap, filesetEntryMap, configConditions, - getEnabledFeatures(), attributeMap); - } - - private ImmutableSet<String> getEnabledFeatures() { - Set<String> enabled = new HashSet<>(); - Set<String> disabled = new HashSet<>(); - for (String feature : Iterables.concat(getConfiguration().getDefaultFeatures(), - getRule().getPackage().getFeatures())) { - if (feature.startsWith("-")) { - disabled.add(feature.substring(1)); - } else if (feature.equals("no_layering_check")) { - // TODO(bazel-team): Remove once we do not have BUILD files left that contain - // 'no_layering_check'. - disabled.add(feature.substring(3)); - } else { - enabled.add(feature); - } - } - return Sets.difference(enabled, disabled).immutableCopy(); + return new RuleContext(this, targetMap, filesetEntryMap, configConditions, attributeMap); } Builder setVisibility(NestedSet<PackageSpecification> visibility) { |