-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[ABLD-395] Framework to create toolchains for OS provided tools #54177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
89d365f
446ae55
f40e478
cad9410
3f1e8f1
c2c8ed3
92c9996
c6e763d
33693b5
8626718
37609a1
b8787a5
3c43004
97bc86b
63df4c2
b9814f4
055806a
d9d76a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| """toolchain to wrap the codesign binary. | ||
|
|
||
| Type: @codesign//:codesign_toolchain_type | ||
|
|
||
| Toolchains: | ||
| - @codesign//:codesign_toolchain: provides the tool | ||
| - @codesign//:codesign_missing_toolchain: provides a fallback toolchain for | ||
| exec platforms where codesign might not be available. | ||
| """ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """Repository rule to autoconfigure a toolchain using the system codesign.""" | ||
|
|
||
| load("//bazel/toolchains/common:defs.bzl", "make_toolchain_repository_rule") | ||
|
|
||
| # This must match the repository name used by register_toolchains in consuming MODULE.bazel files. | ||
| NAME = "macos_codesign" | ||
|
|
||
| find_macos_codesign = make_toolchain_repository_rule(name = NAME, tool_name = "codesign") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # //bazel/toolchains/common |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| """Utilitites for creating toolchains to wrap system provided tools.""" | ||
|
|
||
| def _write_toolchain_repo(rctx, repo_name, tool_name, tool_path, tool_version = "<unknown>", exec_compatible_with = None): | ||
| if not tool_path: | ||
| tool_path = "" | ||
| rctx.template( | ||
| "BUILD", | ||
| Label("@@//bazel/toolchains/common:toolchain_BUILD.tpl"), | ||
| substitutions = { | ||
| "{AVAILABLE}": "1" if tool_path else "0", | ||
| "{EXEC_COMPATIBLE_WITH}": repr(exec_compatible_with), | ||
| "{GENERATOR}": "//bazel/toolchains/common:defs.bzl", | ||
| "{REPO_NAME}": repo_name, | ||
| "{TOOL_NAME}": tool_name, | ||
| "{TOOL_PATH}": str(tool_path), | ||
| "{TOOL_VERSION}": tool_version, | ||
| }, | ||
| executable = False, | ||
| ) | ||
| rctx.template( | ||
| "defs.bzl", | ||
| Label("@@//bazel/toolchains/common:toolchain_defs.bzl.tpl"), | ||
| substitutions = { | ||
| "{AVAILABLE}": "1" if tool_path else "0", | ||
| "{GENERATOR}": "//bazel/toolchains/common:defs.bzl", | ||
| "{REPO_NAME}": repo_name, | ||
| "{TOOL_NAME}": tool_name, | ||
| }, | ||
| executable = False, | ||
| ) | ||
|
|
||
| def _default_repo_builder_impl(rctx): | ||
| tool_name = rctx.attr.tool_name | ||
| tool_path = rctx.which(tool_name) | ||
| if rctx.attr.verbose: | ||
| if tool_path: | ||
| print("Found %s at '%s'" % (tool_name, tool_path)) # buildifier: disable=print | ||
| else: | ||
| print("No system %s found." % tool_name) # buildifier: disable=print | ||
| _write_toolchain_repo( | ||
| rctx = rctx, | ||
| repo_name = rctx.original_name, | ||
| tool_name = rctx.attr.tool_name, | ||
| tool_path = tool_path, | ||
| exec_compatible_with = rctx.attr.exec_compatible_with, | ||
| ) | ||
|
|
||
| def make_toolchain_repository_rule(name, tool_name, impl = _default_repo_builder_impl): | ||
| return repository_rule( | ||
| implementation = impl, | ||
| doc = """Create a repository that defines a {name} toolchain based on tool in the default $PATH.""".format(name = name), | ||
| local = True, | ||
| environ = ["PATH"], | ||
| attrs = { | ||
| "tool_name": attr.string(doc = "The name of the tool to find.", default = tool_name), | ||
| "exec_compatible_with": attr.string_list( | ||
| doc = "exec_compatible_with list to apply to the created toolchain.", | ||
| ), | ||
| "verbose": attr.bool( | ||
| doc = "If true, print status messages.", | ||
| ), | ||
| }, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # This content is generated by {GENERATOR} | ||
| load(":defs.bzl", "is_{TOOL_NAME}_available", "{TOOL_NAME}_toolchain") | ||
|
|
||
| toolchain_type( | ||
| name = "{TOOL_NAME}_toolchain_type", | ||
| visibility = ["//visibility:public"], | ||
| ) | ||
|
|
||
| {TOOL_NAME}_toolchain( | ||
| name = "{TOOL_NAME}_auto", | ||
| path = "{TOOL_PATH}", | ||
| version = "{TOOL_VERSION}", | ||
| ) | ||
|
|
||
| toolchain( | ||
| name = "{TOOL_NAME}_toolchain", | ||
| toolchain = ":{TOOL_NAME}_auto", | ||
| toolchain_type = ":{TOOL_NAME}_toolchain_type", | ||
| exec_compatible_with = {EXEC_COMPATIBLE_WITH}, | ||
| ) | ||
|
|
||
| # {TOOL_NAME}_missing_toolchain provides a fallback toolchain so that toolchain | ||
| # resolution can succeed even on platforms that do not have that tool. | ||
| # If this toolchain is selected, a rule can examine the valid field to determine | ||
| # if the tool is really available. | ||
| {TOOL_NAME}_toolchain( | ||
| name = "no_{TOOL_NAME}", | ||
| ) | ||
|
|
||
| toolchain( | ||
| name = "zzz_{TOOL_NAME}_missing_toolchain", # keep name lexicographically last | ||
| toolchain = ":no_{TOOL_NAME}", | ||
| toolchain_type = ":{TOOL_NAME}_toolchain_type", | ||
| ) | ||
|
|
||
| # Expose the availability of the actual tool as a flag, so we can | ||
| # create a config_setting from it. | ||
| is_{TOOL_NAME}_available( | ||
|
alopezz marked this conversation as resolved.
|
||
| name = "is_{TOOL_NAME}_available", | ||
| build_setting_default = {AVAILABLE}, | ||
|
alopezz marked this conversation as resolved.
|
||
| ) | ||
|
|
||
| # Expose the availability of the toolchain as a config_setting, so we can | ||
| # select() on it. | ||
| config_setting( | ||
| name = "have_{TOOL_NAME}", | ||
| flag_values = { | ||
| ":is_{TOOL_NAME}_available": "1", | ||
| }, | ||
| visibility = ["//visibility:public"], | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| """toolchain to provide the {TOOL_NAME} binary.""" | ||
|
|
||
| load("@@//bazel/toolchains:toolchain_info.bzl", "ToolInfo") | ||
|
|
||
| def _{TOOL_NAME}_toolchain_impl(ctx): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And another question that I have is whether we actually need to be templated with the TOOL_NAME baked in or whether a single common rule can be used to define all these toolchains instead.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For just the two I have done, yes. But that gets in the way of future expansion, where I want different things to customize the template. pkgbuild and codesign, do not have I have that ready in another PR, but it's not needed yet. Essentially the repo_builder call will use a private impl function instead of the default, and your private impl will call do the lookup and then call |
||
| if ctx.attr.label and ctx.attr.path: | ||
| fail("{TOOL_NAME}_toolchain must not specify both label and path.") | ||
| valid = bool(ctx.attr.label) or bool(ctx.attr.path) | ||
| toolchain_info = platform_common.ToolchainInfo( | ||
| {TOOL_NAME} = ToolInfo( | ||
| name = str(ctx.label), | ||
| valid = valid, | ||
| label = ctx.attr.label, | ||
| path = ctx.attr.path, | ||
| version = ctx.attr.version, | ||
| ), | ||
| ) | ||
| return [toolchain_info] | ||
|
|
||
| {TOOL_NAME}_toolchain = rule( | ||
| implementation = _{TOOL_NAME}_toolchain_impl, | ||
| attrs = { | ||
| "label": attr.label( | ||
| doc = "A valid label of a target to build or a prebuilt binary. Mutually exclusive with path.", | ||
| cfg = "exec", | ||
| executable = True, | ||
| allow_files = True, | ||
| ), | ||
| "path": attr.string( | ||
| doc = "The path to the executable. Mutually exclusive with label.", | ||
| ), | ||
| "version": attr.string( | ||
| doc = "The version string of the executable. This should be manually set.", | ||
| ), | ||
| }, | ||
| ) | ||
|
|
||
| # Expose the presence of {TOOL_NAME} as a flag. | ||
| def _is_{TOOL_NAME}_available_impl(ctx): | ||
| return [config_common.FeatureFlagInfo( | ||
| value = ("1" if ctx.build_setting_value else "0"), | ||
| )] | ||
|
|
||
| is_{TOOL_NAME}_available = rule( | ||
| implementation = _is_{TOOL_NAME}_available_impl, | ||
| attrs = {}, | ||
| build_setting = config.bool(flag = False), | ||
| ) | ||
|
aiuto marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """Toolchain to wrap the pkgbuild binary. | ||
|
|
||
| Type: @macos_pkgbuild//:tool_toolchain_type | ||
|
|
||
| Toolchains: | ||
| - @macos_pkgbuild//:macos_pkgbuild_toolchain: provides the tool | ||
| - @macos_pkgbuild//:macos_pkgbuild_missing_toolchain: provides a fallback toolchain for exec platforms where pkgbuild might not be available. | ||
| """ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """Repository rule to autoconfigure a toolchain using the system pkgbuild.""" | ||
|
|
||
| load("//bazel/toolchains/common:defs.bzl", "make_toolchain_repository_rule") | ||
|
|
||
| # This must match the name used by register_toolchains in MODULE.bazel. | ||
| NAME = "macos_pkgbuild" | ||
|
|
||
| find_macos_pkgbuild = make_toolchain_repository_rule(name = NAME, tool_name = "pkgbuild") |
Uh oh!
There was an error while loading. Please reload this page.