Description
The Problem
The data
attribute appears on each of the core Rust rules (e.g. rust_binary
). The documentation for data
says
This attribute can be used to specify any data files that are embedded into the library, such as via the
include_str!
macro.
I have found that include_str()!
works only for "source" files (i.e. files included in the Bazel source tree). Unfortunately, the include_str!()
macro does not work if the data files are generated by some other Bazel target.
Example
To demonstrate this, I've added a small test to my rules_rust
fork.
In this test, one data file is a source file and one data file is generated by a genrule
. The contents of both files are embedded in the rust_test
via the include_str!()
macro.
On my linux system, this rust_test
fails to compile with the following rustc
error:
error: couldn't read test/generated_data/include_str/generated_data.txt: No such file or directory (os error 2)
--> test/generated_data/include_str/include_str.rs:9:13
|
9 | include_str!("generated_data.txt").trim()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
Notice that rustc
has no problem finding source_data.txt
.
I believe that the problem can be seen by inspecting this rustc
action's sandbox. On my Linux system, if I run the test with bazel test --sandbox_debug
, and then change directory to <bazel_workspace_output_base>/sandbox/linux-sandbox/<action_id>/execroot/io_bazel_rules_rust
, the root of the problem becomes clear: the library and the source data are sibling files
./test/generated_data/include_str/include_str.rs
./test/generated_data/include_str/source_data.txt
but the generated file is not
./bazel-out/k8-fastbuild/bin/test/generated_data/include_str/generated_data.txt
So, the generated data file is an input to the rustc
Bazel action, but it isn't anywhere that the rustc
executable can find it. Thus, a compiler error occurs.
Temporary Workaround
In my project where I actually want this feature I have an awful-dreadful-ugly hack to overcome this problem: I add a symlink from my source tree pointing to where I expect the generated file should be under the Bazel workspace's output base; then I add both the generated file and its symlink to the data
attribute.
A Very Rough Idea for a Solution
I have a little bit of experience writing Bazel rules that also needed to deal with this problem. My solution there was for each target to add various ctx.actions.symlink()
actions to place both generated files and source files into a new directory under their logical paths before calling the tool.