Skip to main content

Key building block: run_binary

This rule is an “adapter” from an executable (something you could bazel run) to an action (something you can bazel build). The executable (called a “tool” here) is run in a single action which spawns that executable given some declared inputs, and produces some declared, default outputs. :::caution Bazel’s built-in genrule looks a lot like run_binary, but it’s best to avoid it.
  • Arbitrary bash one-liner, commonly non-hermetic
  • Bash dependency hurts portability
  • Subtly different semantics for expand_location, stamp, etc.
::: Here’s a sample usage, which runs my_tool with three arguments to produce a folder called dir_a:
  1. The path to some.file which is the only input
  2. An -outdir flag, which we know from reading the CLI documentation for my_tool.
    • We’re always required to predict what path the tool will write to. If you get it wrong, Bazel will error that the “output was not produced”.
  3. A syntax-sugar shorthand for “the output folder Bazel assigns for this action”
:::note The js_run_binary rule takes it a step further, adding the ability to:
  • capture stdout/stderr/exit code as “outputs”
  • chdir to a specific working directory
  • throw away log-spam on success
Follow https://github.com/bazel-contrib/bazel-lib/issues/575 :::

Making tools work

The tool in run_binary can be any executable. However some tools don’t work the way Bazel expects. This can usually be fixed without having to change the tool, which is good since most tools are written by third-parties who don’t care about your Bazel migration problems! :::caution Google engineers got in the habit of rewriting everything to work with Blaze. Do not follow their lead! Changing more than one thing at a time makes your migration riskier. ::: You can make most tools work under Bazel by asking: “How can the tool tell that it’s running under Bazel?” There are three ways to make the tool think it’s still running outside Bazel:
  1. “Monkey-patch” the runtime
    • Node.js -require flag to run
    • JVM has a classpath, you can inject a shadowing class
  2. In-process wrapper
    • Peel one layer off the tool’s CLI
    • Write your own CLI that calls its entry point
  3. Parent process wrapper
    • Often a short Bash script
:::note Read more things a program must not do under bazel :::