From cdccb413e73b4528a1d54e9a6d50420549c1fefc Mon Sep 17 00:00:00 2001 From: Casper Meijn Date: Thu, 29 Aug 2024 09:19:40 +0200 Subject: [PATCH] feat(prost-build): emit `rerun` commands Inform `cargo` about the files and env vars used by `prost-build`. Then `cargo` can better determine when to rebuild a project. - Emit `rerun-if-changed` for each proto file specified - Emit `rerun-if-changed` for each include directory specified - Emit `rerun-if-changed` if `file_descriptor_set_path` is set - Emit `rerun-if-env-changed` for `PROTOC` and `PROTOC_INCLUDE` https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed BREAKING CHANGE: Previously `cargo` assumed it had to rerun `build.rs` if any files in the project changed. `prost-build` will now emit `rerun` commands, which means only the explicitly marked files cause a rerun. If your `build.rs` is dependent on any other file paths than those given to `prost-build`, then your `build.rs` needs to emit `rerun` commands as well. --- prost-build/src/config.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/prost-build/src/config.rs b/prost-build/src/config.rs index af0e2e34d..fab275a96 100644 --- a/prost-build/src/config.rs +++ b/prost-build/src/config.rs @@ -889,6 +889,7 @@ impl Config { ) -> Result { let tmp; let file_descriptor_set_path = if let Some(path) = &self.file_descriptor_set_path { + println!("cargo:rerun-if-changed={}", path.display()); path.clone() } else { if self.skip_protoc_run { @@ -909,6 +910,7 @@ impl Config { .arg(&file_descriptor_set_path); for include in includes { + println!("cargo:rerun-if-changed={}", include.as_ref().display()); if include.as_ref().exists() { cmd.arg("-I").arg(include.as_ref()); } else { @@ -930,6 +932,7 @@ impl Config { } for proto in protos { + println!("cargo:rerun-if-changed={}", proto.as_ref().display()); cmd.arg(proto.as_ref()); } @@ -1000,12 +1003,6 @@ impl Config { protos: &[impl AsRef], includes: &[impl AsRef], ) -> Result<()> { - // TODO: This should probably emit 'rerun-if-changed=PATH' directives for cargo, however - // according to [1] if any are output then those paths replace the default crate root, - // which is undesirable. Figure out how to do it in an additive way; perhaps gcc-rs has - // this figured out. - // [1]: http://doc.crates.io/build-script.html#outputs-of-the-build-script - let file_descriptor_set = self.load_fds(protos, includes)?; self.compile_fds(file_descriptor_set) @@ -1224,6 +1221,7 @@ pub fn error_message_protoc_not_found() -> String { /// Returns the path to the `protoc` binary. pub fn protoc_from_env() -> PathBuf { + println!("cargo:rerun-if-env-changed=PROTOC"); env::var_os("PROTOC") .map(PathBuf::from) .unwrap_or(PathBuf::from("protoc")) @@ -1231,6 +1229,7 @@ pub fn protoc_from_env() -> PathBuf { /// Returns the path to the Protobuf include directory. pub fn protoc_include_from_env() -> Option { + println!("cargo:rerun-if-env-changed=PROTOC_INCLUDE"); let protoc_include: PathBuf = env::var_os("PROTOC_INCLUDE")?.into(); if !protoc_include.exists() {