prost icon indicating copy to clipboard operation
prost copied to clipboard

`prost-build` instructions don't work for crates in workspaces

Open nikclayton-dfinity opened this issue 4 years ago • 3 comments

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?

nikclayton-dfinity avatar Apr 17 '20 20:04 nikclayton-dfinity

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?

danburkert avatar Dec 31 '20 20:12 danburkert

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).

jorendorff avatar Apr 24 '21 21:04 jorendorff

(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.)

jorendorff avatar Apr 24 '21 21:04 jorendorff