structbazelskylarkstarlark

Skylark struct with methods


Here's something I tried to do, and it works well. I find it useful, but it feels like a hack, so I'm afraid it will break in the future.

I'm working on converting a large project to Bazel, and we have lots of local wrappers, something like:

my_cc_library(name='a', srcs=['lib.c'])
my_cc_binary(name='b', deps=['a'], srcs=['main.c'])

This requires lots of load commands, which are annoying and a repeating source of errors. If it was normal Python, I'd simply import a whole module. But Skylark requires loading functions one by one.

I can remove the need for individual loads, using a struct.

In my.bzl:

def _my_cc_library(...): ...
def _my_cc_binary(...): ...

my = struct(cc_library=_my_cc_library, cc_binary=_my_cc_binary)

In various BUILD files:

load('//my.bzl', 'my')
my.cc_library(name='a', srcs=['lib.c'])
my.cc_binary(name='b', deps=['a'], srcs=['main.c'])

As I wrote above, it all works well. I can use if for wrappers to native rules, and for various other functions.

But an I abusing the language? Is it prone to break in the future?

Thanks.


Solution

  • This pattern is used in other places (e.g. https://github.com/bazelbuild/bazel-skylib/blob/master/lib/collections.bzl), it's safe to use it.

    Not all tools support it well, though. For example, you won't be able to update your BUILD files with Buildozer - although it's something that can be fixed.

    This requires lots of load commands, which are annoying and a repeating source of errors.

    I agree it's annoying. In the future, we should have better tooling for updating load lines (to automatically add/remove them).

    Rules in BUILD files look like my_cc_library(...) due to historical reasons. For a long time, load didn't exist and all rules were hard-coded in Bazel. Maybe we should encourage the my.cc_library(...) syntax and make it easier to use.