bazelbazel-cpp

How do I wrap `cc_binary`/`cc_library` into a custom rule (not macro!)?


In order to work around a bug, and in order to set platform-specific compiler options, I want to wrap cc_binary (and cc_library) into a custom rule. I do not want to use a macro, as then I'd have to structure my code like that:

deps = select(
        {
            "@platforms//os:linux": deps + ["my-extra-dep"],
            "//conditions:default": deps,
        }
// repeat the same for copts and defines

Instead, I'd like to structure my code like that:

// checks @platforms//os:linux
if is_linux():
  deps = deps + ["my-extra-dep"]
  defines = defines + ["custom-define1", ...]

The latter is only possible in a rule, where one can query platform attributes. In a macro, I'd be stuck selecting every individual attribute.

My issue is with the boilerplate of my custom rule - what should the attrs be, so that I can transparently forward to the native cc_binary/cc_library rule? Am I missing an easy way to do this that is not translating the entire interface specification of the cc_* rules into starlark?


Solution

  • No, there is no generic way to reuse a different rule at the rule-implementation level. However, there are ways to make select trees more succinct. For instance:

    def on_linux(d):
       return select({"@platforms//os:linux": d, "//conditions:default": []})
    
    def macro(deps, defines):
       ...
       deps += on_linux(["my-extra-dep"])
       defines += on_linux(["custom-define", "custom-define2"])