user12398505
user12398505

Reputation:

Bazel: relative local path as url in http_archive()

I am trying to include an external library into my Bazel project. It is a commercial, closed source software library that comes as a bunch of .h and .a files in a tar file (Linux). There is no public download link, you have to download the archive manually somewhere.

Thus, I checked the library archives into Git (let's not discuss this here) in vendor/ and use

http_archive(
    name = "library_name",
    build_file = "//third_party:library_name.BUILD",
    sha256 = "12165fbcbac............",
    urls = ["file:///home/myuser/git/repo/vendor/libraryname.tar.gz"],
)

I would like to not use an absolute path in urls=, so my coworkers can checkout and build the library without hassle. How can I use a relative path with http_archive()?

I have looked at this answer, but it seems to be not exactly the same problem and the example is incomplete.

Upvotes: 8

Views: 7684

Answers (1)

Brian Silverman
Brian Silverman

Reputation: 3858

A very simple custom repository rule can do that for you. repository_ctx.extract does all the heavy lifting. I wrote this up just now as a barebones example:

def _test_archive_impl(repository_ctx):
  repository_ctx.extract(repository_ctx.attr.src)
  repository_ctx.file("BUILD.bazel", repository_ctx.read(repository_ctx.attr.build_file))

test_archive = repository_rule(
    attrs = {
        "src": attr.label(mandatory = True, allow_single_file = True),
        "build_file": attr.label(mandatory = True, allow_single_file = True),
    },
    implementation = _test_archive_impl,
)

For your basic use case, you might not need any changes to that (besides a better name). Adding the ability to pass stripPrefix through would be straightforward. Depending on your use case, build_file_contents like other rules have instead of build_file might be useful too.

For reference, here's the WORKSPACE I used for testing (the rule definition above was in test.bzl):

load("//:test.bzl", "test_archive")

test_archive(
    name = "test_repository",
    src = "//:test.tar.gz",
    build_file = "//:test.BUILD",
)

As an alternative to all of that, you could just check in the files from the archive and then use new_local_repository instead. Easier to work with in some ways, harder in others.

Upvotes: 6

Related Questions