From 136697659dca3c4caa76d669cd18978a897fccda Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Sat, 7 Oct 2023 19:25:58 -0700 Subject: [PATCH] refactor: stop autoregistering toolchains --- .github/workflows/release_prep.sh | 41 +++++++++++- MODULE.bazel | 14 +++- WORKSPACE | 12 +++- docs/BUILD.bazel | 5 ++ docs/extension_utils.md | 71 ++++++++++++++++++++ e2e/copy_to_directory/MODULE.bazel | 14 +++- e2e/copy_to_directory/WORKSPACE | 4 +- e2e/coreutils/MODULE.bazel | 9 ++- e2e/coreutils/WORKSPACE | 4 +- e2e/smoke/MODULE.bazel | 20 ++++++ e2e/smoke/WORKSPACE | 12 +++- lib/BUILD.bazel | 6 ++ lib/extension_utils.bzl | 5 ++ lib/extensions.bzl | 97 +++++++++++++++++++++++---- lib/private/BUILD.bazel | 6 ++ lib/private/extension_utils.bzl | 104 +++++++++++++++++++++++++++++ lib/repositories.bzl | 43 ++++++------ 17 files changed, 418 insertions(+), 49 deletions(-) create mode 100644 docs/extension_utils.md create mode 100644 lib/extension_utils.bzl create mode 100644 lib/private/extension_utils.bzl diff --git a/.github/workflows/release_prep.sh b/.github/workflows/release_prep.sh index 6389995a4..b49d60035 100755 --- a/.github/workflows/release_prep.sh +++ b/.github/workflows/release_prep.sh @@ -30,6 +30,31 @@ cat << EOF \`\`\`starlark bazel_dep(name = "aspect_bazel_lib", version = "${TAG:1}") + +# Optionally register any toolchains used: + +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") + +bazel_lib_toolchains.copy_directory() +bazel_lib_toolchains.copy_to_directory() +bazel_lib_toolchains.jq() +bazel_lib_toolchains.yq() +bazel_lib_toolchains.coreutils() +bazel_lib_toolchains.tar() +bazel_lib_toolchains.expand_template() + +use_repo(bazel_lib_toolchains, "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains") + +register_toolchains( + "@copy_directory_toolchains//:all", + "@copy_to_directory_toolchains//:all", + "@jq_toolchains//:all", + "@yq_toolchains//:all", + "@bsd_tar_toolchains//:all", + "@coreutils_toolchains//:all", + "@expand_template_toolchains//:all", +) + \`\`\` > Read more about bzlmod: @@ -48,10 +73,24 @@ http_archive( url = "https://github.com/aspect-build/bazel-lib/releases/download/${TAG}/${ARCHIVE}", ) -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") +load("//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_copy_directory_toolchains", "register_copy_to_directory_toolchains", "register_coreutils_toolchains", "register_expand_template_toolchains", "register_tar_toolchains") + +# Required bazel-lib dependencies aspect_bazel_lib_dependencies() +# Register any bazel-lib toolchains used + +register_copy_directory_toolchains() + +register_copy_to_directory_toolchains() + +register_expand_template_toolchains() + +register_coreutils_toolchains() + +register_tar_toolchains() + \`\`\` Optional toolchains: diff --git a/MODULE.bazel b/MODULE.bazel index 7c76d029e..9642fa5f5 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -14,17 +14,25 @@ bazel_dep(name = "platforms", version = "0.0.7") # 0.5.4 is the first version with bzlmod support bazel_dep(name = "stardoc", version = "0.5.4", repo_name = "io_bazel_stardoc") -ext = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "ext") -use_repo(ext, "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "tar_toolchains", "yq_toolchains") +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains", dev_dependency = True) +bazel_lib_toolchains.copy_directory() +bazel_lib_toolchains.copy_to_directory() +bazel_lib_toolchains.jq() +bazel_lib_toolchains.yq() +bazel_lib_toolchains.coreutils() +bazel_lib_toolchains.tar() +bazel_lib_toolchains.expand_template() +use_repo(bazel_lib_toolchains, "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains") register_toolchains( "@copy_directory_toolchains//:all", "@copy_to_directory_toolchains//:all", "@jq_toolchains//:all", - "@tar_toolchains//:all", "@yq_toolchains//:all", + "@bsd_tar_toolchains//:all", "@coreutils_toolchains//:all", "@expand_template_toolchains//:all", + dev_dependency = True, ) # To allow /tools to be built from source diff --git a/WORKSPACE b/WORKSPACE index 3d5374de1..8359d9a25 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -10,10 +10,20 @@ load(":internal_deps.bzl", "bazel_lib_internal_deps") # Fetch deps needed only locally for development bazel_lib_internal_deps() -load("//lib:repositories.bzl", "aspect_bazel_lib_dependencies") +load("//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_copy_directory_toolchains", "register_copy_to_directory_toolchains", "register_coreutils_toolchains", "register_expand_template_toolchains", "register_tar_toolchains") aspect_bazel_lib_dependencies() +register_copy_directory_toolchains() + +register_copy_to_directory_toolchains() + +register_expand_template_toolchains() + +register_coreutils_toolchains() + +register_tar_toolchains() + # For running our own unit tests load("@bazel_skylib//lib:unittest.bzl", "register_unittest_toolchains") diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 5a0e47963..7f6c6b786 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -30,6 +30,11 @@ stardoc_with_diff_test( bzl_library_target = "//lib:diff_test", ) +stardoc_with_diff_test( + name = "extension_utils", + bzl_library_target = "//lib:extension_utils", +) + stardoc_with_diff_test( name = "expand_make_vars", bzl_library_target = "//lib:expand_make_vars", diff --git a/docs/extension_utils.md b/docs/extension_utils.md new file mode 100644 index 000000000..af9c1f3ca --- /dev/null +++ b/docs/extension_utils.md @@ -0,0 +1,71 @@ + + +Public API + + + +## extension_utils.toolchain_repos_bfs + +
+extension_utils.toolchain_repos_bfs(mctx, get_tag_fn, toolchain_name, toolchain_repos_fn,
+                                    default_repository, get_name_fn, get_version_fn)
+
+ +Create toolchain repositories from bzlmod extensions using a breadth-first strategy. + +Toolchains are assumed to have a "default" or canonical repository name so that across +all invocations of the module extension with that name only a single toolchain repository +is created. As such, it is recommended to default the toolchain name in the extension's +tag class attributes so that diverging from the canonical name is a special case. + +The resolved toolchain version will be the one invoked closest to the root module, following +Bazel's breadth-first ordering of modules in the dependency graph. + +For example, given the module extension usage in a MODULE file: + +```starlark +ext = use_extension("@my_lib//lib:extensions.bzl", "ext") + +ext.foo_toolchain(version = "1.2.3") # Default `name = "foo"` + +use_repo(ext, "foo") + +register_toolchains( + "@foo//:all", +) +``` + +This macro would be used in the module extension implementation as follows: + +```starlark +extension_utils.toolchain_repos( + mctx = mctx, + get_tag_fn = lambda tags: tags.foo_toolchain, + toolchain_name = "foo", + toolchain_repos_fn = lambda name, version: register_foo_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, +) +``` + +Where `register_foo_toolchains` is a typical WORKSPACE macro used to register +the foo toolchain for a particular version, minus the actual registration step +which is done separately in the MODULE file. + +This macro enforces that only root MODULEs may use a different name for the toolchain +in case several versions of the toolchain repository is desired. + + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| mctx | The module context | none | +| get_tag_fn | A function that takes in module.tags and returns the tag used for the toolchain. For example, tag: lambda tags: tags.foo_toolchain. This is required because foo_toolchain cannot be accessed as a simple string key from module.tags. | none | +| toolchain_name | Name of the toolchain to use in error messages | none | +| toolchain_repos_fn | A function that takes (name, version) and creates a toolchain repository. This lambda should call a typical reposotiory rule to create toolchains. | none | +| default_repository | Default name of the toolchain repository to pass to the repos_fn. By default, it equals toolchain_name. | None | +| get_name_fn | A function that extracts the module name from the toolchain tag's attributes. Defaults to grabbing the name attribute. | None | +| get_version_fn | A function that extracts the module version from the a tag's attributes. Defaults to grabbing the version attribute. Override this to a lambda that returns None if version isn't used as an attribute. | None | + + diff --git a/e2e/copy_to_directory/MODULE.bazel b/e2e/copy_to_directory/MODULE.bazel index 33a7fca6d..c9a23eb2c 100644 --- a/e2e/copy_to_directory/MODULE.bazel +++ b/e2e/copy_to_directory/MODULE.bazel @@ -11,6 +11,14 @@ local_path_override( path = "../..", ) -ext = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "ext") -ext.host() -use_repo(ext, "aspect_bazel_lib_host") +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") +bazel_lib_toolchains.copy_to_directory() +use_repo(bazel_lib_toolchains, "copy_to_directory_toolchains") + +register_toolchains( + "@copy_to_directory_toolchains//:all", +) + +host = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "host") +host.host() +use_repo(host, "aspect_bazel_lib_host") diff --git a/e2e/copy_to_directory/WORKSPACE b/e2e/copy_to_directory/WORKSPACE index 5238a87a0..e6dddf340 100644 --- a/e2e/copy_to_directory/WORKSPACE +++ b/e2e/copy_to_directory/WORKSPACE @@ -3,10 +3,12 @@ local_repository( path = "../..", ) -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_copy_to_directory_toolchains") aspect_bazel_lib_dependencies() +register_copy_to_directory_toolchains() + ############################################ # rules_go is needed to consume tools from sources diff --git a/e2e/coreutils/MODULE.bazel b/e2e/coreutils/MODULE.bazel index b4da586da..519e623af 100644 --- a/e2e/coreutils/MODULE.bazel +++ b/e2e/coreutils/MODULE.bazel @@ -10,5 +10,10 @@ local_path_override( path = "../..", ) -ext = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "ext") -use_repo(ext, "coreutils_toolchains") +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") +bazel_lib_toolchains.coreutils() +use_repo(bazel_lib_toolchains, "coreutils_toolchains") + +register_toolchains( + "@coreutils_toolchains//:all", +) diff --git a/e2e/coreutils/WORKSPACE b/e2e/coreutils/WORKSPACE index 880fc9293..4f6c4851a 100644 --- a/e2e/coreutils/WORKSPACE +++ b/e2e/coreutils/WORKSPACE @@ -3,6 +3,8 @@ local_repository( path = "../..", ) -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies") +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_coreutils_toolchains") aspect_bazel_lib_dependencies() + +register_coreutils_toolchains() diff --git a/e2e/smoke/MODULE.bazel b/e2e/smoke/MODULE.bazel index 11aad36b5..c70a7043f 100644 --- a/e2e/smoke/MODULE.bazel +++ b/e2e/smoke/MODULE.bazel @@ -10,3 +10,23 @@ local_path_override( module_name = "aspect_bazel_lib", path = "../..", ) + +bazel_lib_toolchains = use_extension("@aspect_bazel_lib//lib:extensions.bzl", "toolchains") +bazel_lib_toolchains.copy_directory() +bazel_lib_toolchains.copy_to_directory() +bazel_lib_toolchains.jq() +bazel_lib_toolchains.yq() +bazel_lib_toolchains.coreutils() +bazel_lib_toolchains.tar() +bazel_lib_toolchains.expand_template() +use_repo(bazel_lib_toolchains, "bsd_tar_toolchains", "copy_directory_toolchains", "copy_to_directory_toolchains", "coreutils_toolchains", "expand_template_toolchains", "jq_toolchains", "yq_toolchains") + +register_toolchains( + "@copy_directory_toolchains//:all", + "@copy_to_directory_toolchains//:all", + "@jq_toolchains//:all", + "@yq_toolchains//:all", + "@bsd_tar_toolchains//:all", + "@coreutils_toolchains//:all", + "@expand_template_toolchains//:all", +) diff --git a/e2e/smoke/WORKSPACE b/e2e/smoke/WORKSPACE index 51c5b19e6..7b7c69010 100644 --- a/e2e/smoke/WORKSPACE +++ b/e2e/smoke/WORKSPACE @@ -3,13 +3,19 @@ local_repository( path = "../..", ) -load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_jq_toolchains", "register_yq_toolchains") +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_copy_directory_toolchains", "register_copy_to_directory_toolchains", "register_coreutils_toolchains", "register_expand_template_toolchains", "register_tar_toolchains") aspect_bazel_lib_dependencies() -register_jq_toolchains() +register_copy_directory_toolchains() -register_yq_toolchains() +register_copy_to_directory_toolchains() + +register_expand_template_toolchains() + +register_coreutils_toolchains() + +register_tar_toolchains() ############################################ # rules_go is needed to consume tools from sources diff --git a/lib/BUILD.bazel b/lib/BUILD.bazel index 3f1b13491..ddf71a39b 100644 --- a/lib/BUILD.bazel +++ b/lib/BUILD.bazel @@ -157,6 +157,12 @@ bzl_library( deps = ["//lib/private:diff_test"], ) +bzl_library( + name = "extension_utils", + srcs = ["extension_utils.bzl"], + deps = ["//lib/private:extension_utils"], +) + bzl_library( name = "write_source_files", srcs = ["write_source_files.bzl"], diff --git a/lib/extension_utils.bzl b/lib/extension_utils.bzl new file mode 100644 index 000000000..a56740693 --- /dev/null +++ b/lib/extension_utils.bzl @@ -0,0 +1,5 @@ +"Public API" + +load("//lib/private:extension_utils.bzl", _extension_utils = "extension_utils") + +extension_utils = _extension_utils diff --git a/lib/extensions.bzl b/lib/extensions.bzl index 3fd6fe89f..be6861caf 100644 --- a/lib/extensions.bzl +++ b/lib/extensions.bzl @@ -2,6 +2,16 @@ load( "@aspect_bazel_lib//lib:repositories.bzl", + "DEFAULT_COPY_DIRECTORY_REPOSITORY", + "DEFAULT_COPY_TO_DIRECTORY_REPOSITORY", + "DEFAULT_COREUTILS_REPOSITORY", + "DEFAULT_COREUTILS_VERSION", + "DEFAULT_EXPAND_TEMPLATE_REPOSITORY", + "DEFAULT_JQ_REPOSITORY", + "DEFAULT_JQ_VERSION", + "DEFAULT_TAR_REPOSITORY", + "DEFAULT_YQ_REPOSITORY", + "DEFAULT_YQ_VERSION", "register_copy_directory_toolchains", "register_copy_to_directory_toolchains", "register_coreutils_toolchains", @@ -10,17 +20,10 @@ load( "register_tar_toolchains", "register_yq_toolchains", ) +load("//lib:extension_utils.bzl", "extension_utils") load("//lib/private:host_repo.bzl", "host_repo") -def _toolchain_extension(mctx): - register_copy_directory_toolchains(register = False) - register_copy_to_directory_toolchains(register = False) - register_jq_toolchains(register = False) - register_yq_toolchains(register = False) - register_coreutils_toolchains(register = False) - register_tar_toolchains(register = False) - register_expand_template_toolchains(register = False) - +def _host_extension_impl(mctx): create_host_repo = False for module in mctx.modules: if len(module.tags.host) > 0: @@ -29,8 +32,76 @@ def _toolchain_extension(mctx): if create_host_repo: host_repo(name = "aspect_bazel_lib_host") -# TODO: some way for users to control repo name/version of the tools installed -ext = module_extension( - implementation = _toolchain_extension, - tag_classes = {"host": tag_class(attrs = {})}, +host = module_extension( + implementation = _host_extension_impl, + tag_classes = { + "host": tag_class(attrs = {}), + }, +) + +def _toolchains_extension_impl(mctx): + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.copy_directory, + toolchain_name = "copy_directory", + toolchain_repos_fn = lambda name, version: register_copy_directory_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.copy_to_directory, + toolchain_name = "copy_to_directory", + toolchain_repos_fn = lambda name, version: register_copy_to_directory_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.jq, + toolchain_name = "jq", + toolchain_repos_fn = lambda name, version: register_jq_toolchains(name = name, version = version, register = False), + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.yq, + toolchain_name = "yq", + toolchain_repos_fn = lambda name, version: register_yq_toolchains(name = name, version = version, register = False), + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.coreutils, + toolchain_name = "coreutils", + toolchain_repos_fn = lambda name, version: register_coreutils_toolchains(name = name, version = version, register = False), + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.tar, + toolchain_name = "tar", + toolchain_repos_fn = lambda name, version: register_tar_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, + ) + + extension_utils.toolchain_repos_bfs( + mctx = mctx, + get_tag_fn = lambda tags: tags.expand_template, + toolchain_name = "expand_template", + toolchain_repos_fn = lambda name, version: register_expand_template_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, + ) + +toolchains = module_extension( + implementation = _toolchains_extension_impl, + tag_classes = { + "copy_directory": tag_class(attrs = {"name": attr.string(default = DEFAULT_COPY_DIRECTORY_REPOSITORY)}), + "copy_to_directory": tag_class(attrs = {"name": attr.string(default = DEFAULT_COPY_TO_DIRECTORY_REPOSITORY)}), + "jq": tag_class(attrs = {"name": attr.string(default = DEFAULT_JQ_REPOSITORY), "version": attr.string(default = DEFAULT_JQ_VERSION)}), + "yq": tag_class(attrs = {"name": attr.string(default = DEFAULT_YQ_REPOSITORY), "version": attr.string(default = DEFAULT_YQ_VERSION)}), + "coreutils": tag_class(attrs = {"name": attr.string(default = DEFAULT_COREUTILS_REPOSITORY), "version": attr.string(default = DEFAULT_COREUTILS_VERSION)}), + "tar": tag_class(attrs = {"name": attr.string(default = DEFAULT_TAR_REPOSITORY)}), + "expand_template": tag_class(attrs = {"name": attr.string(default = DEFAULT_EXPAND_TEMPLATE_REPOSITORY)}), + }, ) diff --git a/lib/private/BUILD.bazel b/lib/private/BUILD.bazel index 115aea46b..93a96f853 100644 --- a/lib/private/BUILD.bazel +++ b/lib/private/BUILD.bazel @@ -105,6 +105,12 @@ bzl_library( ], ) +bzl_library( + name = "extension_utils", + srcs = ["extension_utils.bzl"], + visibility = ["//lib:__subpackages__"], +) + bzl_library( name = "docs", srcs = ["docs.bzl"], diff --git a/lib/private/extension_utils.bzl b/lib/private/extension_utils.bzl new file mode 100644 index 000000000..006ad09af --- /dev/null +++ b/lib/private/extension_utils.bzl @@ -0,0 +1,104 @@ +"""Utility functions for bzlmod extensions""" + +def _toolchain_repos_bfs(mctx, get_tag_fn, toolchain_name, toolchain_repos_fn, default_repository = None, get_name_fn = None, get_version_fn = None): + """Create toolchain repositories from bzlmod extensions using a breadth-first strategy. + + Toolchains are assumed to have a "default" or canonical repository name so that across + all invocations of the module extension with that name only a single toolchain repository + is created. As such, it is recommended to default the toolchain name in the extension's + tag class attributes so that diverging from the canonical name is a special case. + + The resolved toolchain version will be the one invoked closest to the root module, following + Bazel's breadth-first ordering of modules in the dependency graph. + + For example, given the module extension usage in a MODULE file: + + ```starlark + ext = use_extension("@my_lib//lib:extensions.bzl", "ext") + + ext.foo_toolchain(version = "1.2.3") # Default `name = "foo"` + + use_repo(ext, "foo") + + register_toolchains( + "@foo//:all", + ) + ``` + + This macro would be used in the module extension implementation as follows: + + ```starlark + extension_utils.toolchain_repos( + mctx = mctx, + get_tag_fn = lambda tags: tags.foo_toolchain, + toolchain_name = "foo", + toolchain_repos_fn = lambda name, version: register_foo_toolchains(name = name, register = False), + get_version_fn = lambda attr: None, + ) + ``` + + Where `register_foo_toolchains` is a typical WORKSPACE macro used to register + the foo toolchain for a particular version, minus the actual registration step + which is done separately in the MODULE file. + + This macro enforces that only root MODULEs may use a different name for the toolchain + in case several versions of the toolchain repository is desired. + + Args: + mctx: The module context + get_tag_fn: A function that takes in `module.tags` and returns the tag used for the toolchain. + For example, `tag: lambda tags: tags.foo_toolchain`. This is required because `foo_toolchain` + cannot be accessed as a simple string key from `module.tags`. + toolchain_name: Name of the toolchain to use in error messages + toolchain_repos_fn: A function that takes (name, version) and creates a toolchain repository. This lambda + should call a typical reposotiory rule to create toolchains. + default_repository: Default name of the toolchain repository to pass to the repos_fn. + By default, it equals `toolchain_name`. + get_name_fn: A function that extracts the module name from the toolchain tag's attributes. Defaults + to grabbing the `name` attribute. + get_version_fn: A function that extracts the module version from the a tag's attributes. Defaults + to grabbing the `version` attribute. Override this to a lambda that returns `None` if + version isn't used as an attribute. + """ + if default_repository == None: + default_repository = toolchain_name + + if get_name_fn == None: + get_name_fn = lambda attr: attr.name + if get_version_fn == None: + get_version_fn = lambda attr: attr.version + + registrations = {} + for mod in mctx.modules: + for attr in get_tag_fn(mod.tags): + name = get_name_fn(attr) + version = get_version_fn(attr) + if name != default_repository and not mod.is_root: + fail("Only the root module may provide a name for the {}} toolchain.".format(toolchain_name)) + + if name in registrations.keys(): + if name == default_repository: + # Prioritize the root-most registration of the default toolchain version and + # ignore any further registrations (modules are processed breadth-first) + continue + if version == registrations[name]: + # No problem to register a matching toolchain twice + continue + fail("Multiple conflicting {} toolchains declared for name {} ({} and {})".format( + toolchain_name, + name, + version, + registrations[name], + )) + else: + registrations[name] = version + + for name, version in registrations.items(): + toolchain_repos_fn( + name = name, + version = version, + ) + +extension_utils = struct( + toolchain_repos_bfs = _toolchain_repos_bfs, +) diff --git a/lib/repositories.bzl b/lib/repositories.bzl index af3dbb3aa..9caf3b1d6 100644 --- a/lib/repositories.bzl +++ b/lib/repositories.bzl @@ -23,23 +23,10 @@ def aspect_bazel_lib_dependencies(): ], ) - # Always register the copy_to_directory toolchain - register_copy_directory_toolchains() - register_copy_to_directory_toolchains() - - # Always register the expand_template toolchain - register_expand_template_toolchains() - - # Always register the coreutils toolchain and the tar toolchain - register_coreutils_toolchains() - register_tar_toolchains() - -# Re-export the default versions +DEFAULT_JQ_REPOSITORY = "jq" DEFAULT_JQ_VERSION = _DEFAULT_JQ_VERSION -DEFAULT_YQ_VERSION = _DEFAULT_YQ_VERSION -DEFAULT_COREUTILS_VERSION = _DEFAULT_COREUTILS_VERSION -def register_jq_toolchains(name = "jq", version = DEFAULT_JQ_VERSION, register = True): +def register_jq_toolchains(name = DEFAULT_JQ_REPOSITORY, version = DEFAULT_JQ_VERSION, register = True): """Registers jq toolchain and repositories Args: @@ -64,7 +51,10 @@ def register_jq_toolchains(name = "jq", version = DEFAULT_JQ_VERSION, register = user_repository_name = name, ) -def register_yq_toolchains(name = "yq", version = DEFAULT_YQ_VERSION, register = True): +DEFAULT_YQ_REPOSITORY = "yq" +DEFAULT_YQ_VERSION = _DEFAULT_YQ_VERSION + +def register_yq_toolchains(name = DEFAULT_YQ_REPOSITORY, version = DEFAULT_YQ_VERSION, register = True): """Registers yq toolchain and repositories Args: @@ -89,7 +79,9 @@ def register_yq_toolchains(name = "yq", version = DEFAULT_YQ_VERSION, register = user_repository_name = name, ) -def register_tar_toolchains(name = "bsd_tar", register = True): +DEFAULT_TAR_REPOSITORY = "bsd_tar" + +def register_tar_toolchains(name = DEFAULT_TAR_REPOSITORY, register = True): """Registers bsdtar toolchain and repositories Args: @@ -110,7 +102,10 @@ def register_tar_toolchains(name = "bsd_tar", register = True): user_repository_name = name, ) -def register_coreutils_toolchains(name = "coreutils", version = DEFAULT_COREUTILS_VERSION, register = True): +DEFAULT_COREUTILS_REPOSITORY = "coreutils" +DEFAULT_COREUTILS_VERSION = _DEFAULT_COREUTILS_VERSION + +def register_coreutils_toolchains(name = DEFAULT_COREUTILS_REPOSITORY, version = DEFAULT_COREUTILS_VERSION, register = True): """Registers coreutils toolchain and repositories Args: @@ -133,7 +128,9 @@ def register_coreutils_toolchains(name = "coreutils", version = DEFAULT_COREUTIL user_repository_name = name, ) -def register_copy_directory_toolchains(name = "copy_directory", register = True): +DEFAULT_COPY_DIRECTORY_REPOSITORY = "copy_directory" + +def register_copy_directory_toolchains(name = DEFAULT_COPY_DIRECTORY_REPOSITORY, register = True): """Registers copy_directory toolchain and repositories Args: @@ -166,7 +163,9 @@ def register_copy_directory_toolchains(name = "copy_directory", register = True) user_repository_name = name, ) -def register_copy_to_directory_toolchains(name = "copy_to_directory", register = True): +DEFAULT_COPY_TO_DIRECTORY_REPOSITORY = "copy_to_directory" + +def register_copy_to_directory_toolchains(name = DEFAULT_COPY_TO_DIRECTORY_REPOSITORY, register = True): """Registers copy_to_directory toolchain and repositories Args: @@ -199,7 +198,9 @@ def register_copy_to_directory_toolchains(name = "copy_to_directory", register = user_repository_name = name, ) -def register_expand_template_toolchains(name = "expand_template", register = True): +DEFAULT_EXPAND_TEMPLATE_REPOSITORY = "expand_template" + +def register_expand_template_toolchains(name = DEFAULT_EXPAND_TEMPLATE_REPOSITORY, register = True): """Registers expand_template toolchain and repositories Args: