From 6e63c3946726549f0b191e934764e74f9d57d1ee Mon Sep 17 00:00:00 2001 From: Karol Zwolak Date: Mon, 10 Nov 2025 13:16:24 +0100 Subject: [PATCH] feat: add rust.rustflags and per target rustflags options to bootstrap.toml This makes easy to persistently pass any flag to the compiler when building rustc. For example you can use a different linker by putting the following in `bootstrap.toml`: ```toml [rust] rustflags = ["-Clinker=clang", "-Clink-arg=--ld-path=wild"] ``` --- bootstrap.example.toml | 12 ++++++++++++ src/bootstrap/src/core/builder/cargo.rs | 16 ++++++++++++++++ src/bootstrap/src/core/config/config.rs | 5 +++++ src/bootstrap/src/core/config/toml/rust.rs | 2 ++ src/bootstrap/src/core/config/toml/target.rs | 2 ++ src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 6 files changed, 42 insertions(+) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 08e96fda0714c..6a8da0305464a 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -708,6 +708,12 @@ # desired in distributions, for example. #rust.rpath = true +# Additional flags to pass to `rustc`. +# Takes precedence over bootstrap's own flags but not over per target rustflags nor env. vars. like RUSTFLAGS. +# Applies to all stages and targets. +# +#rust.rustflags = [] + # Indicates whether symbols should be stripped using `-Cstrip=symbols`. #rust.strip = false @@ -1013,6 +1019,12 @@ # and will override the same option under [rust] section. It only works on Unix platforms #rpath = rust.rpath (bool) +# Additional flags to pass to `rustc`. +# Takes precedence over bootstrap's own flags and `rust.rustflags` but not over env. vars. like RUSTFLAGS. +# Applies to all stages. +# +#rustflags = rust.rustflags + # Force static or dynamic linkage of the standard library for this target. If # this target is a host for rustc, this will also affect the linkage of the # compiler itself. This is useful for building rustc on targets that normally diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index c38e140898543..a685a0f2d8224 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -105,6 +105,7 @@ pub struct Cargo { allow_features: String, release_build: bool, build_compiler_stage: u32, + extra_rustflags: Vec, } impl Cargo { @@ -403,6 +404,11 @@ impl From for BootstrapCommand { cargo.args.insert(0, "--release".into()); } + for arg in &cargo.extra_rustflags { + cargo.rustflags.arg(arg); + cargo.rustdocflags.arg(arg); + } + // Propagate the envs here at the very end to make sure they override any previously set flags. cargo.rustflags.propagate_rustflag_envs(cargo.build_compiler_stage); cargo.rustdocflags.propagate_rustflag_envs(cargo.build_compiler_stage); @@ -1379,6 +1385,15 @@ impl Builder<'_> { rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions"); } + // take target-specific extra rustflags if any otherwise take `rust.rustflags` + let extra_rustflags = self + .config + .target_config + .get(&target) + .map(|t| &t.rustflags) + .unwrap_or(&self.config.rust_rustflags) + .clone(); + let release_build = self.config.rust_optimize.is_release() && // cargo bench/install do not accept `--release` and miri doesn't want it !matches!(cmd_kind, Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest); @@ -1394,6 +1409,7 @@ impl Builder<'_> { allow_features, release_build, build_compiler_stage, + extra_rustflags, } } } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9ad22e9de565d..2f493658ec0ec 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -225,6 +225,7 @@ pub struct Config { pub rust_std_features: BTreeSet, pub rust_break_on_ice: bool, pub rust_parallel_frontend_threads: Option, + pub rust_rustflags: Vec, pub llvm_profile_use: Option, pub llvm_profile_generate: bool, @@ -575,6 +576,7 @@ impl Config { bootstrap_override_lld_legacy: rust_bootstrap_override_lld_legacy, std_features: rust_std_features, break_on_ice: rust_break_on_ice, + rustflags: rust_rustflags, } = toml.rust.unwrap_or_default(); let Llvm { @@ -864,6 +866,7 @@ impl Config { sanitizers: target_sanitizers, profiler: target_profiler, rpath: target_rpath, + rustflags: target_rustflags, crt_static: target_crt_static, musl_root: target_musl_root, musl_libdir: target_musl_libdir, @@ -947,6 +950,7 @@ impl Config { target.sanitizers = target_sanitizers; target.profiler = target_profiler; target.rpath = target_rpath; + target.rustflags = target_rustflags.unwrap_or_default(); target.optimized_compiler_builtins = target_optimized_compiler_builtins; target.jemalloc = target_jemalloc; if let Some(backends) = target_codegen_backends { @@ -1441,6 +1445,7 @@ impl Config { rust_randomize_layout: rust_randomize_layout.unwrap_or(false), rust_remap_debuginfo: rust_remap_debuginfo.unwrap_or(false), rust_rpath: rust_rpath.unwrap_or(true), + rust_rustflags: rust_rustflags.unwrap_or_default(), rust_stack_protector, rust_std_features: rust_std_features .unwrap_or(BTreeSet::from([String::from("panic-unwind")])), diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index a9089ba499a4f..48042ba56bb61 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -33,6 +33,7 @@ define_config! { channel: Option = "channel", musl_root: Option = "musl-root", rpath: Option = "rpath", + rustflags: Option> = "rustflags", strip: Option = "strip", frame_pointers: Option = "frame-pointers", stack_protector: Option = "stack-protector", @@ -375,6 +376,7 @@ pub fn check_incompatible_options_for_ci_rustc( parallel_frontend_threads: _, bootstrap_override_lld: _, bootstrap_override_lld_legacy: _, + rustflags: _, } = ci_rust_config; // There are two kinds of checks for CI rustc incompatible options: diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs index 4c7afa50b9658..847b75e696b47 100644 --- a/src/bootstrap/src/core/config/toml/target.rs +++ b/src/bootstrap/src/core/config/toml/target.rs @@ -37,6 +37,7 @@ define_config! { sanitizers: Option = "sanitizers", profiler: Option = "profiler", rpath: Option = "rpath", + rustflags: Option> = "rustflags", crt_static: Option = "crt-static", musl_root: Option = "musl-root", musl_libdir: Option = "musl-libdir", @@ -70,6 +71,7 @@ pub struct Target { pub sanitizers: Option, pub profiler: Option, pub rpath: Option, + pub rustflags: Vec, pub crt_static: Option, pub musl_root: Option, pub musl_libdir: Option, diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 5f66d8a7d4c6b..ed280addb3b84 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -596,4 +596,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "The `-Zannotate-moves` option is now always enabled when building rustc, sysroot and tools.", }, + ChangeInfo { + change_id: 148795, + severity: ChangeSeverity::Info, + summary: "New options `rust.rustflags` for all targets and `rustflags` par target that will pass specified flags to rustc for all stages. Target specific flags override global `rust.rustflags` ones.", + }, ];