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);
+    }
+  }
+}