Search code examples
bazelbzlmod

Bzlmod Local Registry - BUILD files for Modules for Non-Bazel Targets


I'm trying to create a local bzlmod registry to serve as a common location for deps not yet in BCR (as well as dependencies between my own personal projects). Some of these are not in Bazel. The old way I'd do things was to use http_archive and provide a build_file_content to construct a top-level BUILD file. For deps coming from Maven, I wrote a tiny repo rule:

new_simple_repo.bzl

def _new_simple_repo_impl(ctx):
  path = ctx.attr.path
  if len(path) > 0 and path[-1] != '/':
      path += '/'
  path += "BUILD"
  ctx.file(path, ctx.attr.build_file_content)


new_simple_repo = repository_rule(
    implementation = _new_simple_repo_impl,
    attrs = {
        "path": attr.string(),
        "build_file_content": attr.string(
            mandatory = True,
        ),
    }
)

That would allow me to create a repo with a custom name and specify targets that pointed to the maven repo's various artifacts.

In bzlmod world, it looks like the registry modules themselves use source.json, which functions similarly to http_archive, but there doesn't seem to be an equivalent to build_file_content so I'm left without a BUILD file and my dependent code fails with the (expected) error: BUILD file not found in directory '' of external repository...

More specifics on what I've tried:

I started my local repository with something simple: Google errorprone, which doesn't have any other dependencies. So in addition to the files in the base directory, I just have a modules/errorprone/2.24.1 directory with:

# source.json
{
  "strip_prefix": "error-prone-2.24.1",
  "integrity": "sha256-VenHE87dQDRkKf6vj1fyacYr9Aqg9JCggIZYW9v9Xns=",
  "url": "https://github.com/google/error-prone/archive/refs/tags/v2.24.1.zip",
}
# MODULE.bazel
module(
    name = "errorprone",
    compatibility_level = 2,
    version = "2.24.1",
)

And then in my very simple project to test the registry I have a very simple class that uses an errorprone annotation and:

# java/com/bdl/experimenting/localregistry/BUILD
java_library(
    name = "localregistry",
    srcs = glob(["*.java"]),
    deps = [
        "@errorprone//:annotations", # this target doesn't exist at the moment.
    ],
)

I thought maybe I could use patches to add in the BUILD file, so cribbing from some simple patches in BCR (I'm not 100% sure on how the patch stuff works) I tried adding the following in my registry:

# patches/0001-Add-BUILD-file.patch
--- a/BUILD.bazel
+++ a/BUILD.bazel
@@ -0,0 +1,7 @@
+package(default_visibility = ["//visibility:public"])
+
+java_library(
+    name = "annotations", # But I'm trying to create it here.
+    srcs = glob(["annotations/src/main/java/com/google/annotations/*.java"]),
+)
+

and then modifying the source.json

# source.json (with patch)
{
  "strip_prefix": "error-prone-2.24.1",
  "integrity": "sha256-VenHE87dQDRkKf6vj1fyacYr9Aqg9JCggIZYW9v9Xns=",
  "url": "https://github.com/google/error-prone/archive/refs/tags/v2.24.1.zip",
  "patches": {
    "0001-Add-BUILD-file.patch": "sha256-55+lFBFSqt1yHdsgrrVw/vMwCwAmUoew+07iXprfCb8="
  }
}

but that didn't help.

So maybe what I need is a module extension to take the place of my new_simple_repo rule. But for that rule, it was always used with maven installs, so the assumption was that there would be @maven_whatever//:maven_target targets to point to. In the bzlmod world, I'd need to have srcs pointing to the repo contents instead, and I'm not sure how that would connect in.

And as a side note, if I wanted a module that was coming only from a bunch of maven targets (I could use the maven extension for this no problem), it seems it would still want something in source.json, so I'm not sure how that would work (though I haven't experimented with it yet).


Solution

  • I think there is an error in your patch file

    Change

    --- a/BUILD.bazel
    +++ a/BUILD.bazel
    

    to

    --- /dev/null
    +++ BUILD.bazel
    

    You can also live without a registry. Just make use of local_path_override:

    bazel_dep(name = "some_dependency")  # Does not need to be in any registry
    local_path_override(
        module_name = "some_dependency",
        path = "../third_party/some_dependency",
    )
    

    Of course, you have then to apply our patches directly to the "../third_party/some_dependency" directory