Allow starlark rules to be build settings.
For skylark rules that are declared build settings, we auto-add a nonconfigurable build_setting_default attribute which must be set on a per target basis. We also add access to the build setting value via the rule context object. All of this functionality is hidden behind the --experimental_build_setting_api flag which by default is flipped off.
This includes:
- Add a build_setting parameter to starlark rule construction.
- If a starlark rule sets the build_setting parameter, auto-add a mandatory 'build_setting_default' attribute of the same type.
- Allow the value of a build setting skylark rules to be accessed via ctx.build_setting_value.
- Get rid of BuildSettingDescriptor since we don't need both it and BuildSetting.
- Add the --experimental_build_setting_api flag to SkylarkSemantics flags.
Work towards issue #5577
PiperOrigin-RevId: 219537101
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index fba2b88..56ceb24 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -57,6 +57,7 @@
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.syntax.Type.ConversionException;
+import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.StringUtil;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
@@ -111,6 +112,8 @@
* tree. All targets appearing in these attributes appears beneath the ".runfiles" tree; in
* addition, "deps" may have rule-specific semantics.
* </ul>
+ *
+ * TODO(bazel-team): Consider breaking up this class in more manageable subclasses.
*/
// Non-final only for mocking in tests. Do not subclass!
@Immutable
@@ -607,6 +610,12 @@
}
}
+ /**
+ * Name of default attribute implicitly added to all Skylark RuleClasses that are {@code
+ * build_setting}s.
+ */
+ public static final String SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME = "build_setting_default";
+
/** List of required attributes for normal rules, name and type. */
public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES =
ImmutableList.of(attr("tags", Type.STRING_LIST).build());
@@ -641,6 +650,7 @@
private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
private AdvertisedProviderSet.Builder advertisedProviders = AdvertisedProviderSet.builder();
private BaseFunction configuredTargetFunction = null;
+ private BuildSetting buildSetting = null;
private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
NO_EXTERNAL_BINDINGS;
private Function<? super Rule, ? extends Set<String>> optionReferenceFunction =
@@ -770,6 +780,17 @@
if (skylark) {
assertRuleClassProperStarlarkDefinedTransitionUsage();
}
+ if (buildSetting != null) {
+ Type<?> type = buildSetting.getType();
+ Attribute.Builder<?> attrBuilder =
+ attr(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, type)
+ .nonconfigurable("Build setting defaults are referenced during analysis.")
+ .mandatory();
+ if (BuildType.isLabelType(type)) {
+ attrBuilder.allowedFileTypes(FileTypeSet.ANY_FILE);
+ }
+ this.add(attrBuilder);
+ }
return new RuleClass(
name,
@@ -803,7 +824,8 @@
executionPlatformConstraintsAllowed,
executionPlatformConstraints,
outputFileKind,
- attributes.values());
+ attributes.values(),
+ buildSetting);
}
private void assertSkylarkRuleClassHasImplementationFunction() {
@@ -1142,6 +1164,11 @@
return this;
}
+ public Builder setBuildSetting(BuildSetting buildSetting) {
+ this.buildSetting = buildSetting;
+ return this;
+ }
+
public Builder setExternalBindingsFunction(Function<? super Rule, Map<String, Label>> func) {
this.externalBindingsFunction = func;
return this;
@@ -1418,6 +1445,12 @@
@Nullable private final BaseFunction configuredTargetFunction;
/**
+ * The BuildSetting associated with this rule. Null for all RuleClasses except Skylark-defined
+ * rules that pass {@code build_setting} to their {@code rule()} declaration.
+ */
+ @Nullable private final BuildSetting buildSetting;
+
+ /**
* Returns the extra bindings a workspace function adds to the WORKSPACE file.
*/
private final Function<? super Rule, Map<String, Label>> externalBindingsFunction;
@@ -1506,7 +1539,8 @@
ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed,
Set<Label> executionPlatformConstraints,
OutputFile.Kind outputFileKind,
- Collection<Attribute> attributes) {
+ Collection<Attribute> attributes,
+ @Nullable BuildSetting buildSetting) {
this.name = name;
this.key = key;
this.type = type;
@@ -1541,6 +1575,7 @@
this.supportsPlatforms = supportsPlatforms;
this.executionPlatformConstraintsAllowed = executionPlatformConstraintsAllowed;
this.executionPlatformConstraints = ImmutableSet.copyOf(executionPlatformConstraints);
+ this.buildSetting = buildSetting;
// Create the index and collect non-configurable attributes.
int index = 0;
@@ -2307,6 +2342,11 @@
return configuredTargetFunction;
}
+ @Nullable
+ public BuildSetting getBuildSetting() {
+ return buildSetting;
+ }
+
/**
* Returns a function that computes the external bindings a repository function contributes to
* the WORKSPACE file.