How do I make a bazel `sh_binary` target depend on other binary targets?
An easier approach for me is to add the cc_binary
as a dependency in the data
section. In prefix/BUILD
cc_binary(name = "foo", ...)
sh_test(name = "foo_test", srcs = ["foo_test.sh"], data = [":foo"])
Inside foo_test.sh
, the working directory is different, so you need to find the right prefix
for the binary
#! /usr/bin/env bash
executable=prefix/foo
$executable ...
You can either create a genrule to run these tools as part of the build, or create a sh_binary that depends on the tools via the data
attribute and runs them them.
The genrule approach
This is the easier way and lets you run the tools as part of the build.
genrule(
name = "foo",
tools = [
"//tool_a:py",
"//tool_b:cc",
],
srcs = [
"//source:file1",
":file2",
],
outs = [
"output_file1",
"output_file2",
],
cmd = "$(location //tool_a:py) --input=$(location //source:file1) --output=$(location output_file1) && $(location //tool_b:cc) < $(location :file2) > $(location output_file2)",
)
The sh_binary approach
This is more complicated, but lets you run the sh_binary either as part of the build (if it is in a genrule.tools
, similar to the previous approach) or after the build (from under bazel-bin
).
In the sh_binary
you have to data-depend on the tools:
sh_binary(
name = "foo",
srcs = ["my_shbin.sh"],
data = [
"//tool_a:py",
"//tool_b:cc",
],
)
Then, in the sh_binary
you have to use the so-called "Bash runfiles library" built into Bazel to look up the runtime-path of the binaries. This library's documentation is in its source file.
The idea is:
- the sh_binary has to depend on a specific target
- you have to copy-paste some boilerplate code to the top of the sh_binary (reason is described here)
- then you can use the
rlocation
function to look up the runtime-path of the binaries
For example your my_shbin.sh
may look like this:
#!/bin/bash
# --- begin runfiles.bash initialization ---
...
# --- end runfiles.bash initialization ---
path=$(rlocation "__main__/tool_a/py")
if [[ ! -f "${path:-}" ]]; then
echo >&2 "ERROR: could not look up the Python tool path"
exit 1
fi
$path --input=$1 --output=$2
The __main__
in the rlocation path argument is the name of the workspace. Since your WORKSPACE
file does not have a "workspace" rule in, which would define the workspace's name, Bazel will use the default workspace name, which is __main__
.