diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..7043786ce0374da6be4909a1b81ad940cb59b5a9 --- /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 diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index ecbd999eaf20dc29c1bd25c1e9ec85c61a68c3a2..38543fab0654228579d989c6b81e12fc6b24cc6e 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/README.md b/README.md index 2073abf2c5de826abd5c3c8e16cf7c9aefdb3456..a18401a3ae6458763ca3d898e1e899d1fb2dcbb9 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 1138e73e8d515d4fc2e1ab3b621ae5b07c609ad0..2a4835b1b4ce4dacbcecfe59ce0d71da1edc31d9 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 947ce4da225eeff00f799e9335e6f5a6787a1a3f..108a5ca0fa1510713c8162e7a32edabb8aa8b055 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": "/3M749UD+XvXsUVUe82rrOR0fBWDVdiYpQ6mlpN1U1E=", + "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", @@ -1413,7 +1437,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 a0400cffc0699ab69ea83394c2d8eeed535eb22d..69c9fb159f86fadb4737de4c215b85754f630ad8 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/e2e/toolchain/echo/BUILD.bazel b/e2e/toolchain/echo/BUILD.bazel index bd8e13bce10bbf374e2eced3384ae8d052c9a18a..454d1f404870bd8c7bd4389628699982699a1797 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 75feeea90981d147c6454e5d554aa29d9851bf87..c7db4af27c31a62f2bc94b4254c2a4caceaca5d6 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/triplet/repository.bzl b/toolchain/local/triplet/repository.bzl index 0a58f643319ac9f24a5f8bb43aaa20b9777ec289..6dd6f2b726ecff319dedbdc1fd6189778d11a7c5 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/BUILD.tmpl.bazel b/toolchain/local/which/BUILD.tmpl.bazel index 84f9d9260393e4b0ca8a15fbabfc3a5bbe7880cb..1a7403daa4dc4ed1ece82e25bb7e568a7d232ca3 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 d5cb732e9aa0757a4daee5a643b82fc6145e6d6e..6decf443dafca566d958076a8a77aec7b47ba573 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,12 +50,17 @@ 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( doc = DOC, diff --git a/toolchain/resolved/BUILD.bazel b/toolchain/resolved/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/toolchain/resolved/BUILD.tmpl.bazel b/toolchain/resolved/BUILD.tmpl.bazel new file mode 100644 index 0000000000000000000000000000000000000000..dc8d973550a1477f6bf8cbbecc1701bccab30985 --- /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 0000000000000000000000000000000000000000..1185e76c49c180e34418b43f6807ac2379d40015 --- /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 cc8543a0b4daa1637aa2afe186f1e16c24ad8fcf..56a422643434614995aeed0f5a2136694211086d 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}}"), )