-
Notifications
You must be signed in to change notification settings - Fork 527
Description
The title states most of my question. For example, we can imagine something like this:
cargo_build_script(
name = "build_script",
srcs = ["build.rs"],
compile_data = [":Cargo.toml"],
crate_root = "build.rs",
visibility = ["//visibility:public"],
)
rust_library(
name = "example",
deps = [":build_script"],
compile_data = ["Cargo.toml"],
visibility = ["//visibility:public"],
)Here, build_script produces lib.rs that then should become the crate root of example.
This simply fails the check in rust/private/utils.bzl, line 786:
Error in fail: Couldn't find lib.rs or example.rs among `srcs`, please use `crate_root` to specify the root file.
AFAUI the build script should go into deps, not srcs; build_script produces a directory which is kind of opaque to Bazel (the below error is with srcs = [":build_script"]:
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).
I thought generated crate roots are not at all supported. If so, I'd like your thoughts on how to best add this feature, should cargo_build_script declare the files it generates and then pass this information around in the BuildInfo provider? Because crate_root inside rust_library_common is a File, not a string, so it has to be declared as an individual file. Alternatively, if crate_root can become a string, then maybe cargo_build_script could pre-declare its generated cargo root while still declaring a directory
| out_dir = ctx.actions.declare_directory(ctx.label.name + ".out_dir") |
and then this could be taken into account in rust_library_common.
Then, while reading the source code I noticed that some support for generated source files is definitely there, e.g.:
rules_rust/rust/private/utils.bzl
Lines 849 to 888 in 4461a8a
| def transform_sources(ctx, srcs, compile_data, crate_root): | |
| """Creates symlinks of the source files if needed. | |
| Rustc assumes that the source files are located next to the crate root. | |
| In case of a mix between generated and non-generated source files, this | |
| we violate this assumption, as part of the sources will be located under | |
| bazel-out/... . In order to allow for targets that contain both generated | |
| and non-generated source files, we generate symlinks for all non-generated | |
| files. | |
| Args: | |
| ctx (struct): The current rule's context. | |
| srcs (List[File]): The sources listed in the `srcs` attribute | |
| compile_data (List[File]): The sources listed in the `compile_data` | |
| attribute | |
| crate_root (File): The file specified in the `crate_root` attribute, | |
| if it exists, otherwise None | |
| Returns: | |
| Tuple(List[File], List[File], File): The transformed srcs, compile_data | |
| and crate_root | |
| """ | |
| has_generated_sources = ( | |
| len([src for src in srcs if not src.is_source]) + | |
| len([src for src in compile_data if not src.is_source]) > | |
| 0 | |
| ) | |
| if not has_generated_sources: | |
| return srcs, compile_data, crate_root | |
| package_root = paths.join(ctx.label.workspace_root, ctx.label.package) | |
| generated_sources = [_symlink_for_non_generated_source(ctx, src, package_root) for src in srcs if src != crate_root] | |
| generated_compile_data = [_symlink_for_non_generated_source(ctx, src, package_root) for src in compile_data] | |
| generated_root = crate_root | |
| if crate_root: | |
| generated_root = _symlink_for_non_generated_source(ctx, crate_root, package_root) | |
| generated_sources.append(generated_root) | |
| return generated_sources, generated_compile_data, generated_root |
But it does not seem to support generated crate roots. The word "generated" seems to have two different meanings in this function:
- the first is whether it is a generated file as opposed to a source that returns
Trueforsrc.is_source, the variable namehas_generated_sourcesemploys this meaning; - the second is whether it is a symlink that is generated in the
transform_sourcesfunction, the variable namesgenerated_sources,generated_compile_data, andgenerated_rootemploy the latter meaning.
It would appear from reading the source code that :build_script should be added to compile_data then at least symlink creation will be initiated. But rules_rust still complains about the missing crate root in that case. If crate root is specified as crate_root = "build_script.out_dir/lib.rs" then a new errors results:
ERROR: One of the output paths 'bazel-out/k8-fastbuild/bin/build_script.out_dir' (belonging to //:build_script) and 'bazel-out/k8-fastbuild/bin/build_script.out_dir/lib.rs' (belonging to //:example) 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
Specifying crate_root = "lib.rs" simply complains about non-existing //:lib.rs file, indeed the crate_root attribute is a Label.
So, I'd like to know how this is supposed to work. I am willing to implement support for this as well.