Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9429391
build-std
davidtwco Sep 27, 2025
428ce01
small wording tweaks
davidtwco Sep 29, 2025
5121a0a
elaborate on content of this part of the RFC
davidtwco Sep 29, 2025
00b3f8f
swap default/alternative in examples
davidtwco Sep 29, 2025
d3c2b1a
reword RfL motivation
davidtwco Sep 29, 2025
02f8a08
s/standard_library_support/default_build_std_crate
davidtwco Sep 29, 2025
de66272
reword compiler-builtins/mem sections
davidtwco Sep 29, 2025
98ec3e6
reword caching section
davidtwco Sep 29, 2025
77929ca
clarify what later proposals enable
davidtwco Sep 29, 2025
8f82df4
reword cargo vendor changes
davidtwco Sep 29, 2025
7bfca0b
no further required customisation
davidtwco Sep 29, 2025
3214dba
re-order paragraphs
davidtwco Sep 29, 2025
7865b46
no codegen-units changes for compiler-builtins
davidtwco Sep 29, 2025
b83f3c9
clarify stability implications of RUSTC_BOOTSTRAP in sysroot
davidtwco Sep 29, 2025
82e054d
+multiple `--target` flags
davidtwco Oct 2, 2025
66a0f58
do not specify compatibility mechanism
davidtwco Oct 2, 2025
328a5f2
consistent `build-std-crates`
davidtwco Oct 2, 2025
c48e43d
opaque deps drawback
davidtwco Oct 3, 2025
9719228
standard_library_support
davidtwco Oct 3, 2025
cd627f5
cannot replace/patch
davidtwco Oct 3, 2025
47e90e8
skip -p until explicit deps
davidtwco Oct 3, 2025
dca995f
+other
davidtwco Oct 3, 2025
503a6d9
unstable dep behind cfg requires feature
davidtwco Oct 3, 2025
f436c76
implicit dependencies + multiple dependency tables
davidtwco Oct 3, 2025
0897312
avoid describing relationship between std/alloc/core
davidtwco Oct 3, 2025
74bc861
add unresolved q for public std deps
davidtwco Oct 3, 2025
be70a36
elaborate on trade-off for noprelude of explicit builtin deps
davidtwco Oct 3, 2025
c25a29a
elaborate on always syntax unresolved q
davidtwco Oct 3, 2025
b15595e
build-std=always read together
davidtwco Oct 3, 2025
d890a6a
add future possibility for unstable dep behind cfg
davidtwco Oct 3, 2025
754cd4d
fix broken link
davidtwco Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 329 additions & 0 deletions text/0000-build-std.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
- Feature Name: `build-std`
- Start Date: 2025-06-05
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

<!--

This document is long and has lots of authors, follow these rules to maintain a
consistent voice and structure:

Writing style:

- Text is wrapped at ~80 characters, except for headings

- Use the passive voice

- Items in bullet point lists shouldn't end with a period

- Avoid introducing sections that only include other sections and no written
content within them

- In the proposals, write as if the feature has already been accepted and
implemented

- Leave a line between each bullet point

- With the exception of table of contents-style sections (in this document and
in Appendix I), always use reference-style links

- Use a spell checker and broken link checker

- Use 4 spaces for nested bullets, etc.

Structure:

- Every header has a reference link defined below it with its anchor. Top-level
sections just match the header text. Other sections have a prefix (e.g.
"rationale-foo", not "foo")

- Add parentheses with `([?][anchor])` wherever an explanation is justified,
linking to the relevant sub-section in the rationale/alternative section. This
is not required for unresolved questions and future possibilities

- Each justification/alternative in a section must be included in the bullet
list at the bottom of that sub-section, likewise with unresolved questions and
future possibilities

- Each future possibility, unresolved question and rationale/alternative must
backlink back to the section that links to it

- Rationale/alternatives must be in the order that they are referenced in the
text, including in end-of-sub-section lists

- Add anyone who has provided feedback prior to the publication of the RFC to
the acknowledgements section

Consistency:

- Ensure that Appendix I is up-to-date after any changes

- Appendix II should only reflect the discussion on the cited sources, rather
than the current status quo if it has changed

- build-std should not be in backticks (i.e. not `build-std`)

- "pre-built" should always have a hyphen

- Crate names, Cargo configuration options, compiler flags, file names and
environment variables should always be in a backticks (e.g. `build-std`)

- Values passed to compiler flags should be in double quotes (e.g. "compatible")

Git:

- Try to keep each individual change to a single commit and describe that change
in the commit message

- This makes it easier to review and catch-up

- Keep the first line of commit messages limited to 50 characters and the
remaining lines to 74 characters

-->

# Summary
[summary]: #summary

While Rust's pre-built standard library has proven itself sufficient for the
majority of use cases, there are a handful of use cases that are not well
supported:

1. Rebuilding the standard library to match the user's profile
2. Rebuilding the standard library with ABI-modifying flags
3. Building the standard library for tier three targets

This RFC proposes a handful of changes to Cargo, the compiler and standard
library with the goal of defining a minimal build-std that has the potential of
being stabilised:

- Explicitly declaring support for the standard library in target specs
- Explicit and implicit dependencies on the standard library in `Cargo.toml`
- Re-building the standard library when the profile or target modifiers change

This RFC is co-authored by [David Wood][davidtwco] and
[Adam Gemmell][adamgemmell]. To improve the readability of this RFC, it does not
follow the standard RFC template, while still aiming to capture all of the
salient details that the template encourages. Due to the length of this RFC, it
is split over multiple files to avoid rendering issues and slow loading on some
platforms.

### Scope
[scope]: #scope

build-std, as proposed by this RFC, has many restrictions and limitations that
mean it will not support most use cases that those waiting for build-std hope
that it will. This is an explicit and deliberate choice.

This RFC will focus on resolving the key questions that will enable a MVP of
build-std to be accepted and stabilised. This will lay the foundation for future
proposals to lift restrictions and enable build-std to support more use cases,
without those proposals having to survey the ten+ years of issues, pull requests
and discussion that this RFC has.

As a general rule, this RFC tries to answer the question "what crates of the
standard library get built and when do they get built" and considers anything
else as likely out-of-scope.

### Acknowledgements
[acknowledgements]: #acknowledgements

This RFC would not have been possible without the advice, feedback and support
of [Josh Triplett][joshtriplett], [Eric Huss][ehuss],
[Wesley Wiser][wesleywiser] and [Tomas Sedovic][tomassedovic] throughout this
entire effort.

Thanks to [mati865] for advising on some of the specifics related to special
object files, [petrochenkov] for his expertise on rustc's dependency loading and
name resolution; [fee1-dead] for their early and thorough reviews;
[Ed Page][epage] for writing about opaque dependencies and his invaluable Cargo
expertise; [Jacob Bramley][jacobbramley] for his feedback on early drafts; as
well as [Amanieu D'Antras][amanieu], [Tobias Bieniek][turbo87],
[Adam Harvey][lawngnome], [James Munns][jamesmunns],
[Jonathan Pallant][thejpster], [Jieyou Xu][jieyouxu], [Jakub Beránek][kobzol],
[Weihang Lo][weihanglo], and [Mark Rousskov][simulacrum] for providing feedback
from their areas of expertise on later drafts.

### Terminology
[terminology]: #terminology

The following terminology is used throughout the RFC:

- "the standard library" is used to refer to multiple of the crates that
constitute the standard library such as `core`, `alloc`, `std`, `test`,
`proc_macro` or their dependencies.
- "std" is used to refer only to the `std` crate, not the entirety of the
standard library

Throughout the RFC's "Proposal" sections, parentheses with "?" links will be
present that which link the relevant section in the appropriate "Rationale and
alternatives" section to justify a decision or provide alternatives to it.

Additionally, "note alerts" will be used in the *Proposal* sections to separate
implementation considerations from the core proposal. Implementation detail
should be considered non-normative. These details could change during
implementation and are present solely to demonstrate that the implementation
feasibility has been considered and to provide an example of how implementation
could proceed.

> [!NOTE]
>
> This is an example of a "note alert" that will be used to separate
> implementation detail from the proposal proper.

# Contents
[contents]: #contents

This RFC has two self-contained parts and has been written alongside follow-up
RFCs that extend the infrastructure proposed here. Both parts of this RFC have
value independent of each other while having synergies.

As build-std is a complex feature with many interdependent design decisions, it
is challenging to draft a proposal that is small enough to have an achievable
scope in the short-to-medium term while making a convincing argument that it is
forward-compatible with any desired future extensions. This RFC contains the
initial infrastructure for build-std and the most basic version of the feature.
Later RFCs will extend this infrastructure to improve usability and utility.

1. [Summary][summary] (you are here)

- Introduction to the proposal, its scope, terminology/conventions used and
the structure of the RFC

- [Proposal-wide rationale and alternatives][rationale-and-alternatives]

2. [Background](./0000-build-std/1-background.md)

- Detailed explanations of how relevant and impacted parts of the Rust
toolchain currently work

3. [History](./0000-build-std/2-history.md)

- Chronological summary of the various proposals and discussions that have
taken place relating to the ability to rebuild the standard library, and
of the current experimental implementation in Cargo

4. [Motivation](./0000-build-std/3-motivation.md)

- Descriptions of the varied problems that build-std has been proposed as a
solution to

5. [build-std=always](./0000-build-std/4-build-std-always.md)

- Proposes adding a `build-std = "always|never"` option to the Cargo
configuration which will unconditionally re-build the standard library
crates listed in a new `build-std-crates` option

- [Proposal](./0000-build-std/4-build-std-always.md#proposal)

- [Rationale and alternatives](./0000-build-std/4-build-std-always.md#rationale-and-alternatives)

- [Unresolved questions](./0000-build-std/4-build-std-always.md#unresolved-questions)

- [Future possibilities](./0000-build-std/4-build-std-always.md#future-possibilities)

6. [Explicit dependencies](./0000-build-std/5-standard-library-dependencies.md)
Comment on lines +211 to +225
Copy link

Choose a reason for hiding this comment

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

This RFC includes two separate but related proposals

  • build-std=always
  • Explicit dependencies

I am not seeing any rationale for why these are being conjoined into one RFC. Large RFCs are like large PRs. An area of focus draws everyone's attention, neglecting other topics. Once that area is "resolved enough", people move onto the next one. And so on until everyone is burnt out and we accept or reject it without reviewing important details. This will also make the conversation harder because of how much more there will be. This also pulls teams onto FCPs that aren't relevant.

Examples of splitting related RFCs

I would need to see a strong case made for why these should be kept in the same RFC as having them conjoined will make things harder for all parties involved and, at least for myself, will have less trust in the process.

I could even see splitting build-std=always up further to be team focused, layered where at the bottom is infra and lib, then compiler, then cargo. I've not thought through the implications of doing such a split and have no opinion at the moment on what should be done.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I've kept both together as they address the same motivations, and share the history, prior art, etc sections. We've wrote all of these together to make sure that the proposals synergise and that everything included is presented in the context of the larger feature/vision it enables.

I'm open to splitting it into a handful of RFCs if we can work out how to partition the content up in a way that makes sense. My plan so far has been that by doing lots of iterations with smaller groups and representatives from each team that we should have addressed a majority of the major feedback we're likely to get and the RFC shouldn't be too surprising to any of the affected teams.

Copy link

Choose a reason for hiding this comment

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

The examples I gave are in a similar boat in terms of synergy and being written together. As for any shared content, I'm unsure how best to handle that.

My plan so far has been that by doing lots of iterations with smaller groups and representatives from each team that we should have addressed a majority of the major feedback we're likely to get and the RFC shouldn't be too surprising to any of the affected teams.

My response to some of what was discussed was effectively "let's document this and work it out during the RFC with all parties present". Getting feedback in the small is important for faster iteration but it does not replace having a team-wide, project-wide, and community-wide conversation.

Copy link
Owner Author

Choose a reason for hiding this comment

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

As for any shared content, I'm unsure how best to handle that.

I think the easiest way is probably to pick a part of the proposal to make first - probably explicit dependencies? - and then include all the context/history/etc with that, and then just reference that RFC's context/history/prior art sections from everything that follows.

My response to some of what was discussed was effectively "let's document this and work it out during the RFC with all parties present". Getting feedback in the small is important for faster iteration but it does not replace having a team-wide, project-wide, and community-wide conversation.

👍

Copy link

Choose a reason for hiding this comment

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

I think the easiest way is probably to pick a part of the proposal to make first - probably explicit dependencies? - and then include all the context/history/etc with that, and then just reference that RFC's context/history/prior art sections from everything that follows.

I'd post both at once. I feel like "explicit dependencies" could even stand on its own separate from build-std.

Alternatively, we create another RFC that is laying down the build-std project constraints. Not quite a eRFC but not quite a behavior-specifying RFC, making it so there are (at least) three proposals in flight.

Copy link
Owner Author

@davidtwco davidtwco Oct 3, 2025

Choose a reason for hiding this comment

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

Alternatively, we create another RFC that is laying down the build-std project constraints. Not quite a eRFC but not quite a behavior-specifying RFC, making it so there are (at least) three proposals in flight.

I really like that as an approach. Most of the sections that would make up that RFC are basically already ready and could be posted much sooner than the rest of the RFC, then we can just post everything else in whatever chunks make most sense.


- Proposes supporting explicit dependencies on the standard library crates in
`Cargo.toml`

- Enables Cargo to determine which standard library crates are required by
the crate graph without `build-std-crates` being set

- Necessary for future extensions which support public/private standard
library dependencies or enabling features of the standard library

- [Proposal](./0000-build-std/5-standard-library-dependencies.md#proposal)

- [Rationale and alternatives](./0000-build-std/5-standard-library-dependencies.md#rationale-and-alternatives)

- [Unresolved questions](./0000-build-std/5-standard-library-dependencies.md#unresolved-questions)

- [Future possibilities](./0000-build-std/5-standard-library-dependencies.md#future-possibilities)

7. [Appendix I: Summary of changes](./0000-build-std/6-appendix-summary-of-changes.md)

- Summary of each of the changes which would need implemented in the Rust
toolchain, grouped by the project team whose purview the change would fall
under

8. [Appendix II: Exhaustive literature review](./0000-build-std/7-appendix-literature-review.md)

- More detailed summaries of the relevant issues, discussions, pull requests
and proposals that comprise the history of the build-std feature since
2015

- [*History*](./0000-build-std/2-history.md) aims to summarise this content further and
cover everything that should be necessary to understand the proposal

# Rationale and alternatives
[rationale-and-alternatives]: #rationale-and-alternatives

These rationales and alternatives apply to the proposal as-a-whole:

## Why not do nothing?
[rationale-why-not-do-nothing]: #why-not-do-nothing

Support for rebuilding the standard library is a long-standing feature request
from subsets of the Rust community and blocks the work of some project teams
(e.g. sanitisers and branch protection in the compiler team, amongst others).
Inaction forces these users to remain on nightly and depend on the unstable
`-Zbuild-std` flag indefinitely. RFCs and discussion dating back to the first
stable release of the language demonstrate the longevity of build-std as a
need.

## Shouldn't build-std be part of rustup?
[rationale-in-rustup]: #shouldnt-build-std-be-part-of-rustup

build-std is effectively creating a new sysroot with a customised standard
library. rustup as Rust's toolchain manager has existing machinery to create and
maintain sysroots, and if it could invoke Cargo to build the standard library
then it could create a new toolchain from a build from a `rust-src` component.
rustup would be invoking tools from the next layer of abstraction (Cargo) in the
same way that Cargo invokes tools from the layer of abstraction after it
(rustc).

A brief prototype of this idea was created and a
[short design document was drafted][why-not-rustup] before concluding that it
would not be possible. With Cargo's artifact dependencies it may be desirable
to build with a different standard library and if rustup was creating different
toolchains per-customised standard library then Cargo would need to have
knowledge of these to switch between them, which isn't possible (and something
of a layering violation). It is also unclear how Cargo would find and use the
uncustomized host sysroot for build scripts and procedural macros. In addition
rustup's knowledge of sysroots and toolchains is limited to the archives it
unpacks - it becoming a part of the build system is not trivial, especially
considering it uses a different versioning system to Cargo, Rust and the
standard library.

# Drawbacks
[drawbacks]: #drawbacks

There are some drawbacks to build-std:

- build-std overlaps with the initial designs and ideas for opaque dependencies
in Cargo, thereby introducing a risk of constraining or conflicting with the
eventual complete design for opaque dependencies

[davidtwco]: https://github.com/davidtwco
[adamgemmell]: https://github.com/adamgemmell
[amanieu]: https://github.com/Amanieu
[ehuss]: https://github.com/ehuss
[epage]: https://github.com/epage
[fee1-dead]: https://github.com/fee1-dead
[jacobbramley]: https://github.com/jacobbramley
[jamesmunns]: https://github.com/JamesMunns
[jieyouxu]: https://github.com/jieyouxu
[joshtriplett]: https://github.com/joshtriplett
[kobzol]: https://github.com/kobzol
[lawngnome]: https://github.com/LawnGnome
[mati865]: https://github.com/mati865
[petrochenkov]: https://github.com/petrochenkov
[simulacrum]: https://github.com/simulacrum
[thejpster]: https://github.com/thejpster
[tomassedovic]: https://github.com/tomassedovic
[turbo87]: https://github.com/Turbo87
[weihanglo]: https://github.com/weihanglo
[wesleywiser]: https://github.com/wesleywiser

[why-not-rustup]: https://hackmd.io/@davidtwco/rkYRlKv_1x
Loading