Skip to content

feat: stabilize -Cmetadata=no as default behavior - #17533

Draft
weihanglo wants to merge 1 commit into
rust-lang:masterfrom
weihanglo:embed-metadata
Draft

weihanglo wants to merge 1 commit into
rust-lang:masterfrom
weihanglo:embed-metadata

Conversation

@weihanglo

@weihanglo weihanglo commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Stabilization report: -Zembed-metadata

What is stabilized

This stabilize the cargo side of -Zembed-metadata,
which changes the default behavior without providing any new user facing config:

  • Cargo will pass -Cembed-metadata=no to rustc unconditionally
    when building rlib and dylib crate types.
    The rlib/dylib crate types will contain only a small stub of metadata.
    The full metadata will be stored in a separate .rmeta file.
  • For dylib specifically
    Cargo will also pass --emit=metadata,
    so that the .rmeta file is always generated.
    (rlib already got that since compilation pipelining support years ago)
  • In order to link the new slimmed rlib,
    Cargo will need to pass extra --extern flag to the corresponding .rmeta file
    to get the rustc metadata.
    This affects bin, staticlib, cdylib, proc-macro crate types (except rlib and dylib).

Other user-observable changes

  • The rustc command line length grows because the number of --extern flags doubles.
    Real world projects like cargo, the lagest cmdline length grows from 34k bytes to 43k bytes in a short target dir path (~26%).
  • This reduce the size of the target directory by 5% to 35% on real world projects,
    according to Kobzol's blog post and the Inside Rust post
  • rlib and becomes way less useful when distributed standalone,
    unless the companion .rmeta is copied and explicitly passed with an extra --extern foo=<path>.rmeta for external build tool.

What is not stabilized / included

  • -Zembed-metadata=yes|no flag.
    We keep this nightly only for a few more release in case people need time to adjust their workflow.
  • Uplifting .rmeta next to the uplifted rlib/dylib.

Feedback

Landing plan

  1. Stabilize -Zembed-metadata rust#163436 lands:
    rustc accepts both -C and -Z until Cargo catches up with -C
  2. Cargo stabilization PR lands:
    Detect whether rustc supports -Cembed-metadata
    Can follow how --check-cfg was stabilized (Stabilize -Zcheck-cfg as always enabled #13571).
    This is required because Cargo CI builds on all stable/beta/nightly toolchain.
  3. Sync Cargo into rust-lang/rust
  4. when promoting to beta, bootstrap stops using Cargo -Zembed-metadata
  5. rustc removes -Zembed-metadata

Unresolved questions

Is this a breaking change?

Proposed: May not be.

An uplifted rlib/dylib was still there in the same place,
and its object code is still there as well.
External linkers or loading dylib can still loading them if needed.

The things got removed are rustc metadata inside it.
The metadata was never a thing user can rely on or distribute easily.
Reasons being:

  • Only readable by exactly the same rustc version
  • Not useable alone without transitive deps's rlibs,
    which are already internal/private.
    They anyway need cargo --message-format=json to find their locations.
  • cargo --message-format=json already prints uplifted rlib's internal path.
  • We have changed the default value of split-debuginfo which also changed the final artifact, and that time it affected executables not just rlib (Default macOS targets to unpacked debuginfo #9298)

However, this is really a compatibility note for those already copying/distributing rlib around, even they have already use --message-format=json. We should have a outstanding note in release notes' compatibility note section.

A stable opt-out flag

Proposed: No.

It is unclear why people need this except not breaking their existing CI pipeline.
The code search shows that most nightly reports were fixes by passing .rmeta.
If stable users need it for reasonable use cases, we can always add an stable option later later.

Command-line length

Command-line argument length does grow,
but in 1.100.0 Cargo will the the new build-dir layout,
which is going to force people to use more response files.
At the time this is stabilized,
users and rustc wrapper tools (e.g., sccache) should already be prepared to be compatible with longer command-line argument length.

Some data:

Project Largest call, embed=yes Largest call, embed=no --extern
sccache 38,500 bytes 46,409 (+20.4%) 70 → 139
cargo 34,586 bytes 43,865 (+26.8%) 82 → 163

Implementation history

PR Merged Title
#15378 2025-05-06 add support for -Zembed-metadata
#16513 2026-01-15 invalidate the whole build cache when the flag changes
#17168 2026-07-08 reduce rustc -L args in the new build-dir layout
#17149 2026-07-12 rename -Zno-embed-metadata to -Zembed-metadata=no
#17266 2026-07-27 allow setting -Zembed-metadata from config
#17267 2026-08-17 on by default on nightly

Follow-ups after stabilization

  • Compatibility note in the release notes
  • Remove Cargo -Zembed-metadata after a few releases, if nobody needs it.
  • Remove rustc probe when Cargo's MSRV is at the version stabilizing -Cembed-metadata
  • Decide on rlib uplifting or not (Remove rlibs as final artifacts #17278)

Acknowledgement

See rust-lang/rust#163436


🤖 LLM disclosure: collecting code search results on GitHub; generating "Implementation history" table; commandline argument length benchmark# Stabilization report: -Zembed-metadata

What is stabilized

This stabilize the cargo side of -Zembed-metadata,
which changes the default behavior without providing any new user facing config:

  • Cargo will pass -Cembed-metadata=no to rustc unconditionally
    when building rlib and dylib crate types.
    The rlib/dylib crate types will contain only a small stub of metadata.
    The full metadata will be stored in a separate .rmeta file.
  • For dylib specifically
    Cargo will also pass --emit=metadata,
    so that the .rmeta file is always generated.
    (rlib already got that since compilation pipelining support years ago)
  • In order to link the new slimmed rlib,
    Cargo will need to pass extra --extern flag to the corresponding .rmeta file
    to get the rustc metadata.
    This affects bin, staticlib, cdylib, proc-macro crate types (except rlib and dylib).

Other user-observable changes

  • The rustc command line length grows because the number of --extern flags doubles.
    Real world projects like cargo, the lagest cmdline length grows from 34k bytes to 43k bytes in a short target dir path (~26%).
  • This reduce the size of the target directory by 5% to 35% on real world projects,
    according to Kobzol's blog post and the Inside Rust post
  • rlib and becomes way less useful when distributed standalone,
    unless the companion .rmeta is copied and explicitly passed with an extra --extern foo=<path>.rmeta for external build tool.

What is not stabilized / included

  • -Zembed-metadata=yes|no flag.
    We keep this nightly only for a few more release in case people need time to adjust their workflow.
  • Uplifting .rmeta next to the uplifted rlib/dylib.

Feedback

Landing plan

  1. Stabilize -Zembed-metadata rust#163436 lands:
    rustc accepts both -C and -Z until Cargo catches up with -C
  2. Cargo stabilization PR lands:
    Detect whether rustc supports -Cembed-metadata
    Can follow how --check-cfg was stabilized (Stabilize -Zcheck-cfg as always enabled #13571).
    This is required because Cargo CI builds on all stable/beta/nightly toolchain.
  3. Sync Cargo into rust-lang/rust
  4. when promoting to beta, bootstrap stops using Cargo -Zembed-metadata
  5. rustc removes -Zembed-metadata

Unresolved questions

Uplift .rmeta or not?

Proposed: No.

An uplifted rlib was never enough on its own unless crate has no deps at all. Otherwise you alwasy need to copy transitive deps through parsing cargo --message-format=json, and if you have done that already, it is easy to also copy final rmeta (and potentially final rlib if cargo stops uplifting it in the future).

Arguments for uplifting: rlib is a final artifact (put in target/<profile>/ directory as a user-visible artifact). If we don't uplift rmeta. rlib with only metadata stub is useless. See those feedback above.

A stable opt-out flag

Proposed: No.

It is unclear why people need this except not breaking their existing CI pipeline.
The code search shows that most nightly reports were fixes by passing .rmeta.
If stable users need it for reasonable use cases, we can always add an stable option later later.

Command-line length

Command-line argument length does grow,
but in 1.100.0 Cargo will the the new build-dir layout,
which is going to force people to use more response files.
At the time this is stabilized,
users and rustc wrapper tools (e.g., sccache) should already be prepared to be compatible with longer command-line argument length.

Some data:

Project Largest call, embed=yes Largest call, embed=no --extern
sccache 38,500 bytes 46,409 (+20.4%) 70 → 139
cargo 34,586 bytes 43,865 (+26.8%) 82 → 163

Implementation history

PR Merged Title
#15378 2025-05-06 add support for -Zembed-metadata
#16513 2026-01-15 invalidate the whole build cache when the flag changes
#17168 2026-07-08 reduce rustc -L args in the new build-dir layout
#17149 2026-07-12 rename -Zno-embed-metadata to -Zembed-metadata=no
#17266 2026-07-27 allow setting -Zembed-metadata from config
#17267 2026-08-17 on by default on nightly

Follow-ups after stabilization

Acknowledgement

See rust-lang/rust#163436


🤖 LLM disclosure: collecting code search results on GitHub; generating "Implementation history" table; commandline argument length benchmark

`-Zembed-metadata` is kept as a nightly fallback
@rustbot rustbot added A-build-execution Area: anything dealing with executing the compiler A-cfg-expr Area: Platform cfg expressions A-documenting-cargo-itself Area: Cargo's documentation labels Sep 29, 2026
@epage

epage commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Some questions I have that don't seem to be addressed in the stabilization report

  • How do our stability guarantees fit into this?
  • If rlibs (and dylibs?) have no guarantees, should we clarify that first by no longer uplifting them?

This branch has not been deployed

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

Labels

A-build-execution Area: anything dealing with executing the compiler A-cfg-expr Area: Platform cfg expressions A-documenting-cargo-itself Area: Cargo's documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants