Skip to content

Commit 48b5276

Browse files
authored
Initial rules_toolchain implementation (#9)
1 parent 55698b5 commit 48b5276

File tree

111 files changed

+5756
-773
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+5756
-773
lines changed

.bazelrc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ common --check_direct_dependencies=off
2020
try-import %workspace%/.bazelrc.user
2121

2222
# Stardoc fails without this flag set.
23-
common --noincompatible_disallow_empty_glob
23+
common --noincompatible_disallow_empty_glob
24+
25+
common --experimental_platforms_api
26+
27+
build --host_platform=@rules_toolchains//tests/platforms:host_platform
28+
build --platforms=@rules_toolchains//tests/platforms:target_platform1

.bcr/presubmit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
bcr_test_module:
2-
module_path: "examples/rules_lang"
2+
module_path: "."
33
matrix:
44
platform: ["debian10", "macos", "ubuntu2004", "windows"]
55
bazel: ["8.x", "7.x"]

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
exclude: |
2929
[
3030
{"folder": ".", "bzlmodEnabled": false}
31+
{"folder": "examples/rules_lang", "bzlmodEnabled": false}
3132
]
3233
pre-commit:
3334
runs-on: ubuntu-latest

BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")
22

3+
package(default_visibility = ["//visibility:public"])
4+
35
gazelle_binary(
46
name = "gazelle_bin",
57
languages = ["@bazel_skylib_gazelle_plugin//bzl"],
@@ -9,3 +11,7 @@ gazelle(
911
name = "gazelle",
1012
gazelle = "gazelle_bin",
1113
)
14+
15+
licenses(["notice"])
16+
17+
exports_files(["LICENSE"])

MODULE.bazel

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
module(
22
name = "rules_toolchains",
3-
version = "0.0.0",
43
compatibility_level = 1,
54
)
65

7-
bazel_dep(name = "bazel_skylib", version = "1.4.1")
8-
bazel_dep(name = "platforms", version = "0.0.5")
6+
bazel_dep(name = "bazel_skylib", version = "1.7.1")
7+
bazel_dep(name = "platforms", version = "0.0.10")
8+
bazel_dep(name = "rules_python", version = "1.3.0")
99

10+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
1011
bazel_dep(name = "gazelle", version = "0.35.0", dev_dependency = True, repo_name = "bazel_gazelle")
1112
bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.4.1", dev_dependency = True)
12-
bazel_dep(name = "aspect_bazel_lib", version = "1.32.1", dev_dependency = True)
13+
bazel_dep(name = "aspect_bazel_lib", version = "2.10.0", dev_dependency = True)
1314
bazel_dep(name = "buildifier_prebuilt", version = "6.1.2", dev_dependency = True)
15+
16+
register_toolchains(
17+
"//tests/toolchain:all",
18+
dev_dependency = True,
19+
)

MODULE.bazel.lock

Lines changed: 446 additions & 314 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
1-
# Template for Bazel rules
1+
# Toolchain rules for bazel
22

3-
Copy this template to create a Bazel ruleset.
3+
This repository contains rules for configuring toolchains. It is designed to be integrated with rulesets to allow a ruleset to specify what they _want_ an action to do, and have the configuration decide how to achieve that. For example, a ruleset author would specify `run_action(action_type=compile, variables = struct(header_files = [foo.h], source_files = [foo.cc], output = [foo.o]), inputs=[foo.cc, foo.h], outputs = [foo.o])`, and the configuration would turn that into the command-line `clang++ foo.cc foo.h -o foo.o`.
44

5-
Features:
5+
# Getting Started
66

7-
- follows the official style guide at https://bazel.build/rules/deploying
8-
- allows for both WORKSPACE.bazel and bzlmod (MODULE.bazel) usage
9-
- includes Bazel formatting as a pre-commit hook (using [buildifier])
10-
- includes stardoc API documentation generator
11-
- includes typical toolchain setup
12-
- CI configured with GitHub Actions
13-
- release using GitHub Actions just by pushing a tag
14-
- the release artifact doesn't need to be built by Bazel, but can still exclude files and stamp the version
7+
Add the following to your `MODULE.bazel` file:
158

16-
# Bazel rules for toolchains
9+
```starlark
10+
bazel_dep(name = "rules_testing", version = "<version>")
11+
```
1712

18-
## Installation
13+
## For ruleset authors
1914

20-
From the release you wish to use:
21-
<https://github.com/matts1/rules_toolchains/releases>
22-
copy the WORKSPACE snippet into your `WORKSPACE` file.
15+
Look at `examples/rules_lang`. You will first need to configure your toolchain to take in a `ToolchainConfig` parameter.
2316

24-
To use a commit rather than a release, you can point at any SHA of the repo.
17+
Once you've done that, you'll need to configure your rule to, instead of calling `ctx.actions.run`, call `run_action` (see [`examples/rules_lang/lang/defs.bzl`](examples/rules_lang/lang/defs.bzl)).
2518

26-
For example to use commit `abc123`:
19+
## For toolchain authors
2720

28-
1. Replace `url = "https://github.com/matts1/rules_toolchains/releases/download/v0.1.0/rules_toolchains-v0.1.0.tar.gz"` with a GitHub-provided source archive like `url = "https://github.com/matts1/rules_toolchains/archive/abc123.tar.gz"`
29-
1. Replace `strip_prefix = "rules_toolchains-0.1.0"` with `strip_prefix = "rules_toolchains-abc123"`
30-
1. Update the `sha256`. The easiest way to do this is to comment out the line, then Bazel will
31-
print a message with the correct value. Note that GitHub source archives don't have a strong
32-
guarantee on the sha256 stability, see
33-
<https://github.blog/2023-02-21-update-on-the-future-stability-of-source-code-archives-and-hashes/>
21+
Either use the default toolchain configured by your ruleset author, or create a custom `toolchain_config` rule.
22+
23+
# Testing
24+
25+
`rules_toolchains` supports generating "input files". These files contain a full specification of generated actions, and can be used to validate that your toolchain configuration works as intended with golden tests. For an example of how this works, see `@rules_toolchain//tests`.
26+
27+
# Contributing
28+
29+
We appreciate your help!
30+
31+
To contribute, please read the contribution guidelines: [CONTRIBUTING.md](https://github.com/matts1/rules_toolchains/blob/main/CONTRIBUTING.md).

debug/BUILD.bazel

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2025 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
load("@rules_python//python:defs.bzl", "py_binary")
16+
17+
py_binary(
18+
name = "generate_inputs_file",
19+
srcs = ["generate_inputs_file.py"],
20+
visibility = ["//visibility:public"],
21+
)

debug/generate_inputs_file.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""Generates a file containing a specification of an action that was run.
2+
3+
The file will contain information such as:
4+
* The features in use
5+
* The args in use
6+
* Which command-line entries are generated by which args
7+
* Environment variables
8+
* Input files
9+
"""
10+
11+
import itertools
12+
import json
13+
import os
14+
import re
15+
import sys
16+
17+
def format_dict(d):
18+
return "\n".join(f" {k}={repr(v)}" for k, v in sorted(d.items()))
19+
20+
output_file = sys.argv[1]
21+
args = sys.argv[2:]
22+
arg_groups = []
23+
for arg in sys.argv[2:]:
24+
if arg == "ARG_SPLITTER":
25+
arg_groups.append([])
26+
else:
27+
arg_groups[-1].append(arg)
28+
29+
arg_labels = [label for label in os.environ["ARGS"].split("\n") if label]
30+
31+
assert len(arg_groups) >= len(arg_labels), (sys.argv, arg_groups, arg_labels)
32+
args_by_label = itertools.zip_longest(arg_labels, arg_groups, fillvalue="Extra action args:")
33+
34+
35+
action = os.environ["ACTION"]
36+
env = json.loads(os.environ["ENV"])
37+
features = os.environ["FEATURES"]
38+
outputs = os.environ["OUTPUTS"]
39+
progress_message = os.environ["PROGRESS_MESSAGE"]
40+
tool = os.environ["TOOL"]
41+
tool_exe = os.environ["TOOL_EXE"]
42+
execution_requirements = json.loads(os.environ["EXECUTION_REQUIREMENTS"])
43+
44+
inputs = []
45+
for dirpath, _, filenames in os.walk("."):
46+
for filename in filenames:
47+
inputs.append(f"{dirpath[2:]}/{filename}")
48+
49+
inputs = sorted([
50+
path for path in inputs if "generate_inputs_file" not in path
51+
])
52+
53+
content = [
54+
f"Action: {action}",
55+
f"Tool: {tool} ({tool_exe})",
56+
f"Progress message: {repr(progress_message)}",
57+
"\nInputs:\n{}".format("\n".join(inputs)),
58+
f"\nOutputs:\n{outputs}\n",
59+
f"Features:\n{features}\n",
60+
f"Execution requirements:\n{format_dict(execution_requirements)}\n",
61+
f"Env:\n{format_dict(env)}\n",
62+
"Command-line:",
63+
]
64+
for arg, group in args_by_label:
65+
content.append(arg)
66+
for entry in group:
67+
content.append(f" {entry}")
68+
69+
with open(output_file, 'w') as f:
70+
f.write(re.sub("bazel-out/[^/]*", "bazel-out/<config>", "\n".join(content)))

docs/BUILD.bazel

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,68 @@
33
load("@aspect_bazel_lib//lib:docs.bzl", "stardoc_with_diff_test", "update_docs")
44

55
stardoc_with_diff_test(
6-
name = "rules",
7-
bzl_library_target = "//toolchains:defs",
6+
name = "args",
7+
bzl_library_target = "//toolchains:args",
8+
)
9+
10+
stardoc_with_diff_test(
11+
name = "args_list",
12+
bzl_library_target = "//toolchains:args_list",
13+
)
14+
15+
stardoc_with_diff_test(
16+
name = "feature",
17+
bzl_library_target = "//toolchains:feature",
18+
)
19+
20+
stardoc_with_diff_test(
21+
name = "feature_constraint",
22+
bzl_library_target = "//toolchains:feature_set",
23+
)
24+
25+
stardoc_with_diff_test(
26+
name = "feature_set",
27+
bzl_library_target = "//toolchains:feature_set",
28+
)
29+
30+
stardoc_with_diff_test(
31+
name = "generic_rule",
32+
bzl_library_target = "//toolchains:generic_rule",
33+
)
34+
35+
stardoc_with_diff_test(
36+
name = "mutually_exclusive_category",
37+
bzl_library_target = "//toolchains:mutually_exclusive_category",
38+
)
39+
40+
stardoc_with_diff_test(
41+
name = "tool",
42+
bzl_library_target = "//toolchains:tool",
43+
)
44+
45+
stardoc_with_diff_test(
46+
name = "tool_capability",
47+
bzl_library_target = "//toolchains:tool_capability",
48+
)
49+
50+
stardoc_with_diff_test(
51+
name = "tool_map",
52+
bzl_library_target = "//toolchains:tool_map",
53+
)
54+
55+
stardoc_with_diff_test(
56+
name = "toolchain",
57+
bzl_library_target = "//toolchains:toolchain",
58+
)
59+
60+
stardoc_with_diff_test(
61+
name = "toolchain_info",
62+
bzl_library_target = "//toolchains:toolchain_info",
63+
)
64+
65+
stardoc_with_diff_test(
66+
name = "variables",
67+
bzl_library_target = "//toolchains:variables",
868
)
969

1070
update_docs(name = "update")

0 commit comments

Comments
 (0)