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( name = "sysroot_macos", feature_name = "sysroot", ... ) cc_feature( name = "sysroot_linux", feature_name = "sysroot", ... )</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") cc_feature( name = "opt", feature_name = "opt", args = [":size_optimized"], overrides = "@rules_cc//cc/toolchains/features:opt", )</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",
)