-
Notifications
You must be signed in to change notification settings - Fork 0
build-std: second iteration #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
fbe72b3
to
507b9c5
Compare
Co-authored-by: Adam Gemmell <[email protected]>
507b9c5
to
599ddbf
Compare
599ddbf
to
04e538c
Compare
Panic strategies are unlike other profile settings insofar as they influence | ||
which crates are built and which flags are passed to the standard library build. | ||
For example, if `panic = "unwind"` were set in the Cargo profile then the | ||
`panic_unwind` feature would need to be provided to `std` and `-Cpanic=unwind` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bootstrap just defaults to panic-unwind for std targets all the time it seems. If std is made an optional dependency of sysroot so the sysroot crate can be built for all targets then perhaps panic_unwind should just be a default feature to avoid cargo needing to pass it.
A future better solution involving feature flags once they're stable would allow for not building the panic runtime that won't be used, and would avoid libs needing to specially stabilise the panic-unwind feature now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
..and would avoid libs needing to specially stabilise the panic-unwind feature now.
Our proposal doesn't require this. Cargo will enable the feature sometimes but that doesn't mean it has to be stable. It will need to be part of the contract between the standard library and Cargo, if the feature changes, both need updated, but that doesn't make it stable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be up to the Cargo team to decide - Cargo does not currently use any unstable interfaces for stable features as far as I'm aware.
On our part we can ensure test coverage of this area on both stable/nightly tests in Cargo, but then we hit the problem of needing to update both trees at the same time. We can of course also show a plan to eventually stabilise libs features.
17413d4
to
4f811dd
Compare
4f811dd
to
660ce5b
Compare
Co-authored-by: Adam Gemmell <[email protected]>
bfc0efb
to
905684d
Compare
Just a minor point: I'm not sure how you intend to publish this as an RFC (that is, if you want to push all of this as a single RFC). If that's the plan, the directory structure will need to be a little different. The top-level document has to be |
We can definitely change it to match that. I expect we'll end up changing the structure again prior to publishing anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all very minor points for stage 1a.
> dependencies. | ||
> | ||
> The standard library will always be a non-incremental build | ||
> ([?][rationale-incremental]), with no `depinfo` produced, and only a `rlib` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoiding the depinfo
may be difficult due to the way cargo works. Is there any particular reason say that it is avoided? AFAIK, the cost is negligible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was just based on what I understood the current implementation to be doing since rust-lang/cargo#8177:
- Cargo's dep-info fingerprint tracking will not track the std crate sources, these are tracked via other means.
- Cargo's
.d
dep-info file does not include std crate sources.
Maybe I've phrased it incorrectly here?
text/0000-build-std/4-stage-1a.md
Outdated
If [*Stage 1b* of this proposal][stage1b] is implemented then `build-std-crate` | ||
will not be used unless explicitly set and the crate graph's dependencies on the | ||
standard library will determine which crates are built instead. Otherwise, | ||
`build-std-crate` will default to "std". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you gone with this "default to std" to avoid needing to make sure the compiler knows if std is supported?
We previously had some discussions around rust-lang/cargo#14183 where we added something similar to this (but using target-spec-json). I think we discussed possibly adding a dedicated --print
option instead of using spec-json, but I can't remember if there were some concerns around that?
(Not important, automatic detection could always be added back later, but I'm wondering what the thinking is here.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went with "std" as a default assuming that the most common case would be that the user would want to rebuild the entire standard library, and if their target didn't support std, with this being a manual opt-in mechanism, it's okay if that doesn't work and they need to change this option to compile fewer crates (just alloc/core or core).
It's not ideal for targets where std will never be supported and we might want to just prevent that from happening entirely with a nice message, where we could introduce a --print std-support
-type of option again to give us the ability to prevent those builds. I'm certainly open doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll work on an edit in favour of effectively keeping the behaviour of current -Zbuild-std from rust-lang/cargo#14899 where the default is based on target-spec. We could also prevent building std on no_std targets unless the unstable option that relaxes build-std-crates
is present.
Having the default option for half the targets to be something that never works seems sub-optimal. Even worse is that default happening to build and then breaking all the time. It's fairly feasible for a user to get lucky and not even realise their target is no_std and end up publishing a crate that uses a std API.
When running `cargo doc` for a project to generate documentation and rebuilding | ||
the standard library, the generated documentation for the user's crates will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI, I'm not sure how easy this will be. It may require some ugly special casing in cargo.
There is rust-lang/wg-cargo-std-aware#88 tracking that cargo doc
is mostly broken right now.
rustdoc has special handling where it will auto-link to https://doc.rust-lang.org/, but I'm not sure why it is broken with build-std. An alternative here would be to investigate if that is an easy fix, and just link to the online docs for now.
I'm also not sure if you are aware of -Z rustdoc-map
which provides a way to control how std
documentation links work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have assumed that linking to local standard library documentation would have been the default and "just worked" (that it would just be "do the same thing as any other crate for these crates too), and that linking to the upstream documentation would be harder (but more desirable if possible), which is why I propose the former at the moment.
I'm aware of rust-lang/wg-cargo-std-aware#88 which is why in the rationale for this part I mention we'd need to be able to pass -Zcrate-attr="doc(html_root_url=...)"
with the correct url and it isn't clear what that would be.
Either way, linking to local docs initially seems sufficient for this initial proposal and we could improve that later.
See also my reply to your other comment - #2 (comment)
Cargo would need to pass `-Zcrate-attr="doc(html_root_url=..)"` to the standard | ||
library crates when building them but doesn't have the required information to | ||
know what url to provide. Cargo would require knowledge of the current toolchain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-Zcrate-attr
may not be required. See the comment above about how rustdoc automatically determines if it can link to the online docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should leave the RFC as-written, that we'll link to local docs, and explore this in implementation - it might be trivial to link to the hosted docs if -Zrustdoc-map
can be used and there's just a small issue somewhere, but its hard to know without trying, and what we propose is sufficient if it ends up not being possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went through the introduction and "stage 1a" and left some comments. I think that the individual stages should explicitly list which subset of the main motivation of the RFC is enabled by the given stage. For example, I just finished 1a, and realized that it doesn't solve the use-cases of rebuilding with a custom profile, so it "only" enables the motivation 4) and 5) (building std for tier-3 targets). That's quite important piece of information, IMO, and it should be made more explicit.
Btw, I have to say, this is a momumental amount of work, great job everyone involved! Not just the research itself, but also the structuring of the document, the question mark links are really great to avoid adding tons of explanations and rationale into the "main" text.
standard library will determine which crates are built instead. Otherwise, | ||
`build-std-crate` will default to "std". | ||
|
||
If `std` is to be built and Cargo is building a test using the default test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about PGO? The sysroot
crate has an optional (and non-default) feature called profiler
(https://github.com/rust-lang/rust/blob/21120e297c3d2db6a1f28e1a8798777a52f4fee2/library/sysroot/Cargo.toml#L35), which has to be enabled for PGO to be supported. If users pass -Cprofile-generate
in RUSTFLAGS
(which is opaque to Cargo), this feature would need to be enabled. That would probably require Cargo to scan rustflags (?).
Or maybe we could just build it unconditionally (or vice-versa: forbid PGO with build-std).
Similar question about the backtrace
feature, which is currently not enabled by default, but there I suppose it could just be enabled unconditionally.
Edit: I saw In line with Cargo's stance on not parsing the RUSTFLAGS environment variable, it will not be checked for compilation flags that would require additional crates to be built for compilation to succeed.
mentioned below. Which suggests that we either build the profiler runtime always or never.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(which is opaque to Cargo), this feature would need to be enabled. That would probably require Cargo to scan rustflags (?).
We generally try to steer solutions away from cargo parsing rustflags as it effectively requires us to duplicate rustc's entire CLI parser as-is to ensure correctness as CLIs are context sensitive, dependent on the flags specified, and can support multiple syntaxes for the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd like us to be able to compile profiler-builtins
unconditionally if we can, and if Cargo eventually has a mechanism for enabling/disabling profiling through Cargo configuration, then we can start compiling that crate only when necessary.
In practice, that's tricky because building profiler-builtins
requires a C toolchain. If we are able to ship the C-compiled part as a rustup component, then that might be an option. Otherwise, I'd be happy not building it initially, leaving the ability to do that as a follow-up, and if you set -Cprofile-generate
in RUSTFLAGS
before that follow-up then you're out of luck.
It's similar to sanitizers w/ needing some native component, except profiling is stable. I don't know if that changes the calculus here and we'd need this to work via RUSTFLAGS
w/ build-std. Obviously we can't scan RUSTFLAGS
to prevent this combination.
We'll look into whether it'll be possible to ship in a self-contained
component the native parts that profiler-builtins
needs so that always building it is possible. Definitely some details to work out here.
|
||
..and few disadvantages: | ||
|
||
- A larger `rust-src` component takes up more disk space and takes longer to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some brief stats on x64 Linux:
- Current size of
rust-src
when built locally withxz
and best compression profile: 3.5 MiB archived, 44 MiB extracted. - With stdlib vendored dependencies added: 9.1 MiB archived, 131 MiB extracted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the majority of the extra space from vendoring is from windows-sys (and friends):
16.9 MiB [ 20.0%] /windows-sys
12.6 MiB [ 14.9%] /windows_i686_gnu
12.1 MiB [ 14.4%] /windows_x86_64_gnu
5.3 MiB [ 6.3%] /windows_i686_msvc
5.0 MiB [ 5.9%] /windows_aarch64_msvc
5.0 MiB [ 5.9%] /windows_x86_64_msvc
4.6 MiB [ 5.4%] /libc
3.9 MiB [ 4.7%] /windows_i686_gnullvm
3.7 MiB [ 4.4%] /windows_aarch64_gnullvm
3.7 MiB [ 4.4%] /windows_x86_64_gnullvm
2.3 MiB [ 2.7%] /unicode-width
2.1 MiB [ 2.4%] /object
1.8 MiB [ 2.2%] /gimli
920.0 KiB [ 1.1%] /hashbrown
It does feel unfortunate for users to pay the extra ~90MB of toolchain space for (probably?) unused code in most local build-std use cases... IIUC, the argument that people download that anyways only applies when targeting the windows targets (and even then, you'd probably not be targeting i686, x86_64, and aarch64 windows...).
I think it's worth asking whether we should split rust-src to be optionally distributed for each target, similar to how this RFC was proposing we'd do for the CRT components. Or whether that change could be added later backwards-compatibly? (Even without the vendoring, having the stdarch intrinsics for x86_64 when you don't build for that target feels unfortunate. Disk space is pretty cheap for most people, but still).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could do something like rust-lang/compiler-team#738 to ship a MIR-only rlib that that just "finish" the compilation of, and depend on that instead of rust-src
. If I recall with that though, there were challenges with cfgs that probably still make that impossible, even if we did a per-target partial rlib.
Either way, I think this is more of an optimisation for later rather than an immediate concern. It's a relatively small disk space cost that enables build-std for everyone, and I think that's reasonable, esp. when it can be improved later. Splitting up std per-target might have greater net disk space usage for those compiling to multiple targets regularly. Trade-offs!
|
||
- No further customisation of the pre-built standard library through any means | ||
other than the profile in `Cargo.toml` | ||
- No new C dependencies on the standard library |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why is this needed in general. build-std implements and stabilizes a mechanism for building the standard library (using Cargo). But if the library can be built on a given system or not is always partly a responsibility of the system's user. There are many Rust crates that cannot be built without a C compiler, and I think that's fine; is it necessarily bad that if people want to use build-std, they will need a C compiler?
|
||
> [!NOTE] | ||
> | ||
> Cargo could be made a [JOSH] subtree of the [rust-lang/rust] so that all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this will become a necessity if build-std moves forward.
text/0000-build-std/4-stage-1a.md
Outdated
> the dependencies of the `core`, `alloc` or `std` standard library crates | ||
> individually (via profile overrides, for example). | ||
> | ||
> - The profile defined by the standard library will be used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this will break LTO, because the stdlib will be compiled with -Cembed-bitcode=no
(bootstrap explicitly overrides this with -Cembed-bitcode=yes
to ship libstd that is LTO-compatible). But even without merging the stdlib and user's workspace profiles, this should be relatively easy to go around; cargo would just hardcode -Cembed-bitcode=yes
if the user's profile has LTO enabled (or it would just use it always, but that would waste disk space and possibly some compilation time).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also a bit confused by this, are we ruling out any customization of that profile other than (maybe) via RUSTFLAGS? E.g., opt-level=s or enabling/disabling debuginfo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this will break LTO, because the stdlib will be compiled with -Cembed-bitcode=no (bootstrap explicitly overrides this with -Cembed-bitcode=yes to ship libstd that is LTO-compatible).
We could move -Cembed-bitcode=yes
into the release profile of the standard library (if we permit nightly-only profile.rustflags
to be respected for std even if doing an otherwise stable build).
I'm also a bit confused by this, are we ruling out any customization of that profile other than (maybe) via RUSTFLAGS? E.g., opt-level=s or enabling/disabling debuginfo?
In Stage 1a, all we're enabling is that you can build a vanilla release profile std for a target. In the later stages, we want to enable automatically building a std that has compatible target modifiers (configured through Cargo profiles, somehow), and we want to enable building std with the user's profile.
The standard library sources are distributed in the `rust-src` component by | ||
rustup and placed in the sysroot under `lib/rustlib/src/`. The sources consist | ||
of the `library/` workspace plus `src/llvm-project/libunwind`, which was | ||
required in the past to build the `unwind` crate on some targets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is libunwind still required? I'm a little confused by "in the past" here (do we care about the past for some reason?).
Is it accurate to say that the rust-src
component is a fully vendored set of sources (across both C and Rust) needed to build the standard library, modulo the configuration to do so (which lives in bootstrap and elsewhere)? (E.g., crates.io dependencies are vendored in when creating it)?
Editing after reading further... I see that stage 1a actually proposes extending rust-src to include vendored sources for all Rust dependencies. I think that's confusing to have this section in the background if we're proposing changes for it. I wonder if we could "just" make the vendoring happen as a separate proposal so we can decouple those changes from this wider RFC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unwind now links to primarily the system libunwind, or the sysroot binary. The unwind sources in rust-src haven't been used since rust-lang/rust#85600. rust-src
at the moment is just a copy of certain paths in the rust repo. You're right in that mentioning libunwind sources here is a bit of a nothingburger, I might just fix it and remove it from the background.
A few people have tried so far to have a vendored rust-src (most recently bjorn3) but the Cargo changes currently required are quite tricky. It would make sense to do other large changes proposed around the resolver in this RFC first before handling vendored dependencies. Vendoring could come in a later MCP, what do you think the benefits would be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not super attached to any particular order. It just seems like if we think this is worth doing, it's something that IMO doesn't actually require an RFC or even MCP to do, just bootstrap/cargo PR(s). And landing it cuts the need for the RFC to be proposing anything in this direction, just relying on existing things.
(Effectively I see this as a technique for shortening the RFC by doing non-controversial stuff without it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could definitely explore vendoring deps into rust-src
while we're discussing this draft so we can cut some complexity out. If it isn't straightforward then it's probably not worth spending too much time on separately IMO.
If the default where not "compatible" then when the user enabled a target | ||
modifier through Cargo (when such options are exposed), the user would | ||
immediately face a compilation error and need to go learn about | ||
`build-std = "compatible"` anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From experience with bootstrap, we have had complaints that this kind of "eager" build behavior can cause confusion and annoyance -- the standard library shouldn't take that long to build (1-2 minutes) but it might still be confusing to people why tweaking a line in their toml added extra dependencies (e.g., rust-src component) and incurred this cost. Maybe worth clarifying whether we can find some way to teach users about the cause of the build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very least it makes sense to mention in the documentation for target modifiers exposed through Cargo that they'll necessarily trigger rebuilds of the standard library. I think eager behaviour is the right choice here as long as we can make sure the rebuilds are only when they are actually necessary.
text/0000-build-std/6-stage-2.md
Outdated
The standard library will be rebuilt in its release profile and will only vary | ||
in the target modifier flags necessarily for it to be compatible | ||
([?][rationale-release-profile]). This is primarily useful for prospective users | ||
of target modifier flags. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really this particular section, but: do we have some consideration of how we'd vary the defaults for target modifiers across versions, if they're exposed in Cargo's profiles? It seems more plausible for customized RUSTFLAGS to break than Cargo options).
I'm thinking us e.g. enabling some security mitigation that's an ABI change and so is an (implicit) target modifier...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect if we changed the default for a target modifier in rustc, we'd want to also change the default in std and any Cargo option that tweaks that flag, so as to avoid the default configuration triggering rebuilds of the standard library (which I'm sure we'd notice quite quickly). I don't know how Cargo deals with defaults today (if it defines them or relies on rustc's default) and if we've had a case before where rustc has changed its default but Cargo hasn't.
|
||
The above examples apply to any other profile too, such as `bench` or `test`. | ||
These options are primarily useful for users wanting to use the same codegen | ||
flags with the standard library or have a more debuggable standard library. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work for custom profile names? Do we used the inherited-from profile?
Does this stabilize the meaning of e.g. the debug profile in library/Cargo.toml? Currently it's arguable that none of the profiles in library/ are in any way exposed to users, only the actual configuration used.
(I think this applies to earlier stages... I am still fuzzy on exactly what options/profiles are passed to rustc by Cargo or by external non-Cargo build systems for building their own standard library crates).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hadn't considered custom profile names. I think we'd use the inherited from profile, yeah. I'll update the RFC to mention this.
I'd want our stability guarantees to say that we don't guarantee that any given profile will always build with a given option set, and that if you want to guarantee that, you need to set it yourself. I think we say something like this already.
library on the target. | ||
|
||
Cargo and Rust project documentation will clearly document the configurations | ||
which are tested upstream and are guaranteed to work. Any other configurations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will we do that? If, for example, we look at today's build it's something like "various options, both stable and unstable, set across a dozen or so files, including target-specific and runner-specific files"... or are we envisioning new CI jobs that are dedicated to testing the dist output with particular configurations (probably makes sense)?
Do we expect to guarantee that users can, on stable, reproduce the build that we distributed binaries for? Or can that require extra flags that aren't stable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This paragraph assumes that we can get the release profile to match the pre-built standard library, in which case we would document that the default release configuration, built locally or pre-built, is tested. We don't necessarily need to go into detail on all of the options that this configuration is comprised of. We could similarly chose to say "the release profile with the addition of one of these sanitisers enabled is tested", or something like that.
I'm envisioning something high-level but that gives users a greater level of confidence for some of the common use cases for build-std, like enabling sanitisers.
of the standard library also use unstable features and it is not practical to | ||
special-case all of these crates. | ||
|
||
↩ [*Building the standard library on a stable toolchain*][building-the-standard-library-on-a-stable-toolchain] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we unset or ignore any other flags that affect the build? e.g. -Zallow-features or future extensions to RUSTC_BOOTSTRAP (I think we already support per-crate =1 but at the all hands there was discussion of allowing allow-features via env variables, too).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't intending to - expecting that we're never going to only build the standard library, it'll always be paired with the user's project. So if you have RUSTFLAGS=-Zsome-unstable-flag
then the implied RUSTC_BOOTSTRAP=1
of the sysroot dependencies might mean that those builds succeed using the nightly flag where they might not otherwise, but it'll still fail when it gets to compiling the user's code. That seems okay to me.
I did some experiments with PGO:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left some pretty minor comments. In general, this was well structured and highly legible given the very technical nature. Excellent work!
1. `[target.<triple>]` | ||
2. `[target.<cfg>]` | ||
3. `[build]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This precedence means that target triple/cfg options in low-precedence config locations can override users explicitly asking for build.build-std=always
in high precedence locations, like through --config
, which is unintuitive at best. It's really hard to override those settings in the global config.
|
||
*See the following sections for future possibilities:* | ||
|
||
- [*Warn when `no_std` crates accidentally have a dependency on `std`*][future-no_std-warning] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the meeting, we should make a more explicit plan here so we ensure we're not closing anything off
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor comments on stage-1b.
std = { builtin = true } | ||
alloc = { builtin = true } | ||
core = { builtin = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't seen a discussion about prelude behavior here. I can imagine various different behaviors here:
- Builtin dependencies always use
noprelude
. This relies on rustc to add implicitextern crate
for std/core (conditional on#![no_std]
attribute), which would also implicitly add it to the prelude.- This causes an inconsistency with other dependency declarations. This means that you still have to specify
extern crate alloc;
in all cases, something we've wanted to avoid.
- This causes an inconsistency with other dependency declarations. This means that you still have to specify
- Explicit builtin dependencies do not use
noprelude
. This is a partial backwards incompatibility (see the whole reasonnoprelude
exists), but might be acceptable if this is limited to explicit dependencies, since the user has to manually opt-in to using them (and thus can fix any problems they encounter, possibly makingstd
optional).- That means that implicit builtin dependencies (that is, when no builtins are specified) continue to use
noprelude
, which means that hello_world is not equivalent to what is listed above.
- That means that implicit builtin dependencies (that is, when no builtins are specified) continue to use
I'm not sure what the answer is here, but would be good to think about the compatibility and consistency issues, and come up with a plan.
## Patches | ||
[patches]: #patches | ||
|
||
Under a perma-unstable feature it is permitted to patch standard library | ||
dependencies with `path` and `git` sources (or any other source) | ||
([?][rationale-patching]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is an optional dependency on the standard library then Cargo will | ||
validate that there is at least one non-optional dependency on the standard | ||
library (e.g. an optional `std` and non-optional `core` or `alloc`, or an | ||
optional `alloc` and non-optional `core`). `core` cannot be optional. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this optionality check also check other dependency kinds like target-specific dependencies? For example:
[target.x86_64-pc-windows-gnu.dependencies]
alloc.builtin = true
Does this mean that it uses an explicit alloc on x86_64-pc-windows-gnu
, and an implicit std/alloc/core on all other targets? Or is this an error, requiring a builtin to be specified in [dependencies]
?
Supercedes #1. Intended for discussion with invited reviewers until we're happy enough to post publicly. Feel free to discuss on #project-goals/2025h1/build-std.
Please don't leave feedback on this unless you've been invited to. We'll invite more project members and teams to participate over time and eventually post this publicly for community feedback. With such a large proposal, this sort of staged rollout is the only way we can manage the feedback and evolve the document. If you aren't invited and post anyway, I reserve the right to just delete comments.
Rendered