prost
prost copied to clipboard
`prost-build` instructions don't work for crates in workspaces
If you've got a crate in a workspace you can build it either by:
workspace-root% cargo build -p my-crate
or
workspace-root% cd my-crate
my-crate% cargo build
This causes a problem when you use relative paths in build.rs
, as the prost-build
instructions do, because the working directory is different. In the first example paths will be relative to workspace-root
, in the second example they will be relative to workspace-root/my-crate
.
Assuming a proto file in src/proto/foo.proto
(relative to build.rs
) you need to do something like:
use std::env;
use std::path::Path;
fn main() {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not set");
let proto_file = Path::new(&manifest_dir).join("proto/foo/v1/foo.proto");
let include_path = proto_file
.parent()
.expect("Couldn't determine parent directory of proto_file")
.to_path_buf();
println!("cargo:rerun-if-changed={}", proto_path.to_str().unwrap());
prost_build::compile_protos(&[proto_path], &[include_path]).unwrap();
}
Can this be included as an example?
I use prost-build
in a situation very similar to what this outlines, but it works fine in either case. Could you create a reproducing example in a repository and point to it?
I happened to hit this problem independently. I think the issue is that prost_build::compile_protos
does not print any cargo:rerun-if-changed
lines. Cargo's default behavior is to re-run the build script if any file in the package changes.
In our case, the .proto
files are located outside the particular package where we have this build script.
Everything builds fine the first time, but changing the .proto
files was not enough to get the build script to run again on the next cargo build
.
This can be fixed in a documentation-only way; or prost-build
could be changed to print the relevant cargo:rerun-if
lines on behalf of its user (but I sort of doubt that'd be backward compatible).
(Update: It would not be backward compatible. Imagine a project with a build script that
- uses
prost_build
, reading.proto
files in their project; but also - generates other Rust code, from other project files; and
- does not print any
cargo:rerun-if-changed
lines at all.
Currently, they're OK, because if any file in their project changes, the build script runs. But if prost_build
were to start printing cargo:rerun-if-changed
lines, then only updates to their proto files would cause a rerun. Changes to their other project files would not.)