-
-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: backport 2.x features for interoperability (#657)
- Loading branch information
Showing
10 changed files
with
269 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
"""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 resolution 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, | ||
) |
Oops, something went wrong.