`cargo build --features "X"` doesn't update binary mtime when list of features change
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 15.5k
- Forks
- 3k
- Avg merge
- 23h 30m
- Merged PRs (30d)
- 51
Description
Problem
Cargo doesn't appear to be updating the mtime on the binary in the ./target/debug directory when grabbing that file from the cache. This is breaking my using cargo inside a Makefile because the Makefile believes the built binary is older than it actually is.
Steps
-
Create a repo with the following source
# Cargo.toml [package] name = "minrepro" version = "0.1.0" edition = "2021" [dependencies] [features] feature_a = [] feature_b = []// src/main.rs fn main() { #[cfg(feature = "feature_a")] println!("Hello, Feature A!"); #[cfg(feature = "feature_b")] println!("Hello, Feature B!"); println!("Hello, world!"); }# Makefile to show the problem FEATURES := ifeq ($(FEATURE),A) FEATURES += "feature_a" endif ifeq ($(FEATURE),B) FEATURES += "feature_b" endif .PHONY: all FORCE all: bin ./bin bin: target/debug/minrepro cp target/debug/minrepro bin target/debug/minrepro: FORCE cargo build --features="$(FEATURES)" -
Check the current time
bash$ date Fri Mar 14 10:55:00 PM PDT 202 -
Build the crate with feature a
cargo build --features feature_a Compiling minrepro v0.1.0 (/home/matsch/dev/minrepro) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s -
statthe built binarybash$ stat ./target/debug/minrepro stat ./target/debug/minrepro File: ./target/debug/minrepro Size: 3946232 Blocks: 7712 IO Block: 4096 regular file Device: 253,1 Inode: 58468456 Links: 2 Access: (0755/-rwxr-xr-x) Uid: (1155901/ matsch) Gid: (89939/primarygroup) Access: 2025-03-14 22:55:51.930800853 -0700 Modify: 2025-03-14 22:55:51.930800853 -0700 Change: 2025-03-14 22:55:51.938800874 -0700 Birth: 2025-03-14 22:55:51.874800711 -0700 -
Build the crate with feature b
cargo build --features feature_b Compiling minrepro v0.1.0 (/home/matsch/dev/minrepro) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s -
statthe built binary againstat ./target/debug/minrepro File: ./target/debug/minrepro Size: 3946216 Blocks: 7712 IO Block: 4096 regular file Device: 253,1 Inode: 58470933 Links: 2 Access: (0755/-rwxr-xr-x) Uid: (1155901/ matsch) Gid: (89939/primarygroup) Access: 2025-03-14 23:01:12.287611878 -0700 Modify: 2025-03-14 23:01:12.287611878 -0700 Change: 2025-03-14 23:01:12.295611898 -0700 Birth: 2025-03-14 23:01:12.231611736 -0700 -
Build the crate with feature a again
cargo build --features feature_a Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s -
statthe built binary againstat ./target/debug/minrepro File: ./target/debug/minrepro Size: 3946232 Blocks: 7712 IO Block: 4096 regular file Device: 253,1 Inode: 58468456 Links: 2 Access: (0755/-rwxr-xr-x) Uid: (1155901/ matsch) Gid: (89939/primarygroup) Access: 2025-03-14 22:55:51.930800853 -0700 Modify: 2025-03-14 22:55:51.930800853 -0700 Change: 2025-03-14 23:02:43.063840777 -0700 Birth: 2025-03-14 22:55:51.874800711 -0700
Notice that the "Modify" time is now older than step 5, even though the file on disk has been updated since step "5"
Using the Makefile, I can produce the same issue:
# The first time it works
bash$ FEATURE=B make
cargo build --features=""feature_b""
Compiling minrepro v0.1.0 (/home/matsch/dev/minrepro)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.13s
cp target/debug/minrepro bin
./bin
Hello, Feature B!
Hello, world!
# Same with feature A
bash$ FEATURE=A make
cargo build --features=""feature_a""
Compiling minrepro v0.1.0 (/home/matsch/dev/minrepro)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
cp target/debug/minrepro bin
./bin
Hello, Feature A!
Hello, world!
# But now we go back to feature B and it still outputs feature A
# This is because make has determined the `cp` is not needed because the mtime of `./target/debug/minrepro` is older than `bin`
bash$ FEATURE=B make
cargo build --features=""feature_b""
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
./bin
Hello, Feature A!
Hello, world!
Possible Solution(s)
No response
Notes
No response
Version
cargo --version --verbose
cargo 1.85.0 (d73d2caf9 2024-12-31)
release: 1.85.0
commit-hash: d73d2caf9e41a39daf2a8d6ce60ec80bf354d2a7
commit-date: 2024-12-31
host: x86_64-unknown-linux-gnu
libgit2: 1.8.1 (sys:0.19.0 vendored)
libcurl: 8.9.0-DEV (sys:0.4.74+curl-8.9.0 vendored ssl:OpenSSL/1.1.1w)
ssl: OpenSSL 1.1.1w 11 Sep 2023
os: Debian n/a (rodete) [64-bit]
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the provided minimal crate and alternating feature builds, then trace how Cargo handles cached artifacts and the target/debug binary. Done means switching between feature_a and feature_b updates the binary's mtime when the cached artifact is restored, so the Makefile copies and runs the current build.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100