Skip to content
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

Check build target supports std when building with -Zbuild-std=std #14183

Merged

Conversation

harmou01
Copy link
Contributor

@harmou01 harmou01 commented Jul 3, 2024

What does this PR try to resolve?

Ensures that Cargo first verifies whether a given target supports building the standard library when the -Zbuild-std=std option is passed to Cargo (see issue here). This information can be obtained by querying rustc --print=target-spec-json. The target spec "metadata" contains an Option<bool> determining whether the target supports building std.

In the case this value is false, cargo will stop the build. This avoids the numerous "use of unstable library" errors, giving a cleaner, and simpler, "building std is not supported on this target".

How should we test and review this PR?

It can be manually tested by running cargo build --target <target> -Zbuild-std=std. If a target who's target-spec marks std as false is passed, cargo will exit. This works with multiple --target's, and if any of them don't support std, cargo will exit.

Additional Information

This change relies on two things:

  • The target-spec metadata in rustc needs to be filled out. Currently, most fields are None, which is treated as OK with this change. Meaning this can be merged before the rustc changes.
  • The new test case added with this change will fail without at least aarch64-unknown-none having it's target-spec metadata completed.
  • Some targets have std support marked as "?". If this state is properly represented in the target-spec in the future, it needs to be determined whether this is allowed, so the build can continue, or whether it fails.

@rustbot
Copy link
Collaborator

rustbot commented Jul 3, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @ehuss (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added A-cfg-expr Area: Platform cfg expressions S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 3, 2024
@harmou01
Copy link
Contributor Author

harmou01 commented Jul 3, 2024

r? @ehuss

@rustbot
Copy link
Collaborator

rustbot commented Jul 3, 2024

Could not assign reviewer from: ehuss.
User(s) ehuss are either the PR author, already assigned, or on vacation, and there are no other candidates.
Use r? to specify someone else to assign.

@ehuss
Copy link
Contributor

ehuss commented Jul 3, 2024

Thanks for the PR! Unfortunately I'm not sure this is something we can move forward with in the short term. The --print target-spec-json option would need to be stabilized in order for this to be supported in build-std. I'm not sure how feasible that is. My impression is that it seems like that will be difficult, since some of the fields are somewhat inherently unstable.

There is some more information at rust-lang/rust#38338 and rust-lang/wg-cargo-std-aware#6.

I would suggest getting in contact with the compiler team to suss out the viability of that. There might be other alternatives, such as providing other rustc options for querying/extracting information like this.

@adamgemmell
Copy link

adamgemmell commented Jul 3, 2024

I didn't think that target-spec-json would need to be stable because Cargo and Rustc are versioned together - this creates a contract between the two, but one that can be changed, similar to the contract between Rustc and std (or stdarch as a closer example). Would a test in Rust that tests this integration alleviate your concerns? We only need to parse part of the spec.

Otherwise I doubt the spec can be stabilised, so I think we'd need some other mechanism of getting target info from Rustc. I think this might be useful for things like getting the default panic or unwind strategy too.

@ehuss
Copy link
Contributor

ehuss commented Jul 3, 2024

I didn't think that target-spec-json would need to be stable because Cargo and Rustc are versioned together - this creates a contract between the two, but one that can be changed, similar to the contract between Rustc and std (or stdarch as a closer example).

They aren't exactly tightly coupled with each other. Cargo is expected to work on the previous two versions of rustc (although build-std makes that complicated). Also, since cargo is developed in a separate repository, it makes it difficult to synchronize changes, since a change in rustc could immediately break development in cargo.


I think it might be possible to support this on an advisory basis, but not something we can strictly rely upon. It would likely need a different approach than what is taken in this PR, though. A few things to consider:

  • I'm uncomfortable with setting RUSTC_BOOTSTRAP in TargetInfo::new, since that could leak exposure of unstable options on stable (and generally uncomfortable setting it anywhere). I would suggest collecting the JSON information in a separate call to cached_output. That would also avoid needing to guess where the JSON boundaries are.
  • Ignore all errors from rustc, to handle the case where target-spec-json changes.
  • Ignore all errors from deserialization, to also handle the case if target-spec-json changes.

However, I'm reluctant to do that since I think it introduces risk of breaking cargo's CI and development (since cargo's testsuite could fail). I'm not sure how a test in rust-lang/rust would help, since if the compiler needs to make a change to the target-spec-json output or CLI option, there would be a problem where you can't update both rustc and cargo at the same time. That has been a fundamental problem that has prevented us from adding build-std tests to rust-lang/rust.

I would suggest opening a dialog with the compiler team to see if they have any input on how cargo and rustc can coordinate to obtain this information in a way that would be reliable.

@bors
Copy link
Contributor

bors commented Jul 5, 2024

☔ The latest upstream changes (presumably #14185) made this pull request unmergeable. Please resolve the merge conflicts.

@adamgemmell
Copy link

I appreciate the detailed answer, thanks. Agreed on the RUSTC_BOOTSTRAP=1 hack. On checking the target-spec-json tracking issue it does seem like there's some support for stabilising the print option which surprised me - I think I had it mixed up in my head with the idea of providing the JSON as an input target.

Considering the case where it was stabilised with all fields, current and future, optional. In the case of this PR, it would mean that Cargo handles the "not found" case for the Metadata::std field, probably by printing out a warning, but not error out or break Cargo's CI. Then we'd basically have to wait for a bug report from someone who got the warning and parse the new format while continuing to support the old one.

This seems not ideal, but might it be good enough? The alternative would be a stricter form of stabilisation that makes all current fields mandatory, any future fields optional and all enums non-exhaustive and strings have an undefined format.

@harmou01 harmou01 force-pushed the dev/harmou01/handle-target-build-std branch from d79de0d to db383e7 Compare October 14, 2024 13:09
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

Regardless of my review, Eric's concern in #14183 (comment) should be deeply considered.

src/cargo/core/compiler/build_context/target_info.rs Outdated Show resolved Hide resolved
src/cargo/core/compiler/standard_lib.rs Outdated Show resolved Hide resolved
tests/testsuite/standard_lib.rs Outdated Show resolved Hide resolved
tests/testsuite/freshness.rs Outdated Show resolved Hide resolved
@weihanglo weihanglo added the Z-build-std Nightly: build-std label Oct 15, 2024
@harmou01 harmou01 force-pushed the dev/harmou01/handle-target-build-std branch from db383e7 to e34950e Compare October 15, 2024 09:25
@harmou01
Copy link
Contributor Author

@weihanglo Regarding Eric's concerns about the use of the --print=target-spec-json and the possibility of it changing, @adamgemmell has an RFC open to add a --print=std-support flag, which gives us a simpler and more reliable method for determining std support. We wouldn't have to grab the entire target-spec-json anymore, and therefore wouldn't risk things changing between versions, because rustc would always give a true/false answer. I think this should address Eric's concerns.

The second rustc query wouldn't be needed either if this RFC is implemented, we could revert back to collecting everything with a single query.

rust-lang/rfcs#3693

@adamgemmell
Copy link

rust-lang/rfcs#3693

To elaborate on this we tried to make this patch improve things without waiting for the RFC's proposal to become stable by removing RUSTC_BOOTSTRAP and making Cargo tolerate all failure cases. If you'd feel more comfortable waiting for that solution then we're fine with that of course.

@harmou01 harmou01 force-pushed the dev/harmou01/handle-target-build-std branch from e34950e to 37a326e Compare October 30, 2024 13:47
src/cargo/core/compiler/build_context/target_info.rs Outdated Show resolved Hide resolved
src/cargo/core/compiler/build_context/target_info.rs Outdated Show resolved Hide resolved
tests/testsuite/standard_lib.rs Outdated Show resolved Hide resolved
src/cargo/core/compiler/standard_lib.rs Outdated Show resolved Hide resolved
src/cargo/core/compiler/build_context/target_info.rs Outdated Show resolved Hide resolved
tests/testsuite/cfg.rs Outdated Show resolved Hide resolved
Running cargo with "-Zbuild-std=std" should check whether the build
target supports building the standard library. This information can be
obtained from rustc with the target-spec-json "--print" option. When
'std' is false for the build target, cargo should not attempt to build
the standard library.

This avoids the "use of unstable library" errors, as this check is
performed before Cargo starts trying to build restricted_std code.

Cargo will now emit a warning if the requested target does not support
building the standard library, or if there was an issue when collecting
the necessary information via rustc
Add a new test case to check cargo handles building a target which
doesn't support the standard library properly.
@harmou01 harmou01 force-pushed the dev/harmou01/handle-target-build-std branch from 37a326e to 6a980bc Compare November 21, 2024 14:24
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

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

Thanks for working through the feedback—looks great now!

@weihanglo weihanglo added this pull request to the merge queue Nov 22, 2024
Merged via the queue into rust-lang:master with commit 88edf01 Nov 22, 2024
20 checks passed
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 25, 2024
Update cargo and books

10 commits in 66221abdeca2002d318fde6efff516aab091df0e..4c39aaff66862cc0da52fe529aa1990bb8bb9a22
2024-11-19 21:30:02 +0000 to 2024-11-25 16:36:17 +0000
- feat: Stabilize Edition 2024 (rust-lang/cargo#14828)
- Improve error handling when PathSource is relative (rust-lang/cargo#14854)
- test: address test output nondeterminism  (rust-lang/cargo#14855)
- chore: move supports-unicode to workspace deps (rust-lang/cargo#14853)
- Check build target supports std when building with -Zbuild-std=std (rust-lang/cargo#14183)
- fix(publish): Allow dry-run of a non-bumped workspace  (rust-lang/cargo#14847)
- test: Switch from 'exec_with_output' to 'run' (rust-lang/cargo#14848)
- test(rustflags): Verify -Cmetadata directly, not through -Cextra-filename (rust-lang/cargo#14846)
- chore: remove bors mentions (rust-lang/cargo#14845)
- Clarify how `cargo::metadata` env var is selected (rust-lang/cargo#14842)

## nomicon

1 commits in eac89a3cbe6c4714e5029ae8b5a1c556fd4e8c42..0674321898cd454764ab69702819d39a919afd68
2024-11-16 14:05:28 +0000 to 2024-11-19 12:35:48 +0000
- races: Clarify a “mostly” that might be misread (rust-lang/nomicon#468)

## reference

12 commits in 41ccb0e6478305401dad92e8fd3d04a4304edb4c..5c86c739ec71b8bc839310ff47fa94e94635bba9
2024-11-15 21:45:16 +0000 to 2024-11-25 17:23:35 +0000
- Document `gen` keyword as reserved in Rust 2024 (rust-lang/reference#1501)
- 2024: Update `expr` macro fragment specifier (rust-lang/reference#1639)
- Add rust_2024 prelude (rust-lang/reference#1552)
- 2024: Add reserved syntax (rust-lang/reference#1652)
- Add Lifetime Capture Rules 2024 (rust-lang/reference#1601)
- Add a section dedicated to Edition 2024 changes to temporary scopes (rust-lang/reference#1592)
- 2024: Add unsafe attribute differences (rust-lang/reference#1579)
- 2024: Add updates for unsafe extern blocks (rust-lang/reference#1565)
- Fix rule for lazy boolean temporary drop scope (rust-lang/reference#1681)
- Raw lifetimes (rust-lang/reference#1603)
- Fix some missing emdashes (rust-lang/reference#1676)
- Added an additional example of lifetime elision (rust-lang/reference#1678)

## rustc-dev-guide

6 commits in b679e71..787b416
2024-11-18 16:18:15 +0800 to 2024-11-22 11:17:57 +0000
- Remove constants section as it is outdated
- Flatten generic parameter defs section
- Add instructions to test error code docs (rust-lang/rustc-dev-guide#2145)
- Reorganize the "Source Code Representation" chapters (rust-lang/rustc-dev-guide#2142)
- Make `Diag` a clickable link in Suggestion section (rust-lang/rustc-dev-guide#2140)
- update for rustc_intrinsic_const_stable_indirect (rust-lang/rustc-dev-guide#2138)

## edition-guide

6 commits in 915f9b319c2823f310430ecdecd86264a7870d7e..f48b0e842a3911c63240e955d042089e9e0894c7
2024-11-06 07:23:07 +0000 to 2024-11-25 16:20:27 +0000
- Update for 2024 stabilization (rust-lang/edition-guide#338)
- Enable triagebot merge-conflicts and shortcuts (rust-lang/edition-guide#336)
- Organize the 2024 chapters into sub-chapters by category (rust-lang/edition-guide#334)
- Fix broken Cargo Book link in cargo-resolver.md (rust-lang/edition-guide#335)
- Edition 2024 guide for temporary lifetime changes (rust-lang/edition-guide#318)
- 2024: rustfmt sorting (rust-lang/edition-guide#332)
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 26, 2024
Update cargo and books

10 commits in 66221abdeca2002d318fde6efff516aab091df0e..4c39aaff66862cc0da52fe529aa1990bb8bb9a22
2024-11-19 21:30:02 +0000 to 2024-11-25 16:36:17 +0000
- feat: Stabilize Edition 2024 (rust-lang/cargo#14828)
- Improve error handling when PathSource is relative (rust-lang/cargo#14854)
- test: address test output nondeterminism  (rust-lang/cargo#14855)
- chore: move supports-unicode to workspace deps (rust-lang/cargo#14853)
- Check build target supports std when building with -Zbuild-std=std (rust-lang/cargo#14183)
- fix(publish): Allow dry-run of a non-bumped workspace  (rust-lang/cargo#14847)
- test: Switch from 'exec_with_output' to 'run' (rust-lang/cargo#14848)
- test(rustflags): Verify -Cmetadata directly, not through -Cextra-filename (rust-lang/cargo#14846)
- chore: remove bors mentions (rust-lang/cargo#14845)
- Clarify how `cargo::metadata` env var is selected (rust-lang/cargo#14842)

## nomicon

1 commits in eac89a3cbe6c4714e5029ae8b5a1c556fd4e8c42..0674321898cd454764ab69702819d39a919afd68
2024-11-16 14:05:28 +0000 to 2024-11-19 12:35:48 +0000
- races: Clarify a “mostly” that might be misread (rust-lang/nomicon#468)

## reference

12 commits in 41ccb0e6478305401dad92e8fd3d04a4304edb4c..5c86c739ec71b8bc839310ff47fa94e94635bba9
2024-11-15 21:45:16 +0000 to 2024-11-25 17:23:35 +0000
- Document `gen` keyword as reserved in Rust 2024 (rust-lang/reference#1501)
- 2024: Update `expr` macro fragment specifier (rust-lang/reference#1639)
- Add rust_2024 prelude (rust-lang/reference#1552)
- 2024: Add reserved syntax (rust-lang/reference#1652)
- Add Lifetime Capture Rules 2024 (rust-lang/reference#1601)
- Add a section dedicated to Edition 2024 changes to temporary scopes (rust-lang/reference#1592)
- 2024: Add unsafe attribute differences (rust-lang/reference#1579)
- 2024: Add updates for unsafe extern blocks (rust-lang/reference#1565)
- Fix rule for lazy boolean temporary drop scope (rust-lang/reference#1681)
- Raw lifetimes (rust-lang/reference#1603)
- Fix some missing emdashes (rust-lang/reference#1676)
- Added an additional example of lifetime elision (rust-lang/reference#1678)

## rustc-dev-guide

6 commits in b679e71..787b416
2024-11-18 16:18:15 +0800 to 2024-11-22 11:17:57 +0000
- Remove constants section as it is outdated
- Flatten generic parameter defs section
- Add instructions to test error code docs (rust-lang/rustc-dev-guide#2145)
- Reorganize the "Source Code Representation" chapters (rust-lang/rustc-dev-guide#2142)
- Make `Diag` a clickable link in Suggestion section (rust-lang/rustc-dev-guide#2140)
- update for rustc_intrinsic_const_stable_indirect (rust-lang/rustc-dev-guide#2138)

## edition-guide

6 commits in 915f9b319c2823f310430ecdecd86264a7870d7e..f48b0e842a3911c63240e955d042089e9e0894c7
2024-11-06 07:23:07 +0000 to 2024-11-25 16:20:27 +0000
- Update for 2024 stabilization (rust-lang/edition-guide#338)
- Enable triagebot merge-conflicts and shortcuts (rust-lang/edition-guide#336)
- Organize the 2024 chapters into sub-chapters by category (rust-lang/edition-guide#334)
- Fix broken Cargo Book link in cargo-resolver.md (rust-lang/edition-guide#335)
- Edition 2024 guide for temporary lifetime changes (rust-lang/edition-guide#318)
- 2024: rustfmt sorting (rust-lang/edition-guide#332)
@weihanglo weihanglo added this to the 1.85.0 milestone Nov 28, 2024
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 5, 2024
In rust-lang#14183 Cargo start erroring out if the `metadata.std`
field in a target spet JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't no change the behavior of `-Zbuild-std` with explict
crates set. For example `-Zbuild-std=std` will force to build `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 5, 2024
In rust-lang#14183 Cargo start erroring out if the `metadata.std`
field in a target spet JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't no change the behavior of `-Zbuild-std` with explict
crates set. For example `-Zbuild-std=std` will force to build `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 5, 2024
In rust-lang#14183 Cargo starts bailing out if the `metadata.std`
field in a target spec JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't change the behavior of `-Zbuild-std` with explicit
crates set. For example `-Zbuild-std=std` will force building `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 5, 2024
In rust-lang#14183 Cargo starts bailing out if the `metadata.std`
field in a target spec JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't change the behavior of `-Zbuild-std` with explicit
crates set. For example `-Zbuild-std=std` will force building `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 6, 2024
In rust-lang#14183 Cargo starts bailing out if the `metadata.std`
field in a target spec JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't change the behavior of `-Zbuild-std` with explicit
crates set. For example `-Zbuild-std=std` will force building `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
weihanglo added a commit to weihanglo/cargo that referenced this pull request Dec 6, 2024
In rust-lang#14183 Cargo starts bailing out if the `metadata.std`
field in a target spec JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't change the behavior of `-Zbuild-std` with explicit
crates set. For example `-Zbuild-std=std` will force building `std`.

See Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error
github-merge-queue bot pushed a commit that referenced this pull request Dec 9, 2024
### What does this PR try to resolve?

In #14183 Cargo starts bailing out if the `metadata.std`
field in a target spec JSON is set to `false`.
This is problematic because std for some targets are actually buildable
even they've declared as std-unsupported.

This patch removes the hard error, and instead determines the required
root crates by the `metadata.std` field. That is to say, if a target
is explicitly declared as `std: false`, `-Zbuild-std` will build `core`
and `compiler-builtins` only, no `std` will be built.

This patch doesn't change the behavior of `-Zbuild-std` with explicit
crates set. For example `-Zbuild-std=std` will force building `std`.

See Zulip discussion:

https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error

### How should we test and review this PR?

e18b64f and
125e873 might need a closer look.
Cargo relies on how std workspace is organized with these commits.

Here is an e2e test, if you are willing to test manually.

* Use the current nightly toolchain `rustc 1.85.0-nightly (acabb5248
2024-12-04)`
* `rustup component add rust-src --toolchain nightly`
* `rustup target add aarch64-unknown-none --toolchain nightly`
* Create a `#![no_std]` lib package.
* Run `target/debug/cargo build -Zbuild-std --target
aarch64-unknown-none` in that package. Previously it failed with a
message `building std is not supported on the following targets`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cfg-expr Area: Platform cfg expressions S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. Z-build-std Nightly: build-std
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants