Skip to content

Can't use include_str!() macro with Bazel-generated data files #459

Closed
@dwtj

Description

@dwtj

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions