Skip to content

If an empty build script's output's mtime is newer than the build script binary, it's always considered to be dirty #16104

@sunshowers

Description

@sunshowers

Problem

(Originally reported as oxidecomputer/crucible#1790.)

In the situation where:

  • a build script is a trivial fn main() {}
  • its output's mtime is newer than the build script binary

then the build script is always considered to be dirty, leading to many excessive rebuilds.

It wasn't clear to me how the mtime of the output ended up being newer in this way, but it did in the case of my coworker, and the only way to get out of it was to run cargo clean.

Seems like Cargo should refresh the mtime of the output file to avoid this scenario.

Steps

Minimal repro with instructions is at https://github.com/sunshowers/output-build-script-test.

Normally:

% cargo check -v
   Compiling output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test)
     Running `/opt/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name build_script_build --edition=2021 build.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=176 --crate-type bin --emit=dep-info,link -C embed-bitcode=no --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=79dbd0af7880cfc3 -C extra-filename=-74601695fb5010e2 --out-dir /home/rain/dev/output-build-script-test/target/debug/build/output-build-script-test-74601695fb5010e2 -C incremental=/home/rain/dev/output-build-script-test/target/debug/incremental -L dependency=/home/rain/dev/output-build-script-test/target/debug/deps`
     Running `/home/rain/dev/output-build-script-test/target/debug/build/output-build-script-test-74601695fb5010e2/build-script-build`
     Running `/opt/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name output_build_script_test --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=176 --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=139407a758b9a61d -C extra-filename=-0c40631603a3198e --out-dir /home/rain/dev/output-build-script-test/target/debug/deps -C incremental=/home/rain/dev/output-build-script-test/target/debug/incremental -L dependency=/home/rain/dev/output-build-script-test/target/debug/deps`
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
% cargo check -v
       Fresh output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s```

But if you do:

touch target/debug/build/*/output

Then:

% cargo check -v
       Dirty output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test): the precalculated components changed
   Compiling output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test)
     Running `/home/rain/dev/output-build-script-test/target/debug/build/output-build-script-test-74601695fb5010e2/build-script-build`
     Running `/opt/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name output_build_script_test --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=176 --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=139407a758b9a61d -C extra-filename=-0c40631603a3198e --out-dir /home/rain/dev/output-build-script-test/target/debug/deps -C incremental=/home/rain/dev/output-build-script-test/target/debug/incremental -L dependency=/home/rain/dev/output-build-script-test/target/debug/deps`
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
% cargo check -v
       Dirty output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test): the dependency build_script_build was rebuilt (1760409718.149356849s, 23s after last build at 1760409695.958999891s)
    Checking output-build-script-test v0.1.0 (/home/rain/dev/output-build-script-test)
     Running `/opt/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name output_build_script_test --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=176 --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=139407a758b9a61d -C extra-filename=-0c40631603a3198e --out-dir /home/rain/dev/output-build-script-test/target/debug/deps -C incremental=/home/rain/dev/output-build-script-test/target/debug/incremental -L dependency=/home/rain/dev/output-build-script-test/target/debug/deps`
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s

and so on, i.e. the build script is never considered to be fresh.

Possible Solution(s)

No response

Notes

No response

Version

% cargo --version --verbose
cargo 1.90.0 (840b83a10 2025-07-30)
release: 1.90.0
commit-hash: 840b83a10fb0e039a83f4d70ad032892c287570a
commit-date: 2025-07-30
host: x86_64-unknown-linux-gnu
libgit2: 1.9.1 (sys:0.20.2 vendored)
libcurl: 8.14.1-DEV (sys:0.4.82+curl-8.14.1 vendored ssl:OpenSSL/3.5.0)
ssl: OpenSSL 3.5.0 8 Apr 2025
os: Ubuntu 24.4.0 (noble) [64-bit]

Also repros on nightly:

% cargo +nightly --version --verbose
cargo 1.92.0-nightly (81c3f77a4 2025-10-10)
release: 1.92.0-nightly
commit-hash: 81c3f77a467359c8be6bc747dc93ec66a6e4ce11
commit-date: 2025-10-10
host: x86_64-unknown-linux-gnu
libgit2: 1.9.1 (sys:0.20.2 vendored)
libcurl: 8.15.0-DEV (sys:0.4.83+curl-8.15.0 vendored ssl:OpenSSL/3.5.4)
ssl: OpenSSL 3.5.4 30 Sep 2025
os: Ubuntu 24.4.0 (noble) [64-bit]

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-build-scriptsArea: build.rs scriptsA-rebuild-detectionArea: rebuild detection and fingerprintingC-bugCategory: bugCommand-checkS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions