Search code examples
bazel

Emulate http_file but for a file from another repository


I'm including a repository that has an extra_deps rule of the form:

maybe(
    http_file,
    name = "external_dependency",
    downloaded_file_path = "foo.h",
    sha256 = "<some_sha>",
    urls = ["https://example.com/foo.h"],
)

If I have an existing repository, foo_repo, that provides foo.h, how can I substitute the target for it in place of external_dependency? http_file apparently provides @external_dependency//file, so I can't simply define an alias.


Solution

  • Using https://github.com/bazelbuild/bazel/blob/master/tools/build_defs/repo/http.bzl as a reference, you can define a custom repository rule that provides @external_dependency//file. For example:

    def _repository_file(ctx):
        ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
        ctx.file("file/BUILD.bazel", """
    filegroup(
        name = "file",
        srcs = ["{}"],
        visibility = ["//visibility:public"],
    )
    """.format(ctx.attr.source))
    
    repository_file = repository_rule(
        attrs = {"source": attr.label(mandatory = True, allow_single_file = True)},
        implementation = _repository_file,
        doc = """Analogue of http_file, but for a file in another repository.
    
    Usage:
    repository_file(
        name = "special_file"
        source = "@other_repo//path/to:special_file.txt",
    )
        """,
    )
    

    Now use:

    repository_file(
        name = "external_dependency",
        source = "@foo_repo//path/to:foo.h",
    )