Skip to content

build-std: always#3874

Open
davidtwco wants to merge 27 commits intorust-lang:masterfrom
davidtwco:build-std-part-two-always
Open

build-std: always#3874
davidtwco wants to merge 27 commits intorust-lang:masterfrom
davidtwco:build-std-part-two-always

Conversation

@davidtwco
Copy link
Member

@davidtwco davidtwco commented Oct 31, 2025

Add a new Cargo configuration option, build-std = "always|never", which will unconditionally rebuild standard library dependencies. The set of standard library dependencies can optionally be customised with a new build-std-crates option. It also describes how Cargo (or external tools) should build the standard library crates on stable (i.e., which flags to pass and features to enable).

This proposal limits the ways the built standard library can be customised (such as by settings in the profile) and intends that the build standard library matches the prebuilt one (if available) as closely as possible.

This RFC is is part of the build-std project goal and a series of build-std RFCs:

  1. build-std context (build-std: context #3873)
  2. build-std="always" (this RFC)
  3. Explicit standard library dependencies (build-std: explicit dependencies #3875)
  4. build-std="compatible" (RFC not opened yet)
  5. build-std="match-profile" (RFC not opened yet)

There is also a Zulip channel where you can ask questions about any of the build-std RFCs. This series of RFCs was drafted over many months with the help of stakeholders from many Rust project teams, we thank them for their help!

FCP

Rendered

This was referenced Oct 31, 2025
@davidtwco davidtwco added T-libs-api Relevant to the library API team, which will review and decide on the RFC. T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-cargo Relevant to the Cargo team, which will review and decide on the RFC. labels Oct 31, 2025
@ehuss ehuss moved this to RFC needs review in Cargo status tracker Nov 4, 2025
@epage
Copy link
Contributor

epage commented Jan 20, 2026

@rfcbot fcp concern cargo-config-shorthand

See #3874 (comment)

github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Jan 20, 2026
Destabilise `target-spec-json`

Per rust-lang/compiler-team#944:

> Per rust-lang/rust#71009, the ability to load target spec JSONs was stabilised accidentally. Within the team, we've always considered the format to be unstable and have changed it freely. This has been feasible as custom targets can only be used with core, like any other target, and so custom targets de-facto require nightly to be used (i.e. to build core manually or use Cargo's -Zbuild-std).
>
> Current build-std RFCs (rust-lang/rfcs#3873, rust-lang/rfcs#3874) propose a mechanism for building core on stable (at the request of Rust for Linux), which combined with a stable target-spec-json format, permit the current format to be used much more widely on stable toolchains. This would prevent us from improving the format - making it less tied to LLVM, switching to TOML, enabling keys in the spec to be stabilised individually, etc.
>
> De-stabilising the format gives us the opportunity to improve the format before it is too challenging to do so. Internal company toolchains and projects like Rust for Linux already use target-spec-json, but must use nightly at some point while doing so, so while it could be inconvenient for those users to destabilise this, it is hoped that an minimal alternative that we could choose to stabilise can be proposed relatively quickly.
rust-bors bot pushed a commit to rust-lang/rust that referenced this pull request Jan 21, 2026
…, r=Kobzol

Move bootstrap configuration to library workspace

This creates a new "dist" profile in the standard library which contains configuration for the distributed std artifacts previously contained in bootstrap, in order for a future build-std implementation to use. bootstrap.toml settings continue to override these defaults, as would any RUSTFLAGS provided. I've left some cargo features driven by bootstrap for a future patch.

Unfortunately, profiles aren't expressive enough to express per-target overrides, so [this risc-v example](https://github.com/rust-lang/rust/blob/c8f22ca269a1f2653ac962fe2bc21105065fd6cd/src/bootstrap/src/core/build_steps/compile.rs#L692) was not able to be moved across. This could go in its own profile which Cargo would have to know to use, and then the panic-abort rustflags overrides would need duplicating again. Doesn't seem like a sustainable solution as a couple similar overrides would explode the number of lines here.

We could use a cargo config in the library workspace for this, but this then would have to be respected by Cargo's build-std implementation and I'm not yet sure about the tradeoffs there.

This patch also introduces a build probe to deal with the test crate's stability which is obviously not ideal, I'm open to other solutions here or can back that change out for now if anyone prefers.

cc @Mark-Simulacrum rust-lang/rfcs#3874
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Jan 23, 2026
…, r=Kobzol

Move bootstrap configuration to library workspace

This creates a new "dist" profile in the standard library which contains configuration for the distributed std artifacts previously contained in bootstrap, in order for a future build-std implementation to use. bootstrap.toml settings continue to override these defaults, as would any RUSTFLAGS provided. I've left some cargo features driven by bootstrap for a future patch.

Unfortunately, profiles aren't expressive enough to express per-target overrides, so [this risc-v example](https://github.com/rust-lang/rust/blob/c8f22ca269a1f2653ac962fe2bc21105065fd6cd/src/bootstrap/src/core/build_steps/compile.rs#L692) was not able to be moved across. This could go in its own profile which Cargo would have to know to use, and then the panic-abort rustflags overrides would need duplicating again. Doesn't seem like a sustainable solution as a couple similar overrides would explode the number of lines here.

We could use a cargo config in the library workspace for this, but this then would have to be respected by Cargo's build-std implementation and I'm not yet sure about the tradeoffs there.

This patch also introduces a build probe to deal with the test crate's stability which is obviously not ideal, I'm open to other solutions here or can back that change out for now if anyone prefers.

cc @Mark-Simulacrum rust-lang/rfcs#3874
github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Jan 26, 2026
…, r=Kobzol

Move bootstrap configuration to library workspace

This creates a new "dist" profile in the standard library which contains configuration for the distributed std artifacts previously contained in bootstrap, in order for a future build-std implementation to use. bootstrap.toml settings continue to override these defaults, as would any RUSTFLAGS provided. I've left some cargo features driven by bootstrap for a future patch.

Unfortunately, profiles aren't expressive enough to express per-target overrides, so [this risc-v example](https://github.com/rust-lang/rust/blob/c8f22ca269a1f2653ac962fe2bc21105065fd6cd/src/bootstrap/src/core/build_steps/compile.rs#L692) was not able to be moved across. This could go in its own profile which Cargo would have to know to use, and then the panic-abort rustflags overrides would need duplicating again. Doesn't seem like a sustainable solution as a couple similar overrides would explode the number of lines here.

We could use a cargo config in the library workspace for this, but this then would have to be respected by Cargo's build-std implementation and I'm not yet sure about the tradeoffs there.

This patch also introduces a build probe to deal with the test crate's stability which is obviously not ideal, I'm open to other solutions here or can back that change out for now if anyone prefers.

cc @Mark-Simulacrum rust-lang/rfcs#3874
@ehuss ehuss moved this from FCP merge to FCP blocked in Cargo status tracker Jan 27, 2026
@epage
Copy link
Contributor

epage commented Feb 26, 2026

@rfcbot fcp resolve cargo-config-shorthand

@ehuss ehuss moved this from FCP blocked to FCP merge in Cargo status tracker Mar 3, 2026
@epage
Copy link
Contributor

epage commented Mar 3, 2026

Comment on lines +886 to +896
### Why does "always" rebuild in release profile?
[rationale-release-profile]: #why-does-always-rebuild-in-release-profile

The release profile most closely matches the existing pre-built standard
library, which has proven itself suitable for a majority of use cases.

By minimising the differences between a newly-built std and a pre-built std,
there is less chance of the user experiencing bugs or unexpected behaviour from
the well-tested and supported pre-built std. Later proposals will extend the
`build-std` option with customised standard library builds that use the user's
profile.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't a part of this the idea that building std should be a drop-in for using the regular std so we should build them the same way by default?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this proposal, yes. See my reply to #3874 (comment) for links to the later proposals that add new build-std.when variants.

Building std with user profiles is intended to support more niche cases like enabling target modifier flags that require the entire crate graph to agree on (because of the ABI, for example) and where it wouldn't be appropriate for that to be the default for std. We could ship pre-built standard libraries for those cases (and plan to for sanitizers until we have build-std), but it'd end up with an combinatorial explosion of pre-built standard libraries. If I recall correctly, our proposals for that say you don't get the same stability guarantees/expectations of a std that doesn't match what we ship.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More so I feel like this is an unrepresented motivation in this section.

Copy link
Member Author

@davidtwco davidtwco Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added what I posted in this thread to the RFC in dfabca9

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this still misses the core idea: that build-std is a drop-in for std and should act the same by default.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added that wording specifically in 7509516

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That puts it as a secondary effect rather than a driving principle of the design which was my understanding that it was.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but it'd end up with an combinatorial explosion of pre-built standard libraries.

Yeah, another axis of combinatorial explosion would be cfgs like debug_assertions and no_fp_fmt_parse, but I imagine you don't plan to cover all those either, right?

(To be clear, at least for the Rust for Linux use case, we don't need pre-built standard libraries.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added this to the primary motivation section in 23e7a34 - the intent isn't that is a secondary effect: certainly one of the key design tenets of this RFC's approach is to minimise the differences between the pre-built std and a newly-built std.

Comment on lines +1401 to +1408
### Should the standard library inherit RUSTFLAGS?
[unresolved-inherit-rustflags]: #should-the-standard-library-inherit-rustflags

Existing designs for *[Opaque dependencies]* intended that `RUSTFLAGS` would not
apply to the opaque dependency. However, if a target modifier were set using
`RUSTFLAGS` and build-std ignored the variable, then rustc would fail to build
the user's project due to incompatible target modifiers. This would necessitate
that every stable target modifier be exposed via Cargo to be usable in practice.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Profiles use the workspace's version with a future possibility to use the user's profiles, see #3874 (comment)

RUSTFLAGS should be independent of the local build also but we are not doing it for target modifiers.

This feels inconsistent. If an opaque dependency's profile is independent of the local build unless there is an opt-in, why aren't we doing the same for RUSTFLAGS?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is inconsistent, but I don't find that unexpected. RUSTFLAGS is a global override that applies to every dependency today, and with this proposal, continues to apply to every dependency. As we introduce opaque dependencies, with the standard library being a special-case of that, I think it's okay for there to be a different expectation with regards to whether profiles apply automatically. That we use the opaque dependency's profile independent of the local build is what gives us the "this locally-built std closely matches what upstream distributes" property which reduces the scope of this proposal for the library team.

I'd be happy to add a build-std.use-rustflags = true key for this if we wanted, it isn't something I feel strongly about, but I'm not sure it's necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is inconsistent, but I don't find that unexpected. RUSTFLAGS is a global override that applies to every dependency today, and with this proposal, continues to apply to every dependency.

That applies equally to profiles. What makes profiles different that we leave one global and the other has its expectations changed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that the standard library defines a profile that we can re-use - and by doing so, achieve other goals of this RFC, that we don't expose more surface area of the standard library - but it doesn't define or ship a set of RUSTFLAGS that we could use to achieve the same ends (there's just no mechanism for it to do so).

If there were a DIST_STD_RUSTFLAGS variable that the standard library somehow provided, I'd be happy to use that so that both RUSTFLAGS and profiles have the differing behaviour here, rather than only profiles.

And in our later proposals, we introduce mechanisms such that both RUSTFLAGS and the user's profiles would equally apply to the standard library's dependencies.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is that the standard library defines a profile that we can re-use - and by doing so, achieve other goals of this RFC, that we don't expose more surface area of the standard library - but it doesn't define or ship a set of RUSTFLAGS that we could use to achieve the same ends (there's just no mechanism for it to do so).

You could say that default RUSTFLAGS is it.

To be clear, I'm not necessarily advocating for this to change but that we need to balance the needs of our principles against the immediate users and have a good story to explain why things behave as they do. I'm not convinced by "but we need an exception here but not there".

For example, one potential motivation is that Cargo doesn't and shouldn't do anything special for RUSTFLAGS because it is a low level escape hatch that is opaque to Cargo in terms of what it meas and does. This is generally the take of the Cargo team and limits other uses of specializing of RUSTFLAGS. For example, profile rustflags is likely a perma-unstable feature; we just have not officially said so yet.

And in our later proposals, we introduce mechanisms such that both RUSTFLAGS and the user's profiles would equally apply to the standard library's dependencies.

Yes, you can opt in profiles to act like RUSTSFLAGS but the statement can otherwise be easily misread that we will also provide an opt-out of RUSTFLAGS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to address this in 6937cd9. I'm not sure how else to communicate the rationale behind RUSTFLAGS behaving as proposed and profiles behaving as exposed without it sounding like an exception rather than a balance of principles/needs.

@epage
Copy link
Contributor

epage commented Mar 3, 2026

@rfcbot fcp concern rustflags-profile-inconsistency

See https://github.com/rust-lang/rfcs/pull/3874/changes#r2879178332

@davidtwco davidtwco force-pushed the build-std-part-two-always branch from 7509516 to 23e7a34 Compare March 12, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This RFC is in PFCP or FCP with a disposition to merge it. proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. T-cargo Relevant to the Cargo team, which will review and decide on the RFC. T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Projects

Status: FCP blocked

Development

Successfully merging this pull request may close these issues.