Merge branch 'main' into rules-based-toolchain-example
diff --git a/MODULE.bazel b/MODULE.bazel
index 51a00b2..91092b0 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,11 +1,11 @@
 module(
     name = "rules_cc",
-    version = "0.0.4",
+    version = "0.0.10",
     compatibility_level = 1,
 )
 
 bazel_dep(name = "bazel_skylib", version = "1.7.1")
-bazel_dep(name = "platforms", version = "0.0.7")
+bazel_dep(name = "platforms", version = "0.0.10")
 bazel_dep(name = "stardoc", version = "0.7.0")
 
 cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
diff --git a/WORKSPACE b/WORKSPACE
index 875888e..a4587d5 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -41,10 +41,10 @@
 
 http_archive(
     name = "platforms",
-    sha256 = "3a561c99e7bdbe9173aa653fd579fe849f1d8d67395780ab4770b1f381431d51",
+    sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
-        "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz",
+        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+        "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
     ],
 )
 
diff --git a/cc/action_names.bzl b/cc/action_names.bzl
index 3df7cfa..6735d82 100644
--- a/cc/action_names.bzl
+++ b/cc/action_names.bzl
@@ -88,6 +88,9 @@
 # A string constant for the clif action.
 CLIF_MATCH_ACTION_NAME = "clif-match"
 
+# A string constant for the obj copy actions.
+OBJ_COPY_ACTION_NAME = "objcopy_embed_data"
+
 ACTION_NAMES = struct(
     c_compile = C_COMPILE_ACTION_NAME,
     cpp_compile = CPP_COMPILE_ACTION_NAME,
@@ -113,6 +116,7 @@
     objc_fully_link = OBJC_FULLY_LINK_ACTION_NAME,
     objcpp_compile = OBJCPP_COMPILE_ACTION_NAME,
     clif_match = CLIF_MATCH_ACTION_NAME,
+    objcopy_embed_data = OBJ_COPY_ACTION_NAME,
 )
 
 # Names of actions that parse or compile C++ code.
diff --git a/cc/cc_binary.bzl b/cc/cc_binary.bzl
index 70810a2..f36e431 100644
--- a/cc/cc_binary.bzl
+++ b/cc/cc_binary.bzl
@@ -19,7 +19,7 @@
 # added as a dependency to @rules_cc//:link_extra_lib. The intermediate library
 # @bazel_tools@bazel_tools//tools/cpp:link_extra_lib should either be added as a dependency
 # to @rules_cc//:link_extra_lib, or removed entirely (if possible).
-_LINK_EXTRA_LIB = "@rules_cc//:link_extra_lib"  # copybara-use-repo-external-label
+_LINK_EXTRA_LIB = Label("//:link_extra_lib")
 
 def cc_binary(**attrs):
     """Bazel cc_binary rule.
diff --git a/cc/cc_test.bzl b/cc/cc_test.bzl
index d3ba601..387fd18 100644
--- a/cc/cc_test.bzl
+++ b/cc/cc_test.bzl
@@ -20,7 +20,7 @@
 # added as a dependency to @rules_cc//:link_extra_lib. The intermediate library
 # @bazel_tools@bazel_tools//tools/cpp:link_extra_lib should either be added as a dependency
 # to @rules_cc//:link_extra_lib, or removed entirely (if possible).
-_LINK_EXTRA_LIB = "@rules_cc//:link_extra_lib"  # copybara-use-repo-external-label
+_LINK_EXTRA_LIB = Label("//:link_extra_lib")
 
 def cc_test(**attrs):
     """Bazel cc_test rule.
diff --git a/cc/common/visibility.bzl b/cc/common/visibility.bzl
index dfbc8ce..981ce86 100644
--- a/cc/common/visibility.bzl
+++ b/cc/common/visibility.bzl
@@ -1,3 +1,3 @@
 """Bzl load visibility package specs"""
 
-INTERNAL_VISIBILITY = ["//cc/..."]
+INTERNAL_VISIBILITY = ["public"]
diff --git a/cc/find_cc_toolchain.bzl b/cc/find_cc_toolchain.bzl
index 4129680..c3e9ed4 100644
--- a/cc/find_cc_toolchain.bzl
+++ b/cc/find_cc_toolchain.bzl
@@ -29,7 +29,7 @@
         attrs = {
             "_cc_toolchain": attr.label(
                 default = Label(
-                    "@rules_cc//cc:current_cc_toolchain", # copybara-use-repo-external-label
+                    "@rules_cc//cc:current_cc_toolchain",
                 ),
             ),
         },
@@ -53,7 +53,7 @@
 Bazel version is not needed), it's enough to only keep the toolchain type.
 """
 
-CC_TOOLCHAIN_TYPE = "@bazel_tools//tools/cpp:toolchain_type"  # copybara-use-repo-external-label
+CC_TOOLCHAIN_TYPE = Label("@bazel_tools//tools/cpp:toolchain_type")
 
 def find_cc_toolchain(ctx, *, mandatory = True):
     """
diff --git a/cc/toolchains/BUILD b/cc/toolchains/BUILD
index 8ae4d97..98fe2cf 100644
--- a/cc/toolchains/BUILD
+++ b/cc/toolchains/BUILD
@@ -13,15 +13,11 @@
 # limitations under the License.
 
 load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
 load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
+load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
 load("@stardoc//stardoc:stardoc.bzl", "stardoc")
-
-bool_flag(
-    name = "experimental_enable_rule_based_toolchains",
-    build_setting_default = False,
-    visibility = ["//visibility:public"],
-)
+load("//cc/toolchains/impl:documented_api.bzl", "DOCUMENTED_TOOLCHAIN_RULES")
+load("//cc/toolchains/impl:markdown_helpers.bzl", "xref_substitutions")
 
 bzl_library(
     name = "toolchain_rules",
@@ -49,11 +45,30 @@
 
 stardoc(
     name = "toolchain_api",
-    out = "generated_toolchain_api.md",
+    out = "raw_generated_toolchain_api.md",
     input = "//cc/toolchains/impl:documented_api.bzl",
     deps = [":toolchain_rules"],
 )
 
+expand_template(
+    name = "toolchain_api_md",
+    out = "generated_toolchain_api.md",
+    # Dictionary order 100% matters here!
+    # buildifier: disable=unsorted-dict-items
+    substitutions = {
+        # Strip @rules_cc to prevent instances of @rules_cc@rules_cc//cc.
+        "@rules_cc//cc": "//cc",
+        # In GitHub, we prefer to clarify all the labels that come from
+        # rules_cc.
+        "//cc": "@rules_cc//cc",
+    } | xref_substitutions({
+        "`{}`".format(rule_name): "#{}".format(rule_name)
+        for rule_name in DOCUMENTED_TOOLCHAIN_RULES
+    }),
+    # buildifier: enable=unsorted-dict-items
+    template = ":raw_generated_toolchain_api.md",
+)
+
 diff_test(
     name = "toolchain_api_diff_test",
     file1 = ":generated_toolchain_api.md",
diff --git a/cc/toolchains/actions.bzl b/cc/toolchains/actions.bzl
index fc91787..78c1fc6 100644
--- a/cc/toolchains/actions.bzl
+++ b/cc/toolchains/actions.bzl
@@ -37,14 +37,26 @@
     },
     doc = """A type of action (eg. c_compile, assemble, strip).
 
-Example:
+`cc_action_type` rules are used to associate arguments and tools together to
+perform a specific action. Bazel prescribes a set of known action types that are used to drive
+typical C/C++/ObjC actions like compiling, linking, and archiving. The set of well-known action
+types can be found in [//cc/toolchains/actions:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD).
 
-load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
+It's possible to create project-specific action types for use in toolchains. Be careful when
+doing this, because every toolchain that encounters the action will need to be configured to
+support the custom action type. If your project is a library, avoid creating new action types as
+it will reduce compatibility with existing toolchains and increase setup complexity for users.
+
+Example:
+```
+load("//cc:action_names.bzl", "ACTION_NAMES")
+load("//cc/toolchains:actions.bzl", "cc_action_type")
 
 cc_action_type(
-  name = "cpp_compile",
-  action_name =  = ACTION_NAMES.cpp_compile,
+    name = "cpp_compile",
+    action_name =  = ACTION_NAMES.cpp_compile,
 )
+```
 """,
     provides = [ActionTypeInfo, ActionTypeSetInfo],
 )
@@ -60,15 +72,21 @@
 cc_action_type_set = rule(
     doc = """Represents a set of actions.
 
+This is a convenience rule to allow for more compact representation of a group of action types.
+Use this anywhere a `cc_action_type` is accepted.
+
 Example:
+```
+load("//cc/toolchains:actions.bzl", "cc_action_type_set")
 
 cc_action_type_set(
     name = "link_executable_actions",
     actions = [
-        ":cpp_link_executable",
-        ":lto_index_for_executable",
+        "//cc/toolchains/actions:cpp_link_executable",
+        "//cc/toolchains/actions:lto_index_for_executable",
     ],
 )
+```
 """,
     implementation = _cc_action_type_set_impl,
     attrs = {
diff --git a/cc/toolchains/actions/BUILD b/cc/toolchains/actions/BUILD
index e122f5c..164a336 100644
--- a/cc/toolchains/actions/BUILD
+++ b/cc/toolchains/actions/BUILD
@@ -185,6 +185,13 @@
 )
 
 cc_action_type_set(
+    name = "c_compile_actions",
+    actions = [
+        ":c_compile",
+    ],
+)
+
+cc_action_type_set(
     name = "cpp_compile_actions",
     actions = [
         ":linkstamp_compile",
@@ -201,7 +208,7 @@
     name = "compile_actions",
     actions = [
         ":cpp_compile_actions",
-        ":c_compile",
+        ":c_compile_actions",
         ":assembly_actions",
     ],
 )
diff --git a/cc/toolchains/args.bzl b/cc/toolchains/args.bzl
index 4f71986..bdcf7ce 100644
--- a/cc/toolchains/args.bzl
+++ b/cc/toolchains/args.bzl
@@ -86,30 +86,18 @@
         "actions": attr.label_list(
             providers = [ActionTypeSetInfo],
             mandatory = True,
-            doc = """A list of action types that this flag set applies to.
-
-See @rules_cc//cc/toolchains/actions:all for valid options.
-""",
+            doc = """See documentation for cc_args macro wrapper.""",
         ),
         "allowlist_include_directories": attr.label_list(
             providers = [DirectoryInfo],
-            doc = """Include paths implied by using this rule.
-
-Some flags (e.g. --sysroot) imply certain include paths are available despite
-not explicitly specifying a normal include path flag (`-I`, `-isystem`, etc.).
-Bazel checks that all included headers are properly provided by a dependency or
-allowlisted through this mechanism.
-""",
+            doc = """See documentation for cc_args macro wrapper.""",
         ),
         "env": attr.string_dict(
-            doc = "Environment variables to be added to the command-line.",
+            doc = """See documentation for cc_args macro wrapper.""",
         ),
         "requires_any_of": attr.label_list(
             providers = [FeatureConstraintInfo],
-            doc = """This will be enabled when any of the constraints are met.
-
-If omitted, this flag set will be enabled unconditionally.
-""",
+            doc = """See documentation for cc_args macro wrapper.""",
         ),
         "_variables": attr.label(
             default = "//cc/toolchains/variables:variables",
@@ -128,9 +116,175 @@
 """,
 )
 
-def cc_args(name, format = {}, **kwargs):
+def cc_args(
+        *,
+        name,
+        actions = None,
+        allowlist_include_directories = None,
+        args = None,
+        data = None,
+        env = None,
+        format = {},
+        iterate_over = None,
+        nested = None,
+        requires_not_none = None,
+        requires_none = None,
+        requires_true = None,
+        requires_false = None,
+        requires_equal = None,
+        requires_equal_value = None,
+        requires_any_of = None,
+        **kwargs):
+    """Action-specific arguments for use with a cc_toolchain.
+
+    This rule is the fundamental building building block for every toolchain tool invocation. Each
+    argument expressed in a toolchain tool invocation (e.g. `gcc`, `llvm-ar`) is declared in a
+    `cc_args` rule that applies an ordered list of arguments to a set of toolchain
+    actions. `cc_args` rules can be added unconditionally to a
+    `cc_toolchain`, conditionally via `select()` statements, or dynamically via an
+    intermediate `cc_feature`.
+
+    Conceptually, this is similar to the old `CFLAGS`, `CPPFLAGS`, etc. environment variables that
+    many build systems use to determine which flags to use for a given action. The significant
+    difference is that `cc_args` rules are declared in a structured way that allows for
+    significantly more powerful and sharable toolchain configurations. Also, due to Bazel's more
+    granular action types, it's possible to bind flags to very specific actions (e.g. LTO indexing
+    for an executable vs a dynamic library) multiple different actions (e.g. C++ compile and link
+    simultaneously).
+
+    Example usage:
+    ```
+    load("//cc/toolchains:args.bzl", "cc_args")
+
+    # Basic usage: a trivial flag.
+    #
+    # An example of expressing `-Werror` as a `cc_args` rule.
+    cc_args(
+        name = "warnings_as_errors",
+        actions = [
+            # Applies to all C/C++ compile actions.
+            "//cc/toolchains/actions:compile_actions",
+        ],
+        args = ["-Werror"],
+    )
+
+    # Basic usage: ordered flags.
+    #
+    # An example of linking against libc++, which uses two flags that must be applied in order.
+    cc_args(
+        name = "link_libcxx",
+        actions = [
+            # Applies to all link actions.
+            "//cc/toolchains/actions:link_actions",
+        ],
+        # On tool invocation, this appears as `-Xlinker -lc++`. Nothing will ever end up between
+        # the two flags.
+        args = [
+            "-Xlinker",
+            "-lc++",
+        ],
+    )
+
+    # Advanced usage: built-in variable expansions.
+    #
+    # Expands to `-L/path/to/search_dir` for each directory in the built-in variable
+    # `library_search_directories`. This variable is managed internally by Bazel through inherent
+    # behaviors of Bazel and the interactions between various C/C++ build rules.
+    cc_args(
+        name = "library_search_directories",
+        actions = [
+            "//cc/toolchains/actions:link_actions",
+        ],
+        args = ["-L{search_dir}"],
+        iterate_over = "//cc/toolchains/variables:library_search_directories",
+        requires_not_none = "//cc/toolchains/variables:library_search_directories",
+        format = {
+            "search_dir": "//cc/toolchains/variables:library_search_directories",
+        },
+    )
+    ```
+
+    For more extensive examples, see the usages here:
+        https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args
+
+    Args:
+        name: (str) The name of the target.
+        actions: (List[Label]) A list of labels of `cc_action_type` or
+            `cc_action_type_set` rules that dictate which actions these
+            arguments should be applied to.
+        allowlist_include_directories: (List[Label]) A list of include paths that are implied by
+            using this rule. These must point to a skylib
+            [directory](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/directory_doc.md#directory)
+            or [subdirectory](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/directory_subdirectory_doc.md#subdirectory) rule.
+            Some flags (e.g. --sysroot) imply certain include paths are available despite
+            not explicitly specifying a normal include path flag (`-I`, `-isystem`, etc.).
+            Bazel checks that all included headers are properly provided by a dependency or
+            allowlisted through this mechanism.
+
+            As a rule of thumb, only use this if Bazel is complaining about absolute paths in
+            your toolchain and you've ensured that the toolchain is compiling with the
+            `-no-canonical-prefixes` and/or `-fno-canonical-system-headers` arguments.
+
+            This can help work around errors like:
+            `the source file 'main.c' includes the following non-builtin files with absolute paths
+            (if these are builtin files, make sure these paths are in your toolchain)`.
+        args: (List[str]) The command-line arguments that are applied by using this rule. This is
+            mutually exclusive with [nested](#cc_args-nested).
+        data: (List[Label]) A list of runtime data dependencies that are required for these
+            arguments to work as intended.
+        env: (Dict[str, str]) Environment variables that should be set when the tool is invoked.
+        format: (Dict[str, Label]) A mapping of format strings to the label of the corresponding
+            `cc_variable` that the value should be pulled from. All instances of
+            `{variable_name}` will be replaced with the expanded value of `variable_name` in this
+            dictionary. The complete list of possible variables can be found in
+            https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD.
+            It is not possible to declare custom variables--these are inherent to Bazel itself.
+        iterate_over: (Label) The label of a `cc_variable` that should be iterated over. This is
+            intended for use with built-in variables that are lists.
+        nested: (List[Label]) A list of `cc_nested_args` rules that should be
+            expanded to command-line arguments when this rule is used. This is mutually exclusive
+            with [args](#cc_args-args).
+        requires_not_none: (Label) The label of a `cc_variable` that should be checked
+            for existence before expanding this rule. If the variable is None, this rule will be
+            ignored.
+        requires_none: (Label) The label of a `cc_variable` that should be checked for
+            non-existence before expanding this rule. If the variable is not None, this rule will be
+            ignored.
+        requires_true: (Label) The label of a `cc_variable` that should be checked for
+            truthiness before expanding this rule. If the variable is false, this rule will be
+            ignored.
+        requires_false: (Label) The label of a `cc_variable` that should be checked
+            for falsiness before expanding this rule. If the variable is true, this rule will be
+            ignored.
+        requires_equal: (Label) The label of a `cc_variable` that should be checked
+            for equality before expanding this rule. If the variable is not equal to
+            (requires_equal_value)[#cc_args-requires_equal_value], this rule will be ignored.
+        requires_equal_value: (str) The value to compare (requires_equal)[#cc_args-requires_equal]
+            against.
+        requires_any_of: (List[Label]) These arguments will be used
+            in a tool invocation when at least one of the [cc_feature_constraint](#cc_feature_constraint)
+            entries in this list are satisfied. If omitted, this flag set will be enabled
+            unconditionally.
+        **kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
+    """
     return _cc_args(
         name = name,
+        actions = actions,
+        allowlist_include_directories = allowlist_include_directories,
+        args = args,
+        data = data,
+        env = env,
+        # We flip the key/value pairs in the dictionary here because Bazel doesn't have a
+        # string-keyed label dict attribute type.
         format = {k: v for v, k in format.items()},
+        iterate_over = iterate_over,
+        nested = nested,
+        requires_not_none = requires_not_none,
+        requires_none = requires_none,
+        requires_true = requires_true,
+        requires_false = requires_false,
+        requires_equal = requires_equal,
+        requires_equal_value = requires_equal_value,
+        requires_any_of = requires_any_of,
         **kwargs
     )
diff --git a/cc/toolchains/args/archiver_flags/BUILD b/cc/toolchains/args/archiver_flags/BUILD
index d293ed9..4e3c97f 100644
--- a/cc/toolchains/args/archiver_flags/BUILD
+++ b/cc/toolchains/args/archiver_flags/BUILD
@@ -16,7 +16,7 @@
 
 cc_args(
     name = "create_static_archive",
-    actions = ["//cc/toolchains/actions:cpp_link_static_library"],
+    actions = ["//cc/toolchains/actions:ar_actions"],
     args = select({
         "@platforms//os:macos": ["-static"],
         "//conditions:default": ["rcsD"],
@@ -25,7 +25,7 @@
 
 cc_args(
     name = "output_execpath",
-    actions = ["//cc/toolchains/actions:cpp_link_static_library"],
+    actions = ["//cc/toolchains/actions:ar_actions"],
     args = select({
         "@platforms//os:macos": ["-o"],
         "//conditions:default": [],
@@ -36,7 +36,7 @@
 
 cc_args(
     name = "libraries_to_link",
-    actions = ["//cc/toolchains/actions:cpp_link_static_library"],
+    actions = ["//cc/toolchains/actions:ar_actions"],
     nested = ["libraries_to_link_expansion"],
     requires_not_none = "//cc/toolchains/variables:libraries_to_link",
 )
diff --git a/cc/toolchains/args/force_pic_flags/BUILD b/cc/toolchains/args/force_pic_flags/BUILD
index 63bc341..3eaae56 100644
--- a/cc/toolchains/args/force_pic_flags/BUILD
+++ b/cc/toolchains/args/force_pic_flags/BUILD
@@ -4,10 +4,7 @@
 
 cc_args(
     name = "force_pic_flags",
-    actions = [
-        "//cc/toolchains/actions:cpp_link_executable",
-        "//cc/toolchains/actions:lto_index_for_executable",
-    ],
+    actions = ["//cc/toolchains/actions:link_executable_actions"],
     args = select({
         "@platforms//os:macos": ["-Wl,-pie"],
         "//conditions:default": ["-pie"],
diff --git a/cc/toolchains/args/libraries_to_link/BUILD b/cc/toolchains/args/libraries_to_link/BUILD
index 4bd1331..c338c1c 100644
--- a/cc/toolchains/args/libraries_to_link/BUILD
+++ b/cc/toolchains/args/libraries_to_link/BUILD
@@ -6,14 +6,7 @@
 
 cc_args(
     name = "libraries_to_link",
-    actions = [
-        "//cc/toolchains/actions:cpp_link_executable",
-        "//cc/toolchains/actions:cpp_link_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_executable",
-        "//cc/toolchains/actions:lto_index_for_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_nodeps_dynamic_library",
-    ],
+    actions = ["//cc/toolchains/actions:link_actions"],
     nested = [
         ":thinlto_param_file",
         ":libraries_to_link_args",
diff --git a/cc/toolchains/args/linker_param_file/BUILD b/cc/toolchains/args/linker_param_file/BUILD
index 64471dc..6d1b4b2 100644
--- a/cc/toolchains/args/linker_param_file/BUILD
+++ b/cc/toolchains/args/linker_param_file/BUILD
@@ -12,13 +12,8 @@
 cc_args(
     name = "use_param_file",
     actions = [
-        "//cc/toolchains/actions:cpp_link_executable",
-        "//cc/toolchains/actions:cpp_link_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_executable",
-        "//cc/toolchains/actions:lto_index_for_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_nodeps_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_static_library",
+        "//cc/toolchains/actions:link_actions",
+        "//cc/toolchains/actions:ar_actions",
     ],
     args = ["@{param_file}"],
     format = {"param_file": "//cc/toolchains/variables:linker_param_file"},
diff --git a/cc/toolchains/args/runtime_library_search_directories/BUILD b/cc/toolchains/args/runtime_library_search_directories/BUILD
index 2b980bc..50bdb43 100644
--- a/cc/toolchains/args/runtime_library_search_directories/BUILD
+++ b/cc/toolchains/args/runtime_library_search_directories/BUILD
@@ -32,14 +32,7 @@
 
 cc_args(
     name = "runtime_library_search_directories_static_runtimes_args",
-    actions = [
-        "//cc/toolchains/actions:cpp_link_executable",
-        "//cc/toolchains/actions:cpp_link_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_executable",
-        "//cc/toolchains/actions:lto_index_for_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_nodeps_dynamic_library",
-    ],
+    actions = ["//cc/toolchains/actions:link_actions"],
     nested = [":iterate_over_search_dirs"],
     requires_any_of = [":static_link_cpp_runtimes_enabled"],
     requires_not_none = "//cc/toolchains/variables:runtime_library_search_directories",
@@ -90,14 +83,7 @@
 # longer required.
 cc_args(
     name = "runtime_library_search_directories_args",
-    actions = [
-        "//cc/toolchains/actions:cpp_link_executable",
-        "//cc/toolchains/actions:cpp_link_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_executable",
-        "//cc/toolchains/actions:lto_index_for_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_nodeps_dynamic_library",
-    ],
+    actions = ["//cc/toolchains/actions:link_actions"],
     nested = [":search_dir_args"],
     # Remove the requires_any_of here if the workaround for b/27153401 is no
     # longer required.
diff --git a/cc/toolchains/args/shared_flag/BUILD b/cc/toolchains/args/shared_flag/BUILD
index 6a8401a..0c4f1e9 100644
--- a/cc/toolchains/args/shared_flag/BUILD
+++ b/cc/toolchains/args/shared_flag/BUILD
@@ -4,12 +4,7 @@
 
 cc_args(
     name = "shared_flag",
-    actions = [
-        "//cc/toolchains/actions:cpp_link_dynamic_library",
-        "//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_dynamic_library",
-        "//cc/toolchains/actions:lto_index_for_nodeps_dynamic_library",
-    ],
+    actions = ["//cc/toolchains/actions:dynamic_library_link_actions"],
     args = ["-shared"],
     visibility = ["//visibility:public"],
 )
diff --git a/cc/toolchains/args_list.bzl b/cc/toolchains/args_list.bzl
index fbbaad5..0747acb 100644
--- a/cc/toolchains/args_list.bzl
+++ b/cc/toolchains/args_list.bzl
@@ -24,11 +24,49 @@
 
 cc_args_list = rule(
     implementation = _cc_args_list_impl,
-    doc = "A list of cc_args",
+    doc = """An ordered list of cc_args.
+
+    This is a convenience rule to allow you to group a set of multiple `cc_args` into a
+    single list. This particularly useful for toolchain behaviors that require different flags for
+    different actions.
+
+    Note: The order of the arguments in `args` is preserved to support order-sensitive flags.
+
+    Example usage:
+    ```
+    load("//cc/toolchains:cc_args.bzl", "cc_args")
+    load("//cc/toolchains:args_list.bzl", "cc_args_list")
+
+    cc_args(
+        name = "gc_sections",
+        actions = [
+            "//cc/toolchains/actions:link_actions",
+        ],
+        args = ["-Wl,--gc-sections"],
+    )
+
+    cc_args(
+        name = "function_sections",
+        actions = [
+            "//cc/toolchains/actions:compile_actions",
+            "//cc/toolchains/actions:link_actions",
+        ],
+        args = ["-ffunction-sections"],
+    )
+
+    cc_args_list(
+        name = "gc_functions",
+        args = [
+            ":function_sections",
+            ":gc_sections",
+        ],
+    )
+    ```
+    """,
     attrs = {
         "args": attr.label_list(
             providers = [ArgsListInfo],
-            doc = "The cc_args to include",
+            doc = "(ordered) cc_args to include in this list.",
         ),
     },
     provides = [ArgsListInfo],
diff --git a/cc/toolchains/feature.bzl b/cc/toolchains/feature.bzl
index a282762..f0acbfe 100644
--- a/cc/toolchains/feature.bzl
+++ b/cc/toolchains/feature.bzl
@@ -110,22 +110,23 @@
 toolchain, they can happily live alongside each other in the same BUILD file.
 
 Example:
+```
+cc_feature(
+    name = "sysroot_macos",
+    feature_name = "sysroot",
+    ...
+)
 
-    cc_feature(
-        name = "sysroot_macos",
-        feature_name = "sysroot",
-        ...
-    )
-
-    cc_feature(
-        name = "sysroot_linux",
-        feature_name = "sysroot",
-        ...
-    )
+cc_feature(
+    name = "sysroot_linux",
+    feature_name = "sysroot",
+    ...
+)
+```
 """,
         ),
         "args": attr.label_list(
-            doc = """Args that, when expanded, implement this feature.""",
+            doc = """A list of `cc_args` or `cc_args_list` labels that are expanded when this feature is enabled.""",
             providers = [ArgsListInfo],
         ),
         "requires_any_of": attr.label_list(
@@ -152,7 +153,7 @@
         ),
         "mutually_exclusive": attr.label_list(
             providers = [MutuallyExclusiveCategoryInfo],
-            doc = """A list of things that this is mutually exclusive with.
+            doc = """A list of things that this feature is mutually exclusive with.
 
 It can be either:
 * A feature, in which case the two features are mutually exclusive.
@@ -171,14 +172,16 @@
 that the feature "opt" was defined twice.
 
 Example:
+```
+load("//cc/toolchains:feature.bzl", "cc_feature")
 
-    cc_feature(
-      name = "opt",
-      feature_name = "opt",
-      ...
-      overrides = "@toolchain//features/well_known:opt",
-    )
-
+cc_feature(
+    name = "opt",
+    feature_name = "opt",
+    args = [":size_optimized"],
+    overrides = "//cc/toolchains/features:opt",
+)
+```
 """,
         ),
     },
@@ -188,53 +191,58 @@
         FeatureConstraintInfo,
         MutuallyExclusiveCategoryInfo,
     ],
-    doc = """Defines the implemented behavior of a C/C++ toolchain feature.
+    doc = """A dynamic set of toolchain flags that create a singular [feature](https://bazel.build/docs/cc-toolchain-config-reference#features) definition.
 
-A feature is basically a toggleable list of args. There are a variety of
-dependencies and compatibility requirements that must be satisfied for the
-listed args to be applied.
+A feature is basically a dynamically toggleable `cc_args_list`. There are a variety of
+dependencies and compatibility requirements that must be satisfied to enable a
+`cc_feature`. Once those conditions are met, the arguments in [`cc_feature.args`](#cc_feature-args)
+are expanded and added to the command-line.
 
 A feature may be enabled or disabled through the following mechanisms:
-* Via command-line flags, or a `.bazelrc`.
-* Through inter-feature relationships (enabling one feature may implicitly
-  enable another).
-* Individual rules may elect to manually enable or disable features through the
-  builtin `features` attribute.
+* Via command-line flags, or a `.bazelrc` file via the
+  [`--features` flag](https://bazel.build/reference/command-line-reference#flag--features)
+* Through inter-feature relationships (via [`cc_feature.implies`](#cc_feature-implies)) where one
+  feature may implicitly enable another.
+* Individual rules (e.g. `cc_library`) or `package` definitions may elect to manually enable or
+  disable features through the
+  [`features` attribute](https://bazel.build/reference/be/common-definitions#common.features).
 
-Because of the toggleable nature of toolchain features, it's generally best to
-avoid defining features as part of your toolchain with the following exceptions:
-* You want build files to be able to configure compiler flags. For example, a
+Note that a feature may alternate between enabled and disabled dynamically over the course of a
+build. Because of their toggleable nature, it's generally best to avoid adding arguments to a
+`cc_toolchain` as a `cc_feature` unless strictly necessary. Instead, prefer to express arguments
+via [`cc_toolchain.args`](#cc_toolchain-args) whenever possible.
+
+You should use a `cc_feature` when any of the following apply:
+* You need the flags to be dynamically toggled over the course of a build.
+* You want build files to be able to configure the flags in question. For example, a
   binary might specify `features = ["optimize_for_size"]` to create a small
   binary instead of optimizing for performance.
 * You need to carry forward Starlark toolchain behaviors. If you're migrating a
   complex Starlark-based toolchain definition to these rules, many of the
-  workflows and flags were likely based on features. This rule exists to support
-  those existing structures.
+  workflows and flags were likely based on features.
 
-If you want to be able to configure flags via the bazel command-line, instead
-consider making a bool_flag, and then making your `cc_args` `select` on those
-flags.
+If you only need to configure flags via the Bazel command-line, instead
+consider adding a
+[`bool_flag`](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/common_settings_doc.md#bool_flag)
+paired with a [`config_setting`](https://bazel.build/reference/be/general#config_setting)
+and then make your `cc_args` rule `select` on the `config_setting`.
 
 For more details about how Bazel handles features, see the official Bazel
 documentation at
 https://bazel.build/docs/cc-toolchain-config-reference#features.
 
-Examples:
+Example:
+```
+load("//cc/toolchains:feature.bzl", "cc_feature")
 
-    # A feature that can be easily toggled to optimize for size
-    cc_feature(
-        name = "optimize_for_size",
-        feature_name = "optimize_for_size",
-        args = [":optimize_for_size_args"],
-    )
-
-    # This feature signals a capability, and doesn't have associated flags.
-    #
-    # For a list of well-known features, see:
-    #    https://bazel.build/docs/cc-toolchain-config-reference#wellknown-features
-    cc_feature(
-        name = "supports_pic",
-        overrides = "//cc/toolchains/features:supports_pic
-    )
+# A feature that enables LTO, which may be incompatible when doing interop with various
+# languages (e.g. rust, go), or may need to be disabled for particular `cc_binary` rules
+# for various reasons.
+cc_feature(
+    name = "lto",
+    feature_name = "lto",
+    args = [":lto_args"],
+)
+```
 """,
 )
diff --git a/cc/toolchains/feature_constraint.bzl b/cc/toolchains/feature_constraint.bzl
index c6ae44a..8a3d60f 100644
--- a/cc/toolchains/feature_constraint.bzl
+++ b/cc/toolchains/feature_constraint.bzl
@@ -47,8 +47,26 @@
         ),
     },
     provides = [FeatureConstraintInfo],
-    doc = """Defines a constraint on features.
+    doc = """Defines a compound relationship between features.
 
-Can be used with require_any_of to specify that something is only enabled when
-a constraint is met.""",
+This rule can be used with [`cc_args.require_any_of`](#cc_args-require_any_of) to specify that a set
+of arguments are only enabled when a constraint is met. Both `all_of` and `none_of` must be
+satisfied simultaneously.
+
+This is basically a `cc_feature_set` that supports `none_of` expressions. This extra flexibility
+is why this rule may only be used by [`cc_args.require_any_of`](#cc_args-require_any_of).
+
+Example:
+```
+load("//cc/toolchains:feature_constraint.bzl", "cc_feature_constraint")
+
+# A constraint that requires a `linker_supports_thinlto` feature to be enabled,
+# AND a `no_optimization` to be disabled.
+cc_feature_constraint(
+    name = "thinlto_constraint",
+    all_of = [":linker_supports_thinlto"],
+    none_of = [":no_optimization"],
+)
+```
+""",
 )
diff --git a/cc/toolchains/feature_set.bzl b/cc/toolchains/feature_set.bzl
index 07af6d1..5fcdae4 100644
--- a/cc/toolchains/feature_set.bzl
+++ b/cc/toolchains/feature_set.bzl
@@ -44,14 +44,20 @@
     provides = [FeatureSetInfo],
     doc = """Defines a set of features.
 
-Example:
+This may be used by both `cc_feature` and `cc_args` rules, and is effectively a way to express
+a logical `AND` operation across multiple requred features.
 
-    cc_feature_set(
-        name = "thin_lto_requirements",
-        all_of = [
-            ":thin_lto",
-            ":opt",
-        ],
-    )
+Example:
+```
+load("//cc/toolchains:feature_set.bzl", "cc_feature_set")
+
+cc_feature_set(
+    name = "thin_lto_requirements",
+    all_of = [
+        ":thin_lto",
+        ":opt",
+    ],
+)
+```
 """,
 )
diff --git a/cc/toolchains/impl/documented_api.bzl b/cc/toolchains/impl/documented_api.bzl
index d840b7e..a863290 100644
--- a/cc/toolchains/impl/documented_api.bzl
+++ b/cc/toolchains/impl/documented_api.bzl
@@ -13,6 +13,48 @@
 # limitations under the License.
 """This is a list of rules/macros that should be exported as documentation."""
 
+load("//cc/toolchains:actions.bzl", _cc_action_type = "cc_action_type", _cc_action_type_set = "cc_action_type_set")
+load("//cc/toolchains:args.bzl", _cc_args = "cc_args")
+load("//cc/toolchains:args_list.bzl", _cc_args_list = "cc_args_list")
+load("//cc/toolchains:feature.bzl", _cc_feature = "cc_feature")
+load("//cc/toolchains:feature_constraint.bzl", _cc_feature_constraint = "cc_feature_constraint")
+load("//cc/toolchains:feature_set.bzl", _cc_feature_set = "cc_feature_set")
+load("//cc/toolchains:mutually_exclusive_category.bzl", _cc_mutually_exclusive_category = "cc_mutually_exclusive_category")
+load("//cc/toolchains:nested_args.bzl", _cc_nested_args = "cc_nested_args")
+load("//cc/toolchains:tool.bzl", _cc_tool = "cc_tool")
 load("//cc/toolchains:tool_map.bzl", _cc_tool_map = "cc_tool_map")
+load("//cc/toolchains/impl:external_feature.bzl", _cc_external_feature = "cc_external_feature")
+load("//cc/toolchains/impl:variables.bzl", _cc_variable = "cc_variable")
 
 cc_tool_map = _cc_tool_map
+cc_tool = _cc_tool
+cc_args = _cc_args
+cc_nested_args = _cc_nested_args
+cc_args_list = _cc_args_list
+cc_action_type = _cc_action_type
+cc_action_type_set = _cc_action_type_set
+cc_variable = _cc_variable
+cc_feature = _cc_feature
+cc_feature_constraint = _cc_feature_constraint
+cc_feature_set = _cc_feature_set
+cc_mutually_exclusive_category = _cc_mutually_exclusive_category
+cc_external_feature = _cc_external_feature
+
+# This list is used to automatically remap instances of `foo` to [`foo`](#foo)
+# links in the generated documentation so that maintainers don't need to manually
+# ensure every reference to a rule is properly linked.
+DOCUMENTED_TOOLCHAIN_RULES = [
+    "cc_tool_map",
+    "cc_tool",
+    "cc_args",
+    "cc_nested_args",
+    "cc_args_list",
+    "cc_action_type",
+    "cc_action_type_set",
+    "cc_variable",
+    "cc_feature",
+    "cc_feature_constraint",
+    "cc_feature_set",
+    "cc_mutually_exclusive_category",
+    "cc_external_feature",
+]
diff --git a/cc/toolchains/impl/external_feature.bzl b/cc/toolchains/impl/external_feature.bzl
index 1e11bc9..027738f 100644
--- a/cc/toolchains/impl/external_feature.bzl
+++ b/cc/toolchains/impl/external_feature.bzl
@@ -69,5 +69,26 @@
         ),
     },
     provides = [FeatureInfo, FeatureSetInfo, FeatureConstraintInfo],
-    doc = "A declaration that a feature with this name is defined elsewhere.",
+    doc = """A declaration that a [feature](https://bazel.build/docs/cc-toolchain-config-reference#features) with this name is defined elsewhere.
+
+This rule communicates that a feature has been defined externally to make it possible to reference
+features that live outside the rule-based cc toolchain ecosystem. This allows various toolchain
+rules to reference the external feature without accidentally re-defining said feature.
+
+This rule is currently considered a private API of the toolchain rules to encourage the Bazel
+ecosystem to migrate to properly defining their features as rules.
+
+Example:
+```
+load("//cc/toolchains:external_feature.bzl", "cc_external_feature")
+
+# rules_rust defines a feature that is disabled whenever rust artifacts are being linked using
+# the cc toolchain to signal that incompatible flags should be disabled as well.
+cc_external_feature(
+    name = "rules_rust_unsupported_feature",
+    feature_name = "rules_rust_unsupported_feature",
+    overridable = False,
+)
+```
+""",
 )
diff --git a/cc/toolchains/impl/markdown_helpers.bzl b/cc/toolchains/impl/markdown_helpers.bzl
new file mode 100644
index 0000000..1ae401f
--- /dev/null
+++ b/cc/toolchains/impl/markdown_helpers.bzl
@@ -0,0 +1,53 @@
+# Copyright 2024 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.
+"""A few small helpers for working with Markdown."""
+
+def markdown_link(link_text, href):
+    """Creates a markdown link.
+
+    Args:
+      link_text: The text to display for the link.
+      href: The href for the link.
+
+    Returns:
+      A markdown link.
+    """
+    return "[" + link_text + "](" + href + ")"
+
+def xref_substitutions(match_text_patterns):
+    """Creates a dictionary of substitutions for use for linkification of text.
+
+    Example:
+    ```
+    # Produces a dictionary containing:
+    #   {
+    #     "foo": "[foo](http://foo.com)"
+    #     "bar": "[bar](http://bar.com)"
+    #   }
+    substitutions = xref_substitutions({
+        "foo": "http://foo.com",
+        "bar": "http://bar.com",
+    })
+    ```
+
+    Args:
+      match_text_patterns: A dictionary mapping string literals to the links they should point to.
+
+    Returns:
+      A dictionary of string literals mapped to their linkified substitutions.
+    """
+    return {
+        match_text: markdown_link(match_text, href)
+        for match_text, href in match_text_patterns.items()
+    }
diff --git a/cc/toolchains/impl/toolchain_config.bzl b/cc/toolchains/impl/toolchain_config.bzl
index 5c8d69c..da2a873 100644
--- a/cc/toolchains/impl/toolchain_config.bzl
+++ b/cc/toolchains/impl/toolchain_config.bzl
@@ -13,7 +13,6 @@
 # limitations under the License.
 """Implementation of the cc_toolchain rule."""
 
-load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
 load(
     "//cc/toolchains:cc_toolchain_info.bzl",
     "ActionTypeSetInfo",
@@ -52,9 +51,6 @@
     if ctx.attr.features:
         fail("Features is a reserved attribute in bazel. Did you mean 'known_features' or 'enabled_features'?")
 
-    if not ctx.attr._enabled[BuildSettingInfo].value and not ctx.attr.skip_experimental_flag_validation_for_test:
-        fail("Rule based toolchains are experimental. To use it, please add --@rules_cc//cc/toolchains:experimental_enable_rule_based_toolchains to your bazelrc")
-
     toolchain_config = toolchain_config_info(
         label = ctx.label,
         known_features = ctx.attr.known_features + [ctx.attr._builtin_features],
@@ -86,7 +82,7 @@
         ),
         # This allows us to support all_files.
         # If all_files was simply an alias to
-        # ///cc/toolchains/actions:all_actions,
+        # //cc/toolchains/actions:all_actions,
         # then if a toolchain introduced a new type of action, it wouldn't get
         # put in all_files.
         DefaultInfo(files = depset(transitive = toolchain_config.files.values())),
@@ -101,9 +97,7 @@
         "args": attr.label_list(providers = [ArgsListInfo]),
         "known_features": attr.label_list(providers = [FeatureSetInfo]),
         "enabled_features": attr.label_list(providers = [FeatureSetInfo]),
-        "skip_experimental_flag_validation_for_test": attr.bool(default = False),
         "_builtin_features": attr.label(default = "//cc/toolchains/features:all_builtin_features"),
-        "_enabled": attr.label(default = "//cc/toolchains:experimental_enable_rule_based_toolchains"),
     },
     provides = [ToolchainConfigInfo],
 )
diff --git a/cc/toolchains/impl/variables.bzl b/cc/toolchains/impl/variables.bzl
index c2820f3..aac945e 100644
--- a/cc/toolchains/impl/variables.bzl
+++ b/cc/toolchains/impl/variables.bzl
@@ -67,19 +67,32 @@
 )
 
 def cc_variable(name, type, **kwargs):
-    """Defines a variable for both the specified variable, and all nested ones.
+    """Exposes a toolchain variable to use in toolchain argument expansions.
 
-    Eg. cc_variable(
-      name = "foo",
-      type = types.list(types.struct(bar = types.string))
+    This internal rule exposes [toolchain variables](https://bazel.build/docs/cc-toolchain-config-reference#cctoolchainconfiginfo-build-variables)
+    that may be expanded in `cc_args` or `cc_nested_args`
+    rules. Because these varaibles merely expose variables inherrent to Bazel,
+    it's not possible to declare custom variables.
+
+    For a full list of available variables, see
+    [//cc/toolchains/varaibles:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD).
+
+    Example:
+    ```
+    load("//cc/toolchains/impl:variables.bzl", "cc_variable")
+
+    # Defines two targets, ":foo" and ":foo.bar"
+    cc_variable(
+        name = "foo",
+        type = types.list(types.struct(bar = types.string)),
     )
-
-    would define two targets, ":foo" and ":foo.bar"
+    ```
 
     Args:
         name: (str) The name of the outer variable, and the rule.
-        type: The type of the variable, constructed using types above.
-        **kwargs: kwargs to pass to _cc_variable.
+        type: The type of the variable, constructed using `types` factory in
+            [//cc/toolchains/impl:variables.bzl](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/impl/variables.bzl).
+        **kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
     """
     _cc_variable(name = name, type = json.encode(type), **kwargs)
 
diff --git a/cc/toolchains/mutually_exclusive_category.bzl b/cc/toolchains/mutually_exclusive_category.bzl
index 9920290..f83b554 100644
--- a/cc/toolchains/mutually_exclusive_category.bzl
+++ b/cc/toolchains/mutually_exclusive_category.bzl
@@ -23,7 +23,40 @@
 
 cc_mutually_exclusive_category = rule(
     implementation = _cc_mutually_exclusive_category_impl,
-    doc = "A category of features, for which only one can be enabled",
+    doc = """A rule used to categorize `cc_feature` definitions for which only one can be enabled.
+
+This is used by [`cc_feature.mutually_exclusive`](#cc_feature-mutually_exclusive) to express groups
+of `cc_feature` definitions that are inherently incompatible with each other and must be treated as
+mutually exclusive.
+
+Warning: These groups are keyed by name, so two `cc_mutually_exclusive_category` definitions of the
+same name in different packages will resolve to the same logical group.
+
+Example:
+```
+load("//cc/toolchains:feature.bzl", "cc_feature")
+load("//cc/toolchains:mutually_exclusive_category.bzl", "cc_mutually_exclusive_category")
+
+cc_mutually_exclusive_category(
+    name = "opt_level",
+)
+
+cc_feature(
+    name = "speed_optimized",
+    mutually_exclusive = [":opt_level"],
+)
+
+cc_feature(
+    name = "size_optimized",
+    mutually_exclusive = [":opt_level"],
+)
+
+cc_feature(
+    name = "unoptimized",
+    mutually_exclusive = [":opt_level"],
+)
+```
+""",
     attrs = {},
     provides = [MutuallyExclusiveCategoryInfo],
 )
diff --git a/cc/toolchains/nested_args.bzl b/cc/toolchains/nested_args.bzl
index 1d31275..d81dd99 100644
--- a/cc/toolchains/nested_args.bzl
+++ b/cc/toolchains/nested_args.bzl
@@ -41,9 +41,88 @@
 """,
 )
 
-def cc_nested_args(name, format = {}, **kwargs):
+def cc_nested_args(
+        *,
+        name,
+        args = None,
+        data = None,
+        format = {},
+        iterate_over = None,
+        nested = None,
+        requires_not_none = None,
+        requires_none = None,
+        requires_true = None,
+        requires_false = None,
+        requires_equal = None,
+        requires_equal_value = None,
+        **kwargs):
+    """Nested arguments for use in more complex `cc_args` expansions.
+
+    While this rule is very similar in shape to `cc_args`, it is intended to be used as a
+    dependency of `cc_args` to provide additional arguments that should be applied to the
+    same actions as defined by the parent `cc_args` rule. The key motivation for this rule
+    is to allow for more complex variable-based argument expensions.
+
+    Prefer expressing collections of arguments as `cc_args` and
+    `cc_args_list` rules when possible.
+
+    For living examples of how this rule is used, see the usages here:
+        https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args/runtime_library_search_directories/BUILD
+        https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args/libraries_to_link/BUILD
+
+    Note: These examples are non-trivial, but they illustrate when it is absolutely necessary to
+    use this rule.
+
+    Args:
+        name: (str) The name of the target.
+        args: (List[str]) The command-line arguments that are applied by using this rule. This is
+            mutually exclusive with [nested](#cc_nested_args-nested).
+        data: (List[Label]) A list of runtime data dependencies that are required for these
+            arguments to work as intended.
+        format: (Dict[str, Label]) A mapping of format strings to the label of the corresponding
+            `cc_variable` that the value should be pulled from. All instances of
+            `{variable_name}` will be replaced with the expanded value of `variable_name` in this
+            dictionary. The complete list of possible variables can be found in
+            https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD.
+            It is not possible to declare custom variables--these are inherent to Bazel itself.
+        iterate_over: (Label) The label of a `cc_variable` that should be iterated
+            over. This is intended for use with built-in variables that are lists.
+        nested: (List[Label]) A list of `cc_nested_args` rules that should be
+            expanded to command-line arguments when this rule is used. This is mutually exclusive
+            with [args](#cc_nested_args-args).
+        requires_not_none: (Label) The label of a `cc_variable` that should be checked
+            for existence before expanding this rule. If the variable is None, this rule will be
+            ignored.
+        requires_none: (Label) The label of a `cc_variable` that should be checked for
+            non-existence before expanding this rule. If the variable is not None, this rule will be
+            ignored.
+        requires_true: (Label) The label of a `cc_variable` that should be checked for
+            truthiness before expanding this rule. If the variable is false, this rule will be
+            ignored.
+        requires_false: (Label) The label of a `cc_variable` that should be checked
+            for falsiness before expanding this rule. If the variable is true, this rule will be
+            ignored.
+        requires_equal: (Label) The label of a `cc_variable` that should be checked
+            for equality before expanding this rule. If the variable is not equal to
+            (requires_equal_value)[#cc_nested_args-requires_equal_value], this rule will be ignored.
+        requires_equal_value: (str) The value to compare
+            (requires_equal)[#cc_nested_args-requires_equal] against.
+        **kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
+    """
     return _cc_nested_args(
         name = name,
+        args = args,
+        data = data,
+        # We flip the key/value pairs in the dictionary here because Bazel doesn't have a
+        # string-keyed label dict attribute type.
         format = {k: v for v, k in format.items()},
+        iterate_over = iterate_over,
+        nested = nested,
+        requires_not_none = requires_not_none,
+        requires_none = requires_none,
+        requires_true = requires_true,
+        requires_false = requires_false,
+        requires_equal = requires_equal,
+        requires_equal_value = requires_equal_value,
         **kwargs
     )
diff --git a/cc/toolchains/tool.bzl b/cc/toolchains/tool.bzl
index 159a9d6..0dc309d 100644
--- a/cc/toolchains/tool.bzl
+++ b/cc/toolchains/tool.bzl
@@ -66,13 +66,17 @@
             cfg = "exec",
             doc = """The underlying binary that this tool represents.
 
-Usually just a single prebuilt (eg. @sysroot//:bin/clang), but may be any
+Usually just a single prebuilt (eg. @toolchain//:bin/clang), but may be any
 executable label.
 """,
         ),
         "data": attr.label_list(
             allow_files = True,
-            doc = "Additional files that are required for this tool to run.",
+            doc = """Additional files that are required for this tool to run.
+
+Frequently, clang and gcc require additional files to execute as they often shell out to
+other binaries (e.g. `cc1`).
+""",
         ),
         "allowlist_include_directories": attr.label_list(
             providers = [DirectoryInfo],
@@ -82,17 +86,34 @@
 unless flags like `-nostdinc` are provided. Bazel checks that all included
 headers are properly provided by a dependency or allowlisted through this
 mechanism.
+
+As a rule of thumb, only use this if Bazel is complaining about absolute paths in your
+toolchain and you've ensured that the toolchain is compiling with the `-no-canonical-prefixes`
+and/or `-fno-canonical-system-headers` arguments.
+
+This can help work around errors like:
+`the source file 'main.c' includes the following non-builtin files with absolute paths
+(if these are builtin files, make sure these paths are in your toolchain)`.
 """,
         ),
     },
     provides = [ToolInfo],
-    doc = """Declares a tool that can be bound to action configs.
+    doc = """Declares a tool for use by toolchain actions.
 
-A tool is a binary with extra metadata for the action config rule to consume
-(eg. execution_requirements).
+`cc_tool` rules are used in a `cc_tool_map` rule to ensure all files and
+metadata required to run a tool are available when constructing a `cc_toolchain`.
+
+In general, include all files that are always required to run a tool (e.g. libexec/** and
+cross-referenced tools in bin/*) in the [data](#cc_tool-data) attribute. If some files are only
+required when certain flags are passed to the tool, consider using a `cc_args` rule to
+bind the files to the flags that require them. This reduces the overhead required to properly
+enumerate a sandbox with all the files required to run a tool, and ensures that there isn't
+unintentional leakage across configurations and actions.
 
 Example:
 ```
+load("//cc/toolchains:tool.bzl", "cc_tool")
+
 cc_tool(
     name = "clang_tool",
     executable = "@llvm_toolchain//:bin/clang",
diff --git a/cc/toolchains/tool_map.bzl b/cc/toolchains/tool_map.bzl
index 62e94e6..b4f7e35 100644
--- a/cc/toolchains/tool_map.bzl
+++ b/cc/toolchains/tool_map.bzl
@@ -70,11 +70,12 @@
 def cc_tool_map(name, tools, **kwargs):
     """A toolchain configuration rule that maps toolchain actions to tools.
 
-    A cc_tool_map aggregates all the tools that may be used for a given toolchain and maps them to
-    their corresponding actions. Conceptually, this is similar to the `CXX=/path/to/clang++`
-    environment variables that most build systems use to determine which tools to use for a given
-    action. To simplify usage, some actions have been grouped together (for example,
-    //cc/toolchains/actions:cpp_compile_actions) to
+    A `cc_tool_map` aggregates all the tools that may be used for a given toolchain
+    and maps them to their corresponding actions. Conceptually, this is similar to the
+    `CXX=/path/to/clang++` environment variables that most build systems use to determine which
+    tools to use for a given action. To simplify usage, some actions have been grouped together (for
+    example,
+    [//cc/toolchains/actions:cpp_compile_actions](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD)) to
     logically express "all the C++ compile actions".
 
     In Bazel, there is a little more granularity to the mapping, so the mapping doesn't follow the
@@ -106,7 +107,8 @@
 
     Args:
         name: (str) The name of the target.
-        tools: (Dict[target providing ActionTypeSetInfo, Executable target]) A mapping between `cc_action_type` targets
+        tools: (Dict[Label, Label]) A mapping between
+            `cc_action_type`/`cc_action_type_set` targets
             and the `cc_tool` or executable target that implements that action.
         **kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
     """
diff --git a/cc/toolchains/toolchain.bzl b/cc/toolchains/toolchain.bzl
index 8ee15de..ca4b639 100644
--- a/cc/toolchains/toolchain.bzl
+++ b/cc/toolchains/toolchain.bzl
@@ -27,28 +27,28 @@
 #  work out what actions correspond to what file groups.
 _LEGACY_FILE_GROUPS = {
     "ar_files": [
-        "@rules_cc//cc/toolchains/actions:ar_actions",  # copybara-use-repo-external-label
+        Label("//cc/toolchains/actions:ar_actions"),
     ],
     "as_files": [
-        "@rules_cc//cc/toolchains/actions:assembly_actions",  # copybara-use-repo-external-label
+        Label("//cc/toolchains/actions:assembly_actions"),
     ],
     "compiler_files": [
-        "@rules_cc//cc/toolchains/actions:cc_flags_make_variable",  # copybara-use-repo-external-label
-        "@rules_cc//cc/toolchains/actions:c_compile",  # copybara-use-repo-external-label
-        "@rules_cc//cc/toolchains/actions:cpp_compile",  # copybara-use-repo-external-label
-        "@rules_cc//cc/toolchains/actions:cpp_header_parsing",  # copybara-use-repo-external-label
+        Label("//cc/toolchains/actions:cc_flags_make_variable"),
+        Label("//cc/toolchains/actions:c_compile"),
+        Label("//cc/toolchains/actions:cpp_compile"),
+        Label("//cc/toolchains/actions:cpp_header_parsing"),
     ],
     # There are no actions listed for coverage, dwp, and objcopy in action_names.bzl.
     "coverage_files": [],
     "dwp_files": [],
     "linker_files": [
-        "@rules_cc//cc/toolchains/actions:cpp_link_dynamic_library",  # copybara-use-repo-external-label
-        "@rules_cc//cc/toolchains/actions:cpp_link_nodeps_dynamic_library",  # copybara-use-repo-external-label
-        "@rules_cc//cc/toolchains/actions:cpp_link_executable",  # copybara-use-repo-external-label
+        Label("//cc/toolchains/actions:cpp_link_dynamic_library"),
+        Label("//cc/toolchains/actions:cpp_link_nodeps_dynamic_library"),
+        Label("//cc/toolchains/actions:cpp_link_executable"),
     ],
     "objcopy_files": [],
     "strip_files": [
-        "@rules_cc//cc/toolchains/actions:strip",  # copybara-use-repo-external-label
+        Label("//cc/toolchains/actions:strip"),
     ],
 }
 
diff --git a/cc/toolchains/toolchain_api.md b/cc/toolchains/toolchain_api.md
index 3a4a490..418ef52 100644
--- a/cc/toolchains/toolchain_api.md
+++ b/cc/toolchains/toolchain_api.md
@@ -2,6 +2,577 @@
 
 This is a list of rules/macros that should be exported as documentation.
 
+<a id="cc_action_type"></a>
+
+## cc_action_type
+
+<pre>
+cc_action_type(<a href="#cc_action_type-name">name</a>, <a href="#cc_action_type-action_name">action_name</a>)
+</pre>
+
+A type of action (eg. c_compile, assemble, strip).
+
+[`cc_action_type`](#cc_action_type) rules are used to associate arguments and tools together to
+perform a specific action. Bazel prescribes a set of known action types that are used to drive
+typical C/C++/ObjC actions like compiling, linking, and archiving. The set of well-known action
+types can be found in [@rules_cc//cc/toolchains/actions:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD).
+
+It's possible to create project-specific action types for use in toolchains. Be careful when
+doing this, because every toolchain that encounters the action will need to be configured to
+support the custom action type. If your project is a library, avoid creating new action types as
+it will reduce compatibility with existing toolchains and increase setup complexity for users.
+
+Example:
+```
+load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
+load("@rules_cc//cc/toolchains:actions.bzl", "cc_action_type")
+
+cc_action_type(
+    name = "cpp_compile",
+    action_name =  = ACTION_NAMES.cpp_compile,
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_action_type-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_action_type-action_name"></a>action_name |  -   | String | required |  |
+
+
+<a id="cc_action_type_set"></a>
+
+## cc_action_type_set
+
+<pre>
+cc_action_type_set(<a href="#cc_action_type_set-name">name</a>, <a href="#cc_action_type_set-actions">actions</a>, <a href="#cc_action_type_set-allow_empty">allow_empty</a>)
+</pre>
+
+Represents a set of actions.
+
+This is a convenience rule to allow for more compact representation of a group of action types.
+Use this anywhere a [`cc_action_type`](#cc_action_type) is accepted.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:actions.bzl", "cc_action_type_set")
+
+cc_action_type_set(
+    name = "link_executable_actions",
+    actions = [
+        "@rules_cc//cc/toolchains/actions:cpp_link_executable",
+        "@rules_cc//cc/toolchains/actions:lto_index_for_executable",
+    ],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_action_type_set-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_action_type_set-actions"></a>actions |  A list of cc_action_type or cc_action_type_set   | <a href="https://bazel.build/concepts/labels">List of labels</a> | required |  |
+| <a id="cc_action_type_set-allow_empty"></a>allow_empty |  -   | Boolean | optional |  `False`  |
+
+
+<a id="cc_args_list"></a>
+
+## cc_args_list
+
+<pre>
+cc_args_list(<a href="#cc_args_list-name">name</a>, <a href="#cc_args_list-args">args</a>)
+</pre>
+
+An ordered list of cc_args.
+
+This is a convenience rule to allow you to group a set of multiple [`cc_args`](#cc_args) into a
+single list. This particularly useful for toolchain behaviors that require different flags for
+different actions.
+
+Note: The order of the arguments in `args` is preserved to support order-sensitive flags.
+
+Example usage:
+```
+load("@rules_cc//cc/toolchains:cc_args.bzl", "cc_args")
+load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list")
+
+cc_args(
+    name = "gc_sections",
+    actions = [
+        "@rules_cc//cc/toolchains/actions:link_actions",
+    ],
+    args = ["-Wl,--gc-sections"],
+)
+
+cc_args(
+    name = "function_sections",
+    actions = [
+        "@rules_cc//cc/toolchains/actions:compile_actions",
+        "@rules_cc//cc/toolchains/actions:link_actions",
+    ],
+    args = ["-ffunction-sections"],
+)
+
+cc_args_list(
+    name = "gc_functions",
+    args = [
+        ":function_sections",
+        ":gc_sections",
+    ],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_args_list-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_args_list-args"></a>args |  (ordered) cc_args to include in this list.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+
+
+<a id="cc_external_feature"></a>
+
+## cc_external_feature
+
+<pre>
+cc_external_feature(<a href="#cc_external_feature-name">name</a>, <a href="#cc_external_feature-feature_name">feature_name</a>, <a href="#cc_external_feature-overridable">overridable</a>)
+</pre>
+
+A declaration that a [feature](https://bazel.build/docs/cc-toolchain-config-reference#features) with this name is defined elsewhere.
+
+This rule communicates that a feature has been defined externally to make it possible to reference
+features that live outside the rule-based cc toolchain ecosystem. This allows various toolchain
+rules to reference the external feature without accidentally re-defining said feature.
+
+This rule is currently considered a private API of the toolchain rules to encourage the Bazel
+ecosystem to migrate to properly defining their features as rules.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:external_feature.bzl", "cc_external_feature")
+
+# rules_rust defines a feature that is disabled whenever rust artifacts are being linked using
+# the cc toolchain to signal that incompatible flags should be disabled as well.
+cc_external_feature(
+    name = "rules_rust_unsupported_feature",
+    feature_name = "rules_rust_unsupported_feature",
+    overridable = False,
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_external_feature-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_external_feature-feature_name"></a>feature_name |  The name of the feature   | String | required |  |
+| <a id="cc_external_feature-overridable"></a>overridable |  Whether the feature can be overridden   | Boolean | required |  |
+
+
+<a id="cc_feature"></a>
+
+## cc_feature
+
+<pre>
+cc_feature(<a href="#cc_feature-name">name</a>, <a href="#cc_feature-args">args</a>, <a href="#cc_feature-feature_name">feature_name</a>, <a href="#cc_feature-implies">implies</a>, <a href="#cc_feature-mutually_exclusive">mutually_exclusive</a>, <a href="#cc_feature-overrides">overrides</a>, <a href="#cc_feature-requires_any_of">requires_any_of</a>)
+</pre>
+
+A dynamic set of toolchain flags that create a singular [feature](https://bazel.build/docs/cc-toolchain-config-reference#features) definition.
+
+A feature is basically a dynamically toggleable [`cc_args_list`](#cc_args_list). There are a variety of
+dependencies and compatibility requirements that must be satisfied to enable a
+[`cc_feature`](#cc_feature). Once those conditions are met, the arguments in [`cc_feature.args`](#cc_feature-args)
+are expanded and added to the command-line.
+
+A feature may be enabled or disabled through the following mechanisms:
+* Via command-line flags, or a `.bazelrc` file via the
+  [`--features` flag](https://bazel.build/reference/command-line-reference#flag--features)
+* Through inter-feature relationships (via [`cc_feature.implies`](#cc_feature-implies)) where one
+  feature may implicitly enable another.
+* Individual rules (e.g. `cc_library`) or `package` definitions may elect to manually enable or
+  disable features through the
+  [`features` attribute](https://bazel.build/reference/be/common-definitions#common.features).
+
+Note that a feature may alternate between enabled and disabled dynamically over the course of a
+build. Because of their toggleable nature, it's generally best to avoid adding arguments to a
+`cc_toolchain` as a [`cc_feature`](#cc_feature) unless strictly necessary. Instead, prefer to express arguments
+via [`cc_toolchain.args`](#cc_toolchain-args) whenever possible.
+
+You should use a [`cc_feature`](#cc_feature) when any of the following apply:
+* You need the flags to be dynamically toggled over the course of a build.
+* You want build files to be able to configure the flags in question. For example, a
+  binary might specify `features = ["optimize_for_size"]` to create a small
+  binary instead of optimizing for performance.
+* You need to carry forward Starlark toolchain behaviors. If you're migrating a
+  complex Starlark-based toolchain definition to these rules, many of the
+  workflows and flags were likely based on features.
+
+If you only need to configure flags via the Bazel command-line, instead
+consider adding a
+[`bool_flag`](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/common_settings_doc.md#bool_flag)
+paired with a [`config_setting`](https://bazel.build/reference/be/general#config_setting)
+and then make your [`cc_args`](#cc_args) rule `select` on the `config_setting`.
+
+For more details about how Bazel handles features, see the official Bazel
+documentation at
+https://bazel.build/docs/cc-toolchain-config-reference#features.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature")
+
+# A feature that enables LTO, which may be incompatible when doing interop with various
+# languages (e.g. rust, go), or may need to be disabled for particular `cc_binary` rules
+# for various reasons.
+cc_feature(
+    name = "lto",
+    feature_name = "lto",
+    args = [":lto_args"],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_feature-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_feature-args"></a>args |  A list of [`cc_args`](#cc_args) or [`cc_args_list`](#cc_args_list) labels that are expanded when this feature is enabled.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+| <a id="cc_feature-feature_name"></a>feature_name |  The name of the feature that this rule implements.<br><br>The feature name is a string that will be used in the `features` attribute of rules to enable them (eg. `cc_binary(..., features = ["opt"])`.<br><br>While two features with the same `feature_name` may not be bound to the same toolchain, they can happily live alongside each other in the same BUILD file.<br><br>Example: <pre><code>cc_feature(&#10;    name = "sysroot_macos",&#10;    feature_name = "sysroot",&#10;    ...&#10;)&#10;&#10;cc_feature(&#10;    name = "sysroot_linux",&#10;    feature_name = "sysroot",&#10;    ...&#10;)</code></pre>   | String | optional |  `""`  |
+| <a id="cc_feature-implies"></a>implies |  List of features enabled along with this feature.<br><br>Warning: If any of the features cannot be enabled, this feature is silently disabled.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+| <a id="cc_feature-mutually_exclusive"></a>mutually_exclusive |  A list of things that this feature is mutually exclusive with.<br><br>It can be either: * A feature, in which case the two features are mutually exclusive. * A [`cc_mutually_exclusive_category`](#cc_mutually_exclusive_category), in which case all features that write     `mutually_exclusive = [":category"]` are mutually exclusive with each other.<br><br>If this feature has a side-effect of implementing another feature, it can be useful to list that feature here to ensure they aren't enabled at the same time.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+| <a id="cc_feature-overrides"></a>overrides |  A declaration that this feature overrides a known feature.<br><br>In the example below, if you missed the "overrides" attribute, it would complain that the feature "opt" was defined twice.<br><br>Example: <pre><code>load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature")&#10;&#10;cc_feature(&#10;    name = "opt",&#10;    feature_name = "opt",&#10;    args = [":size_optimized"],&#10;    overrides = "@rules_cc//cc/toolchains/features:opt",&#10;)</code></pre>   | <a href="https://bazel.build/concepts/labels">Label</a> | optional |  `None`  |
+| <a id="cc_feature-requires_any_of"></a>requires_any_of |  A list of feature sets that define toolchain compatibility.<br><br>If *at least one* of the listed [`cc_feature_set`](#cc_feature_set)s are fully satisfied (all features exist in the toolchain AND are currently enabled), this feature is deemed compatible and may be enabled.<br><br>Note: Even if `cc_feature.requires_any_of` is satisfied, a feature is not enabled unless another mechanism (e.g. command-line flags, `cc_feature.implies`, `cc_toolchain_config.enabled_features`) signals that the feature should actually be enabled.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+
+
+<a id="cc_feature_constraint"></a>
+
+## cc_feature_constraint
+
+<pre>
+cc_feature_constraint(<a href="#cc_feature_constraint-name">name</a>, <a href="#cc_feature_constraint-all_of">all_of</a>, <a href="#cc_feature_constraint-none_of">none_of</a>)
+</pre>
+
+Defines a compound relationship between features.
+
+This rule can be used with [`cc_args.require_any_of`](#cc_args-require_any_of) to specify that a set
+of arguments are only enabled when a constraint is met. Both `all_of` and `none_of` must be
+satisfied simultaneously.
+
+This is basically a [`cc_feature_set`](#cc_feature_set) that supports `none_of` expressions. This extra flexibility
+is why this rule may only be used by [`cc_args.require_any_of`](#cc_args-require_any_of).
+
+Example:
+```
+load("@rules_cc//cc/toolchains:feature_constraint.bzl", "cc_feature_constraint")
+
+# A constraint that requires a `linker_supports_thinlto` feature to be enabled,
+# AND a `no_optimization` to be disabled.
+cc_feature_constraint(
+    name = "thinlto_constraint",
+    all_of = [":linker_supports_thinlto"],
+    none_of = [":no_optimization"],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_feature_constraint-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_feature_constraint-all_of"></a>all_of |  -   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+| <a id="cc_feature_constraint-none_of"></a>none_of |  -   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+
+
+<a id="cc_feature_set"></a>
+
+## cc_feature_set
+
+<pre>
+cc_feature_set(<a href="#cc_feature_set-name">name</a>, <a href="#cc_feature_set-all_of">all_of</a>)
+</pre>
+
+Defines a set of features.
+
+This may be used by both [`cc_feature`](#cc_feature) and [`cc_args`](#cc_args) rules, and is effectively a way to express
+a logical `AND` operation across multiple requred features.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:feature_set.bzl", "cc_feature_set")
+
+cc_feature_set(
+    name = "thin_lto_requirements",
+    all_of = [
+        ":thin_lto",
+        ":opt",
+    ],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_feature_set-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_feature_set-all_of"></a>all_of |  A set of features   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+
+
+<a id="cc_mutually_exclusive_category"></a>
+
+## cc_mutually_exclusive_category
+
+<pre>
+cc_mutually_exclusive_category(<a href="#cc_mutually_exclusive_category-name">name</a>)
+</pre>
+
+A rule used to categorize [`cc_feature`](#cc_feature) definitions for which only one can be enabled.
+
+This is used by [`cc_feature.mutually_exclusive`](#cc_feature-mutually_exclusive) to express groups
+of [`cc_feature`](#cc_feature) definitions that are inherently incompatible with each other and must be treated as
+mutually exclusive.
+
+Warning: These groups are keyed by name, so two [`cc_mutually_exclusive_category`](#cc_mutually_exclusive_category) definitions of the
+same name in different packages will resolve to the same logical group.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature")
+load("@rules_cc//cc/toolchains:mutually_exclusive_category.bzl", "cc_mutually_exclusive_category")
+
+cc_mutually_exclusive_category(
+    name = "opt_level",
+)
+
+cc_feature(
+    name = "speed_optimized",
+    mutually_exclusive = [":opt_level"],
+)
+
+cc_feature(
+    name = "size_optimized",
+    mutually_exclusive = [":opt_level"],
+)
+
+cc_feature(
+    name = "unoptimized",
+    mutually_exclusive = [":opt_level"],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_mutually_exclusive_category-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+
+
+<a id="cc_tool"></a>
+
+## cc_tool
+
+<pre>
+cc_tool(<a href="#cc_tool-name">name</a>, <a href="#cc_tool-src">src</a>, <a href="#cc_tool-data">data</a>, <a href="#cc_tool-allowlist_include_directories">allowlist_include_directories</a>)
+</pre>
+
+Declares a tool for use by toolchain actions.
+
+[`cc_tool`](#cc_tool) rules are used in a [`cc_tool_map`](#cc_tool_map) rule to ensure all files and
+metadata required to run a tool are available when constructing a `cc_toolchain`.
+
+In general, include all files that are always required to run a tool (e.g. libexec/** and
+cross-referenced tools in bin/*) in the [data](#cc_tool-data) attribute. If some files are only
+required when certain flags are passed to the tool, consider using a [`cc_args`](#cc_args) rule to
+bind the files to the flags that require them. This reduces the overhead required to properly
+enumerate a sandbox with all the files required to run a tool, and ensures that there isn't
+unintentional leakage across configurations and actions.
+
+Example:
+```
+load("@rules_cc//cc/toolchains:tool.bzl", "cc_tool")
+
+cc_tool(
+    name = "clang_tool",
+    executable = "@llvm_toolchain//:bin/clang",
+    # Suppose clang needs libc to run.
+    data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
+    tags = ["requires-network"],
+)
+```
+
+**ATTRIBUTES**
+
+
+| Name  | Description | Type | Mandatory | Default |
+| :------------- | :------------- | :------------- | :------------- | :------------- |
+| <a id="cc_tool-name"></a>name |  A unique name for this target.   | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required |  |
+| <a id="cc_tool-src"></a>src |  The underlying binary that this tool represents.<br><br>Usually just a single prebuilt (eg. @toolchain//:bin/clang), but may be any executable label.   | <a href="https://bazel.build/concepts/labels">Label</a> | optional |  `None`  |
+| <a id="cc_tool-data"></a>data |  Additional files that are required for this tool to run.<br><br>Frequently, clang and gcc require additional files to execute as they often shell out to other binaries (e.g. `cc1`).   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+| <a id="cc_tool-allowlist_include_directories"></a>allowlist_include_directories |  Include paths implied by using this tool.<br><br>Compilers may include a set of built-in headers that are implicitly available unless flags like `-nostdinc` are provided. Bazel checks that all included headers are properly provided by a dependency or allowlisted through this mechanism.<br><br>As a rule of thumb, only use this if Bazel is complaining about absolute paths in your toolchain and you've ensured that the toolchain is compiling with the `-no-canonical-prefixes` and/or `-fno-canonical-system-headers` arguments.<br><br>This can help work around errors like: `the source file 'main.c' includes the following non-builtin files with absolute paths (if these are builtin files, make sure these paths are in your toolchain)`.   | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional |  `[]`  |
+
+
+<a id="cc_args"></a>
+
+## cc_args
+
+<pre>
+cc_args(<a href="#cc_args-name">name</a>, <a href="#cc_args-actions">actions</a>, <a href="#cc_args-allowlist_include_directories">allowlist_include_directories</a>, <a href="#cc_args-args">args</a>, <a href="#cc_args-data">data</a>, <a href="#cc_args-env">env</a>, <a href="#cc_args-format">format</a>, <a href="#cc_args-iterate_over">iterate_over</a>, <a href="#cc_args-nested">nested</a>,
+        <a href="#cc_args-requires_not_none">requires_not_none</a>, <a href="#cc_args-requires_none">requires_none</a>, <a href="#cc_args-requires_true">requires_true</a>, <a href="#cc_args-requires_false">requires_false</a>, <a href="#cc_args-requires_equal">requires_equal</a>,
+        <a href="#cc_args-requires_equal_value">requires_equal_value</a>, <a href="#cc_args-requires_any_of">requires_any_of</a>, <a href="#cc_args-kwargs">kwargs</a>)
+</pre>
+
+Action-specific arguments for use with a cc_toolchain.
+
+This rule is the fundamental building building block for every toolchain tool invocation. Each
+argument expressed in a toolchain tool invocation (e.g. `gcc`, `llvm-ar`) is declared in a
+[`cc_args`](#cc_args) rule that applies an ordered list of arguments to a set of toolchain
+actions. [`cc_args`](#cc_args) rules can be added unconditionally to a
+`cc_toolchain`, conditionally via `select()` statements, or dynamically via an
+intermediate [`cc_feature`](#cc_feature).
+
+Conceptually, this is similar to the old `CFLAGS`, `CPPFLAGS`, etc. environment variables that
+many build systems use to determine which flags to use for a given action. The significant
+difference is that [`cc_args`](#cc_args) rules are declared in a structured way that allows for
+significantly more powerful and sharable toolchain configurations. Also, due to Bazel's more
+granular action types, it's possible to bind flags to very specific actions (e.g. LTO indexing
+for an executable vs a dynamic library) multiple different actions (e.g. C++ compile and link
+simultaneously).
+
+Example usage:
+```
+load("@rules_cc//cc/toolchains:args.bzl", "cc_args")
+
+# Basic usage: a trivial flag.
+#
+# An example of expressing `-Werror` as a [`cc_args`](#cc_args) rule.
+cc_args(
+    name = "warnings_as_errors",
+    actions = [
+        # Applies to all C/C++ compile actions.
+        "@rules_cc//cc/toolchains/actions:compile_actions",
+    ],
+    args = ["-Werror"],
+)
+
+# Basic usage: ordered flags.
+#
+# An example of linking against libc++, which uses two flags that must be applied in order.
+cc_args(
+    name = "link_libcxx",
+    actions = [
+        # Applies to all link actions.
+        "@rules_cc//cc/toolchains/actions:link_actions",
+    ],
+    # On tool invocation, this appears as `-Xlinker -lc++`. Nothing will ever end up between
+    # the two flags.
+    args = [
+        "-Xlinker",
+        "-lc++",
+    ],
+)
+
+# Advanced usage: built-in variable expansions.
+#
+# Expands to `-L/path/to/search_dir` for each directory in the built-in variable
+# `library_search_directories`. This variable is managed internally by Bazel through inherent
+# behaviors of Bazel and the interactions between various C/C++ build rules.
+cc_args(
+    name = "library_search_directories",
+    actions = [
+        "@rules_cc//cc/toolchains/actions:link_actions",
+    ],
+    args = ["-L{search_dir}"],
+    iterate_over = "@rules_cc//cc/toolchains/variables:library_search_directories",
+    requires_not_none = "@rules_cc//cc/toolchains/variables:library_search_directories",
+    format = {
+        "search_dir": "@rules_cc//cc/toolchains/variables:library_search_directories",
+    },
+)
+```
+
+For more extensive examples, see the usages here:
+    https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args
+
+
+**PARAMETERS**
+
+
+| Name  | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="cc_args-name"></a>name |  (str) The name of the target.   |  none |
+| <a id="cc_args-actions"></a>actions |  (List[Label]) A list of labels of [`cc_action_type`](#cc_action_type) or [`cc_action_type_set`](#cc_action_type_set) rules that dictate which actions these arguments should be applied to.   |  `None` |
+| <a id="cc_args-allowlist_include_directories"></a>allowlist_include_directories |  (List[Label]) A list of include paths that are implied by using this rule. These must point to a skylib [directory](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/directory_doc.md#directory) or [subdirectory](https://github.com/bazelbuild/bazel-skylib/tree/main/doc/directory_subdirectory_doc.md#subdirectory) rule. Some flags (e.g. --sysroot) imply certain include paths are available despite not explicitly specifying a normal include path flag (`-I`, `-isystem`, etc.). Bazel checks that all included headers are properly provided by a dependency or allowlisted through this mechanism.<br><br>As a rule of thumb, only use this if Bazel is complaining about absolute paths in your toolchain and you've ensured that the toolchain is compiling with the `-no-canonical-prefixes` and/or `-fno-canonical-system-headers` arguments.<br><br>This can help work around errors like: `the source file 'main.c' includes the following non-builtin files with absolute paths (if these are builtin files, make sure these paths are in your toolchain)`.   |  `None` |
+| <a id="cc_args-args"></a>args |  (List[str]) The command-line arguments that are applied by using this rule. This is mutually exclusive with [nested](#cc_args-nested).   |  `None` |
+| <a id="cc_args-data"></a>data |  (List[Label]) A list of runtime data dependencies that are required for these arguments to work as intended.   |  `None` |
+| <a id="cc_args-env"></a>env |  (Dict[str, str]) Environment variables that should be set when the tool is invoked.   |  `None` |
+| <a id="cc_args-format"></a>format |  (Dict[str, Label]) A mapping of format strings to the label of the corresponding [`cc_variable`](#cc_variable) that the value should be pulled from. All instances of `{variable_name}` will be replaced with the expanded value of `variable_name` in this dictionary. The complete list of possible variables can be found in https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD. It is not possible to declare custom variables--these are inherent to Bazel itself.   |  `{}` |
+| <a id="cc_args-iterate_over"></a>iterate_over |  (Label) The label of a [`cc_variable`](#cc_variable) that should be iterated over. This is intended for use with built-in variables that are lists.   |  `None` |
+| <a id="cc_args-nested"></a>nested |  (List[Label]) A list of [`cc_nested_args`](#cc_nested_args) rules that should be expanded to command-line arguments when this rule is used. This is mutually exclusive with [args](#cc_args-args).   |  `None` |
+| <a id="cc_args-requires_not_none"></a>requires_not_none |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for existence before expanding this rule. If the variable is None, this rule will be ignored.   |  `None` |
+| <a id="cc_args-requires_none"></a>requires_none |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for non-existence before expanding this rule. If the variable is not None, this rule will be ignored.   |  `None` |
+| <a id="cc_args-requires_true"></a>requires_true |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for truthiness before expanding this rule. If the variable is false, this rule will be ignored.   |  `None` |
+| <a id="cc_args-requires_false"></a>requires_false |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for falsiness before expanding this rule. If the variable is true, this rule will be ignored.   |  `None` |
+| <a id="cc_args-requires_equal"></a>requires_equal |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for equality before expanding this rule. If the variable is not equal to (requires_equal_value)[#cc_args-requires_equal_value], this rule will be ignored.   |  `None` |
+| <a id="cc_args-requires_equal_value"></a>requires_equal_value |  (str) The value to compare (requires_equal)[#cc_args-requires_equal] against.   |  `None` |
+| <a id="cc_args-requires_any_of"></a>requires_any_of |  (List[Label]) These arguments will be used in a tool invocation when at least one of the [cc_feature_constraint](#cc_feature_constraint) entries in this list are satisfied. If omitted, this flag set will be enabled unconditionally.   |  `None` |
+| <a id="cc_args-kwargs"></a>kwargs |  [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.   |  none |
+
+
+<a id="cc_nested_args"></a>
+
+## cc_nested_args
+
+<pre>
+cc_nested_args(<a href="#cc_nested_args-name">name</a>, <a href="#cc_nested_args-args">args</a>, <a href="#cc_nested_args-data">data</a>, <a href="#cc_nested_args-format">format</a>, <a href="#cc_nested_args-iterate_over">iterate_over</a>, <a href="#cc_nested_args-nested">nested</a>, <a href="#cc_nested_args-requires_not_none">requires_not_none</a>, <a href="#cc_nested_args-requires_none">requires_none</a>,
+               <a href="#cc_nested_args-requires_true">requires_true</a>, <a href="#cc_nested_args-requires_false">requires_false</a>, <a href="#cc_nested_args-requires_equal">requires_equal</a>, <a href="#cc_nested_args-requires_equal_value">requires_equal_value</a>, <a href="#cc_nested_args-kwargs">kwargs</a>)
+</pre>
+
+Nested arguments for use in more complex [`cc_args`](#cc_args) expansions.
+
+While this rule is very similar in shape to [`cc_args`](#cc_args), it is intended to be used as a
+dependency of [`cc_args`](#cc_args) to provide additional arguments that should be applied to the
+same actions as defined by the parent [`cc_args`](#cc_args) rule. The key motivation for this rule
+is to allow for more complex variable-based argument expensions.
+
+Prefer expressing collections of arguments as [`cc_args`](#cc_args) and
+[`cc_args_list`](#cc_args_list) rules when possible.
+
+For living examples of how this rule is used, see the usages here:
+    https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args/runtime_library_search_directories/BUILD
+    https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/args/libraries_to_link/BUILD
+
+Note: These examples are non-trivial, but they illustrate when it is absolutely necessary to
+use this rule.
+
+
+**PARAMETERS**
+
+
+| Name  | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="cc_nested_args-name"></a>name |  (str) The name of the target.   |  none |
+| <a id="cc_nested_args-args"></a>args |  (List[str]) The command-line arguments that are applied by using this rule. This is mutually exclusive with [nested](#cc_nested_args-nested).   |  `None` |
+| <a id="cc_nested_args-data"></a>data |  (List[Label]) A list of runtime data dependencies that are required for these arguments to work as intended.   |  `None` |
+| <a id="cc_nested_args-format"></a>format |  (Dict[str, Label]) A mapping of format strings to the label of the corresponding [`cc_variable`](#cc_variable) that the value should be pulled from. All instances of `{variable_name}` will be replaced with the expanded value of `variable_name` in this dictionary. The complete list of possible variables can be found in https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD. It is not possible to declare custom variables--these are inherent to Bazel itself.   |  `{}` |
+| <a id="cc_nested_args-iterate_over"></a>iterate_over |  (Label) The label of a [`cc_variable`](#cc_variable) that should be iterated over. This is intended for use with built-in variables that are lists.   |  `None` |
+| <a id="cc_nested_args-nested"></a>nested |  (List[Label]) A list of [`cc_nested_args`](#cc_nested_args) rules that should be expanded to command-line arguments when this rule is used. This is mutually exclusive with [args](#cc_nested_args-args).   |  `None` |
+| <a id="cc_nested_args-requires_not_none"></a>requires_not_none |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for existence before expanding this rule. If the variable is None, this rule will be ignored.   |  `None` |
+| <a id="cc_nested_args-requires_none"></a>requires_none |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for non-existence before expanding this rule. If the variable is not None, this rule will be ignored.   |  `None` |
+| <a id="cc_nested_args-requires_true"></a>requires_true |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for truthiness before expanding this rule. If the variable is false, this rule will be ignored.   |  `None` |
+| <a id="cc_nested_args-requires_false"></a>requires_false |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for falsiness before expanding this rule. If the variable is true, this rule will be ignored.   |  `None` |
+| <a id="cc_nested_args-requires_equal"></a>requires_equal |  (Label) The label of a [`cc_variable`](#cc_variable) that should be checked for equality before expanding this rule. If the variable is not equal to (requires_equal_value)[#cc_nested_args-requires_equal_value], this rule will be ignored.   |  `None` |
+| <a id="cc_nested_args-requires_equal_value"></a>requires_equal_value |  (str) The value to compare (requires_equal)[#cc_nested_args-requires_equal] against.   |  `None` |
+| <a id="cc_nested_args-kwargs"></a>kwargs |  [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.   |  none |
+
+
 <a id="cc_tool_map"></a>
 
 ## cc_tool_map
@@ -12,31 +583,32 @@
 
 A toolchain configuration rule that maps toolchain actions to tools.
 
-A cc_tool_map aggregates all the tools that may be used for a given toolchain and maps them to
-their corresponding actions. Conceptually, this is similar to the `CXX=/path/to/clang++`
-environment variables that most build systems use to determine which tools to use for a given
-action. To simplify usage, some actions have been grouped together (for example,
-//third_party/bazel_rules/rules_cc/cc/toolchains/actions:cpp_compile_actions) to
+A [`cc_tool_map`](#cc_tool_map) aggregates all the tools that may be used for a given toolchain
+and maps them to their corresponding actions. Conceptually, this is similar to the
+`CXX=/path/to/clang++` environment variables that most build systems use to determine which
+tools to use for a given action. To simplify usage, some actions have been grouped together (for
+example,
+[@rules_cc//cc/toolchains/actions:cpp_compile_actions](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD)) to
 logically express "all the C++ compile actions".
 
 In Bazel, there is a little more granularity to the mapping, so the mapping doesn't follow the
 traditional `CXX`, `AR`, etc. naming scheme. For a comprehensive list of all the well-known
-actions, see //third_party/bazel_rules/rules_cc/cc/toolchains/actions:BUILD.
+actions, see @rules_cc//cc/toolchains/actions:BUILD.
 
 Example usage:
 ```
-load("//third_party/bazel_rules/rules_cc/cc/toolchains:tool_map.bzl", "cc_tool_map")
+load("@rules_cc//cc/toolchains:tool_map.bzl", "cc_tool_map")
 
 cc_tool_map(
     name = "all_tools",
     tools = {
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:assembly_actions": ":asm",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:c_compile": ":clang",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:cpp_compile_actions": ":clang++",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:link_actions": ":lld",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:objcopy_embed_data": ":llvm-objcopy",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:strip": ":llvm-strip",
-        "//third_party/bazel_rules/rules_cc/cc/toolchains/actions:ar_actions": ":llvm-ar",
+        "@rules_cc//cc/toolchains/actions:assembly_actions": ":asm",
+        "@rules_cc//cc/toolchains/actions:c_compile": ":clang",
+        "@rules_cc//cc/toolchains/actions:cpp_compile_actions": ":clang++",
+        "@rules_cc//cc/toolchains/actions:link_actions": ":lld",
+        "@rules_cc//cc/toolchains/actions:objcopy_embed_data": ":llvm-objcopy",
+        "@rules_cc//cc/toolchains/actions:strip": ":llvm-strip",
+        "@rules_cc//cc/toolchains/actions:ar_actions": ":llvm-ar",
     },
 )
 ```
@@ -53,7 +625,47 @@
 | Name  | Description | Default Value |
 | :------------- | :------------- | :------------- |
 | <a id="cc_tool_map-name"></a>name |  (str) The name of the target.   |  none |
-| <a id="cc_tool_map-tools"></a>tools |  (Dict[target providing ActionTypeSetInfo, Executable target]) A mapping between `cc_action_type` targets and the `cc_tool` or executable target that implements that action.   |  none |
+| <a id="cc_tool_map-tools"></a>tools |  (Dict[Label, Label]) A mapping between [`cc_action_type`](#cc_action_type)/[`cc_action_type_set`](#cc_action_type_set) targets and the [`cc_tool`](#cc_tool) or executable target that implements that action.   |  none |
 | <a id="cc_tool_map-kwargs"></a>kwargs |  [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.   |  none |
 
 
+<a id="cc_variable"></a>
+
+## cc_variable
+
+<pre>
+cc_variable(<a href="#cc_variable-name">name</a>, <a href="#cc_variable-type">type</a>, <a href="#cc_variable-kwargs">kwargs</a>)
+</pre>
+
+Exposes a toolchain variable to use in toolchain argument expansions.
+
+This internal rule exposes [toolchain variables](https://bazel.build/docs/cc-toolchain-config-reference#cctoolchainconfiginfo-build-variables)
+that may be expanded in [`cc_args`](#cc_args) or [`cc_nested_args`](#cc_nested_args)
+rules. Because these varaibles merely expose variables inherrent to Bazel,
+it's not possible to declare custom variables.
+
+For a full list of available variables, see
+[@rules_cc//cc/toolchains/varaibles:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD).
+
+Example:
+```
+load("@rules_cc//cc/toolchains/impl:variables.bzl", "cc_variable")
+
+# Defines two targets, ":foo" and ":foo.bar"
+cc_variable(
+    name = "foo",
+    type = types.list(types.struct(bar = types.string)),
+)
+```
+
+
+**PARAMETERS**
+
+
+| Name  | Description | Default Value |
+| :------------- | :------------- | :------------- |
+| <a id="cc_variable-name"></a>name |  (str) The name of the outer variable, and the rule.   |  none |
+| <a id="cc_variable-type"></a>type |  The type of the variable, constructed using `types` factory in [@rules_cc//cc/toolchains/impl:variables.bzl](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/impl/variables.bzl).   |  none |
+| <a id="cc_variable-kwargs"></a>kwargs |  [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.   |  none |
+
+
diff --git a/tests/rule_based_toolchain/toolchain_config/BUILD b/tests/rule_based_toolchain/toolchain_config/BUILD
index 981758e..b002eff 100644
--- a/tests/rule_based_toolchain/toolchain_config/BUILD
+++ b/tests/rule_based_toolchain/toolchain_config/BUILD
@@ -63,7 +63,6 @@
     ],
     enabled_features = [":simple_feature"],
     known_features = [":compile_feature"],
-    skip_experimental_flag_validation_for_test = True,
     tool_map = ":compile_tool_map",
 )