From 2abc324257966474b552877b2e80b257374ef885 Mon Sep 17 00:00:00 2001 From: Vitali Lovich Date: Fri, 31 Jan 2025 00:33:27 -0800 Subject: [PATCH] Don't dirty shadow.rs unless contents have changed Stop spurious rebuilds for any project that uses shadow-rs - even if no source has changed, because the shadow.rs file is blindly clobbered on every build, cargo thinks something has changed due to the directive to rebuild if shadow.rs changes. Instead, check if any of the new contents are actually different, ignoring the "Generation time" header. --- src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 93a123e..dc95551 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -327,6 +327,23 @@ pub(crate) fn get_std_env() -> BTreeMap { env_map } +fn is_same_contents, P2: AsRef>(p1: P1, p2: P2) -> SdResult { + let c1 = std::fs::read_to_string(p1.as_ref())?; + let c2 = std::fs::read_to_string(p2.as_ref())?; + + // Skip the auto-generated header comment which always changes + let c1 = c1 + .split('\n') + .skip_while(|line| line.starts_with("//")) + .collect::>(); + let c2 = c2 + .split('\n') + .skip_while(|line| line.starts_with("//")) + .collect::>(); + + Ok(c1 == c2) +} + /// `shadow-rs` configuration. /// /// This struct encapsulates the configuration for the `shadow-rs` build process. It allows for fine-grained control over @@ -474,9 +491,10 @@ impl Shadow { path.join(DEFINE_SHADOW_RS) } }; + let tmp_out = out.with_file_name(format!(".{DEFINE_SHADOW_RS}.tmp")); let mut shadow = Shadow { - f: File::create(out)?, + f: File::create(&tmp_out)?, map: Default::default(), std_env: Default::default(), deny_const, @@ -502,6 +520,10 @@ impl Shadow { shadow.write_all()?; + if !is_same_contents(&tmp_out, &out).unwrap_or(false) { + std::fs::rename(tmp_out, out)?; + } + // handle hook if let Some(h) = builder.get_hook() { shadow.hook(h.hook_inner())?