I have a bash script:
mkdir a_dir
echo "Hello World!" > a_dir/out1.txt
echo "Hello World!" > a_dir/out2.txt
I would like to create an action to run the script, and have the files it creates declared as outputs, and be able to pass them as inputs to other actions.
The problem is I can't figure out how to reference the files weather with ctx.actions.declare_file
or some other method that I'm not aware of.
I think what I'm looking for is a method to get File
objects that reference files under the execroot
path.
Note: The actual binary I will be running instead of the bash script doesn't grant control over the path of its output, so declaring a file within the implementation function and passing it as a parameter to the binary is not an option.
After looking online and opening a thread on bazel-discuss, It seems like there isn't any way of declaring outputs outside of the output root.
The solution I chose is creating a wrapper script which cd
s into the output directory, out_dir
, which is evaluated as paths.join(ctx.bin_dir.path, ctx.label.package)
The reason I chose cd
rather mv
or cp
is discussed in the bazel-discuss thread.
After cd
into out_dir
, the paths of files given to the binary as arguments are no longer valid, and can be fixed by prepending them with ..
s. If the files that are to be fixed are in a depset
and you require to fix the paths without converting the depset
to a list, you can prepend the path-fix using the format_each
parameter of args.add_all()
.
This is not the most elegant solution, but as far as I know, does not compromise functionality. Here is some example code:
# Inside implementation function:
out_dir = paths.join(ctx.bin_dir.path, ctx.label.package)
path_fix = "/".join(len(out_dir.split("/"))*[".."])
args = ctx.actions.args()
args.add_all(files_depset, format_each=path_fix+"/%s")
ctx.actions.run_shell(..., command = "cd {out_dir}; {binary} $@".format(
out_dir = out_dir,
binary = your_binary
))