Create the native version of label_setting and label_flag.
See the javadoc of LabelBuildSettings for explanation on why these are defined natively instead of in starlark (at least for V1 of SBC). TL;DR - free-for-all implementation functions for label-typed build settings are dangerous since we actually return providers of the targets that correspond to those labels.
context: https://docs.google.com/document/d/1vc8v-kXjvgZOdQdnxPTaV0rrLxtP2XwnD2tAZlYJOqw/edit#bookmark=id.a6x3vcng0anx
PiperOrigin-RevId: 226210154
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/GenericRules.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/GenericRules.java
index 2b81f74..107faf5 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/GenericRules.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/GenericRules.java
@@ -19,6 +19,8 @@
import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule;
import com.google.devtools.build.lib.bazel.rules.common.BazelFilegroupRule;
import com.google.devtools.build.lib.rules.Alias.AliasRule;
+import com.google.devtools.build.lib.rules.LabelBuildSettings.LabelBuildFlagRule;
+import com.google.devtools.build.lib.rules.LabelBuildSettings.LabelBuildSettingRule;
import com.google.devtools.build.lib.rules.core.CoreRules;
import com.google.devtools.build.lib.rules.genquery.GenQueryRule;
import com.google.devtools.build.lib.rules.test.TestSuiteRule;
@@ -43,6 +45,8 @@
builder.addRuleDefinition(new BazelFilegroupRule());
builder.addRuleDefinition(new TestSuiteRule());
builder.addRuleDefinition(new GenQueryRule());
+ builder.addRuleDefinition(new LabelBuildSettingRule());
+ builder.addRuleDefinition(new LabelBuildFlagRule());
try {
builder.addWorkspaceFilePrefix(
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 6a93d24..28184d6 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
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.packages;
+import static com.google.devtools.build.lib.packages.Attribute.ANY_RULE;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
@@ -616,6 +617,9 @@
*/
public static final String SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME = "build_setting_default";
+ public static final String BUILD_SETTING_DEFAULT_NONCONFIGURABLE =
+ "Build setting defaults are referenced during analysis.";
+
/** 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());
@@ -784,10 +788,11 @@
Type<?> type = buildSetting.getType();
Attribute.Builder<?> attrBuilder =
attr(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, type)
- .nonconfigurable("Build setting defaults are referenced during analysis.")
+ .nonconfigurable(BUILD_SETTING_DEFAULT_NONCONFIGURABLE)
.mandatory();
if (BuildType.isLabelType(type)) {
attrBuilder.allowedFileTypes(FileTypeSet.ANY_FILE);
+ attrBuilder.allowedRuleClasses(ANY_RULE);
}
this.add(attrBuilder);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/LabelBuildSettings.java b/src/main/java/com/google/devtools/build/lib/rules/LabelBuildSettings.java
new file mode 100644
index 0000000..90029aa
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/LabelBuildSettings.java
@@ -0,0 +1,108 @@
+// Copyright 2018 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;
+
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL;
+import static com.google.devtools.build.lib.packages.RuleClass.Builder.SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME;
+
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault;
+import com.google.devtools.build.lib.packages.BuildSetting;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.rules.LateBoundAlias.CommonAliasRule;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
+
+/**
+ * Native implementation of label setting and flags.
+ *
+ * <p>While most build settings are completely defined in starlark, we're natively defining
+ * label-typed ones because:
+ *
+ * <ul>
+ * <li>they're essentially special Alias targets
+ * <li>we don't have a known use case where you'd want to manipulate a label-typed build setting
+ * in its implementation section.
+ * </ul>
+ *
+ * <p>Once we do have (2), we can consider switching over to starlark implementation. The dangers
+ * there involve the implementation function returning a label we've never seen before in the build.
+ * And since label-typed build settings actually return the providers of the targets they point to,
+ * we'd have to be able to load and configure potentially arbitrary labels on the fly. This is not
+ * possible today and could easily introduce large performance issues.
+ */
+public class LabelBuildSettings {
+ @AutoCodec @VisibleForSerialization
+ // TODO(b/65746853): find a way to do this without passing the entire BuildConfiguration
+ static final LabelLateBoundDefault<BuildConfiguration> ACTUAL =
+ LabelLateBoundDefault.fromTargetConfiguration(
+ BuildConfiguration.class,
+ null,
+ (rule, attributes, configuration) -> {
+ if (rule == null || configuration == null) {
+ return attributes.get(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, LABEL);
+ }
+ Object commandLineValue =
+ configuration.getOptions().getStarlarkOptions().get(rule.getLabel());
+ return commandLineValue == null
+ ? attributes.get(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, LABEL)
+ : (Label) commandLineValue;
+ });
+
+ private static RuleClass buildRuleClass(RuleClass.Builder builder, boolean flag) {
+ return builder
+ .removeAttribute("licenses")
+ .removeAttribute("distribs")
+ .add(attr(":alias", LABEL).value(ACTUAL))
+ .setBuildSetting(new BuildSetting(flag, LABEL))
+ .canHaveAnyProvider()
+ .supportsPlatforms(false)
+ .build();
+ }
+
+ /**
+ * Rule definition of label_setting TODO(b/110417082): documentation when other documentation on
+ * SBC exists and we can point to it.
+ */
+ public static class LabelBuildSettingRule extends CommonAliasRule<BuildConfiguration> {
+
+ public LabelBuildSettingRule() {
+ super("label_setting", env -> ACTUAL, BuildConfiguration.class);
+ }
+
+ @Override
+ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
+ return buildRuleClass(builder, false);
+ }
+ }
+
+ /**
+ * Rule definition of label_flag TODO(b/110417082): documentation when other documentation on SBC
+ * exists and we can point to it.
+ */
+ public static class LabelBuildFlagRule extends CommonAliasRule<BuildConfiguration> {
+
+ public LabelBuildFlagRule() {
+ super("label_flag", env -> ACTUAL, BuildConfiguration.class);
+ }
+
+ @Override
+ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) {
+ return buildRuleClass(builder, true);
+ }
+ }
+}