Skip to content

*.rcgu.o files accumulate forever with -Csplit-debuginfo=unpacked since 1.88 #161824

Description

@dasboe

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-debuginfoArea: Debugging information in compiled programs (DWARF, PDB, etc.)C-bugCategory: This is a bug.T-cargoRelevant to the cargo team, which will review and decide on the PR/issue.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions