Search code examples
bazelpatchbazel-rules

With Bazels `http_archive` - is there a way to add already existing files to the extracted sources?


With Bazel I'm building an external library using http_archive together with some patches which bring additional features:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    http_archive(
        name="some-lib",
        build_file="@my-project//some-lib:BUILD.some-lib",
        url="https://example/download/some-lib.tar.gz",
        sha256="8d9405baf113a9f25e4fb961d56f9f231da02e3ada0f41dbb0fa4654534f717b",
        patches=[
            "//some-lib/patches:01-add-additional-features.dif",
        ],
        patch_args=["-p1"],
        patch_tool="patch",
    )

The file structure looks like this:

some-lib
├── BUILD
├── BUILD.some-lib
├── include/additional_features.h
├── some-lib.bzl
└── patches
    ├── 01-add-additional-features.dif
    └── BUILD

This basically works but I still struggle with adding include/additional_features.h into the extracted source folder.

I first tried to just list the file in the filegroup I use to later run configure_make like this:

filegroup(
    name="all_srcs",
    srcs=glob(["**"]) + ["@my-project//some-lib:include/additional_features.h"],
)

then I'm getting

no such target '//some-lib:includes/additional_features.h': target 'includes/additional_features.h' not declared in package 'some-lib'; however, a source file of this name exists.

My next idea was to use the tools http_archive provides to make the file part of the source folder. While you can use patches to modify the extracted folder you'd need a dedicated dif file just to create the extra header file, which then you would have to create in advance (i.E. create a Bazel rule) and declare it a dependency etc.. which I'd like to avoid to keep things simple.

There is also patch_cmds which next to patches can be used to modify the extracted source folder by running arbitrary bash commands so I tried something like this:

    patch_cmds=[
        "cp @my-project//some-lib:include/additional_features.h include/",
    ],

but this does not work for me, I'm getting

Error in fail: Error applying patch command cp @my-project//some-lib:include/additional_features.h include/:
cp: cannot stat '@my-project//some-lib:include/additional_features.h': No such file or directory

So it looks like the syntax for specifying a path like I do with build_file does not work with patch_cmds or that file can't be accessed at that specific stage.

Does one of the approaches I tried actual work and I just didn't use the right syntax?

What's the Bazel-way to add (a bunch of) readily available files (i.e. in the same repository as the Bazel-rules I provide) to a http_archive based source directory?


Solution

  • The error message already suggests to use exports_files.

    Try putting

    exports_files(
        ["include/additional_features.h"],
        visibility=["//visibility:public"],
    )
    

    in some-lib/BUILD, so that Bazel will let you reference source files from the //some-lib package in the external repository (and elsewhere).

    You might then have to reference it in your rule to be able to use it. E.g. a configure_make could look like this:

    configure_make(
        name="my_library",
        lib_source=":all_srcs",
        build_data=["@some-project//some-lib:include/additional_features.h"],
        copts=[
            "-I$EXT_BUILD_ROOT/include",
        ],
    
        ...
    
    )