Search code examples
bazelbzlmod

How to provide a MODULE.bazel file to local_path_override?


I search for a way to provide a MODULE.bazel file to local_path_override.

Example:

MODULE.bazel:

bazel_dep(name = "fmt", version = "10.1.1")

local_path_override(
    module_name = "fmt",
    # Local copy of https://github.com/fmtlib/fmt at some newer commit as 10.1.1
    # Does not have a MODULE.bazel file
    path = "../third_party/fmt",
)

What I actually want to do is something like this:

bazel_dep(name = "fmt", version = "10.1.1")

local_path_override(
    module_name = "fmt",
    module_file = "//:fmt.MODULE.bazel", # provide a MODULE.bazel file here
    # Local copy of https://github.com/fmtlib/fmt at some newer commit as 10.1.1
    # Does not have a MODULE.bazel file
    path = "../third_party/fmt",
)

I want to provide a MODULE.bazel from outside, since the local copy does not have one. Please note that the attribute module_file does not exist and was just an idea how I could imagine how this could work.

Using a WORKSPACE approach it worked this way:

new_local_repository(
    name = "fmt",
    build_file = "//:fmt.BUILD",
    path = "../third_party/fmt",
)

I search for something similar in the Bzlmod world.

I was also thinking if I could use archive_override providing the MODULE.bazel file as a patch. It seems that archive_override can handle file:// URLs, but as for as I understand this does not work with relative path names (such as ../third_party/fmt) and would require me to define an absolute system specific path.

BTW: I am using Bazel 6.3.2


Solution

  • Ondrej K. is right. The doc states:

    To perform module resolution, Bazel starts by reading the root module's MODULE.bazel file, and then repeatedly requests any dependency's MODULE.bazel file from a Bazel registry until it discovers the entire dependency graph.

    By default, Bazel then selects one version of each module to use. Bazel represents each module with a repo, and consults the registry again to learn how to define each of the repos.

    That's why MODULE.bazel files are embedded into the registries. They are accessed before the actual versions are chosen, i.e. fetched for real. Patching them thereafter has no effect.

    To override a dependency's MODULE.bazel, the way I do it is by creating a local registry. It's kind of overkill, but I doubt there would be another way, as of now (Bazel 7.1).

    Say you want to override curl version 8.4.0:

    1. Create a directory, e.g. registry,
    2. Add the following to .bazelrc:
      common --registry=file:///%workspace%/registry
      common --registry=https://bcr.bazel.build
      
    3. Put that file into registry,
    4. Create tree registry/modules/curl with that content . Remove other versions (directories and from metadata.json).
    5. Add a patch in registry/modules/curl/8.4.0/patches and reference it in registry/modules/curl/8.4.0/source.json. Dict values are integrity metadata, e.g. "sha256-" + base64_encode(hash).
    6. Run bazel shutdown and bazel build --lockfile_mode=off to refresh resolution data.