The critical job of a build system is to convert source files into artifacts. In this part, we will use a template file as a source code example and convert it into an executable. Conceptually, it is the same process we would use to compile a Go or Rust binary except for the complexities of dealing with platforms and languages.
As a disclaimer, please be aware that
sh_binary
native rule is a better solution for using shell script in
production-quality builds.
Source Attribute #
We will start with adding a source attribute to our rule:
demo_binary = rule(
implementation = _demo_binary_impl,
executable = True,
attrs = {
"message": attr.string(mandatory = True),
"out": attr.output(mandatory = True),
"src": attr.label(
mandatory = True,
allow_single_file = [".tpl"],
),
},
)
The attr.label
type tells Bazel to treat this attribute as
a target. We provide a list of allowed extensions.
The allow_single_file
parameter prevents users from passing
a list of multiple source files.
The BUILD
file will refer to a source file:
demo_binary(
name = "source",
src = "hello.tpl",
out = "hello",
message = "Hello, World!",
)
Template #
The content of the template file is almost identical to
the _TEMPLATE
variable we used
before
#!/bin/sh
echo "{MESSAGE}"
The only difference is the placeholder. We will use Bazel’s
expand_template
function that allows passing any string as a substitution token;
it makes sense to make it a bit clearer than just a pair of
brackets.
Finally, we can replace write
action in the implementation function:
def _demo_binary_impl(ctx):
out = ctx.outputs.out
ctx.actions.expand_template(
output = out,
template = ctx.file.src,
substitutions = {
"{MESSAGE}": ctx.attr.message,
},
)
return [DefaultInfo(
files = depset([out]),
executable = out,
)]
We use ctx.file
to refer to the src
attribute and provide a list
of substitutions. Building and running the example will produce the
familiar message:
$ bazel run //source
..
Target //source:source up-to-date:
bazel-bin/source/hello
...
Hello, World!
The complete example is in the repo.