From 7725409b8a6091f0441c1aeca28ebc53816d1c88 Mon Sep 17 00:00:00 2001 From: Boleyn Su Date: Mon, 1 Jul 2024 16:09:04 +0800 Subject: [PATCH 1/2] Implement binary_toolchain --- lib/binary_toolchain.bzl | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 lib/binary_toolchain.bzl diff --git a/lib/binary_toolchain.bzl b/lib/binary_toolchain.bzl new file mode 100644 index 000000000..c7ba6cdd5 --- /dev/null +++ b/lib/binary_toolchain.bzl @@ -0,0 +1,69 @@ +BinaryInfo = provider( + doc = "Provide info for binary", + fields = { + "bin": "Target for the binary", + }, +) + +def _toolchain_impl(ctx): + binary_info = BinaryInfo( + bin = ctx.attr.bin, + ) + + toolchain_info = platform_common.ToolchainInfo( + binary_info = binary_info, + ) + + return [toolchain_info] + +binary_toolchain = rule( + implementation = _toolchain_impl, + attrs = { + "bin": attr.label( + mandatory = True, + allow_single_file = True, + executable = True, + cfg = "exec", + ), + }, +) + +binary_runtime_toolchain = rule( + implementation = _toolchain_impl, + attrs = { + "bin": attr.label( + mandatory = True, + allow_single_file = True, + executable = True, + cfg = "target", + ), + }, +) + +def _resolved_binary_rule_impl(ctx, toolchain_type, template_variable): + bin = ctx.toolchains[toolchain_type].binary_info.bin[DefaultInfo] + + out = ctx.actions.declare_file(ctx.attr.name + ".exe") + ctx.actions.symlink( + target_file = bin.files_to_run.executable, + output = out, + is_executable = True, + ) + + return [ + DefaultInfo( + executable = out, + files = bin.files, + runfiles = bin.default_runfiles, + ), + platform_common.TemplateVariableInfo({ + template_variable: out.path, + } if template_variable != None else {}), + ] + +def resolved_binary_rule(*, toolchain_type, template_variable = None): + return rule( + implementation = lambda ctx: _resolved_binary_rule_impl(ctx, toolchain_type, template_variable), + executable = True, + toolchains = [toolchain_type], + ) From 6fcde2fc81bebe96953a6eb13dfba7e14d75e82a Mon Sep 17 00:00:00 2001 From: Boleyn Su Date: Mon, 1 Jul 2024 16:11:46 +0800 Subject: [PATCH 2/2] Use binary_toolchain to implement jq_toolchain/jq --- lib/BUILD.bazel | 4 ++ lib/private/jq.bzl | 2 +- lib/private/jq_toolchain.bzl | 78 +++++++----------------------------- lib/tests/jq/BUILD.bazel | 14 +++++++ 4 files changed, 33 insertions(+), 65 deletions(-) diff --git a/lib/BUILD.bazel b/lib/BUILD.bazel index c1d808754..e33a32711 100644 --- a/lib/BUILD.bazel +++ b/lib/BUILD.bazel @@ -40,6 +40,10 @@ toolchain_type( name = "jq_toolchain_type", ) +toolchain_type( + name = "jq_runtime_toolchain_type", +) + toolchain_type( name = "yq_toolchain_type", ) diff --git a/lib/private/jq.bzl b/lib/private/jq.bzl index 7c8a4931b..1073f104f 100644 --- a/lib/private/jq.bzl +++ b/lib/private/jq.bzl @@ -30,7 +30,7 @@ def _expand_locations(ctx, s): return expand_locations(ctx, s, targets = ctx.attr.data).split(" ") def _jq_impl(ctx): - jq_bin = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"].jqinfo.bin + jq_bin = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"].binary_info.bin[DefaultInfo].files_to_run.executable out = ctx.outputs.out or ctx.actions.declare_file(ctx.attr.name + ".json") if ctx.attr.expand_args: diff --git a/lib/private/jq_toolchain.bzl b/lib/private/jq_toolchain.bzl index f76eeefc8..8473d910f 100644 --- a/lib/private/jq_toolchain.bzl +++ b/lib/private/jq_toolchain.bzl @@ -57,72 +57,15 @@ JQ_VERSIONS = { }, } -JqInfo = provider( - doc = "Provide info for executing jq", - fields = { - "bin": "Executable jq binary", - }, -) - -def _jq_toolchain_impl(ctx): - binary = ctx.file.bin - - # Make the $(JQ_BIN) variable available in places like genrules. - # See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables - template_variables = platform_common.TemplateVariableInfo({ - "JQ_BIN": binary.path, - }) - default_info = DefaultInfo( - files = depset([binary]), - runfiles = ctx.runfiles(files = [binary]), - ) - jq_info = JqInfo( - bin = binary, - ) - - # Export all the providers inside our ToolchainInfo - # so the resolved_toolchain rule can grab and re-export them. - toolchain_info = platform_common.ToolchainInfo( - jqinfo = jq_info, - template_variables = template_variables, - default = default_info, - ) - - return [default_info, toolchain_info, template_variables] - -jq_toolchain = rule( - implementation = _jq_toolchain_impl, - attrs = { - "bin": attr.label( - mandatory = True, - allow_single_file = True, - ), - }, -) - def _jq_toolchains_repo_impl(rctx): # Expose a concrete toolchain which is the result of Bazel resolving the toolchain # for the execution or target platform. # Workaround for https://github.com/bazelbuild/bazel/issues/14009 starlark_content = """# @generated by @aspect_bazel_lib//lib/private:jq_toolchain.bzl +load("@aspect_bazel_lib//lib:binary_toolchain.bzl", "resolved_binary_rule") -# Forward all the providers -def _resolved_toolchain_impl(ctx): - toolchain_info = ctx.toolchains["@aspect_bazel_lib//lib:jq_toolchain_type"] - return [ - toolchain_info, - toolchain_info.default, - toolchain_info.jqinfo, - toolchain_info.template_variables, - ] - -# Copied from java_toolchain_alias -# https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl -resolved_toolchain = rule( - implementation = _resolved_toolchain_impl, - toolchains = ["@aspect_bazel_lib//lib:jq_toolchain_type"], - incompatible_use_toolchain_transition = True, -) +resolved_toolchain = resolved_binary_rule(toolchain_type = "@aspect_bazel_lib//lib:jq_toolchain_type", template_variable = "JQ_BIN") +resolved_binary = resolved_binary_rule(toolchain_type = "@aspect_bazel_lib//lib:jq_runtime_toolchain_type", template_variable = "JQ_BIN") """ rctx.file("defs.bzl", starlark_content) @@ -132,10 +75,10 @@ resolved_toolchain = rule( # By default all these toolchains are registered by the jq_register_toolchains macro # so you don't normally need to interact with these targets. -load(":defs.bzl", "resolved_toolchain") +load(":defs.bzl", "resolved_toolchain", "resolved_binary") resolved_toolchain(name = "resolved_toolchain", visibility = ["//visibility:public"]) - +resolved_binary(name = "resolved_binary", visibility = ["//visibility:public"]) """ for [platform, meta] in JQ_PLATFORMS.items(): @@ -146,6 +89,12 @@ toolchain( toolchain = "@{user_repository_name}_{platform}//:jq_toolchain", toolchain_type = "@aspect_bazel_lib//lib:jq_toolchain_type", ) +toolchain( + name = "{platform}_runtime_toolchain", + target_compatible_with = {compatible_with}, + toolchain = "@{user_repository_name}_{platform}//:jq_runtime_toolchain", + toolchain_type = "@aspect_bazel_lib//lib:jq_runtime_toolchain_type", +) """.format( platform = platform, user_repository_name = rctx.attr.user_repository_name, @@ -182,9 +131,10 @@ def _jq_platform_repo_impl(rctx): integrity = JQ_VERSIONS[rctx.attr.version][release_platform], ) build_content = """# @generated by @aspect_bazel_lib//lib/private:jq_toolchain.bzl -load("@aspect_bazel_lib//lib/private:jq_toolchain.bzl", "jq_toolchain") +load("@aspect_bazel_lib//lib:binary_toolchain.bzl", "binary_toolchain", "binary_runtime_toolchain") exports_files(["{0}"]) -jq_toolchain(name = "jq_toolchain", bin = "{0}", visibility = ["//visibility:public"]) +binary_toolchain(name = "jq_toolchain", bin = "{0}", visibility = ["//visibility:public"]) +binary_runtime_toolchain(name = "jq_runtime_toolchain", bin = "{0}", visibility = ["//visibility:public"]) """.format("jq.exe" if is_windows else "jq") # Base BUILD file for this repository diff --git a/lib/tests/jq/BUILD.bazel b/lib/tests/jq/BUILD.bazel index c1d16f58e..56e6c68fe 100644 --- a/lib/tests/jq/BUILD.bazel +++ b/lib/tests/jq/BUILD.bazel @@ -164,6 +164,20 @@ diff_test( file2 = "a_pretty.json", ) +genrule( + name = "case_genrule_tool", + srcs = ["a.json"], + outs = ["genrule_tool_output.json"], + cmd = "$(execpath @jq_toolchains//:resolved_binary) '.' $(location a.json) > $@", + tools = ["@jq_toolchains//:resolved_binary"], +) + +diff_test( + name = "case_genrule_tool_test", + file1 = "genrule_tool_output.json", + file2 = "a_pretty.json", +) + # Raw input (--raw-input / -R) jq( name = "case_raw_input",