rules_rust icon indicating copy to clipboard operation
rules_rust copied to clipboard

rust_library doesn't work with copy_to_directory output

Open mikea opened this issue 7 months ago • 1 comments

Setup:

$ tree .
.
├── BUILD.bazel
├── MODULE.bazel
└── src
    ├── a
    │   └── main.rs
    └── foo
        └── mod.rs

MODULE.bazel:

bazel_dep(name = "rules_rust", version = "0.60.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.15.3")

BUILD.bazel:

load("@rules_rust//rust:defs.bzl", "rust_binary")
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")

copy_to_directory(
    name = "copy_srcs",
    srcs = glob([
        "src/**/*.rs",
    ]),
    replace_prefixes = {
        "src/a/": "",
        "src/foo/": "foo/",
    },
)

rust_binary(
    name = "hello_world",
    srcs = [":copy_srcs"],
    deps = [],
)

main.rs:

mod foo;

fn main() {
    foo::hello_world();
}

foo.rs

pub fn hello_world() {
    println!("Hello from foo!");
}

Trying to build this gives:

ERROR: /home/mikea/tmp/rust_bazel_test/BUILD.bazel:32:12: in rust_binary rule //:hello_world: 
Traceback (most recent call last):
        File "/home/mikea/.cache/bazel/_bazel_mikea/873f4a151b5bd21ce14e322b91406545/external/rules_rust+/rust/private/rust.bzl", line 239, column 37, in _rust_binary_impl
                providers = rustc_compile_action(
        File "/home/mikea/.cache/bazel/_bazel_mikea/873f4a151b5bd21ce14e322b91406545/external/rules_rust+/rust/private/rustc.bzl", line 1258, column 46, in rustc_compile_action
                args, env_from_args = construct_arguments(
        File "/home/mikea/.cache/bazel/_bazel_mikea/873f4a151b5bd21ce14e322b91406545/external/rules_rust+/rust/private/rustc.bzl", line 937, column 20, in construct_arguments
                rustc_flags.add(crate_info.root)
Error in add: Cannot add directories to Args#add since they may expand to multiple values. Either use Args#add_all (if you want expansion) or args.add(directory.path) (if you do not).
ERROR: /home/mikea/tmp/rust_bazel_test/BUILD.bazel:32:12: Analysis of target '//:hello_world' failed

You can verify that resulting directory structure is ok:

bazel build //:copy_srcs && tree bazel-bin/copy_srcs/
bazel-bin/copy_srcs/
├── foo
│   └── mod.rs
└── main.rs

If I try to use data then I have a different error:

rust_binary(
    name = "hello_world",
    srcs = ["copy_srcs/lib.rs"],
    compile_data = [":copy_srcs"],
    deps = [],
)

gives

ERROR: One of the output paths 'bazel-out/k8-fastbuild/bin/copy_srcs' (belonging to //:copy_srcs) and 'bazel-out/k8-fastbuild/bin/copy_srcs/lib.rs' (belonging to //:hello_world) is a prefix of the other. These actions cannot be simultaneously present; please rename one of the output files or build just one of them
ERROR: One of the output paths 'bazel-out/k8-fastbuild/bin/copy_srcs' (belonging to //:copy_srcs) and 'bazel-out/k8-fastbuild/bin/copy_srcs/lib.rs' (belonging to //:hello_world) is a prefix of the other. These actions cannot be simultaneously present; please rename one of the output files or build just one of them

I can't seem to find a combination of attributes to use copy_to_directoy output.

Thanks.

mikea avatar Apr 24 '25 19:04 mikea

A possible workoaround would be to use genrule directrly. This seems to work:

genrule(
    name = "generate_srcs",
    srcs = ["src/a/main.rs", "src/foo/mod.rs"],
    outs = ["main.rs", "foo/mod.rs"],
    cmd = """
        cp $(location src/a/main.rs) $(location main.rs)
        cp $(location src/foo/mod.rs) $(location foo/mod.rs)
    """,
    visibility = ["//visibility:public"],
)

rust_binary(
    name = "hello_world",
    srcs = [":generate_srcs"],
    deps = [],
)

However being able to consume copy_to_directory et al output would be much much more convenient.

mikea avatar Apr 25 '25 15:04 mikea