This is part N in a series describing how I created the bazel infrastructure to build all the third party packages for mjmech. Previously we have:
- Building mjmech software with bazel
- Configuring bazel to cross compile for the rpi3
- Building mjmech dependencies with bazel
- First bazel-ified packages
We left off with the first, very simple packages configured to build with bazel. In this installment we will tackle those that require at least minimal configuration, i.e. those that have some files which are normally generated as part of the build process.
snappy / template_file
snappy (https://github.com/google/snappy), a file compression library, is largely a pure C++ project, but it does have a single generated header file. There are a few possible options within bazel to handle this. The simplest would be to use a macro, although that has complications with respect to namespacing and label resolution. Here, I created a custom rule, called “template_file”.
As seen in the source on github the interface is relatively simple:
template_file( src, is_executable, substitutions, substitution_list, )
There are two possible forms for passing in substitutions, either a string_dict when using “substitutions”, or a list of KEY=VALUE strings in “substitution_list”. The two forms are present because starlark can make it awkward to deal with dictionaries, so often working with a list is much more convenient.
The snappy build rule uses this to generate snappy-stubs-public.h
:
template_file( name = "snappy-stubs-public.h", src = "snappy-stubs-public.h.in", substitutions = { "${HAVE_STDINT_H_01}": "1", "${HAVE_STDDEF_H_01}": "1", "${HAVE_SYS_UIO_H_01}": "1", "${SNAPPY_MAJOR}": "1", "${SNAPPY_MINOR}": "1", "${SNAPPY_PATCHLEVEL}": "7", }, )
log4cpp / autoconf
Next up in the difficulty level is log4cpp, which uses autoconf as its native build system. autoconf typically has a config.h.in file, defined in a semi-standardized format, mostly comprised of lines like:
/* Define to 1 if you have the header file. */ #undef HAVE_STRING_H
The pre-processing stage turns each of those lines into either an actual #define, or just a a comment saying that it continues to be undefined.
That is substantive enough that the simple built-in bazel template rule won’t cut it though. For this, we split the work into two pieces, 1) a python helper script to do the actual formatting and 2) a starlark bazel rule which defaults in some common autoconf defines. For the bazel_deps repository, the bazel autoconf rule has basically every autoconf define that is shared by more than one project in it, to reduce duplication and make it more likely that all the dependencies are configured consistently.
With the two of them together, the resulting BUILD
file defines a cc_library
as normal, but it depends upon the new autoconf rule like found in the log4cpp instance:
autoconf_config( name = "include/log4cpp/config.h", src = "include/config.h.in", package = "log4cpp", version = "1.1.3", defines = autoconf_standard_defines + [ "DISABLE_SMTP", "DISABLE_REMOTE_SYSLOG", ], prefix = "LOG4CPP_", )