c++bazelbuck

Bazel: how to glob headers into one include path


In Buck, one might write:

exported_headers = subdir_glob([
    ("lib/source", "video/**/*.h"),
    ("lib/source", "audio/**/*.h"),
],
excludes = [
    "lib/source/video/codecs/*.h",
],
prefix = "MediaLib/")

This line would make those headers available under MediaLib/. What would be the equivalent in Bazel?


Solution

  • I ended up writing a rule to do this. It provides something similar to the output of a filegroup, and could be combined with cc_library in a macro.

    def _impl_flat_hdr_dir(ctx):
        path = ctx.attr.include_path
        d = ctx.actions.declare_directory(path)
        dests = [ctx.actions.declare_file(path + "/" + h.basename)
                 for h in ctx.files.hdrs]
    
        cmd = """
            mkdir -p {path};
            cp {hdrs} {path}/.
            """.format(path=d.path, hdrs=" ".join([h.path for h in ctx.files.hdrs]))
    
        ctx.actions.run_shell(
           command = cmd,
           inputs = ctx.files.hdrs,
           outputs = dests + [d],
           progress_message = "doing stuff!!!"
        )
    
        return struct(
           files = depset(dests)
        )
    
    flat_hdr_dir = rule(
        _impl_flat_hdr_dir,
        attrs = {
            "hdrs": attr.label_list(allow_files = True),
            "include_path": attr.string(mandatory = True),
        },
        output_to_genfiles = True,
    )