121 lines
4.9 KiB
Python
121 lines
4.9 KiB
Python
# 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`. The extension is marked as reproducible if supported by the current
|
|
version of Bazel and thus doesn't result in a lockfile entry.
|
|
"""
|
|
|
|
def _ext_impl(module_ctx):
|
|
macro()
|
|
|
|
# Setting `reproducible` is safe since `macro`, as a function without parameters, must be
|
|
# deterministic.
|
|
return _use_all_repos(module_ctx, reproducible = True)
|
|
|
|
kwargs = {}
|
|
if doc != None:
|
|
kwargs["doc"] = doc
|
|
|
|
return module_extension(
|
|
implementation = _ext_impl,
|
|
**kwargs
|
|
)
|
|
|
|
def _use_all_repos(module_ctx, reproducible = False):
|
|
"""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.
|
|
reproducible: The value of the `reproducible` parameter to pass to the
|
|
[`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html)
|
|
object returned by this function. This is safe to set with Bazel versions that don't
|
|
support this parameter and will be ignored in that case.
|
|
|
|
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
|
|
|
|
# module_ctx.extension_metadata has the paramater `reproducible` as of Bazel 7.1.0. We can't
|
|
# test for it directly and would ideally use bazel_features to check for it, but adding a
|
|
# dependency on it would require complicating the WORKSPACE setup for skylib. Thus, test for
|
|
# it by checking the availability of another feature introduced in 7.1.0.
|
|
extension_metadata_kwargs = {}
|
|
if hasattr(module_ctx, "watch"):
|
|
extension_metadata_kwargs["reproducible"] = reproducible
|
|
|
|
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",
|
|
**extension_metadata_kwargs
|
|
)
|
|
|
|
modules = struct(
|
|
as_extension = _as_extension,
|
|
use_all_repos = _use_all_repos,
|
|
)
|