bazelfpgabuckpantsplease.build

Can bazel package depend on a source file in another package


A few years ago I wrote a set of wrappers for Bazel that enabled me to use it to build FPGA code. The FPGA bit is only relevant because the full clean build takes many CPU days so I really care about caching and minimizing rebuilds.

Using Bazel v0.28 I never found a way to have my Bazel package depend on a single source file from somewhere else in the git repo. It felt like this wasn't something Bazel was designed for.

We want to do this because we have a library of VHDL source files that are parameterized and the parameters are set in the instantiating VHDL source. (VHDL generics). If we declare this library as a Bazel package in its own right then a change to one library file would rebuild everything (at huge time cost) when in practice only a couple of steps might need to be rebuilt.

I worked around this with a python script to copy all the individual source files into a subdirectory and then generate the BUILD file to reference these copies. The resulting build process is:

  1. call python preparation script
  2. bazel build //:allfpgas
  3. call python result extractor

This is clearly quite ugly but the benefits were huge so we live with it.

Now we want to leverage Bazel to build our Java, C++ etc so I wanted to revisit and try and make everything work with Bazel alone.

In the latest Bazel is there a way to have a BUILD package depend on individual source files outside of the package directory? If Bazel cant, would buck pants or please.build work better for our use case?


Solution

  • The Bazel rules for most languages support doing something like this already. For example, the Python rules bundle source files from multiple packages together, and the C++ rules manage include files from other packages. Somehow the rule has to pass the source files around in providers, so that another rule can generate actions which use them. Hard to be more specific without knowing which rules you're using.

    If you just want to copy the files, you can do that in bazel with a genrule. In the package with the source file:

    exports_files(["templated1.vhd", "templated2.vhd"])
    

    In the package that uses it:

    genrule(
        name = "copy_templates",
        srcs = ["//somewhere:templated1.vhd", "//somewhere:templated2.vhd"],
        outs = ["templated1.vhd", "templated2.vhd"],
        cmd = "cp $(SRCS) $(RULEDIR)",
    )
    
    some_library(
        srcs = ["templated1.vhd", "templated2.vhd", "other.vhd"],
    )
    

    If you want to deduplicate that across multiple packages that use it, put the filenames in a list and write a macro to create the genrule.