Skip to content

Commit

Permalink
[rule-based toolchains] Add rules to define artifact_name_pattern
Browse files Browse the repository at this point in the history
Required to override Bazel's (Linux) defaults for macOS and Windows toolchains.
  • Loading branch information
Yannic committed Feb 7, 2025
1 parent a116227 commit 846c1fc
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 2 deletions.
103 changes: 103 additions & 0 deletions cc/toolchains/artifacts.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright 2025 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.

"""Rules to turn artifact categories into targets."""

load(":cc_toolchain_info.bzl", "ArtifactCategoryInfo", "ArtifactNamePatternInfo")

visibility("public")

def _cc_artifact_category_impl(ctx):
return [
ArtifactCategoryInfo(
label = ctx.label,
name = ctx.attr.name,
),
]

cc_artifact_category = rule(
implementation = _cc_artifact_category_impl,
doc = """
An artifact category (eg. static_library, executable, object_file).
Example:
```
load("//cc/toolchains:artifacts.bzl", "cc_artifact_category")
cc_artifact_category(
name = "static_library",
)
```
""",
provides = [
ArtifactCategoryInfo,
],
)

def _cc_artifact_name_pattern_impl(ctx):
return [
ArtifactNamePatternInfo(
label = ctx.label,
category = ctx.attr.category[ArtifactCategoryInfo],
prefix = ctx.attr.prefix,
extension = ctx.attr.extension,
),
]

cc_artifact_name_pattern = rule(
implementation = _cc_artifact_name_pattern_impl,
attrs = {
"category": attr.label(
mandatory = True,
providers = [
ArtifactCategoryInfo,
],
),
"prefix": attr.string(
mandatory = True,
),
"extension": attr.string(
mandatory = True,
),
},
doc = """
The name for an artifact of a given category of input or output artifacts to an
action.
This is used to declare that executables should follow `<name>.exe` on Windows,
or shared libraries should follow `lib<name>.dylib` on macOS.
Example:
```
load("//cc/toolchains:artifacts.bzl", "cc_artifact_name_pattern")
cc_artifact_name_pattern(
name = "static_library",
category = "//cc/toolchains/artifacts:static_library",
prefix = "lib",
extension = ".a",
)
cc_artifact_name_pattern(
name = "executable",
category = "//cc/toolchains/artifacts:executable",
prefix = "",
extension = "",
)
```
""",
provides = [
ArtifactNamePatternInfo,
],
)
137 changes: 137 additions & 0 deletions cc/toolchains/artifacts/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Copyright 2025 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.

# Derived from @bazel//src/main/starlark/builtins_bzl/common/cc:cc_helper_internal.bzl

load("//cc/toolchains:artifacts.bzl", "cc_artifact_category")

cc_artifact_category(
name = "alwayslink_static_library",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "clif_output_proto",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "coverage_data_file",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_module",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_module_gcm",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_module_ifc",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_modules_ddi",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_modules_info",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_modules_modmap",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "cpp_modules_modmap_input",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "dynamic_library",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "executable",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "generated_assembly",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "generated_header",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "included_file_list",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "interface_library",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "object_file",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "pic_file",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "pic_object_file",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "preprocessed_c_source",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "preprocessed_cpp_source",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "processed_header",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "serialized_diagnostics_file",
visibility = ["//visibility:public"],
)

cc_artifact_category(
name = "static_library",
visibility = ["//visibility:public"],
)
21 changes: 21 additions & 0 deletions cc/toolchains/cc_toolchain_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ ActionTypeSetInfo = provider(
},
)

ArtifactCategoryInfo = provider(
doc = "A category of artifacts (eg. static_library, executable, object_file)",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"name": "(str) The name of the artifact category, as defined by Bazel",
},
)

ArtifactNamePatternInfo = provider(
doc = "A name pattern for artifacts",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"category": "(ArtifactCategoryInfo) The artifact category this pattern is for",
"prefix": "(str) The prefix for creating the artifact",
"extension": "(str) The extension for creating the artifact",
},
)

VariableInfo = provider(
"""A variable defined by the toolchain""",
# @unsorted-dict-items
Expand Down Expand Up @@ -187,6 +207,7 @@ ToolchainConfigInfo = provider(
"enabled_features": "(Sequence[FeatureInfo]) The features That are enabled by default for this toolchain",
"tool_map": "(ToolConfigInfo) A provider mapping toolchain action types to tools.",
"args": "(Sequence[ArgsInfo]) A list of arguments to be unconditionally applied to the toolchain.",
"artifact_name_patterns": "Sequence[ArtifactNamePatternInfo] A artifact name patterns for this toolchain",
"files": "(dict[ActionTypeInfo, depset[File]]) Files required for the toolchain, keyed by the action type.",
"allowlist_include_directories": "(depset[DirectoryInfo]) Built-in include directories implied by this toolchain's args and tools that should be allowlisted in Bazel's include checker",
},
Expand Down
11 changes: 11 additions & 0 deletions cc/toolchains/impl/legacy_converter.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
load(
"//cc:cc_toolchain_config_lib.bzl",
legacy_action_config = "action_config",
legacy_artifact_name_pattern = "artifact_name_pattern",
legacy_env_entry = "env_entry",
legacy_env_set = "env_set",
legacy_feature = "feature",
Expand Down Expand Up @@ -201,8 +202,18 @@ def convert_toolchain(toolchain):
for d in toolchain.allowlist_include_directories.to_list()
]

artifact_name_patterns = [
legacy_artifact_name_pattern(
category_name = p.category.name,
prefix = p.prefix,
extension = p.extension,
)
for p in toolchain.artifact_name_patterns
]

return struct(
features = [ft for ft in features if ft != None],
action_configs = sorted(action_configs, key = lambda ac: ac.action_name),
cxx_builtin_include_directories = cxx_builtin_include_directories,
artifact_name_patterns = artifact_name_patterns,
)
4 changes: 4 additions & 0 deletions cc/toolchains/impl/toolchain_config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ load(
"//cc/toolchains:cc_toolchain_info.bzl",
"ActionTypeSetInfo",
"ArgsListInfo",
"ArtifactNamePatternInfo",
"FeatureSetInfo",
"ToolConfigInfo",
"ToolchainConfigInfo",
Expand Down Expand Up @@ -58,6 +59,7 @@ def _cc_toolchain_config_impl(ctx):
enabled_features = ctx.attr.enabled_features,
tool_map = ctx.attr.tool_map,
args = ctx.attr.args,
artifact_name_patterns = ctx.attr.artifact_name_patterns,
)

legacy = convert_toolchain(toolchain_config)
Expand All @@ -67,6 +69,7 @@ def _cc_toolchain_config_impl(ctx):
cc_common.create_cc_toolchain_config_info(
ctx = ctx,
action_configs = legacy.action_configs,
artifact_name_patterns = legacy.artifact_name_patterns,
features = legacy.features,
cxx_builtin_include_directories = legacy.cxx_builtin_include_directories,
# toolchain_identifier is deprecated, but setting it to None results
Expand Down Expand Up @@ -102,6 +105,7 @@ cc_toolchain_config = rule(
"args": attr.label_list(providers = [ArgsListInfo]),
"known_features": attr.label_list(providers = [FeatureSetInfo]),
"enabled_features": attr.label_list(providers = [FeatureSetInfo]),
"artifact_name_patterns": attr.label_list(providers = [ArtifactNamePatternInfo]),
"_builtin_features": attr.label(default = "//cc/toolchains/features:all_builtin_features"),
},
provides = [ToolchainConfigInfo],
Expand Down
6 changes: 4 additions & 2 deletions cc/toolchains/impl/toolchain_config_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.
"""Helper functions to create and validate a ToolchainConfigInfo."""

load("//cc/toolchains:cc_toolchain_info.bzl", "ToolConfigInfo", "ToolchainConfigInfo")
load("//cc/toolchains:cc_toolchain_info.bzl", "ArtifactNamePatternInfo", "ToolConfigInfo", "ToolchainConfigInfo")
load(":args_utils.bzl", "get_action_type")
load(":collect.bzl", "collect_args_lists", "collect_features")

Expand Down Expand Up @@ -130,7 +130,7 @@ def _collect_files_for_action_type(action_type, tool_map, features, args):

return depset(transitive = transitive_files)

def toolchain_config_info(label, known_features = [], enabled_features = [], args = [], tool_map = None, fail = fail):
def toolchain_config_info(label, known_features = [], enabled_features = [], args = [], artifact_name_patterns = [], tool_map = None, fail = fail):
"""Generates and validates a ToolchainConfigInfo from lists of labels.
Args:
Expand All @@ -139,6 +139,7 @@ def toolchain_config_info(label, known_features = [], enabled_features = [], arg
enabled_features: (List[Target]) A list of features that are enabled by
default. Every enabled feature is implicitly also a known feature.
args: (List[Target]) A list of targets providing ArgsListInfo
artifact_name_patterns: (List[Target]) A list of targets providing ArtifactNamePatternInfo.
tool_map: (Target) A target providing ToolMapInfo.
fail: A fail function. Use only during tests.
Returns:
Expand Down Expand Up @@ -179,6 +180,7 @@ def toolchain_config_info(label, known_features = [], enabled_features = [], arg
args = args,
files = files,
allowlist_include_directories = allowlist_include_directories,
artifact_name_patterns = [t[ArtifactNamePatternInfo] for t in artifact_name_patterns],
)
_validate_toolchain(toolchain_config, fail = fail)
return toolchain_config
1 change: 1 addition & 0 deletions tests/rule_based_toolchain/subjects.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ _ToolchainConfigFactory = generate_factory(
args = ProviderSequence(_ArgsFactory),
files = dict_key_subject(_subjects.depset_file),
allowlist_include_directories = _FakeDirectoryDepset,
artifact_name_patterns = [],
),
)

Expand Down

0 comments on commit 846c1fc

Please sign in to comment.