bazelbuild / bazelbuild/bazel

FR: allow modules to define aliases for extensions

Open
#25,112 1 comment 0 reactions 1 assignee Assigned to @Wyverald View on GitHub
area-Bzlmod P2 team-ExternalDeps type: feature request
Dominant language
Java
Stars
25.8k
Forks
4.6k
Avg merge
2d 20h
Merged PRs (30d)
72

Description

### Description of the feature request:

Today, a problem module extension owners have is its very difficult to refactor or grow the APIs for their module extensions. Effectively, they are locked into the `(path, name)` they initially choose. Trying to refactor an extension means either (a) changing the path (which breaks dependencies), or (b) using a new path (and then neither extension can see info about the other, even though they do the same thing). Similar problems occur if trying to merge different extensions into one extension.

The net effect is authors have to make the perfect choice on their first try, which is when they're least likely to do so. As an example, many modules put all their extensions in a single `extensions.bzl`. Meanwhile, the advice is to have separate files for each extension because it allows, if desired in the future, one extension to load() files generated by another.

To help address this, I propose having a way for MODULE files to say that one `(path, name)` has the same underlying identity as another `(path, name)`. The overarching goal is to give module and extension owners some flexibility in refactoring and growing their bzlmod-phase APIs.

e.g., if I was factoring `extensions.bzl%foo` into a separate file, `foo_overrides.bzl%foo_overrides`, in my MODULE file I would put:

```
# lang's MODULE.bazel
module_extension_alias(":extensions.bzl", "foo", actual_bzl="foo_overrides.bzl", actual_name="foo_overrides")
```

Under the hood, Bazel would transparently give `use_extension(":extensions.bzl", "foo")` the internal identifier of `foo_overrides.bzl%foo_overrides`. And thus when a user does:

```
# userA's MODULE.bazel
foo = use_extension("@lang//:extensions.bzl", "foo")

# userB's MODULE.bazel
foo = use_extension("@lang//:foo_overrides.bzl", "foo_overrides")
```

They merge into the same bzlmod thing (not sure on what the internal terms are), such that in the module_extension implementation, it sees the calls from both usages.

I don't know much about how things work internally, so don't want to proscribe much.

I think the first-order use case is:
* I have a monolithic extensions.bzl file and want to split it up into one-file-per-extension. ("Oops, I didn't know I would need to split them up"). IMHO, this is probably the most common.

Second order:
* I have multiple extensions and want to merge them into one extension. ("Oops, I was too aggressive and split things up too much" or "Argh, I followed best practices, but it turns out one extension needs to see the tag class calls of the other extension"). (As an aside, a different solution to this problem is to somehow allow an extension to somehow see another extension)

cc @Wyverald

### Which category does this issue belong to?

External Dependency

### What underlying problem are you trying to solve with this feature?

_No response_

### Which operating system are you running Bazel on?

_No response_

### What is the output of `bazel info release`?

_No response_

### If `bazel info release` returns `development version` or `(@non-git)`, tell us how you built Bazel.

_No response_

### What's the output of `git remote get-url origin; git rev-parse HEAD` ?

```text

```

### Have you found anything relevant by searching the web?

_No response_

### Any other information, logs, or outputs that you want to share?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.