From 7678662f58a058e0ebde2eda4cf321f749ee1f09 Mon Sep 17 00:00:00 2001 From: mnmn-f <213242706@seu.edu.cn> Date: Mon, 16 Mar 2026 18:52:43 +0800 Subject: [PATCH] bootstrap: add an initial stdarch test step --- library/std/src/lib.rs | 6 +- library/stdarch/Cargo.toml | 8 + .../crates/core_arch/src/core_arch_docs.md | 34 +-- .../core_arch/src/core_arch_docs_examples.md | 137 +++++++++ .../core_arch_docs_other_architectures_std.md | 27 ++ .../core_arch/src/core_arch_docs_prefix.md | 178 +++++++++++ library/stdarch/examples/gaussian.rs | 22 +- src/bootstrap/src/core/build_steps/doc.rs | 287 ++++++++++++++---- src/bootstrap/src/core/build_steps/test.rs | 112 +++++-- .../builder/cli_paths/snapshots/x_bench.snap | 3 + .../builder/cli_paths/snapshots/x_doc.snap | 3 + .../builder/cli_paths/snapshots/x_miri.snap | 3 + .../builder/cli_paths/snapshots/x_test.snap | 3 + .../cli_paths/snapshots/x_test_library.snap | 3 + .../snapshots/x_test_skip_coverage.snap | 3 + .../snapshots/x_test_skip_tests.snap | 3 + .../src/core/builder/cli_paths/tests.rs | 1 + src/bootstrap/src/core/builder/tests.rs | 121 +++++++- src/bootstrap/src/core/metadata.rs | 4 +- 19 files changed, 857 insertions(+), 101 deletions(-) create mode 100644 library/stdarch/crates/core_arch/src/core_arch_docs_examples.md create mode 100644 library/stdarch/crates/core_arch/src/core_arch_docs_other_architectures_std.md create mode 100644 library/stdarch/crates/core_arch/src/core_arch_docs_prefix.md diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6fcb28edc7d84..f81e7c249c055 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -652,7 +652,11 @@ pub mod task { pub use core::task::*; } -#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] +#[doc = concat!( + include_str!("../../stdarch/crates/core_arch/src/core_arch_docs_prefix.md"), + include_str!("../../stdarch/crates/core_arch/src/core_arch_docs_other_architectures_std.md"), + include_str!("../../stdarch/crates/core_arch/src/core_arch_docs_examples.md"), +)] #[stable(feature = "simd_arch", since = "1.27.0")] pub mod arch { #[stable(feature = "simd_arch", since = "1.27.0")] diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml index e3963a69879a1..c08faee587cee 100644 --- a/library/stdarch/Cargo.toml +++ b/library/stdarch/Cargo.toml @@ -18,3 +18,11 @@ incremental = true debug = 1 opt-level = 3 incremental = true + +# The "dist" profile is used by bootstrap when building stdarch docs as part +# of the distribution pipeline. Keep it aligned with the library workspace so +# `cargo doc --profile=dist` works when stdarch is built as its own workspace. +[profile.dist] +inherits = "release" +codegen-units = 1 +debug = 1 diff --git a/library/stdarch/crates/core_arch/src/core_arch_docs.md b/library/stdarch/crates/core_arch/src/core_arch_docs.md index 9b52fb2af1598..30e9ded870d8f 100644 --- a/library/stdarch/crates/core_arch/src/core_arch_docs.md +++ b/library/stdarch/crates/core_arch/src/core_arch_docs.md @@ -199,23 +199,23 @@ others at: * [`loongarch64`] * [`s390x`] -[`x86`]: ../../core/arch/x86/index.html -[`x86_64`]: ../../core/arch/x86_64/index.html -[`arm`]: ../../core/arch/arm/index.html -[`aarch64`]: ../../core/arch/aarch64/index.html -[`amdgpu`]: ../../core/arch/amdgpu/index.html -[`hexagon`]: ../../core/arch/hexagon/index.html -[`riscv32`]: ../../core/arch/riscv32/index.html -[`riscv64`]: ../../core/arch/riscv64/index.html -[`mips`]: ../../core/arch/mips/index.html -[`mips64`]: ../../core/arch/mips64/index.html -[`powerpc`]: ../../core/arch/powerpc/index.html -[`powerpc64`]: ../../core/arch/powerpc64/index.html -[`nvptx`]: ../../core/arch/nvptx/index.html -[`wasm32`]: ../../core/arch/wasm32/index.html -[`loongarch32`]: ../../core/arch/loongarch32/index.html -[`loongarch64`]: ../../core/arch/loongarch64/index.html -[`s390x`]: ../../core/arch/s390x/index.html +[`x86`]: crate::arch::x86 +[`x86_64`]: crate::arch::x86_64 +[`arm`]: crate::arch::arm +[`aarch64`]: crate::arch::aarch64 +[`amdgpu`]: crate::arch::amdgpu +[`hexagon`]: crate::arch::hexagon +[`riscv32`]: crate::arch::riscv32 +[`riscv64`]: crate::arch::riscv64 +[`mips`]: crate::arch::mips +[`mips64`]: crate::arch::mips64 +[`powerpc`]: crate::arch::powerpc +[`powerpc64`]: crate::arch::powerpc64 +[`nvptx`]: crate::arch::nvptx +[`wasm32`]: crate::arch::wasm32 +[`loongarch32`]: crate::arch::loongarch32 +[`loongarch64`]: crate::arch::loongarch64 +[`s390x`]: crate::arch::s390x # Examples diff --git a/library/stdarch/crates/core_arch/src/core_arch_docs_examples.md b/library/stdarch/crates/core_arch/src/core_arch_docs_examples.md new file mode 100644 index 0000000000000..5bf48cff0df85 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/core_arch_docs_examples.md @@ -0,0 +1,137 @@ +# Examples + +First let's take a look at not actually using any intrinsics but instead +using LLVM's auto-vectorization to produce optimized vectorized code for +AVX2 and also for the default platform. + +```rust +fn main() { + let mut dst = [0]; + add_quickly(&[1], &[2], &mut dst); + assert_eq!(dst[0], 3); +} + +fn add_quickly(a: &[u8], b: &[u8], c: &mut [u8]) { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + // Note that this `unsafe` block is safe because we're testing + // that the `avx2` feature is indeed available on our CPU. + if is_x86_feature_detected!("avx2") { + return unsafe { add_quickly_avx2(a, b, c) }; + } + } + + add_quickly_fallback(a, b, c) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +unsafe fn add_quickly_avx2(a: &[u8], b: &[u8], c: &mut [u8]) { + add_quickly_fallback(a, b, c) // the function below is inlined here +} + +fn add_quickly_fallback(a: &[u8], b: &[u8], c: &mut [u8]) { + for ((a, b), c) in a.iter().zip(b).zip(c) { + *c = *a + *b; + } +} +``` + +Next up let's take a look at an example of manually using intrinsics. Here +we'll be using SSE4.1 features to implement hex encoding. + +``` +fn main() { + let mut dst = [0; 32]; + hex_encode(b"\x01\x02\x03", &mut dst); + assert_eq!(&dst[..6], b"010203"); + + let mut src = [0; 16]; + for i in 0..16 { + src[i] = (i + 1) as u8; + } + hex_encode(&src, &mut dst); + assert_eq!(&dst, b"0102030405060708090a0b0c0d0e0f10"); +} + +pub fn hex_encode(src: &[u8], dst: &mut [u8]) { + let len = src.len().checked_mul(2).unwrap(); + assert!(dst.len() >= len); + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("sse4.1") { + return unsafe { hex_encode_sse41(src, dst) }; + } + } + + hex_encode_fallback(src, dst) +} + +// translated from +// +#[target_feature(enable = "sse4.1")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +unsafe fn hex_encode_sse41(mut src: &[u8], dst: &mut [u8]) { + #[cfg(target_arch = "x86")] + use std::arch::x86::*; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::*; + + unsafe { + let ascii_zero = _mm_set1_epi8(b'0' as i8); + let nines = _mm_set1_epi8(9); + let ascii_a = _mm_set1_epi8((b'a' - 9 - 1) as i8); + let and4bits = _mm_set1_epi8(0xf); + + let mut i = 0_isize; + while src.len() >= 16 { + let invec = _mm_loadu_si128(src.as_ptr() as *const _); + + let masked1 = _mm_and_si128(invec, and4bits); + let masked2 = _mm_and_si128(_mm_srli_epi64(invec, 4), and4bits); + + // return 0xff corresponding to the elements > 9, or 0x00 otherwise + let cmpmask1 = _mm_cmpgt_epi8(masked1, nines); + let cmpmask2 = _mm_cmpgt_epi8(masked2, nines); + + // add '0' or the offset depending on the masks + let masked1 = _mm_add_epi8( + masked1, + _mm_blendv_epi8(ascii_zero, ascii_a, cmpmask1), + ); + let masked2 = _mm_add_epi8( + masked2, + _mm_blendv_epi8(ascii_zero, ascii_a, cmpmask2), + ); + + // interleave masked1 and masked2 bytes + let res1 = _mm_unpacklo_epi8(masked2, masked1); + let res2 = _mm_unpackhi_epi8(masked2, masked1); + + _mm_storeu_si128(dst.as_mut_ptr().offset(i * 2) as *mut _, res1); + _mm_storeu_si128( + dst.as_mut_ptr().offset(i * 2 + 16) as *mut _, + res2, + ); + src = &src[16..]; + i += 16; + } + + let i = i as usize; + hex_encode_fallback(src, &mut dst[i * 2..]); + } +} + +fn hex_encode_fallback(src: &[u8], dst: &mut [u8]) { + fn hex(byte: u8) -> u8 { + static TABLE: &[u8] = b"0123456789abcdef"; + TABLE[byte as usize] + } + + for (byte, slots) in src.iter().zip(dst.chunks_mut(2)) { + slots[0] = hex((*byte >> 4) & 0xf); + slots[1] = hex(*byte & 0xf); + } +} +``` diff --git a/library/stdarch/crates/core_arch/src/core_arch_docs_other_architectures_std.md b/library/stdarch/crates/core_arch/src/core_arch_docs_other_architectures_std.md new file mode 100644 index 0000000000000..b9bd597ca4212 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/core_arch_docs_other_architectures_std.md @@ -0,0 +1,27 @@ +# Other architectures + +This documentation is only for one particular architecture, you can find +others at: + +* [`x86`] +* [`x86_64`] +* `arm` +* [`aarch64`] +* `amdgpu` +* `hexagon` +* `riscv32` +* `riscv64` +* `mips` +* `mips64` +* `powerpc` +* `powerpc64` +* `nvptx` +* [`wasm32`] +* `loongarch32` +* `loongarch64` +* `s390x` + +[`x86`]: crate::arch::x86 +[`x86_64`]: crate::arch::x86_64 +[`aarch64`]: crate::arch::aarch64 +[`wasm32`]: crate::arch::wasm32 diff --git a/library/stdarch/crates/core_arch/src/core_arch_docs_prefix.md b/library/stdarch/crates/core_arch/src/core_arch_docs_prefix.md new file mode 100644 index 0000000000000..05b49d70962ec --- /dev/null +++ b/library/stdarch/crates/core_arch/src/core_arch_docs_prefix.md @@ -0,0 +1,178 @@ +SIMD and vendor intrinsics module. + +This module is intended to be the gateway to architecture-specific +intrinsic functions, typically related to SIMD (but not always!). Each +architecture that Rust compiles to may contain a submodule here, which +means that this is not a portable module! If you're writing a portable +library take care when using these APIs! + +Under this module you'll find an architecture-named module, such as +`x86_64`. Each `#[cfg(target_arch)]` that Rust can compile to may have a +module entry here, only present on that particular target. For example the +`i686-pc-windows-msvc` target will have an `x86` module here, whereas +`x86_64-pc-windows-msvc` has `x86_64`. + +[rfc]: https://github.com/rust-lang/rfcs/pull/2325 +[tracked]: https://github.com/rust-lang/rust/issues/48556 + +# Overview + +This module exposes vendor-specific intrinsics that typically correspond to +a single machine instruction. These intrinsics are not portable: their +availability is architecture-dependent, and not all machines of that +architecture might provide the intrinsic. + +The `arch` module is intended to be a low-level implementation detail for +higher-level APIs. Using it correctly can be quite tricky as you need to +ensure at least a few guarantees are upheld: + +* The correct architecture's module is used. For example the `arm` module + isn't available on the `x86_64-unknown-linux-gnu` target. This is + typically done by ensuring that `#[cfg]` is used appropriately when using + this module. +* The CPU the program is currently running on supports the function being + called. For example it is unsafe to call an AVX2 function on a CPU that + doesn't actually support AVX2. + +As a result of the latter of these guarantees all intrinsics in this module +are `unsafe` and extra care needs to be taken when calling them! + +# CPU Feature Detection + +In order to call these APIs in a safe fashion there's a number of +mechanisms available to ensure that the correct CPU feature is available +to call an intrinsic. Let's consider, for example, the `_mm256_add_epi64` +intrinsics on the `x86` and `x86_64` architectures. This function requires +the AVX2 feature as [documented by Intel][intel-dox] so to correctly call +this function we need to (a) guarantee we only call it on `x86`/`x86_64` +and (b) ensure that the CPU feature is available + +[intel-dox]: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_add_epi64&expand=100 + +## Static CPU Feature Detection + +The first option available to us is to conditionally compile code via the +`#[cfg]` attribute. CPU features correspond to the `target_feature` cfg +available, and can be used like so: + +```ignore +#[cfg( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "avx2" + ) +)] +fn foo() { + #[cfg(target_arch = "x86")] + use std::arch::x86::_mm256_add_epi64; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::_mm256_add_epi64; + + unsafe { + _mm256_add_epi64(...); + } +} +``` + +Here we're using `#[cfg(target_feature = "avx2")]` to conditionally compile +this function into our module. This means that if the `avx2` feature is +*enabled statically* then we'll use the `_mm256_add_epi64` function at +runtime. The `unsafe` block here can be justified through the usage of +`#[cfg]` to only compile the code in situations where the safety guarantees +are upheld. + +Statically enabling a feature is typically done with the `-C +target-feature` or `-C target-cpu` flags to the compiler. For example if +your local CPU supports AVX2 then you can compile the above function with: + +```sh +$ RUSTFLAGS='-C target-cpu=native' cargo build +``` + +Or otherwise you can specifically enable just the AVX2 feature: + +```sh +$ RUSTFLAGS='-C target-feature=+avx2' cargo build +``` + +Note that when you compile a binary with a particular feature enabled it's +important to ensure that you only run the binary on systems which satisfy +the required feature set. + +## Dynamic CPU Feature Detection + +Sometimes statically dispatching isn't quite what you want. Instead you +might want to build a portable binary that runs across a variety of CPUs, +but at runtime it selects the most optimized implementation available. This +allows you to build a "least common denominator" binary which has certain +sections more optimized for different CPUs. + +Taking our previous example from before, we're going to compile our binary +*without* AVX2 support, but we'd like to enable it for just one function. +We can do that in a manner like: + +```ignore +fn foo() { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + if is_x86_feature_detected!("avx2") { + return unsafe { foo_avx2() }; + } + } + + // fallback implementation without using AVX2 +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[target_feature(enable = "avx2")] +unsafe fn foo_avx2() { + #[cfg(target_arch = "x86")] + use std::arch::x86::_mm256_add_epi64; + #[cfg(target_arch = "x86_64")] + use std::arch::x86_64::_mm256_add_epi64; + + unsafe { _mm256_add_epi64(...); } +} +``` + +There's a couple of components in play here, so let's go through them in +detail! + +* First up we notice the `is_x86_feature_detected!` macro. Provided by + the standard library, this macro will perform necessary runtime detection + to determine whether the CPU the program is running on supports the + specified feature. In this case the macro will expand to a boolean + expression evaluating to whether the local CPU has the AVX2 feature or + not. + + Note that this macro, like the `arch` module, is platform-specific. For + example calling `is_x86_feature_detected!("avx2")` on ARM will be a + compile time error. To ensure we don't hit this error a statement level + `#[cfg]` is used to only compile usage of the macro on `x86`/`x86_64`. + +* Next up we see our AVX2-enabled function, `foo_avx2`. This function is + decorated with the `#[target_feature]` attribute which enables a CPU + feature for just this one function. Using a compiler flag like `-C + target-feature=+avx2` will enable AVX2 for the entire program, but using + an attribute will only enable it for the one function. Usage of the + `#[target_feature]` attribute currently requires the function to also be + `unsafe`, as we see here. This is because the function can only be + correctly called on systems which have the AVX2 (like the intrinsics + themselves). + +And with all that we should have a working program! This program will run +across all machines and it'll use the optimized AVX2 implementation on +machines where support is detected. + +# Ergonomics + +It's important to note that using the `arch` module is not the easiest +thing in the world, so if you're curious to try it out you may want to +brace yourself for some wordiness! + +The primary purpose of this module is to enable stable crates on crates.io +to build up much more ergonomic abstractions which end up using SIMD under +the hood. Over time these abstractions may also move into the standard +library itself, but for now this module is tasked with providing the bare +minimum necessary to use vendor intrinsics on stable Rust. + diff --git a/library/stdarch/examples/gaussian.rs b/library/stdarch/examples/gaussian.rs index dea16f797aca6..03cb0c5d1b507 100644 --- a/library/stdarch/examples/gaussian.rs +++ b/library/stdarch/examples/gaussian.rs @@ -19,20 +19,26 @@ //! //! To build (requires Hexagon toolchain): //! -//! RUSTFLAGS="-C target-feature=+hvxv62,+hvx-length128b \ -//! -C linker=hexagon-unknown-linux-musl-clang" \ -//! cargo +nightly build -p stdarch_examples --bin gaussian \ -//! --target hexagon-unknown-linux-musl \ -//! -Zbuild-std -Zbuild-std-features=llvm-libunwind +//! ```text +//! RUSTFLAGS="-C target-feature=+hvxv62,+hvx-length128b \ +//! -C linker=hexagon-unknown-linux-musl-clang" \ +//! cargo +nightly build -p stdarch_examples --bin gaussian \ +//! --target hexagon-unknown-linux-musl \ +//! -Zbuild-std -Zbuild-std-features=llvm-libunwind +//! ``` //! //! To run under QEMU: //! -//! qemu-hexagon -L /target/hexagon-unknown-linux-musl \ -//! target/hexagon-unknown-linux-musl/debug/gaussian +//! ```text +//! qemu-hexagon -L /target/hexagon-unknown-linux-musl \ +//! target/hexagon-unknown-linux-musl/debug/gaussian +//! ``` //! //! # Building and Running (Other targets) //! -//! cargo +nightly run -p stdarch_examples --bin gaussian +//! ```text +//! cargo +nightly run -p stdarch_examples --bin gaussian +//! ``` #![cfg_attr(target_arch = "hexagon", feature(stdarch_hexagon))] #![cfg_attr(target_arch = "hexagon", feature(hexagon_target_feature))] diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a918ae929d2e0..ec29ff476316f 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -621,12 +621,20 @@ impl Step for SharedAssets { } } +/// Document the standard library using `build_compiler`. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +enum StdWorkspace { + Std, + Stdarch, +} + /// Document the standard library using `build_compiler`. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Std { build_compiler: Compiler, target: TargetSelection, format: DocumentationFormat, + workspace: StdWorkspace, crates: Vec, } @@ -636,7 +644,7 @@ impl Std { target: TargetSelection, format: DocumentationFormat, ) -> Self { - Std { build_compiler, target, format, crates: vec![] } + Std { build_compiler, target, format, workspace: StdWorkspace::Std, crates: vec![] } } } @@ -645,7 +653,11 @@ impl Step for Std { type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").path("library") + run.crate_or_deps("sysroot") + .path("library") + .path("library/stdarch") + .path("library/stdarch/crates/core_arch") + .path("library/stdarch/examples") } fn is_default_step(builder: &Builder<'_>) -> bool { @@ -653,21 +665,76 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { - let crates = compile::std_crates_for_run_make(&run); - let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false); - if crates.is_empty() && target_is_no_std { + let builder = run.builder; + let build_compiler = builder.compiler_for_std(builder.top_stage); + let format = if builder.config.cmd.json() { + DocumentationFormat::Json + } else { + DocumentationFormat::Html + }; + + if run.paths.is_empty() { + let crates = compile::std_crates_for_run_make(&run); + let target_is_no_std = builder.no_std(run.target).unwrap_or(false); + if crates.is_empty() && target_is_no_std { + return; + } + builder.ensure(Std { + build_compiler, + target: run.target, + format, + workspace: StdWorkspace::Std, + crates, + }); return; } - run.builder.ensure(Std { - build_compiler: run.builder.compiler_for_std(run.builder.top_stage), - target: run.target, - format: if run.builder.config.cmd.json() { - DocumentationFormat::Json - } else { - DocumentationFormat::Html - }, - crates, - }); + + let mut std_crates = Vec::new(); + let mut stdarch_crates = Vec::new(); + let mut stdarch_requested = false; + + for pathset in &run.paths { + let path = &pathset.assert_single_path().path; + if path.starts_with("library/stdarch") { + stdarch_requested = true; + if let Some(krate) = builder.crate_paths.get(path) { + stdarch_crates.push(krate.clone()); + } + } else if let Some(krate) = builder.crate_paths.get(path) { + std_crates.push(krate.clone()); + } + } + + std_crates.sort(); + std_crates.dedup(); + stdarch_crates.sort(); + stdarch_crates.dedup(); + + if stdarch_requested && stdarch_crates.is_empty() { + stdarch_crates.push("core_arch".to_owned()); + if !builder.no_std(run.target).unwrap_or(false) { + stdarch_crates.push("stdarch_examples".to_owned()); + } + } + + if !std_crates.is_empty() { + builder.ensure(Std { + build_compiler, + target: run.target, + format, + workspace: StdWorkspace::Std, + crates: std_crates, + }); + } + if !stdarch_crates.is_empty() { + builder.ensure(Std { + build_compiler, + target: run.target, + format, + workspace: StdWorkspace::Stdarch, + crates: stdarch_crates, + }); + } } /// Compile all standard library documentation. @@ -676,14 +743,29 @@ impl Step for Std { /// dependencies. This is largely just a wrapper around `cargo doc`. fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.target; - let crates = if self.crates.is_empty() { - builder - .in_tree_crates("sysroot", Some(target)) - .iter() - .map(|c| c.name.to_string()) - .collect() - } else { - self.crates + let crates = match self.workspace { + StdWorkspace::Std => { + if self.crates.is_empty() { + builder + .in_tree_crates("sysroot", Some(target)) + .iter() + .map(|c| c.name.to_string()) + .collect() + } else { + self.crates + } + } + StdWorkspace::Stdarch => { + if self.crates.is_empty() { + let mut crates = vec!["core_arch".to_owned()]; + if !builder.no_std(target).unwrap_or(false) { + crates.push("stdarch_examples".to_owned()); + } + crates + } else { + self.crates + } + } }; let out = match self.format { @@ -693,45 +775,72 @@ impl Step for Std { t!(fs::create_dir_all(&out)); - if self.format == DocumentationFormat::Html { + if self.format == DocumentationFormat::Html && self.workspace == StdWorkspace::Std { builder.ensure(SharedAssets { target: self.target }); } - let index_page = builder - .src - .join("src/doc/index.md") - .into_os_string() - .into_string() - .expect("non-utf8 paths are unsupported"); - let mut extra_args = match self.format { - DocumentationFormat::Html => { - vec!["--markdown-css", "rust.css", "--markdown-no-toc", "--index-page", &index_page] - } - DocumentationFormat::Json => vec!["--output-format", "json"], - }; + match self.workspace { + StdWorkspace::Std => { + let index_page = builder + .src + .join("src/doc/index.md") + .into_os_string() + .into_string() + .expect("non-utf8 paths are unsupported"); + let mut extra_args = match self.format { + DocumentationFormat::Html => vec![ + "--markdown-css", + "rust.css", + "--markdown-no-toc", + "--index-page", + &index_page, + ], + DocumentationFormat::Json => vec!["--output-format", "json"], + }; - if !builder.config.docs_minification { - extra_args.push("--disable-minification"); - } - // For `--index-page` and `--output-format=json`. - extra_args.push("-Zunstable-options"); + if !builder.config.docs_minification { + extra_args.push("--disable-minification"); + } + // For `--index-page` and `--output-format=json`. + extra_args.push("-Zunstable-options"); - doc_std(builder, self.format, self.build_compiler, target, &out, &extra_args, &crates); + doc_std( + builder, + self.format, + self.build_compiler, + target, + &out, + &extra_args, + &crates, + ); + } + StdWorkspace::Stdarch => { + doc_stdarch(builder, self.format, self.build_compiler, target, &out, &crates); + } + } // Open if the format is HTML if let DocumentationFormat::Html = self.format { - if builder.paths.iter().any(|path| path.ends_with("library")) { - // For `x.py doc library --open`, open `std` by default. - let index = out.join("std").join("index.html"); - builder.maybe_open_in_browser::(index); - } else { - for requested_crate in crates { - if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { - let index = out.join(requested_crate).join("index.html"); + match self.workspace { + StdWorkspace::Std => { + if builder.paths.iter().any(|path| path.ends_with("library")) { + // For `x.py doc library --open`, open `std` by default. + let index = out.join("std").join("index.html"); builder.maybe_open_in_browser::(index); - break; + } else { + for requested_crate in crates { + if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { + let index = out.join(requested_crate).join("index.html"); + builder.maybe_open_in_browser::(index); + break; + } + } } } + StdWorkspace::Stdarch => { + let index = out.join(&crates[0]).join("index.html"); + builder.maybe_open_in_browser::(index); + } } } @@ -740,13 +849,33 @@ impl Step for Std { fn metadata(&self) -> Option { Some( - StepMetadata::doc("std", self.target) - .built_by(self.build_compiler) - .with_metadata(format!("crates=[{}]", self.crates.join(","))), + StepMetadata::doc( + match self.workspace { + StdWorkspace::Std => "std", + StdWorkspace::Stdarch => "stdarch", + }, + self.target, + ) + .built_by(self.build_compiler) + .with_metadata(format!("crates=[{}]", self.crates.join(","))), ) } } +#[cfg(test)] +impl Std { + pub(crate) fn workspace_name(&self) -> &'static str { + match self.workspace { + StdWorkspace::Std => "std", + StdWorkspace::Stdarch => "stdarch", + } + } + + pub(crate) fn crate_names(&self) -> &[String] { + &self.crates + } +} + /// Name of the crates that are visible to consumers of the standard library. /// Documentation for internal crates is handled by the rustc step, so internal crates will show /// up there. @@ -829,6 +958,56 @@ fn doc_std( builder.cp_link_r(&out_dir, out); } +fn doc_stdarch( + builder: &Builder<'_>, + format: DocumentationFormat, + build_compiler: Compiler, + target: TargetSelection, + out: &Path, + requested_crates: &[String], +) { + let target_doc_dir_name = + if format == DocumentationFormat::Json { "stdarch-json-doc" } else { "stdarch-doc" }; + let target_dir = + builder.stage_out(build_compiler, Mode::Std).join(target).join(target_doc_dir_name); + let out_dir = target_dir.join(target).join("doc"); + + let mut cargo = builder::Cargo::new( + builder, + build_compiler, + Mode::Std, + SourceType::InTree, + target, + Kind::Doc, + ); + cargo.arg("--manifest-path").arg(builder.src.join("library/stdarch/Cargo.toml")); + for krate in requested_crates { + cargo.arg("-p").arg(krate); + } + cargo + .arg("--no-deps") + .arg("--target-dir") + .arg(&*target_dir.to_string_lossy()) + .arg("-Zskip-rustdoc-fingerprint") + .rustdocflag("--resource-suffix") + .rustdocflag(&builder.version); + + if format == DocumentationFormat::Json { + cargo.arg("--output-format").arg("json").rustdocflag("-Zunstable-options"); + } + + if builder.config.library_docs_private_items { + cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items"); + } + + let description = + format!("stdarch{} in {} format", crate_description(requested_crates), format.as_str()); + let _guard = builder.msg(Kind::Doc, description, Mode::Std, build_compiler, target); + + cargo.into_cmd().run(builder); + builder.cp_link_r(&out_dir, out); +} + /// Prepare a compiler that will be able to document something for `target` at `stage`. pub fn prepare_doc_compiler( builder: &Builder<'_>, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7be45c5fa9d40..9d2674c9acc0f 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2906,6 +2906,7 @@ impl Step for CrateLibrustc { build_compiler: self.build_compiler, target: self.target, mode: Mode::Rustc, + workspace: CrateWorkspace::Std, crates: self.crates, }); } @@ -3028,12 +3029,19 @@ fn prepare_cargo_test( /// FIXME(Zalathar): Try to split this into two separate steps: a user-visible /// step for testing standard library crates, and an internal step used for both /// library crates and compiler crates. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum CrateWorkspace { + Std, + Stdarch, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Crate { /// The compiler that will *build* libstd or rustc in test mode. build_compiler: Compiler, target: TargetSelection, mode: Mode, + workspace: CrateWorkspace, crates: Vec, } @@ -3041,7 +3049,12 @@ impl Step for Crate { type Output = (); fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests") + run.crate_or_deps("sysroot") + .crate_or_deps("coretests") + .crate_or_deps("alloctests") + .path("library/stdarch") + .path("library/stdarch/crates/core_arch") + .path("library/stdarch/examples") } fn is_default_step(_builder: &Builder<'_>) -> bool { @@ -3052,13 +3065,53 @@ impl Step for Crate { let builder = run.builder; let host = run.build_triple(); let build_compiler = builder.compiler(builder.top_stage, host); - let crates = run - .paths - .iter() - .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) - .collect(); + let mut std_crates = + if run.paths.is_empty() { run.make_run_crates(Alias::Library) } else { Vec::new() }; + let mut stdarch_crates = Vec::new(); + let mut stdarch_requested = false; + + for pathset in &run.paths { + let path = &pathset.assert_single_path().path; + if path.starts_with("library/stdarch") { + stdarch_requested = true; + if let Some(krate) = builder.crate_paths.get(path) { + stdarch_crates.push(krate.clone()); + } + } else if let Some(krate) = builder.crate_paths.get(path) { + std_crates.push(krate.clone()); + } + } - builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates }); + std_crates.sort(); + std_crates.dedup(); + stdarch_crates.sort(); + stdarch_crates.dedup(); + + if stdarch_requested && stdarch_crates.is_empty() { + stdarch_crates.push("core_arch".to_owned()); + if !builder.no_std(run.target).unwrap_or(false) { + stdarch_crates.push("stdarch_examples".to_owned()); + } + } + + if !std_crates.is_empty() { + builder.ensure(Crate { + build_compiler, + target: run.target, + mode: Mode::Std, + workspace: CrateWorkspace::Std, + crates: std_crates, + }); + } + if !stdarch_crates.is_empty() { + builder.ensure(Crate { + build_compiler, + target: run.target, + mode: Mode::Std, + workspace: CrateWorkspace::Stdarch, + crates: stdarch_crates, + }); + } } /// Runs all unit tests plus documentation tests for a given crate defined @@ -3142,17 +3195,26 @@ impl Step for Crate { match mode { Mode::Std => { - if builder.kind == Kind::Miri { - // We can't use `std_cargo` as that uses `optimized-compiler-builtins` which - // needs host tools for the given target. This is similar to what `compile::Std` - // does when `is_for_mir_opt_tests` is true. There's probably a chance for - // de-duplication here... `std_cargo` should support a mode that avoids needing - // host tools. - cargo - .arg("--manifest-path") - .arg(builder.src.join("library/sysroot/Cargo.toml")); - } else { - compile::std_cargo(builder, target, &mut cargo, &[]); + match self.workspace { + CrateWorkspace::Std => { + if builder.kind == Kind::Miri { + // We can't use `std_cargo` as that uses `optimized-compiler-builtins` which + // needs host tools for the given target. This is similar to what `compile::Std` + // does when `is_for_mir_opt_tests` is true. There's probably a chance for + // de-duplication here... `std_cargo` should support a mode that avoids needing + // host tools. + cargo + .arg("--manifest-path") + .arg(builder.src.join("library/sysroot/Cargo.toml")); + } else { + compile::std_cargo(builder, target, &mut cargo, &[]); + } + } + CrateWorkspace::Stdarch => { + cargo + .arg("--manifest-path") + .arg(builder.src.join("library/stdarch/Cargo.toml")); + } } } Mode::Rustc => { @@ -3177,6 +3239,20 @@ impl Step for Crate { } } +#[cfg(test)] +impl Crate { + pub(crate) fn workspace_name(&self) -> &'static str { + match self.workspace { + CrateWorkspace::Std => "std", + CrateWorkspace::Stdarch => "stdarch", + } + } + + pub(crate) fn crate_names(&self) -> &[String] { + &self.crates + } +} + /// Run cargo tests for the rustdoc crate. /// Rustdoc is special in various ways, which is why this step is different from `Crate`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap index 294623f073864..e739e1bb5e9d8 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap @@ -15,6 +15,9 @@ expression: bench - Set({bench::library/rustc-std-workspace-core}) - Set({bench::library/std}) - Set({bench::library/std_detect}) + - Set({bench::library/stdarch}) + - Set({bench::library/stdarch/crates/core_arch}) + - Set({bench::library/stdarch/examples}) - Set({bench::library/sysroot}) - Set({bench::library/test}) - Set({bench::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_doc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_doc.snap index 610a71ab70cf3..24954ee9593c8 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_doc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_doc.snap @@ -27,6 +27,9 @@ expression: doc - Set({doc::library/rustc-std-workspace-core}) - Set({doc::library/std}) - Set({doc::library/std_detect}) + - Set({doc::library/stdarch}) + - Set({doc::library/stdarch/crates/core_arch}) + - Set({doc::library/stdarch/examples}) - Set({doc::library/sysroot}) - Set({doc::library/test}) - Set({doc::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_miri.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_miri.snap index 552697b378bcc..0caf1daf7bc77 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_miri.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_miri.snap @@ -15,6 +15,9 @@ expression: miri - Set({miri::library/rustc-std-workspace-core}) - Set({miri::library/std}) - Set({miri::library/std_detect}) + - Set({miri::library/stdarch}) + - Set({miri::library/stdarch/crates/core_arch}) + - Set({miri::library/stdarch/examples}) - Set({miri::library/sysroot}) - Set({miri::library/test}) - Set({miri::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index ac2f315d39d96..36ff6438aba24 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -65,6 +65,9 @@ expression: test - Set({test::library/rustc-std-workspace-core}) - Set({test::library/std}) - Set({test::library/std_detect}) + - Set({test::library/stdarch}) + - Set({test::library/stdarch/crates/core_arch}) + - Set({test::library/stdarch/examples}) - Set({test::library/sysroot}) - Set({test::library/test}) - Set({test::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap index dfc397597a877..1325470d257d2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap @@ -15,6 +15,9 @@ expression: test library - Set({test::library/rustc-std-workspace-core}) - Set({test::library/std}) - Set({test::library/std_detect}) + - Set({test::library/stdarch}) + - Set({test::library/stdarch/crates/core_arch}) + - Set({test::library/stdarch/examples}) - Set({test::library/sysroot}) - Set({test::library/test}) - Set({test::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index 09adbb0041ae6..9df8bfd8aa158 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -64,6 +64,9 @@ expression: test --skip=coverage - Set({test::library/rustc-std-workspace-core}) - Set({test::library/std}) - Set({test::library/std_detect}) + - Set({test::library/stdarch}) + - Set({test::library/stdarch/crates/core_arch}) + - Set({test::library/stdarch/examples}) - Set({test::library/sysroot}) - Set({test::library/test}) - Set({test::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap index b5fccfcb966bb..e9a656361cec2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap @@ -28,6 +28,9 @@ expression: test --skip=tests - Set({test::library/rustc-std-workspace-core}) - Set({test::library/std}) - Set({test::library/std_detect}) + - Set({test::library/stdarch}) + - Set({test::library/stdarch/crates/core_arch}) + - Set({test::library/stdarch/examples}) - Set({test::library/sysroot}) - Set({test::library/test}) - Set({test::library/unwind}) diff --git a/src/bootstrap/src/core/builder/cli_paths/tests.rs b/src/bootstrap/src/core/builder/cli_paths/tests.rs index 39293abd4fb94..db7abe444ea86 100644 --- a/src/bootstrap/src/core/builder/cli_paths/tests.rs +++ b/src/bootstrap/src/core/builder/cli_paths/tests.rs @@ -26,6 +26,7 @@ fn render_steps_for_cli_args(args_str: &str) -> String { .args(args) .hosts(hosts) .targets(targets) + .no_override_download_ci_llvm() .create_config(); let mut build = Build::new(config); // Some rustdoc test steps are only run by default if nodejs is diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f34b284dbb9cc..f10612997f6d1 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -39,6 +39,28 @@ fn run_build(paths: &[PathBuf], config: Config) -> Cache { builder.cache } +fn configure_stdarch_test(paths: &[&str]) -> Config { + let ctx = TestCtx::new(); + ctx.config("test") + .args(paths) + .args(&["--ci", "true"]) + .hosts(&[TEST_TRIPLE_1]) + .targets(&[TEST_TRIPLE_1]) + .no_override_download_ci_llvm() + .create_config() +} + +fn configure_stdarch_doc(paths: &[&str]) -> Config { + let ctx = TestCtx::new(); + ctx.config("doc") + .args(paths) + .args(&["--ci", "true"]) + .hosts(&[TEST_TRIPLE_1]) + .targets(&[TEST_TRIPLE_1]) + .no_override_download_ci_llvm() + .create_config() +} + fn check_cli(paths: [&str; N]) { run_build( &paths.map(PathBuf::from), @@ -140,6 +162,28 @@ fn validate_path_remap() { }); } +#[test] +fn test_stdarch_workspace_metadata_is_loaded() { + let build = Build::new(configure_stdarch_test(&[])); + + assert_eq!( + build.crate_paths.get(&PathBuf::from("library/stdarch/crates/core_arch")), + Some(&"core_arch".to_owned()) + ); +} + +#[test] +fn test_doc_stdarch() { + let config = configure_stdarch_doc(&["library/stdarch"]); + let cache = run_build(&config.paths.clone(), config); + assert_eq!( + cache.inspect_all_steps_of_type::(|step, _| { + (step.workspace_name().to_owned(), step.crate_names().join(",")) + }), + vec![("stdarch".to_owned(), "core_arch,stdarch_examples".to_owned())] + ); +} + #[test] fn check_missing_paths_for_x_test_tests() { let build = Build::new(configure("test", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); @@ -320,6 +364,18 @@ fn test_test_compiler() { assert_eq!((compiler, cranelift, gcc), (true, false, false)); } +#[test] +fn test_test_stdarch() { + let config = configure_stdarch_test(&["library/stdarch"]); + let cache = run_build(&config.paths.clone(), config); + assert_eq!( + cache.inspect_all_steps_of_type::(|step, ()| { + (step.workspace_name().to_owned(), step.crate_names().join(",")) + }), + vec![("stdarch".to_owned(), "core_arch,stdarch_examples".to_owned())] + ); +} + #[test] fn test_test_coverage() { struct Case { @@ -1031,6 +1087,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustdoc 1 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] "); } @@ -1097,6 +1154,8 @@ mod snapshot { insta::assert_snapshot!( ctx .config("dist") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1111,6 +1170,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -1148,6 +1208,8 @@ mod snapshot { insta::assert_snapshot!( ctx.config("dist") .path("rustc-docs") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&["--set", "build.compiler-docs=true"]) .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 @@ -1163,6 +1225,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [doc] rustc 1 -> rustc 2 [build] rustc 1 -> rustc 2 [doc] rustc 1 -> Rustdoc 2 @@ -1199,6 +1262,8 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("dist") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ "--set", "build.extended=true", @@ -1224,6 +1289,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> LldWrapper 2 [build] rustc 1 -> WasmComponentLd 2 @@ -1283,6 +1349,8 @@ mod snapshot { .config("dist") .hosts(&[&host_target()]) .targets(&[&host_target(), TEST_TRIPLE_1]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1304,7 +1372,9 @@ mod snapshot { [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -1359,6 +1429,8 @@ mod snapshot { .config("dist") .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target()]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1373,6 +1445,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -1422,6 +1495,8 @@ mod snapshot { .config("dist") .hosts(&[&host_target(), TEST_TRIPLE_1]) .targets(&[&host_target(), TEST_TRIPLE_1]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1443,7 +1518,9 @@ mod snapshot { [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -1507,6 +1584,8 @@ mod snapshot { .config("dist") .hosts(&[]) .targets(&[TEST_TRIPLE_1]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1522,6 +1601,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [doc] nomicon (book) [doc] rustc 1 -> reference (book) 2 [doc] rustdoc (book) @@ -1549,6 +1629,8 @@ mod snapshot { .config("dist") .hosts(&[TEST_TRIPLE_1]) .targets(&[TEST_TRIPLE_1]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&["--set", "rust.channel=nightly", "--set", "build.extended=true"]) .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 @@ -1566,6 +1648,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] llvm [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 @@ -1629,6 +1712,8 @@ mod snapshot { .config("dist") .hosts(&[TEST_TRIPLE_1]) .targets(&[TEST_TRIPLE_1]) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ "--set", "rust.channel=nightly", @@ -1693,6 +1778,8 @@ mod snapshot { insta::assert_snapshot!( ctx .config("dist") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"]) .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 @@ -1709,6 +1796,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> rustc_codegen_cranelift 2 [build] rustc 1 -> error-index 2 @@ -1777,6 +1865,8 @@ mod snapshot { ctx .config("dist") .path("rustc-docs") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -1791,6 +1881,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -2065,6 +2156,7 @@ mod snapshot { ctx.config("test") // Bootstrap only runs by default on CI, so we have to emulate that also locally. .args(&["--ci", "true"]) + .no_override_download_ci_llvm() // These rustdoc tests requires nodejs to be present. // We can't easily opt out of it, so if it is present on the local PC, the test // would have different result on CI, where nodejs might be missing. @@ -2120,6 +2212,7 @@ mod snapshot { [doc] book/2018-edition (book) [doc] rustc 0 -> standalone 1 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 0 -> error-index 1 [doc] rustc 0 -> error-index 1 [doc] nomicon (book) @@ -2301,6 +2394,7 @@ mod snapshot { [doc] book/2018-edition (book) [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 [doc] nomicon (book) @@ -2509,6 +2603,8 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("doc") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] rustc 0 -> UnstableBookGen 1 [build] rustc 0 -> Rustbook 1 @@ -2523,6 +2619,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustdoc 1 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 0 -> error-index 1 [doc] rustc 0 -> error-index 1 [doc] nomicon (book) @@ -2547,11 +2644,14 @@ mod snapshot { insta::assert_snapshot!( ctx.config("doc") .path("library") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustdoc 1 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] "); } @@ -2618,11 +2718,14 @@ mod snapshot { ctx.config("doc") .path("library") .override_target_no_std(&host_target()) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,core] + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] "); } @@ -2634,11 +2737,14 @@ mod snapshot { .path("library") .targets(&[TEST_TRIPLE_1]) .override_target_no_std(TEST_TRIPLE_1) + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .render_steps(), @r" [build] llvm [build] rustc 0 -> rustc 1 [build] rustdoc 1 - [doc] rustc 1 -> std 1 crates=[alloc,core] + [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] "); } @@ -2860,6 +2966,8 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("install") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -2889,6 +2997,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -2919,6 +3028,8 @@ mod snapshot { insta::assert_snapshot!( ctx.config("install") .path("src") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -2948,6 +3059,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> error-index 2 [doc] rustc 1 -> error-index 2 @@ -2975,6 +3087,8 @@ mod snapshot { insta::assert_snapshot!( ctx.config("install") .path("src") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -3005,6 +3119,8 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("install") + .args(&["--ci", "true"]) + .no_override_download_ci_llvm() .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -3036,6 +3152,7 @@ mod snapshot { [build] rustdoc 1 [doc] rustc 1 -> standalone 2 [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> stdarch 2 crates=[core_arch,stdarch_examples] [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 [build] rustc 1 -> error-index 2 diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index c79fbbeb55cc1..a97deb9f1fb23 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -93,9 +93,11 @@ fn workspace_members(build: &Build) -> Vec { packages }; - // Collects `metadata.packages` from the root and library workspaces. + // Collect `metadata.packages` from the workspaces that bootstrap may need + // to resolve from CLI paths. let mut packages = vec![]; packages.extend(collect_metadata("Cargo.toml")); packages.extend(collect_metadata("library/Cargo.toml")); + packages.extend(collect_metadata("library/stdarch/Cargo.toml")); packages }