From 9c5616a19569fad7c14f789fd9a048b6a054c86f Mon Sep 17 00:00:00 2001 From: lancethepants Date: Tue, 8 Mar 2022 11:10:07 -0700 Subject: [PATCH 1/9] Update armv7-unknown-linux-uclibceabi platform support page. --- .../armv7-unknown-linux-uclibceabi.md | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md index d58b8570595..71afca527d1 100644 --- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md @@ -36,8 +36,8 @@ target = ["armv7-unknown-linux-uclibceabi"] cc = "/path/to/arm-unknown-linux-uclibcgnueabi-gcc" cxx = "/path/to/arm-unknown-linux-uclibcgnueabi-g++" ar = "path/to/arm-unknown-linux-uclibcgnueabi-ar" -ranlib = "path/to/arm-unknown-linux-uclibcgnueabi-" -linker = "/path/to/arm-unknown-linux-uclibcgnueabi-" +ranlib = "path/to/arm-unknown-linux-uclibcgnueabi-ranlib" +linker = "/path/to/arm-unknown-linux-uclibcgnueabi-gcc" ``` ## Building Rust programs @@ -75,27 +75,37 @@ To cross compile, you'll need to: ``` * Build with: ```text - CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ - CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \ - AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \ + CC_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ + CXX_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \ + AR_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \ + CFLAGS_armv7_unknown_linux_uclibceabi="-march=armv7-a -mtune=cortex-a9" \ + CXXFLAGS_armv7_unknown_linux_uclibceabi="-march=armv7-a -mtune=cortex-a9" \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUSTFLAGS='-Clink-arg=-s -Clink-arg=-Wl,--dynamic-linker=/mmc/lib/ld-uClibc.so.1 -Clink-arg=-Wl,-rpath,/mmc/lib' \ - cargo +stage2 build --target armv7-unknown-linux-uclibceabi --release + cargo +stage2 \ + build \ + --target armv7-unknown-linux-uclibceabi \ + --release ``` * Copy the binary to your target device and run. -We specify `CC`, `CXX`, and `AR` because somtimes a project or a subproject requires the use of your `'C'` cross toolchain. Since Tomatoware has a modified sysroot we also pass via RUSTFLAGS the location of the dynamic-linker and rpath. +We specify `CC`, `CXX`, `AR`, `CFLAGS`, and `CXXFLAGS` environment variables because somtimes a project or a subproject requires the use of your `'C'` cross toolchain. Since Tomatoware has a modified sysroot we also pass via RUSTFLAGS the location of the dynamic-linker and rpath. ### Test with QEMU To test a cross-compiled binary on your build system follow the instructions for `Cross Compilation`, install `qemu-arm-static`, and run with the following. ```text -CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ -CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \ -AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \ +CC_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ +CXX_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \ +AR_armv7_unknown_linux_uclibceabi=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \ +CFLAGS_armv7_unknown_linux_uclibceabi="-march=armv7-a -mtune=cortex-a9" \ +CXXFLAGS_armv7_unknown_linux_uclibceabi="-march=armv7-a -mtune=cortex-a9" \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUNNER="qemu-arm-static -L /opt/tomatoware/arm-soft-mmc/arm-tomatoware-linux-uclibcgnueabi/sysroot/" \ -cargo +stage2 run --target armv7-unknown-linux-uclibceabi --release +cargo +stage2 \ +run \ +--target armv7-unknown-linux-uclibceabi \ +--release ``` ### Run in a chroot From ecf46d1074f0bb6d57bf4c3434cbe4b06c247f33 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 10 Mar 2022 22:57:02 +0400 Subject: [PATCH 2/9] Add `Atomic*::get_mut_slice` Just as `get_mut` is the inverse of `from_mut`, `get_mut_slice` is the inverse of `from_mut_slice`. --- library/core/src/sync/atomic.rs | 110 ++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 2da04ab2cea..bc36798409b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -340,6 +340,40 @@ impl AtomicBool { unsafe { &mut *(v as *mut bool as *mut Self) } } + /// Get non-atomic access to a `&mut [AtomicBool]` slice. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut, inline_const, scoped_threads)] + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// + /// let mut some_bools = [const { AtomicBool::new(false) }; 10]; + /// + /// let view: &mut [bool] = AtomicBool::get_mut_slice(&mut some_bools); + /// assert_eq!(view, [false; 10]); + /// view[..5].copy_from_slice(&[true; 5]); + /// + /// std::thread::scope(|s| { + /// for t in &some_bools[..5] { + /// s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true)); + /// } + /// + /// for f in &some_bools[5..] { + /// s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false)); + /// } + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [bool] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [bool]) } + } + /// Get atomic access to a `&mut [bool]` slice. /// /// # Examples @@ -971,6 +1005,46 @@ impl AtomicPtr { unsafe { &mut *(v as *mut *mut T as *mut Self) } } + /// Get non-atomic access to a `&mut [AtomicPtr]` slice. + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut, inline_const, scoped_threads)] + /// use std::ptr::null_mut; + /// use std::sync::atomic::{AtomicPtr, Ordering}; + /// + /// let mut some_ptrs = [const { AtomicPtr::new(null_mut::()) }; 10]; + /// + /// let view: &mut [*mut String] = AtomicPtr::get_mut_slice(&mut some_ptrs); + /// assert_eq!(view, [null_mut::(); 10]); + /// view + /// .iter_mut() + /// .enumerate() + /// .for_each(|(i, ptr)| *ptr = Box::into_raw(Box::new(format!("iteration#{i}")))); + /// + /// std::thread::scope(|s| { + /// for ptr in &some_ptrs { + /// s.spawn(move || { + /// let ptr = ptr.load(Ordering::Relaxed); + /// assert!(!ptr.is_null()); + /// + /// let name = unsafe { Box::from_raw(ptr) }; + /// println!("Hello, {name}!"); + /// }); + /// } + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [*mut T]) } + } + /// Get atomic access to a slice of pointers. /// /// # Examples @@ -1521,6 +1595,42 @@ macro_rules! atomic_int { unsafe { &mut *(v as *mut $int_type as *mut Self) } } + #[doc = concat!("Get non-atomic access to a `&mut [", stringify!($atomic_type), "]` slice")] + /// + /// This is safe because the mutable reference guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_mut, inline_const, scoped_threads)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] + /// + #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")] + /// + #[doc = concat!("let view: &mut [", stringify!($int_type), "] = ", stringify!($atomic_type), "::get_mut_slice(&mut some_ints);")] + /// assert_eq!(view, [0; 10]); + /// view + /// .iter_mut() + /// .enumerate() + /// .for_each(|(idx, int)| *int = idx as _); + /// + /// std::thread::scope(|s| { + /// some_ints + /// .iter() + /// .enumerate() + /// .for_each(|(idx, int)| { + /// s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _)); + /// }) + /// }); + /// ``` + #[inline] + #[unstable(feature = "atomic_from_mut", issue = "76314")] + pub fn get_mut_slice(this: &mut [Self]) -> &mut [$int_type] { + // SAFETY: the mutable reference guarantees unique ownership. + unsafe { &mut *(this as *mut [Self] as *mut [$int_type]) } + } + #[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")] /// /// # Examples From 1d13de686706f48f9da30b5640dd16b357df2806 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sat, 12 Mar 2022 08:00:45 -0500 Subject: [PATCH 3/9] Implement `BITS` constant for non-zero integers --- library/core/src/num/nonzero.rs | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5bdd78aa2de..05e53175873 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1090,3 +1090,41 @@ nonzero_min_max_signed! { NonZeroI128(i128); NonZeroIsize(isize); } + +macro_rules! nonzero_bits { + ( $( $Ty: ident($Int: ty); )+ ) => { + $( + impl $Ty { + /// The size of this non-zero integer type in bits. + /// + #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_bits)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] + /// ``` + #[unstable(feature = "nonzero_bits", issue = "94881")] + pub const BITS: u32 = <$Int>::BITS; + } + )+ + } +} + +nonzero_bits! { + NonZeroU8(u8); + NonZeroI8(i8); + NonZeroU16(u16); + NonZeroI16(i16); + NonZeroU32(u32); + NonZeroI32(i32); + NonZeroU64(u64); + NonZeroI64(i64); + NonZeroU128(u128); + NonZeroI128(i128); + NonZeroUsize(usize); + NonZeroIsize(isize); +} From 6b5acf0d4063fc726f68fcd444140ffd576b7304 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Sat, 12 Mar 2022 08:01:35 -0500 Subject: [PATCH 4/9] Use `Self::BITS` in `log2` implementation --- library/core/src/num/nonzero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 05e53175873..c3652931478 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -465,7 +465,7 @@ macro_rules! nonzero_unsigned_operations { without modifying the original"] #[inline] pub const fn log2(self) -> u32 { - <$Int>::BITS - 1 - self.leading_zeros() + Self::BITS - 1 - self.leading_zeros() } /// Returns the base 10 logarithm of the number, rounded down. From 88609e51265a563552e8fb4509f83a99e15451b2 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 2 Mar 2022 18:38:40 +0100 Subject: [PATCH 5/9] Rename derive_merge macro to define_config and move Deserialize impl into it --- src/bootstrap/config.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0c0a4733231..7e6eecaaa88 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -362,11 +362,13 @@ impl Merge for TomlConfig { // We are using a decl macro instead of a derive proc macro here to reduce the compile time of // rustbuild. -macro_rules! derive_merge { +macro_rules! define_config { ($(#[$attr:meta])* struct $name:ident { $($field:ident: $field_ty:ty,)* }) => { $(#[$attr])* + #[derive(Deserialize)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct $name { $($field: $field_ty,)* } @@ -383,10 +385,9 @@ macro_rules! derive_merge { } } -derive_merge! { +define_config! { /// TOML representation of various global build decisions. - #[derive(Deserialize, Default)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] + #[derive(Default)] struct Build { build: Option, host: Option>, @@ -429,10 +430,8 @@ derive_merge! { } } -derive_merge! { +define_config! { /// TOML representation of various global install decisions. - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Install { prefix: Option, sysconfdir: Option, @@ -444,10 +443,8 @@ derive_merge! { } } -derive_merge! { +define_config! { /// TOML representation of how the LLVM build is configured. - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Llvm { skip_rebuild: Option, optimize: Option, @@ -479,9 +476,7 @@ derive_merge! { } } -derive_merge! { - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] +define_config! { struct Dist { sign_folder: Option, gpg_password_file: Option, @@ -505,10 +500,8 @@ impl Default for StringOrBool { } } -derive_merge! { +define_config! { /// TOML representation of how the Rust build is configured. - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Rust { optimize: Option, debug: Option, @@ -560,10 +553,8 @@ derive_merge! { } } -derive_merge! { +define_config! { /// TOML representation of how each build target is configured. - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct TomlTarget { cc: Option, cxx: Option, From a0b4d2136d639590fa2be32f8b092c5766bc92af Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 2 Mar 2022 19:43:43 +0100 Subject: [PATCH 6/9] Use trimmed down deserialization impl for config This reduces binary size from 10.1MiB (6.2MiB for just rustbuild code) to 9.7MiB (5.8MiB for just rustbuild code). This also reduces compile time from ~6.1s for incr recompilation to ~5.6s. There is still a lot of unnecessary code due to the toml crate monomorphizing every deserialization impl 5 times. --- src/bootstrap/config.rs | 383 +++++++++++++++++++++++++--------------- 1 file changed, 237 insertions(+), 146 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7e6eecaaa88..762f18fb32f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -17,7 +17,7 @@ use crate::channel::GitInfo; pub use crate::flags::Subcommand; use crate::flags::{Color, Flags}; use crate::util::{exe, t}; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; macro_rules! check_ci_llvm { ($name:expr) => { @@ -364,13 +364,11 @@ impl Merge for TomlConfig { // rustbuild. macro_rules! define_config { ($(#[$attr:meta])* struct $name:ident { - $($field:ident: $field_ty:ty,)* + $($field:ident: Option<$field_ty:ty> = $field_key:literal,)* }) => { $(#[$attr])* - #[derive(Deserialize)] - #[serde(deny_unknown_fields, rename_all = "kebab-case")] struct $name { - $($field: $field_ty,)* + $($field: Option<$field_ty>,)* } impl Merge for $name { @@ -382,6 +380,99 @@ macro_rules! define_config { )* } } + + // The following is a trimmed version of what serde_derive generates. All parts not relevant + // for toml deserialization have been removed. This reduces the binary size and improves + // compile time of rustbuild. + impl<'de> Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[allow(non_camel_case_types)] + enum FieldName { + $($field,)* + } + struct FieldNameVisitor; + impl<'de> serde::de::Visitor<'de> for FieldNameVisitor { + type Value = FieldName; + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("field identifier") + } + + #[inline] + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + match value { + $($field_key => Ok(FieldName::$field),)* + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + impl<'de> Deserialize<'de> for FieldName { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserializer::deserialize_identifier(deserializer, FieldNameVisitor) + } + } + struct Field; + impl<'de> serde::de::Visitor<'de> for Field { + type Value = $name; + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(concat!("struct ", stringify!($name))) + } + + #[inline] + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + $(let mut $field: Option<$field_ty> = None;)* + while let Some(key) = + match serde::de::MapAccess::next_key::(&mut map) { + Ok(val) => val, + Err(err) => { + return Err(err); + } + } + { + match key { + $(FieldName::$field => { + if $field.is_some() { + return Err(::duplicate_field( + $field_key, + )); + } + $field = match serde::de::MapAccess::next_value::<$field_ty>( + &mut map, + ) { + Ok(val) => Some(val), + Err(err) => { + return Err(err); + } + }; + })* + } + } + Ok($name { $($field),* }) + } + } + const FIELDS: &'static [&'static str] = &[ + $($field_key,)* + ]; + Deserializer::deserialize_struct( + deserializer, + stringify!($name), + FIELDS, + Field, + ) + } + } } } @@ -389,101 +480,101 @@ define_config! { /// TOML representation of various global build decisions. #[derive(Default)] struct Build { - build: Option, - host: Option>, - target: Option>, - build_dir: Option, - cargo: Option, - rustc: Option, - rustfmt: Option, - docs: Option, - compiler_docs: Option, - docs_minification: Option, - submodules: Option, - fast_submodules: Option, - gdb: Option, - nodejs: Option, - npm: Option, - python: Option, - locked_deps: Option, - vendor: Option, - full_bootstrap: Option, - extended: Option, - tools: Option>, - verbose: Option, - sanitizers: Option, - profiler: Option, - cargo_native_static: Option, - low_priority: Option, - configure_args: Option>, - local_rebuild: Option, - print_step_timings: Option, - print_step_rusage: Option, - check_stage: Option, - doc_stage: Option, - build_stage: Option, - test_stage: Option, - install_stage: Option, - dist_stage: Option, - bench_stage: Option, - patch_binaries_for_nix: Option, + build: Option = "build", + host: Option> = "host", + target: Option> = "target", + build_dir: Option = "build-dir", + cargo: Option = "cargo", + rustc: Option = "rustc", + rustfmt: Option = "rustfmt", + docs: Option = "docs", + compiler_docs: Option = "compiler-docs", + docs_minification: Option = "docs-minification", + submodules: Option = "submodules", + fast_submodules: Option = "fast-submodules", + gdb: Option = "gdb", + nodejs: Option = "nodejs", + npm: Option = "npm", + python: Option = "python", + locked_deps: Option = "locked-deps", + vendor: Option = "vendor", + full_bootstrap: Option = "full-bootstrap", + extended: Option = "extended", + tools: Option> = "tools", + verbose: Option = "verbose", + sanitizers: Option = "sanitizers", + profiler: Option = "profiler", + cargo_native_static: Option = "cargo-native-static", + low_priority: Option = "low-priority", + configure_args: Option> = "configure-args", + local_rebuild: Option = "local-rebuild", + print_step_timings: Option = "print-step-timings", + print_step_rusage: Option = "print-step-rusage", + check_stage: Option = "check-stage", + doc_stage: Option = "doc-stage", + build_stage: Option = "build-stage", + test_stage: Option = "test-stage", + install_stage: Option = "install-stage", + dist_stage: Option = "dist-stage", + bench_stage: Option = "bench-stage", + patch_binaries_for_nix: Option = "patch-binaries-for-nix", } } define_config! { /// TOML representation of various global install decisions. struct Install { - prefix: Option, - sysconfdir: Option, - docdir: Option, - bindir: Option, - libdir: Option, - mandir: Option, - datadir: Option, + prefix: Option = "prefix", + sysconfdir: Option = "sysconfdir", + docdir: Option = "docdir", + bindir: Option = "bindir", + libdir: Option = "libdir", + mandir: Option = "mandir", + datadir: Option = "datadir", } } define_config! { /// TOML representation of how the LLVM build is configured. struct Llvm { - skip_rebuild: Option, - optimize: Option, - thin_lto: Option, - release_debuginfo: Option, - assertions: Option, - tests: Option, - plugins: Option, - ccache: Option, - version_check: Option, - static_libstdcpp: Option, - ninja: Option, - targets: Option, - experimental_targets: Option, - link_jobs: Option, - link_shared: Option, - version_suffix: Option, - clang_cl: Option, - cflags: Option, - cxxflags: Option, - ldflags: Option, - use_libcxx: Option, - use_linker: Option, - allow_old_toolchain: Option, - polly: Option, - clang: Option, - download_ci_llvm: Option, - build_config: Option>, + skip_rebuild: Option = "skip-rebuild", + optimize: Option = "optimize", + thin_lto: Option = "thin-lto", + release_debuginfo: Option = "release-debuginfo", + assertions: Option = "assertions", + tests: Option = "tests", + plugins: Option = "plugins", + ccache: Option = "ccache", + version_check: Option = "version-check", + static_libstdcpp: Option = "static-libstdcpp", + ninja: Option = "ninja", + targets: Option = "targets", + experimental_targets: Option = "experimental-targets", + link_jobs: Option = "link-jobs", + link_shared: Option = "link-shared", + version_suffix: Option = "version-suffix", + clang_cl: Option = "clang-cl", + cflags: Option = "cflags", + cxxflags: Option = "cxxflags", + ldflags: Option = "ldflags", + use_libcxx: Option = "use-libcxx", + use_linker: Option = "use-linker", + allow_old_toolchain: Option = "allow-old-toolchain", + polly: Option = "polly", + clang: Option = "clang", + download_ci_llvm: Option = "download-ci-llvm", + build_config: Option> = "build-config", } } define_config! { struct Dist { - sign_folder: Option, - gpg_password_file: Option, - upload_addr: Option, - src_tarball: Option, - missing_tools: Option, - compression_formats: Option>, + sign_folder: Option = "sign-folder", + gpg_password_file: Option = "gpg-password-file", + upload_addr: Option = "upload-addr", + src_tarball: Option = "src-tarball", + missing_tools: Option = "missing-tools", + compression_formats: Option> = "compression-formats", } } @@ -503,76 +594,76 @@ impl Default for StringOrBool { define_config! { /// TOML representation of how the Rust build is configured. struct Rust { - optimize: Option, - debug: Option, - codegen_units: Option, - codegen_units_std: Option, - debug_assertions: Option, - debug_assertions_std: Option, - overflow_checks: Option, - overflow_checks_std: Option, - debug_logging: Option, - debuginfo_level: Option, - debuginfo_level_rustc: Option, - debuginfo_level_std: Option, - debuginfo_level_tools: Option, - debuginfo_level_tests: Option, - run_dsymutil: Option, - backtrace: Option, - incremental: Option, - parallel_compiler: Option, - default_linker: Option, - channel: Option, - description: Option, - musl_root: Option, - rpath: Option, - verbose_tests: Option, - optimize_tests: Option, - codegen_tests: Option, - ignore_git: Option, - dist_src: Option, - save_toolstates: Option, - codegen_backends: Option>, - lld: Option, - use_lld: Option, - llvm_tools: Option, - deny_warnings: Option, - backtrace_on_ice: Option, - verify_llvm_ir: Option, - thin_lto_import_instr_limit: Option, - remap_debuginfo: Option, - jemalloc: Option, - test_compare_mode: Option, - llvm_libunwind: Option, - control_flow_guard: Option, - new_symbol_mangling: Option, - profile_generate: Option, - profile_use: Option, + optimize: Option = "optimize", + debug: Option = "debug", + codegen_units: Option = "codegen-units", + codegen_units_std: Option = "codegen-units-std", + debug_assertions: Option = "debug-assertions", + debug_assertions_std: Option = "debug-assertions-std", + overflow_checks: Option = "overflow-checks", + overflow_checks_std: Option = "overflow-checks-std", + debug_logging: Option = "debug-logging", + debuginfo_level: Option = "debuginfo-level", + debuginfo_level_rustc: Option = "debuginfo-level-rustc", + debuginfo_level_std: Option = "debuginfo-level-std", + debuginfo_level_tools: Option = "debuginfo-level-tools", + debuginfo_level_tests: Option = "debuginfo-level-tests", + run_dsymutil: Option = "run-dsymutil", + backtrace: Option = "backtrace", + incremental: Option = "incremental", + parallel_compiler: Option = "parallel-compiler", + default_linker: Option = "default-linker", + channel: Option = "channel", + description: Option = "description", + musl_root: Option = "musl-root", + rpath: Option = "rpath", + verbose_tests: Option = "verbose-tests", + optimize_tests: Option = "optimize-tests", + codegen_tests: Option = "codegen-tests", + ignore_git: Option = "ignore-git", + dist_src: Option = "dist-src", + save_toolstates: Option = "save-toolstates", + codegen_backends: Option> = "codegen-backends", + lld: Option = "lld", + use_lld: Option = "use-lld", + llvm_tools: Option = "llvm-tools", + deny_warnings: Option = "deny-warnings", + backtrace_on_ice: Option = "backtrace-on-ice", + verify_llvm_ir: Option = "verify-llvm-ir", + thin_lto_import_instr_limit: Option = "thin-lto-import-instr-limit", + remap_debuginfo: Option = "remap-debuginfo", + jemalloc: Option = "jemalloc", + test_compare_mode: Option = "test-compare-mode", + llvm_libunwind: Option = "llvm-libunwind", + control_flow_guard: Option = "control-flow-guard", + new_symbol_mangling: Option = "new-symbol-mangling", + profile_generate: Option = "profile-generate", + profile_use: Option = "profile-use", // ignored; this is set from an env var set by bootstrap.py - download_rustc: Option, + download_rustc: Option = "download-rustc", } } define_config! { /// TOML representation of how each build target is configured. struct TomlTarget { - cc: Option, - cxx: Option, - ar: Option, - ranlib: Option, - default_linker: Option, - linker: Option, - llvm_config: Option, - llvm_filecheck: Option, - android_ndk: Option, - sanitizers: Option, - profiler: Option, - crt_static: Option, - musl_root: Option, - musl_libdir: Option, - wasi_root: Option, - qemu_rootfs: Option, - no_std: Option, + cc: Option = "cc", + cxx: Option = "cxx", + ar: Option = "ar", + ranlib: Option = "ranlib", + default_linker: Option = "default-linker", + linker: Option = "linker", + llvm_config: Option = "llvm-config", + llvm_filecheck: Option = "llvm-filecheck", + android_ndk: Option = "android-ndk", + sanitizers: Option = "sanitizers", + profiler: Option = "profiler", + crt_static: Option = "crt-static", + musl_root: Option = "musl-root", + musl_libdir: Option = "musl-libdir", + wasi_root: Option = "wasi-root", + qemu_rootfs: Option = "qemu-rootfs", + no_std: Option = "no-std", } } From dca8ff5b252ce2430fa61e6a5bd230b1edc9ea50 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 3 Mar 2022 18:44:02 +0100 Subject: [PATCH 7/9] Prevent duplicate monomorphization of deserialization impls This reduces binary size from 9.7MiB (5.8MiB for just rustbuild code) to 9.3MiB (5.3MiB for just rustbuild code). This doesn't reduce compile time in a statistically significant way. --- src/bootstrap/config.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 762f18fb32f..6e8471b1de7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -731,7 +731,11 @@ impl Config { let contents = t!(fs::read_to_string(file), format!("config file {} not found", file.display())); - match toml::from_str(&contents) { + // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of + // TomlConfig and sub types to be monomorphized 5x by toml. + match toml::from_str(&contents) + .and_then(|table: toml::Value| TomlConfig::deserialize(table)) + { Ok(table) => table, Err(err) => { println!("failed to parse TOML configuration '{}': {}", file.display(), err); From a0163f748719c743f0d53b66e41158fbd7dbd035 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Mar 2022 17:35:02 +0100 Subject: [PATCH 8/9] Remove FieldName enum --- src/bootstrap/config.rs | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 6e8471b1de7..e744810295d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -389,37 +389,6 @@ macro_rules! define_config { where D: Deserializer<'de>, { - #[allow(non_camel_case_types)] - enum FieldName { - $($field,)* - } - struct FieldNameVisitor; - impl<'de> serde::de::Visitor<'de> for FieldNameVisitor { - type Value = FieldName; - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("field identifier") - } - - #[inline] - fn visit_str(self, value: &str) -> Result - where - E: serde::de::Error, - { - match value { - $($field_key => Ok(FieldName::$field),)* - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - impl<'de> Deserialize<'de> for FieldName { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Deserializer::deserialize_identifier(deserializer, FieldNameVisitor) - } - } struct Field; impl<'de> serde::de::Visitor<'de> for Field { type Value = $name; @@ -434,15 +403,15 @@ macro_rules! define_config { { $(let mut $field: Option<$field_ty> = None;)* while let Some(key) = - match serde::de::MapAccess::next_key::(&mut map) { + match serde::de::MapAccess::next_key::(&mut map) { Ok(val) => val, Err(err) => { return Err(err); } } { - match key { - $(FieldName::$field => { + match &*key { + $($field_key => { if $field.is_some() { return Err(::duplicate_field( $field_key, @@ -457,6 +426,9 @@ macro_rules! define_config { } }; })* + key => { + return Err(serde::de::Error::unknown_field(key, FIELDS)); + } } } Ok($name { $($field),* }) From cd5e75a691f68167df16b6a98fafcbc41d4afd57 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Mar 2022 15:09:48 +0100 Subject: [PATCH 9/9] Omit stdarch test crates from the rust-src component These crates aren't necessary for building the standard library. This saves 30MB of disk space. Fixes #94906 --- src/bootstrap/dist.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5f92cc2ca6f..76054122d00 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -821,6 +821,11 @@ impl Step for Src { // not needed and contains symlinks which rustup currently // chokes on when unpacking. "library/backtrace/crates", + // these are 30MB combined and aren't necessary for building + // the standard library. + "library/stdarch/crates/Cargo.toml", + "library/stdarch/crates/stdarch-verify", + "library/stdarch/crates/intrinsic-test", ], &dst_src, );