On macOS, every codegen invocation since 1.88 leaves a full set of *.rcgu.o files behind in target/debug/deps, and nothing ever cleans them up. Before 1.88 a rebuild overwrote the previous set.
I ran into this because the deps dir of our workspace had grown to 3.29 million files (341 GB) over roughly eight weeks of heavy use. At that size every rustc and rustdoc start spends minutes before doing anything useful, since the -L dependency directory is read eagerly at startup into a sorted index (#132910). cargo test --doc sat at 0% CPU for over half an hour; a sample of the process showed it inside getdirentries64 under SearchPath::new.
What I believe is going on: cargo defaults split-debuginfo to unpacked on macOS, so rustc deliberately keeps the object files after linking because the DWARF lives in them (preserve_objects_for_their_debuginfo). That was harmless while the object names were stable per unit, a rebuild simply replaced the old set. Then #139453 (shipped in 1.88) started prepending a per-invocation random string to temp file names so concurrent invocations can't collide. The preserved objects get that random component too, so now each rebuild writes a brand new set and the old ones just stay there forever.
Repro with any small lib crate (mine has 3 modules, so 3 CGUs):
$ for i in 1 2 3; do echo "// edit $i" >> src/lib.rs; cargo +1.85 build; done
$ ls target/debug/deps/*.rcgu.o | wc -l
3
$ rm -rf target && for i in 4 5 6; do echo "// edit $i" >> src/lib.rs; cargo +stable build; done
$ ls target/debug/deps/*.rcgu.o | wc -l
9
On 1.85.1 the files are named leakprobe-<metadata>.<cgu>.rcgu.o. On 1.95.0 there's an extra segment: leakprobe-<metadata>.<cgu>.<invocation-random>.rcgu.o. 1.88 and 1.97 behave like 1.95.
The dev profile defaults to 256 codegen units, so a large crate can leak a few hundred files per rebuild. A workspace that gets built and tested all day reaches millions of files in weeks, and the readdir cost of the bloated deps dir then taxes every compiler start in that workspace.
Deleting the stale objects doesn't upset cargo at all (everything still reports Fresh afterwards, you only lose debugger/backtrace symbolication for binaries that were already built), which suggests the backend could remove old *.rcgu.o matching the unit's extra-filename hash before writing the new set. rust-lang/cargo#16665 looks like the same problem seen from the outside (deps dir size blowing up incremental build times on macOS) without the cause identified.
Meta:
rustc 1.85.1 (4eb161250 2025-03-15) does not leak
rustc 1.88.0 (6b00bc388 2025-06-23) leaks
rustc 1.95.0 (59807616e 2026-04-14) leaks
host: aarch64-apple-darwin, macOS 26.4
On macOS, every codegen invocation since 1.88 leaves a full set of
*.rcgu.ofiles behind intarget/debug/deps, and nothing ever cleans them up. Before 1.88 a rebuild overwrote the previous set.I ran into this because the deps dir of our workspace had grown to 3.29 million files (341 GB) over roughly eight weeks of heavy use. At that size every rustc and rustdoc start spends minutes before doing anything useful, since the
-L dependencydirectory is read eagerly at startup into a sorted index (#132910).cargo test --docsat at 0% CPU for over half an hour; asampleof the process showed it insidegetdirentries64underSearchPath::new.What I believe is going on: cargo defaults
split-debuginfotounpackedon macOS, so rustc deliberately keeps the object files after linking because the DWARF lives in them (preserve_objects_for_their_debuginfo). That was harmless while the object names were stable per unit, a rebuild simply replaced the old set. Then #139453 (shipped in 1.88) started prepending a per-invocation random string to temp file names so concurrent invocations can't collide. The preserved objects get that random component too, so now each rebuild writes a brand new set and the old ones just stay there forever.Repro with any small lib crate (mine has 3 modules, so 3 CGUs):
On 1.85.1 the files are named
leakprobe-<metadata>.<cgu>.rcgu.o. On 1.95.0 there's an extra segment:leakprobe-<metadata>.<cgu>.<invocation-random>.rcgu.o. 1.88 and 1.97 behave like 1.95.The dev profile defaults to 256 codegen units, so a large crate can leak a few hundred files per rebuild. A workspace that gets built and tested all day reaches millions of files in weeks, and the readdir cost of the bloated deps dir then taxes every compiler start in that workspace.
Deleting the stale objects doesn't upset cargo at all (everything still reports
Freshafterwards, you only lose debugger/backtrace symbolication for binaries that were already built), which suggests the backend could remove old*.rcgu.omatching the unit's extra-filename hash before writing the new set. rust-lang/cargo#16665 looks like the same problem seen from the outside (deps dir size blowing up incremental build times on macOS) without the cause identified.Meta: