With Bazel how do I make part of one genrules' source files (e.g. header files) available to another genrule?

335 views Asked by At

Maybe this is a no-brainer and I just didn't get the concept yet.

I have a genrule, basically wrapping an existing make/config workflow to integrate it into a Bazel-based build configuration. In my example I'd like to build openssl, and then (with the same approach) some library depending on openssl, say xmlsec1

My (shortened) rule for openssl looks like this:

genrule(
    name = "build",
    visibility = ["//visibility:public"],
    srcs = glob(["**/*"], exclude=["bazel-*"]),
    outs =  [
        "libssl.a",
        "libcrypto.a",
        "include/openssl/opensslconf.h",
    ],
    cmd = """
        OUT_DIR="$$(realpath $(RULEDIR))"
        pushd "$$(dirname $(location config))"
        ./config
        make
        make -j6 DESTDIR="$$OUT_DIR" install_sw install_ssldirs
    """
)

This builds fine and $OUT_DIR contains all files I need to build against openssl

I'd now like to create another genrule building xmlsec1 which needs the path to openssls header files.

Now if I want to access a header, say include/opensslv.h it won't be part of @openssl//:builds artifacts since I didn't explicitly listing it in outs. But doing so results in

ERROR: Traceback (most recent call last):
    File "/bla/blubb/.cache/bazel/_bazel_me/f68917ddf601b6533d6db04f8101d580/external/openssl/BUILD.bazel", line 37, column 8, in <toplevel>
        genrule(
Error in genrule: rule 'build' has file 'include/openssl/opensslv.h' as both an input and an output

which is correct of course, but what can I do about it?

Removing those header files from srcs doen't work neither, since they wouldn't be available at build time.

One way would be to make install openssl to some destination directory, listing each of the dozens of header files explicitly and using that prefix in all dependent projects. But that doesn't feel right.

What's the recommended way to pass lists of files from one genrule to another?

1

There are 1 answers

0
ahumesky On

xmlsec1 could have include/openssl/opensslv.h in its own srcs directly. The build genrule shouldn't really need include/openssl/opensslv.h in its outs both because that would be a circular dependency as bazel said, and because the genrule doesn't really build that file: it already exists on disk (I assume it's getting captured by the glob())

There may be nicer way to organize the library though, something like this:

genrule(
    name = "build_openssl",
    visibility = ["//visibility:private"],
    outs =  [
        "libssl.a",
        "libcrypto.a",
        "include/openssl/opensslconf.h",
    ],
    .....,
)

cc_library(
    name = "openssl",
    srcs = [":build_openssl"],
    hdrs = [
        "include/openssl/opensslv.h",
        # other headers that openssl should provide
    ],
)

then your other rules can depend on the openssl cc_library and get both the .a files and the header files. (I have not tested this though)