From 251dde9c45a4fd3d0fbb32cac4c884a412920fd0 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Wed, 15 Nov 2023 16:03:54 +0000 Subject: [PATCH 1/3] chore: add editor configuration --- .editorconfig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7043786 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +max_line_length = 120 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.py] +indent_size = 4 +tab_size = 4 +max_line_length = 88 -- GitLab From 7e3b58635c7c375269e1643195f0a829ec59dcf1 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Wed, 15 Nov 2023 17:46:10 +0000 Subject: [PATCH 2/3] fix: correct executable permissions of repository files The default is to set files as executable in repository rules. We often do not want that. --- MODULE.bazel.lock | 2 +- e2e/MODULE.bazel.lock | 4 ++-- e2e/test/fixture/repository.bzl | 2 +- toolchain/local/triplet/repository.bzl | 2 +- toolchain/local/which/repository.bzl | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index ecbd999..38543fa 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -656,7 +656,7 @@ "moduleExtensions": { "//:MODULE.bazel%_repo_rules": { "general": { - "bzlTransitiveDigest": "mvwjHUR6LfdJXlUKr5URiiM5nIkorGaL+UsIyVuakBw=", + "bzlTransitiveDigest": "VGGV2/aS8KP0wlEaxXfdomUzHtZ4Ry+aV/L2Ktp3UCo=", "accumulatedFileDigests": {}, "envVariables": {}, "generatedRepoSpecs": { diff --git a/e2e/MODULE.bazel.lock b/e2e/MODULE.bazel.lock index 947ce4d..cda51e0 100644 --- a/e2e/MODULE.bazel.lock +++ b/e2e/MODULE.bazel.lock @@ -762,7 +762,7 @@ "moduleExtensions": { "//:MODULE.bazel%_repo_rules": { "general": { - "bzlTransitiveDigest": "/3M749UD+XvXsUVUe82rrOR0fBWDVdiYpQ6mlpN1U1E=", + "bzlTransitiveDigest": "figbycfs0eedg4q0hn0jabk4GTgsOnMACf+3OyeLvps=", "accumulatedFileDigests": {}, "envVariables": {}, "generatedRepoSpecs": { @@ -1413,7 +1413,7 @@ }, "@rules_toolchain~override//:MODULE.bazel%_repo_rules": { "general": { - "bzlTransitiveDigest": "mvwjHUR6LfdJXlUKr5URiiM5nIkorGaL+UsIyVuakBw=", + "bzlTransitiveDigest": "VGGV2/aS8KP0wlEaxXfdomUzHtZ4Ry+aV/L2Ktp3UCo=", "accumulatedFileDigests": {}, "envVariables": {}, "generatedRepoSpecs": { diff --git a/e2e/test/fixture/repository.bzl b/e2e/test/fixture/repository.bzl index a0400cf..69c9fb1 100644 --- a/e2e/test/fixture/repository.bzl +++ b/e2e/test/fixture/repository.bzl @@ -18,7 +18,7 @@ def implementation(rctx): map = {l: "{}/{}".format(l.package, l.name) for l in rctx.attr.srcs} for label, path in map.items(): - rctx.file(path, content = rctx.read(label)) + rctx.file(path, content = rctx.read(label), executable = False) rctx.template("BUILD.bazel", rctx.attr.template, { "{{srcs}}": repr(map.values()), diff --git a/toolchain/local/triplet/repository.bzl b/toolchain/local/triplet/repository.bzl index 0a58f64..6dd6f2b 100644 --- a/toolchain/local/triplet/repository.bzl +++ b/toolchain/local/triplet/repository.bzl @@ -17,7 +17,7 @@ def implementation(rctx): triplet = detect(rctx) rctx.template("triplet.bzl", rctx.attr.template, { "{{value}}": triplet.value, - }) + }, executable = False) rctx.file("BUILD.bazel", "") triplet = repository_rule( diff --git a/toolchain/local/which/repository.bzl b/toolchain/local/which/repository.bzl index d5cb732..abad59c 100644 --- a/toolchain/local/which/repository.bzl +++ b/toolchain/local/which/repository.bzl @@ -46,7 +46,7 @@ def implementation(rctx): "{{program}}": program, "{{path}}": str(path.realpath), "{{variable}}": rctx.attr.variable or program.upper(), - }) + }, executable = False) which = repository_rule( doc = DOC, -- GitLab From 7ad98062778c17c7b143a2a366b18361ba950d09 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Wed, 15 Nov 2023 16:03:04 +0000 Subject: [PATCH 3/3] feat: add a `resolved` target to local binary repositories This removes the need for a custom `resolved` rule for every toolchain. Upgrade path is to add the `toolchain_type` to the local repository rule in `MODULE.bazel` and change the `resolved` target to an alias. A `toolchain_resolved` repository rule is added as well for toolchains that do not use local binaries. This patch hugely simplifies the creation of toolchains downstream. --- README.md | 37 +++------------ e2e/MODULE.bazel | 12 ++++- e2e/MODULE.bazel.lock | 36 ++++++++++++--- e2e/toolchain/echo/BUILD.bazel | 6 +-- toolchain/defs.bzl | 2 + toolchain/local/which/BUILD.tmpl.bazel | 6 +++ toolchain/local/which/repository.bzl | 20 +++++++-- toolchain/resolved/BUILD.bazel | 0 toolchain/resolved/BUILD.tmpl.bazel | 7 +++ toolchain/resolved/repository.bzl | 45 +++++++++++++++++++ .../resolved/resolved.tmpl.bzl | 6 +-- 11 files changed, 130 insertions(+), 47 deletions(-) create mode 100644 toolchain/resolved/BUILD.bazel create mode 100644 toolchain/resolved/BUILD.tmpl.bazel create mode 100644 toolchain/resolved/repository.bzl rename e2e/toolchain/echo/resolved.bzl => toolchain/resolved/resolved.tmpl.bzl (55%) diff --git a/README.md b/README.md index 2073abf..a18401a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,10 @@ Add the following to `MODULE.bazel`: ```py which = use_repo_rule("@rules_toolchain//toolchain:defs.bzl", "toolchain_local_which") -which("echo") +which( + name = "echo", + toolchain_type = "//toolchain/echo:type", +) ``` The `echo` tool will be found on the `PATH`. @@ -41,12 +44,10 @@ Create a `toolchain/echo/BUILD.bazel` with the following: ```py load("@rules_toolchain//toolchain:defs.bzl", "toolchain_symlink_target", "toolchain_test") -# Custom rule, described in the next section -load(":resolved.bzl", "resolved") - # The `toolchain/echo:type` for registration toolchain_type( name = "type", + visibility = ["//visibility:public"], ) # Register the `local` binary as a toolchain @@ -85,33 +86,9 @@ toolchain( ) # Provide a resolved toolchain target -resolved( +alias( name = "resolved", - toolchain_type = ":type", -) -``` - -#### Resolved - -To work around a [quirk in Bazel][resolved], the resolution of the toolchain must be defined in a separate rule. - -`@rules_toolchain` provides the necessary building blocks for this rule. - -Create `toolchain/echo/resolved.bzl` to provide the `resolved` rule that is used above: - -```py -load("@rules_toolchain//toolchain:resolved.bzl", _resolved = "export") - -visibility("toolchain/echo/...") - -DOC = _resolved.doc - -ATTRS = _resolved.attrs - -implementation = _resolved.implementation - -resolved = _resolved.rule( - toolchain = Label("//toolchain/echo:type"), + actual = "@echo//:resolved", ) ``` diff --git a/e2e/MODULE.bazel b/e2e/MODULE.bazel index 1138e73..2a4835b 100644 --- a/e2e/MODULE.bazel +++ b/e2e/MODULE.bazel @@ -14,7 +14,17 @@ local_path_override( which = use_repo_rule("@rules_toolchain//toolchain:defs.bzl", "toolchain_local_which") -which(name = "echo") +which( + name = "echo", + toolchain_type = "//toolchain/echo:type", +) + +resolved = use_repo_rule("@rules_toolchain//toolchain:defs.bzl", "toolchain_resolved") + +resolved( + name = "resolved", + toolchain_type = "//toolchain/echo:type", +) register_toolchains("//toolchain/echo:all") diff --git a/e2e/MODULE.bazel.lock b/e2e/MODULE.bazel.lock index cda51e0..108a5ca 100644 --- a/e2e/MODULE.bazel.lock +++ b/e2e/MODULE.bazel.lock @@ -1,6 +1,6 @@ { "lockFileVersion": 3, - "moduleFileHash": "7ff95807f953adb3cee60c034542c31fd3f27dec0c2bfcc56a49d1259662afe0", + "moduleFileHash": "a4f83750c39dd1dd3c7f4cb6e91173765b61fec4346ea33df2f4a7cb7e60c729", "flags": { "cmdRegistries": [ "https://bcr.bazel.build/" @@ -38,6 +38,7 @@ }, "imports": { "echo": "echo", + "resolved": "resolved", "fixture-amd64-linux-gnu": "fixture-amd64-linux-gnu", "fixture-arm64-linux-gnu": "fixture-arm64-linux-gnu", "fixture-arm-linux-musl": "fixture-arm-linux-musl", @@ -48,6 +49,7 @@ { "tagName": "@rules_toolchain//toolchain:defs.bzl%toolchain_local_which", "attributeValues": { + "toolchain_type": "//toolchain/echo:type", "name": "echo" }, "devDependency": false, @@ -57,6 +59,19 @@ "column": 6 } }, + { + "tagName": "@rules_toolchain//toolchain:defs.bzl%toolchain_resolved", + "attributeValues": { + "toolchain_type": "//toolchain/echo:type", + "name": "resolved" + }, + "devDependency": false, + "location": { + "file": "@@//:MODULE.bazel", + "line": 24, + "column": 9 + } + }, { "tagName": "//test/fixture:repository.bzl%fixture", "attributeValues": { @@ -65,7 +80,7 @@ "devDependency": false, "location": { "file": "@@//:MODULE.bazel", - "line": 23, + "line": 33, "column": 8 } }, @@ -77,7 +92,7 @@ "devDependency": false, "location": { "file": "@@//:MODULE.bazel", - "line": 27, + "line": 37, "column": 8 } }, @@ -89,7 +104,7 @@ "devDependency": false, "location": { "file": "@@//:MODULE.bazel", - "line": 31, + "line": 41, "column": 8 } }, @@ -106,7 +121,7 @@ "devDependency": false, "location": { "file": "@@//:MODULE.bazel", - "line": 37, + "line": 47, "column": 7 } } @@ -762,7 +777,7 @@ "moduleExtensions": { "//:MODULE.bazel%_repo_rules": { "general": { - "bzlTransitiveDigest": "figbycfs0eedg4q0hn0jabk4GTgsOnMACf+3OyeLvps=", + "bzlTransitiveDigest": "da/DoHSQBm39DhgiqteTa0XULbwxsr8VGJ6XQ/cPUmw=", "accumulatedFileDigests": {}, "envVariables": {}, "generatedRepoSpecs": { @@ -770,9 +785,18 @@ "bzlFile": "@@rules_toolchain~override//toolchain/local/which:repository.bzl", "ruleClassName": "which", "attributes": { + "toolchain_type": "@@//toolchain/echo:type", "name": "_main~_repo_rules~echo" } }, + "resolved": { + "bzlFile": "@@rules_toolchain~override//toolchain/resolved:repository.bzl", + "ruleClassName": "resolved", + "attributes": { + "toolchain_type": "@@//toolchain/echo:type", + "name": "_main~_repo_rules~resolved" + } + }, "fixture-amd64-linux-gnu": { "bzlFile": "@@//test/fixture:repository.bzl", "ruleClassName": "fixture", diff --git a/e2e/toolchain/echo/BUILD.bazel b/e2e/toolchain/echo/BUILD.bazel index bd8e13b..454d1f4 100644 --- a/e2e/toolchain/echo/BUILD.bazel +++ b/e2e/toolchain/echo/BUILD.bazel @@ -1,8 +1,8 @@ -load(":resolved.bzl", "resolved") load("@rules_toolchain//toolchain:defs.bzl", "toolchain_symlink_target", "toolchain_test") toolchain_type( name = "type", + visibility = ["//visibility:public"], ) toolchain_symlink_target( @@ -21,9 +21,9 @@ alias( actual = "hermetic", ) -resolved( +alias( name = "resolved", - toolchain = ":type", + actual = "@echo//:resolved", ) toolchain_test( diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl index 75feeea..c7db4af 100644 --- a/toolchain/defs.bzl +++ b/toolchain/defs.bzl @@ -4,6 +4,7 @@ load("//toolchain/symlink/target:rule.bzl", _symlink_target = "target") load("//toolchain/test:rule.bzl", _test = "test") load("//toolchain/local/which:repository.bzl", _local_which = "which") load("//toolchain/local/select:repository.bzl", _local_select = "select") +load("//toolchain/resolved:repository.bzl", _resolved = "resolved") visibility("public") @@ -13,3 +14,4 @@ toolchain_symlink_target = _symlink_target toolchain_test = _test toolchain_local_which = _local_which toolchain_local_select = _local_select +toolchain_resolved = _resolved diff --git a/toolchain/local/which/BUILD.tmpl.bazel b/toolchain/local/which/BUILD.tmpl.bazel index 84f9d92..1a7403d 100644 --- a/toolchain/local/which/BUILD.tmpl.bazel +++ b/toolchain/local/which/BUILD.tmpl.bazel @@ -1,4 +1,5 @@ load("@rules_toolchain//toolchain:defs.bzl", "toolchain_symlink_path") +load("//:resolved.bzl", "resolved") package(default_visibility = ["//visibility:public"]) @@ -8,3 +9,8 @@ toolchain_symlink_path( tags = ["no-remote"], variable = "{{variable}}", ) + +resolved( + name = "resolved", + toolchain = "{{toolchain_type}}", +) diff --git a/toolchain/local/which/repository.bzl b/toolchain/local/which/repository.bzl index abad59c..6decf44 100644 --- a/toolchain/local/which/repository.bzl +++ b/toolchain/local/which/repository.bzl @@ -27,9 +27,18 @@ ATTRS = { "variable": attr.string( doc = "The variable name for Make or the execution environment.", ), - "template": attr.label( + "toolchain_type": attr.label( + doc = "The toolchain type for the binary.", + mandatory = True, + ), + "resolved": attr.label( + doc = "The tepmlate that is expanded into the `resolved.bzl`.", + default = "//toolchain/resolved:resolved.tmpl.bzl", + allow_single_file = True, + ), + "build": attr.label( doc = "The template that is expanded into the `BUILD.bazel`.", - default = Label(":BUILD.tmpl.bazel"), + default = ":BUILD.tmpl.bazel", allow_single_file = True, ), } @@ -41,11 +50,16 @@ def implementation(rctx): if not path: fail("Cannot find `{}` on `PATH`".format(program)) - rctx.template("BUILD.bazel", rctx.attr.template, { + rctx.template("resolved.bzl", rctx.attr.resolved, { + "{{toolchain_type}}": str(rctx.attr.toolchain_type), + }, executable = False) + + rctx.template("BUILD.bazel", rctx.attr.build, { "{{name}}": rctx.attr.target or program, "{{program}}": program, "{{path}}": str(path.realpath), "{{variable}}": rctx.attr.variable or program.upper(), + "{{toolchain_type}}": str(rctx.attr.toolchain_type), }, executable = False) which = repository_rule( diff --git a/toolchain/resolved/BUILD.bazel b/toolchain/resolved/BUILD.bazel new file mode 100644 index 0000000..e69de29 diff --git a/toolchain/resolved/BUILD.tmpl.bazel b/toolchain/resolved/BUILD.tmpl.bazel new file mode 100644 index 0000000..dc8d973 --- /dev/null +++ b/toolchain/resolved/BUILD.tmpl.bazel @@ -0,0 +1,7 @@ +load("//:resolved.bzl", "resolved") + +resolved( + name = "resolved", + toolchain = "{{toolchain_type}}", + visibility = ["//visibility:public"], +) diff --git a/toolchain/resolved/repository.bzl b/toolchain/resolved/repository.bzl new file mode 100644 index 0000000..1185e76 --- /dev/null +++ b/toolchain/resolved/repository.bzl @@ -0,0 +1,45 @@ +visibility("//toolchain/...") + +DOC = """Creates a repository that provides a toolchain resolution rule. + +Due to a [quirk] in Bazel, a custom rule needs to be created for each toolchain type. + +```py +toolchain_resolved( + name = "echo", + toolchain_type = "@rules_abc//abc/toolchain/cli:type", +) +``` + +[quirk]: https://github.com/bazelbuild/bazel/issues/14009 +""" + +ATTRS = { + "toolchain_type": attr.label( + doc = "The toolchain type to resolve.", + mandatory = True, + ), + "resolved": attr.label( + doc = "The template that is expanded into the `resolved.bzl`.", + default = Label(":resolved.tmpl.bzl"), + allow_single_file = True, + ), + "build": attr.label( + doc = "The template that is expanded into the `BUILD.bazel`.", + default = Label(":BUILD.tmpl.bazel"), + allow_single_file = True, + ), +} + +def implementation(rctx): + substitutions = { + "{{toolchain_type}}": str(rctx.attr.toolchain_type), + } + rctx.template("resolved.bzl", rctx.attr.resolved, substitutions, executable = False) + rctx.template("BUILD.bazel", rctx.attr.build, substitutions, executable = False) + +resolved = repository_rule( + doc = DOC, + implementation = implementation, + attrs = ATTRS, +) diff --git a/e2e/toolchain/echo/resolved.bzl b/toolchain/resolved/resolved.tmpl.bzl similarity index 55% rename from e2e/toolchain/echo/resolved.bzl rename to toolchain/resolved/resolved.tmpl.bzl index cc8543a..56a4226 100644 --- a/e2e/toolchain/echo/resolved.bzl +++ b/toolchain/resolved/resolved.tmpl.bzl @@ -1,13 +1,11 @@ load("@rules_toolchain//toolchain:resolved.bzl", _resolved = "export") -visibility("//toolchain/echo/...") - -DOC = _resolved.doc.format(toolchain = "echo") +DOC = _resolved.doc ATTRS = _resolved.attrs implementation = _resolved.implementation resolved = _resolved.rule( - toolchain_type = Label("//toolchain/echo:type"), + toolchain_type = Label("{{toolchain_type}}"), ) -- GitLab