-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add helper functions for module extensions as
modules
(#456)
Adds a new module `modules` with two helper functions for module extensions: * `use_all_repos` makes it easy to return an appropriate `extension_metadata` from a module extension (if supported) to indicate that all repositories generated by the extension should be imported via `use_repo`. * `as_extension` turns a WORKSPACE macro into a module extension that uses `use_all_repos` to automate the generation of `use_repo` calls.
- Loading branch information
Showing
8 changed files
with
266 additions
and
0 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
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,76 @@ | ||
<!-- Generated with Stardoc: http://skydoc.bazel.build --> | ||
|
||
Skylib module containing utilities for Bazel modules and module extensions. | ||
|
||
<a id="modules.as_extension"></a> | ||
|
||
## modules.as_extension | ||
|
||
<pre> | ||
modules.as_extension(<a href="#modules.as_extension-macro">macro</a>, <a href="#modules.as_extension-doc">doc</a>) | ||
</pre> | ||
|
||
Wraps a WORKSPACE dependency macro into a module extension. | ||
|
||
Example: | ||
```starlark | ||
def rules_foo_deps(optional_arg = True): | ||
some_repo_rule(name = "foobar") | ||
http_archive(name = "bazqux") | ||
|
||
rules_foo_deps_ext = modules.as_extension(rules_foo_deps) | ||
``` | ||
|
||
|
||
**PARAMETERS** | ||
|
||
|
||
| Name | Description | Default Value | | ||
| :------------- | :------------- | :------------- | | ||
| <a id="modules.as_extension-macro"></a>macro | A [WORKSPACE dependency macro](https://bazel.build/rules/deploying#dependencies), i.e., a function with no required parameters that instantiates one or more repository rules. | none | | ||
| <a id="modules.as_extension-doc"></a>doc | A description of the module extension that can be extracted by documentation generating tools. | <code>None</code> | | ||
|
||
**RETURNS** | ||
|
||
A module extension that generates the repositories instantiated by the given macro and also | ||
uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be | ||
imported via `use_repo`. | ||
|
||
|
||
<a id="modules.use_all_repos"></a> | ||
|
||
## modules.use_all_repos | ||
|
||
<pre> | ||
modules.use_all_repos(<a href="#modules.use_all_repos-module_ctx">module_ctx</a>) | ||
</pre> | ||
|
||
Return from a module extension that should have all its repositories imported via `use_repo`. | ||
|
||
Example: | ||
```starlark | ||
def _ext_impl(module_ctx): | ||
some_repo_rule(name = "foobar") | ||
http_archive(name = "bazqux") | ||
return modules.use_all_repos(module_ctx) | ||
|
||
ext = module_extension(_ext_impl) | ||
``` | ||
|
||
|
||
**PARAMETERS** | ||
|
||
|
||
| Name | Description | Default Value | | ||
| :------------- | :------------- | :------------- | | ||
| <a id="modules.use_all_repos-module_ctx"></a>module_ctx | The [<code>module_ctx</code>](https://bazel.build/rules/lib/builtins/module_ctx) object passed to the module extension's implementation function. | none | | ||
|
||
**RETURNS** | ||
|
||
An [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) | ||
object that, when returned from a module extension implementation function, specifies that all | ||
repositories generated by this extension should be imported via `use_repo`. If the current | ||
version of Bazel doesn't support `extension_metadata`, returns `None` instead, which can | ||
safely be returned from a module extension implementation function in all versions of Bazel. | ||
|
||
|
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,99 @@ | ||
# Copyright 2023 The Bazel Authors. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Skylib module containing utilities for Bazel modules and module extensions.""" | ||
|
||
def _as_extension(macro, doc = None): | ||
"""Wraps a WORKSPACE dependency macro into a module extension. | ||
Example: | ||
```starlark | ||
def rules_foo_deps(optional_arg = True): | ||
some_repo_rule(name = "foobar") | ||
http_archive(name = "bazqux") | ||
rules_foo_deps_ext = modules.as_extension(rules_foo_deps) | ||
``` | ||
Args: | ||
macro: A [WORKSPACE dependency macro](https://bazel.build/rules/deploying#dependencies), i.e., | ||
a function with no required parameters that instantiates one or more repository rules. | ||
doc: A description of the module extension that can be extracted by documentation generating | ||
tools. | ||
Returns: | ||
A module extension that generates the repositories instantiated by the given macro and also | ||
uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be | ||
imported via `use_repo`. | ||
""" | ||
|
||
def _ext_impl(module_ctx): | ||
macro() | ||
return _use_all_repos(module_ctx) | ||
|
||
return module_extension( | ||
implementation = _ext_impl, | ||
doc = doc, | ||
) | ||
|
||
def _use_all_repos(module_ctx): | ||
"""Return from a module extension that should have all its repositories imported via `use_repo`. | ||
Example: | ||
```starlark | ||
def _ext_impl(module_ctx): | ||
some_repo_rule(name = "foobar") | ||
http_archive(name = "bazqux") | ||
return modules.use_all_repos(module_ctx) | ||
ext = module_extension(_ext_impl) | ||
``` | ||
Args: | ||
module_ctx: The [`module_ctx`](https://bazel.build/rules/lib/builtins/module_ctx) object | ||
passed to the module extension's implementation function. | ||
Returns: | ||
An [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) | ||
object that, when returned from a module extension implementation function, specifies that all | ||
repositories generated by this extension should be imported via `use_repo`. If the current | ||
version of Bazel doesn't support `extension_metadata`, returns `None` instead, which can | ||
safely be returned from a module extension implementation function in all versions of Bazel. | ||
""" | ||
|
||
# module_ctx.extension_metadata is available in Bazel 6.2.0 and later. | ||
# If not available, returning None from a module extension is equivalent to not returning | ||
# anything. | ||
extension_metadata = getattr(module_ctx, "extension_metadata", None) | ||
if not extension_metadata: | ||
return None | ||
|
||
# module_ctx.root_module_has_non_dev_dependency is available in Bazel 6.3.0 and later. | ||
root_module_has_non_dev_dependency = getattr( | ||
module_ctx, | ||
"root_module_has_non_dev_dependency", | ||
None, | ||
) | ||
if root_module_has_non_dev_dependency == None: | ||
return None | ||
|
||
return extension_metadata( | ||
root_module_direct_deps = "all" if root_module_has_non_dev_dependency else [], | ||
root_module_direct_dev_deps = [] if root_module_has_non_dev_dependency else "all", | ||
) | ||
|
||
modules = struct( | ||
as_extension = _as_extension, | ||
use_all_repos = _use_all_repos, | ||
) |
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,70 @@ | ||
# Copyright 2017 The Bazel Authors. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
"""Test usage of modules.bzl.""" | ||
|
||
load("//lib:modules.bzl", "modules") | ||
load("//rules:build_test.bzl", "build_test") | ||
|
||
def _repo_rule_impl(repository_ctx): | ||
repository_ctx.file("WORKSPACE") | ||
repository_ctx.file("BUILD", """exports_files(["hello"])""") | ||
repository_ctx.file("hello", "Hello, Bzlmod!") | ||
|
||
_repo_rule = repository_rule(_repo_rule_impl) | ||
|
||
def _workspace_macro(register_toolchains = False): | ||
_repo_rule(name = "foo") | ||
_repo_rule(name = "bar") | ||
if register_toolchains: | ||
native.register_toolchains() | ||
|
||
as_extension_test_ext = modules.as_extension( | ||
_workspace_macro, | ||
doc = "Only used for testing modules.as_extension().", | ||
) | ||
|
||
def _use_all_repos_ext_impl(module_ctx): | ||
_repo_rule(name = "baz") | ||
_repo_rule(name = "qux") | ||
return modules.use_all_repos(module_ctx) | ||
|
||
use_all_repos_test_ext = module_extension( | ||
_use_all_repos_ext_impl, | ||
doc = "Only used for testing modules.use_all_repos().", | ||
) | ||
|
||
# buildifier: disable=unnamed-macro | ||
def modules_test_suite(): | ||
"""Creates the tests for modules.bzl if Bzlmod is enabled.""" | ||
|
||
is_bzlmod_enabled = str(Label("//tests:module_tests.bzl")).startswith("@@") | ||
if not is_bzlmod_enabled: | ||
return | ||
|
||
build_test( | ||
name = "modules_as_extension_test", | ||
targets = [ | ||
"@foo//:hello", | ||
"@bar//:hello", | ||
], | ||
) | ||
|
||
build_test( | ||
name = "modules_use_all_repos_test", | ||
targets = [ | ||
"@baz//:hello", | ||
"@qux//:hello", | ||
], | ||
) |