Hello,
I am trying to use the new BzlMod feature to manage external repositories whose content is
already extracted in the project's source tree. The idea is that all downloads of third-party code should be performed up-front using a tool like
repo,
gclient or git sub-modules, then the build itself would not be allowed to download extra things from the network, and should avoid extracting archives into the bazel output root, if not necessary. I believe this corresponds to the "entreprise use-case" and "offline build" in the
original BzlMod design doc.
I have experimented with different ways to achieve that, and uploaded the results at
https://github.com/digit-google/bazel-experiments/tree/main/bzlmod-prebuilt-modules for others to see. I have a few questions for the Bazel team:
1) When do we expect native.local_repository() to work in module extensions?
2) Any chance to have the --registry option support (relative) file paths, in addition to URLs, to access a local registry?
3) Any chance we can have a local registry that contains source.json files that points to pre-extracted directories, instead of tarball archives? Possibly using relative file paths? If so, what would be a good way to check for integrity?
For the record, for the Fuchsia platform build (which is not using Bazel at the moment), where we expect to see a few dozen of external repositories. Without BzlMod, our alternative is to manually patch all WORKSPACE files from these dependencies, which is simply not scalable, pleasant or maintainable, which is why I am enthusiastic and grateful for BzlMod to exist :-)
For the sake of completeness, here's the result of my experiments (which will explain ny questions):
What works:
local-module-directoriesa top-level MODULE.bazel file that uses bazel_dep() and local_path_override() to override the path of each repository. This forces the project's MODULE.bazel file to know the exact location of each versioned external workspace. I verified that the final output base did contain symlinks to these workspaces, instead of trying to copy them, so everything is fine, except for the annoyance that we need to maintain the content of this MODULE.bazel file manually to ensure it is always in sync with the other repo/gclient/submodules manifest, which is annoying.
local-register-with-urls
This uses a local registry whose source.json points to compressed archives of the external repo with file:/// URLs. However, because file:// URLs can only be absolute, this requires generating the content of the source.json file as well as the .bazelrc file (which contains the `common --registry file:///absolute/path/to/registry) to adapt them to the checkout's final absolute location. Also this still requires compressed archives, which sometimes need to be patched to support BzlMode (for example bazel-skylib-1.0.3.tar.gz does not include a WORKSPACE file and is thus unusable as-is with BzlMod).
What does not work:
local-module-extensions
Trying to use an intermediate module that provides an extension that creates all the remote repositories through a starlark function. Ideally, this would allow reading the repo manifest and generating the local_path_override() objects automatically from it. Unfortunately, this does not work because native.local_repository() does not work in module extensions. This is actually documented as footnote 2 in the
BzlMod Migration Guide so there is hope this will be solved at some point.
local-registry-with-files
Trying to setup a local registry that contains source.json files whose "url" entry points to the prebuilt directory (e.g. "url": "file:///....../prebuilt/platforms-0.0.4"). This does not work because Bazel really expects an archive file path instead of a directory path. From the
current code. Also an "integrity" value is needed, and I didn't find a way to create one from a prebuilt directory.
Also note that the --registry option expects a URL, when using a file path instead (e.g. --registry path/to/registry), Bazel crashes with an exception (see
this README.md for details).
It works if a file:// URL is used, but these are always absolute paths (the URL spec does not support relative file paths), which forces the .bazelrc file that contains the option to be auto-generated to adjust to the absolute checkout path directory, which is slightly annoying.
Thanks for BzlMod,
- Digit
Fuchsia Build Team