Create canonical flag types for use within Bazel rules.

In an ideal world,  we would use the definitions from skylib. In the real world, we do not want to take a hard dependency on skylib in Bazel, so we will provide a set strictly for built-in Starlark based rules.

Note: These can not be generally used yet. They require --experimental_build_settings_api. That is planned to be turned on in 0.28.

Closes #8639.

PiperOrigin-RevId: 257327261
diff --git a/tools/BUILD b/tools/BUILD
index c13fab2..38689a4 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -13,6 +13,7 @@
         "//tools/buildstamp:srcs",
         "//tools/build_defs:srcs",
         "//tools/build_rules:srcs",
+        "//tools/config:srcs",
         "//tools/coverage:srcs",
         "//tools/java:srcs",
         "//tools/jdk:srcs",
diff --git a/tools/config/BUILD b/tools/config/BUILD
new file mode 100644
index 0000000..7a757b2
--- /dev/null
+++ b/tools/config/BUILD
@@ -0,0 +1,20 @@
+# Common config settings and flags.
+#
+# These definitions are only for local use within Bazel built-in tools.
+# In all other cases, use types from github.com/bazelbuild/bazel-skylib.
+
+licenses(["notice"])  # Apache 2.0
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+    visibility = [
+        "//tools:__pkg__",
+        "//tools/build_defs:__pkg__",
+    ],
+)
+
+exports_files(
+    ["common_settings.bzl"],
+    visibility = ["//tools:__subpackages__"],
+)
diff --git a/tools/config/README.md b/tools/config/README.md
new file mode 100644
index 0000000..3d74a09
--- /dev/null
+++ b/tools/config/README.md
@@ -0,0 +1,44 @@
+# Common scalar build settings.
+
+## Overview
+
+These definitions are only for use in Bazel built-in tools.  In all
+other cases, use flag type definitions from
+github.com/bazelbuild/bazel-skylib/rules/common_settings.bzl.
+
+<a name="basic-example"></a>
+## Basic Example
+
+### //tools/my_pkg/BUILD
+
+```python
+load("//tools/config:common_settings.bzl", "bool_flag")
+
+bool_flag(
+    name = "experimental_new_behavior",
+    build_setting_default = False,
+)
+```
+
+### //tools/my_pkg/myrule.bzl
+
+```python
+load("//tools/flags:flags.bzl", "BuildSettingInfo")
+
+
+def _myrule_impl(ctx):
+    if ctx.attr._experimental_new_behavior[BuildSettingInfo].value:
+       ...
+    ...
+
+
+myrule = rule(
+    implementation = _myrule_impl.
+    attrs = {
+        ...
+
+        "_experimental_new_behavior": attr.label(
+            default = "//tools/my_pkg:experimental_new_behavior"),
+    },
+)
+```
diff --git a/tools/config/common_settings.bzl b/tools/config/common_settings.bzl
new file mode 100644
index 0000000..333ab29
--- /dev/null
+++ b/tools/config/common_settings.bzl
@@ -0,0 +1,104 @@
+# Copyright 2019 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.
+"""Common build setting rules for use in Bazel tools
+
+Warning: The content of this file is copied from
+https://github.com/bazelbuild/bazel-skylib/rules/common_settings.bzl
+We maintain this private copy only to prevent taking a dependency on skylib.
+Please do not innovate make modifications here.
+
+These rules return a BuildSettingInfo with the value of the build setting.
+For label-typed settings, use the native label_flag and label_setting rules.
+
+More documentation on how to use build settings at
+https://docs.bazel.build/versions/master/skylark/config.html#user-defined-build-settings
+"""
+
+BuildSettingInfo = provider(
+    doc = "A singleton provider that contains the raw value of a build setting",
+    fields = {
+        "value": "The value of the build setting in the current configuration. " +
+                 "This value may come from the command line or an upstream transition, " +
+                 "or else it will be the build setting's default.",
+    },
+)
+
+def _impl(ctx):
+    return BuildSettingInfo(value = ctx.build_setting_value)
+
+int_flag = rule(
+    implementation = _impl,
+    build_setting = config.int(flag = True),
+    doc = "An int-typed build setting that can be set on the command line",
+)
+
+int_setting = rule(
+    implementation = _impl,
+    build_setting = config.int(),
+    doc = "An int-typed build setting that cannot be set on the command line",
+)
+
+bool_flag = rule(
+    implementation = _impl,
+    build_setting = config.bool(flag = True),
+    doc = "A bool-typed build setting that can be set on the command line",
+)
+
+bool_setting = rule(
+    implementation = _impl,
+    build_setting = config.bool(),
+    doc = "A bool-typed build setting that cannot be set on the command line",
+)
+
+string_list_flag = rule(
+    implementation = _impl,
+    build_setting = config.string_list(flag = True),
+    doc = "A string list-typed build setting that can be set on the command line",
+)
+
+string_list_setting = rule(
+    implementation = _impl,
+    build_setting = config.string_list(),
+    doc = "A string list-typed build setting that cannot be set on the command line",
+)
+
+def _string_impl(ctx):
+    allowed_values = ctx.attr.values
+    value = ctx.build_setting_value
+    if len(allowed_values) == 0 or value in ctx.attr.values:
+        return BuildSettingInfo(value = value)
+    else:
+        fail("Error setting " + str(ctx.label) + ": invalid value '" + value + "'. Allowed values are " + str(allowed_values))
+
+string_flag = rule(
+    implementation = _string_impl,
+    build_setting = config.string(flag = True),
+    attrs = {
+        "values": attr.string_list(
+            doc = "The list of allowed values for this setting. An error is raised if any other value is given.",
+        ),
+    },
+    doc = "A string-typed build setting that can be set on the command line",
+)
+
+string_setting = rule(
+    implementation = _string_impl,
+    build_setting = config.string(),
+    attrs = {
+        "values": attr.string_list(
+            doc = "The list of allowed values for this setting. An error is raised if any other value is given.",
+        ),
+    },
+    doc = "A string-typed build setting that cannot be set on the command line",
+)