src/bootstrap/src/core/config/config.rs RUST 2,689 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,689.
1//! This module defines the central `Config` struct, which aggregates all components2//! of the bootstrap configuration into a single unit.3//!4//! It serves as the primary public interface for accessing the bootstrap configuration.5//! The module coordinates the overall configuration parsing process using logic from `parsing.rs`6//! and provides top-level methods such as `Config::parse()` for initialization, as well as7//! utility methods for querying and manipulating the complete configuration state.8//!9//! Additionally, this module contains the core logic for parsing, validating, and inferring10//! the final `Config` from various raw inputs.11//!12//! It manages the process of reading command-line arguments, environment variables,13//! and the `bootstrap.toml` file—merging them, applying defaults, and performing14//! cross-component validation. The main `parse_inner` function and its supporting15//! helpers reside here, transforming raw `Toml` data into the structured `Config` type.16use std::cell::Cell;17use std::collections::{BTreeSet, HashMap, HashSet};18use std::io::IsTerminal;19use std::path::{Path, PathBuf, absolute};20use std::str::FromStr;21use std::sync::{Arc, Mutex};22use std::{cmp, env, fs};2324use build_helper::ci::CiEnv;25use build_helper::exit;26use build_helper::git::{GitConfig, PathFreshness, check_path_modifications};27use serde::Deserialize;28#[cfg(feature = "tracing")]29use tracing::{instrument, span};3031use crate::core::build_steps::llvm;32use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;33pub use crate::core::config::flags::Subcommand;34use crate::core::config::flags::{Color, Flags, Warnings};35use crate::core::config::target_selection::TargetSelectionList;36use crate::core::config::toml::TomlConfig;37use crate::core::config::toml::build::{Build, Tool};38use crate::core::config::toml::change_id::ChangeId;39use crate::core::config::toml::dist::Dist;40use crate::core::config::toml::gcc::Gcc;41use crate::core::config::toml::install::Install;42use crate::core::config::toml::llvm::Llvm;43use crate::core::config::toml::rust::{44    BootstrapOverrideLld, Rust, RustOptimize, check_incompatible_options_for_ci_rustc,45    parse_codegen_backends,46};47use crate::core::config::toml::target::{48    DefaultLinuxLinkerOverride, Target, TomlTarget, default_linux_linker_overrides,49};50use crate::core::config::{51    CompilerBuiltins, DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt,52    RustcLto, SplitDebuginfo, StringOrBool, threads_from_config,53};54use crate::core::download::{55    DownloadContext, download_beta_toolchain, is_download_ci_available, maybe_download_rustfmt,56};57use crate::utils::channel;58use crate::utils::exec::{ExecutionContext, command};59use crate::utils::helpers::{exe, get_host_target};60use crate::{CodegenBackendKind, GitInfo, OnceLock, TargetSelection, check_ci_llvm, helpers, t};6162/// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic.63/// This means they can be modified and changes to these paths should never trigger a compiler build64/// when "if-unchanged" is set.65///66/// NOTE: Paths must have the ":!" prefix to tell git to ignore changes in those paths during67/// the diff check.68///69/// WARNING: Be cautious when adding paths to this list. If a path that influences the compiler build70/// is added here, it will cause bootstrap to skip necessary rebuilds, which may lead to risky results.71/// For example, "src/bootstrap" should never be included in this list as it plays a crucial role in the72/// final output/compiler, which can be significantly affected by changes made to the bootstrap sources.73#[rustfmt::skip] // We don't want rustfmt to oneline this list74pub const RUSTC_IF_UNCHANGED_ALLOWED_PATHS: &[&str] = &[75    ":!library",76    ":!src/tools",77    ":!src/librustdoc",78    ":!src/rustdoc-json-types",79    ":!tests",80    ":!triagebot.toml",81    ":!src/bootstrap/defaults",82];8384/// Global configuration for the entire build and/or bootstrap.85///86/// This structure is parsed from `bootstrap.toml`, and some of the fields are inferred from `git` or build-time parameters.87///88/// Note that this structure is not decoded directly into, but rather it is89/// filled out from the decoded forms of the structs below. For documentation90/// on each field, see the corresponding fields in91/// `bootstrap.example.toml`.92#[derive(Clone)]93pub struct Config {94    pub change_id: Option<ChangeId>,95    pub bypass_bootstrap_lock: bool,96    pub ccache: Option<String>,97    /// Call Build::ninja() instead of this.98    pub ninja_in_file: bool,99    pub submodules: Option<bool>,100    pub compiler_docs: bool,101    pub library_docs_private_items: bool,102    pub docs_minification: bool,103    pub docs: bool,104    pub locked_deps: bool,105    pub vendor: bool,106    pub target_config: HashMap<TargetSelection, Target>,107    pub full_bootstrap: bool,108    pub bootstrap_cache_path: Option<PathBuf>,109    pub extended: bool,110    pub tools: Option<HashSet<String>>,111    /// Specify build configuration specific for some tool, such as enabled features, see [Tool].112    /// The key in the map is the name of the tool, and the value is tool-specific configuration.113    pub tool: HashMap<String, Tool>,114    pub sanitizers: bool,115    pub profiler: bool,116    pub omit_git_hash: bool,117    pub skip: Vec<PathBuf>,118    pub include_default_paths: bool,119    pub rustc_error_format: Option<String>,120    pub json_output: bool,121    pub compile_time_deps: bool,122    pub test_compare_mode: bool,123    pub color: Color,124    pub patch_binaries_for_nix: Option<bool>,125    pub stage0_metadata: build_helper::stage0_parser::Stage0,126    pub android_ndk: Option<PathBuf>,127    pub optimized_compiler_builtins: CompilerBuiltins,128129    pub stdout_is_tty: bool,130    pub stderr_is_tty: bool,131132    pub on_fail: Option<String>,133    pub explicit_stage_from_cli: bool,134    pub explicit_stage_from_config: bool,135    pub stage: u32,136    pub keep_stage: Vec<u32>,137    pub keep_stage_std: Vec<u32>,138    pub src: PathBuf,139    /// defaults to `bootstrap.toml`140    pub config: Option<PathBuf>,141    pub jobs: Option<u32>,142    pub cmd: Subcommand,143    pub quiet: bool,144    pub incremental: bool,145    pub dump_bootstrap_shims: bool,146    /// Arguments appearing after `--` to be forwarded to tools,147    /// e.g. `--fix-broken` or test arguments.148    pub free_args: Vec<String>,149150    /// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should.151    pub download_rustc_commit: Option<String>,152153    pub deny_warnings: bool,154    pub backtrace_on_ice: bool,155156    // llvm codegen options157    pub llvm_assertions: bool,158    pub llvm_tests: bool,159    pub llvm_enzyme: bool,160    pub llvm_offload: bool,161    pub llvm_plugins: bool,162    pub llvm_optimize: bool,163    pub llvm_thin_lto: bool,164    pub llvm_release_debuginfo: bool,165    pub llvm_static_stdcpp: bool,166    pub llvm_libzstd: bool,167    pub llvm_link_shared: Cell<Option<bool>>,168    pub llvm_clang_cl: Option<String>,169    pub llvm_targets: Option<String>,170    pub llvm_experimental_targets: Option<String>,171    pub llvm_link_jobs: Option<u32>,172    pub llvm_version_suffix: Option<String>,173    pub llvm_use_linker: Option<String>,174    pub llvm_clang_dir: Option<PathBuf>,175    pub llvm_allow_old_toolchain: bool,176    pub llvm_polly: bool,177    pub llvm_clang: bool,178    pub llvm_enable_warnings: bool,179    pub llvm_from_ci: bool,180    pub llvm_build_config: HashMap<String, String>,181182    pub bootstrap_override_lld: BootstrapOverrideLld,183    pub lld_enabled: bool,184    pub llvm_tools_enabled: bool,185    pub llvm_bitcode_linker_enabled: bool,186187    pub llvm_cflags: Option<String>,188    pub llvm_cxxflags: Option<String>,189    pub llvm_ldflags: Option<String>,190    pub llvm_use_libcxx: bool,191192    // gcc codegen options193    pub gcc_ci_mode: GccCiMode,194    pub libgccjit_libs_dir: Option<PathBuf>,195196    // rust codegen options197    pub rust_optimize: RustOptimize,198    pub rust_codegen_units: Option<u32>,199    pub rust_codegen_units_std: Option<u32>,200    pub rustc_debug_assertions: bool,201    pub std_debug_assertions: bool,202    pub tools_debug_assertions: bool,203204    pub rust_overflow_checks: bool,205    pub rust_overflow_checks_std: bool,206    pub rust_debug_logging: bool,207    pub rust_debuginfo_level_rustc: DebuginfoLevel,208    pub rust_debuginfo_level_std: DebuginfoLevel,209    pub rust_debuginfo_level_tools: DebuginfoLevel,210    pub rust_debuginfo_level_tests: DebuginfoLevel,211    pub rust_rpath: bool,212    pub rust_strip: bool,213    pub rust_frame_pointers: bool,214    pub rust_stack_protector: Option<String>,215    pub rustc_default_linker: Option<String>,216    pub rust_optimize_tests: bool,217    pub rust_dist_src: bool,218    pub rust_codegen_backends: Vec<CodegenBackendKind>,219    pub rust_verify_llvm_ir: bool,220    pub rust_thin_lto_import_instr_limit: Option<u32>,221    pub rust_randomize_layout: bool,222    pub rust_remap_debuginfo: bool,223    pub rust_new_symbol_mangling: Option<bool>,224    pub rust_annotate_moves_size_limit: Option<u64>,225    pub rust_profile_use: Option<String>,226    pub rust_profile_generate: Option<String>,227    pub rust_lto: RustcLto,228    pub rust_validate_mir_opts: Option<u32>,229    pub rust_std_features: BTreeSet<String>,230    pub rust_break_on_ice: bool,231    pub rust_parallel_frontend_threads: Option<u32>,232    pub rust_rustflags: Vec<String>,233234    pub llvm_profile_use: Option<String>,235    pub llvm_profile_generate: bool,236    pub llvm_libunwind_default: Option<LlvmLibunwind>,237    pub enable_bolt_settings: bool,238239    pub reproducible_artifacts: Vec<String>,240241    pub host_target: TargetSelection,242    pub hosts: Vec<TargetSelection>,243    pub targets: Vec<TargetSelection>,244    pub local_rebuild: bool,245    pub jemalloc: bool,246    pub control_flow_guard: bool,247    pub ehcont_guard: bool,248249    // dist misc250    pub dist_sign_folder: Option<PathBuf>,251    pub dist_upload_addr: Option<String>,252    pub dist_compression_formats: Option<Vec<String>>,253    pub dist_compression_profile: String,254    pub dist_include_mingw_linker: bool,255    pub dist_vendor: bool,256257    // libstd features258    pub backtrace: bool, // support for RUST_BACKTRACE259260    // misc261    pub low_priority: bool,262    pub channel: String,263    pub description: Option<String>,264    pub verbose_tests: bool,265    pub save_toolstates: Option<PathBuf>,266    pub print_step_timings: bool,267    pub print_step_rusage: bool,268269    // Fallback musl-root for all targets270    pub musl_root: Option<PathBuf>,271    pub prefix: Option<PathBuf>,272    pub sysconfdir: Option<PathBuf>,273    pub datadir: Option<PathBuf>,274    pub docdir: Option<PathBuf>,275    pub bindir: PathBuf,276    pub libdir: Option<PathBuf>,277    pub mandir: Option<PathBuf>,278    pub codegen_tests: bool,279    pub nodejs: Option<PathBuf>,280    pub yarn: Option<PathBuf>,281    pub gdb: Option<PathBuf>,282    pub lldb: Option<PathBuf>,283    pub python: Option<PathBuf>,284    pub windows_rc: Option<PathBuf>,285    pub reuse: Option<PathBuf>,286    pub cargo_native_static: bool,287    pub configure_args: Vec<String>,288    pub out: PathBuf,289    pub rust_info: channel::GitInfo,290291    pub cargo_info: channel::GitInfo,292    pub rust_analyzer_info: channel::GitInfo,293    pub clippy_info: channel::GitInfo,294    pub miri_info: channel::GitInfo,295    pub rustfmt_info: channel::GitInfo,296    pub enzyme_info: channel::GitInfo,297    pub in_tree_llvm_info: channel::GitInfo,298    pub in_tree_gcc_info: channel::GitInfo,299300    // These are either the stage0 downloaded binaries or the locally installed ones.301    pub initial_cargo: PathBuf,302    pub initial_rustc: PathBuf,303    pub initial_rustdoc: PathBuf,304    pub initial_cargo_clippy: Option<PathBuf>,305    pub initial_sysroot: PathBuf,306    pub initial_rustfmt: Option<PathBuf>,307308    /// The paths to work with. For example: with `./x check foo bar` we get309    /// `paths=["foo", "bar"]`.310    pub paths: Vec<PathBuf>,311312    /// Command for visual diff display, e.g. `diff-tool --color=always`.313    pub compiletest_diff_tool: Option<String>,314315    /// Whether to allow running both `compiletest` self-tests and `compiletest`-managed test suites316    /// against the stage 0 (rustc, std).317    ///318    /// This is only intended to be used when the stage 0 compiler is actually built from in-tree319    /// sources.320    pub compiletest_allow_stage0: bool,321322    /// Default value for `--extra-checks`323    pub tidy_extra_checks: Option<String>,324    pub ci_env: CiEnv,325326    /// Cache for determining path modifications327    pub path_modification_cache: Arc<Mutex<HashMap<Vec<&'static str>, PathFreshness>>>,328329    /// Skip checking the standard library if `rust.download-rustc` isn't available.330    /// This is mostly for RA as building the stage1 compiler to check the library tree331    /// on each code change might be too much for some computers.332    pub skip_std_check_if_no_download_rustc: bool,333334    pub exec_ctx: ExecutionContext,335}336337impl Config {338    pub fn set_dry_run(&mut self, dry_run: DryRun) {339        self.exec_ctx.set_dry_run(dry_run);340    }341342    pub fn get_dry_run(&self) -> &DryRun {343        self.exec_ctx.get_dry_run()344    }345346    #[cfg_attr(347        feature = "tracing",348        instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::parse", skip_all)349    )]350    pub fn parse(flags: Flags) -> Config {351        Self::parse_inner(flags, Self::get_toml)352    }353354    #[cfg_attr(355        feature = "tracing",356        instrument(357            target = "CONFIG_HANDLING",358            level = "trace",359            name = "Config::parse_inner",360            skip_all361        )362    )]363    pub(crate) fn parse_inner(364        flags: Flags,365        get_toml: impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>,366    ) -> Config {367        // Destructure flags to ensure that we use all its fields368        // The field variables are prefixed with `flags_` to avoid clashes369        // with values from TOML config files with same names.370        let Flags {371            cmd: flags_cmd,372            verbose: flags_verbose,373            quiet: flags_quiet,374            incremental: flags_incremental,375            config: flags_config,376            build_dir: flags_build_dir,377            build: flags_build,378            host: flags_host,379            target: flags_target,380            exclude: flags_exclude,381            skip: flags_skip,382            include_default_paths: flags_include_default_paths,383            rustc_error_format: flags_rustc_error_format,384            on_fail: flags_on_fail,385            dry_run: flags_dry_run,386            dump_bootstrap_shims: flags_dump_bootstrap_shims,387            stage: flags_stage,388            keep_stage: flags_keep_stage,389            keep_stage_std: flags_keep_stage_std,390            src: flags_src,391            jobs: flags_jobs,392            warnings: flags_warnings,393            json_output: flags_json_output,394            compile_time_deps: flags_compile_time_deps,395            color: flags_color,396            bypass_bootstrap_lock: flags_bypass_bootstrap_lock,397            rust_profile_generate: flags_rust_profile_generate,398            rust_profile_use: flags_rust_profile_use,399            llvm_profile_use: flags_llvm_profile_use,400            llvm_profile_generate: flags_llvm_profile_generate,401            enable_bolt_settings: flags_enable_bolt_settings,402            skip_stage0_validation: flags_skip_stage0_validation,403            reproducible_artifact: flags_reproducible_artifact,404            paths: flags_paths,405            set: flags_set,406            free_args: flags_free_args,407            ci: flags_ci,408            skip_std_check_if_no_download_rustc: flags_skip_std_check_if_no_download_rustc,409        } = flags;410411        #[cfg(feature = "tracing")]412        span!(413            target: "CONFIG_HANDLING",414            tracing::Level::TRACE,415            "collecting paths and path exclusions",416            "flags.paths" = ?flags_paths,417            "flags.skip" = ?flags_skip,418            "flags.exclude" = ?flags_exclude419        );420421        if flags_cmd.no_doc() {422            eprintln!(423                "WARN: `x.py test --no-doc` is renamed to `--all-targets`. `--no-doc` will be removed in the near future. Additionally `--tests` is added which only executes unit and integration tests."424            )425        }426427        // Set config values based on flags.428        let mut exec_ctx = ExecutionContext::new(flags_verbose, flags_cmd.fail_fast());429        exec_ctx.set_dry_run(if flags_dry_run { DryRun::UserSelected } else { DryRun::Disabled });430431        let default_src_dir = {432            let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));433            // Undo `src/bootstrap`434            manifest_dir.parent().unwrap().parent().unwrap().to_owned()435        };436        let src = if let Some(s) = compute_src_directory(flags_src, &exec_ctx) {437            s438        } else {439            default_src_dir.clone()440        };441442        #[cfg(test)]443        {444            if let Some(config_path) = flags_config.as_ref() {445                assert!(446                    !config_path.starts_with(&src),447                    "Path {config_path:?} should not be inside or equal to src dir {src:?}"448                );449            } else {450                panic!("During test the config should be explicitly added");451            }452        }453454        // Now load the TOML config, as soon as possible455        let (mut toml, toml_path) = load_toml_config(&src, flags_config, &get_toml);456457        postprocess_toml(&mut toml, &src, toml_path.clone(), &exec_ctx, &flags_set, &get_toml);458459        // Now override TOML values with flags, to make sure that we won't later override flags with460        // TOML values by accident instead, because flags have higher priority.461        let Build {462            description: build_description,463            build: build_build,464            host: build_host,465            target: build_target,466            build_dir: build_build_dir,467            cargo: mut build_cargo,468            rustc: mut build_rustc,469            rustdoc: build_rustdoc,470            rustfmt: build_rustfmt,471            cargo_clippy: build_cargo_clippy,472            docs: build_docs,473            compiler_docs: build_compiler_docs,474            library_docs_private_items: build_library_docs_private_items,475            docs_minification: build_docs_minification,476            submodules: build_submodules,477            gdb: build_gdb,478            lldb: build_lldb,479            nodejs: build_nodejs,480481            yarn: build_yarn,482            npm: build_npm,483            python: build_python,484            windows_rc: build_windows_rc,485            reuse: build_reuse,486            locked_deps: build_locked_deps,487            vendor: build_vendor,488            full_bootstrap: build_full_bootstrap,489            bootstrap_cache_path: build_bootstrap_cache_path,490            extended: build_extended,491            tools: build_tools,492            tool: build_tool,493            verbose: build_verbose,494            sanitizers: build_sanitizers,495            profiler: build_profiler,496            cargo_native_static: build_cargo_native_static,497            low_priority: build_low_priority,498            configure_args: build_configure_args,499            local_rebuild: build_local_rebuild,500            print_step_timings: build_print_step_timings,501            print_step_rusage: build_print_step_rusage,502            check_stage: build_check_stage,503            doc_stage: build_doc_stage,504            build_stage: build_build_stage,505            test_stage: build_test_stage,506            install_stage: build_install_stage,507            dist_stage: build_dist_stage,508            bench_stage: build_bench_stage,509            patch_binaries_for_nix: build_patch_binaries_for_nix,510            // This field is only used by bootstrap.py511            metrics: _,512            android_ndk: build_android_ndk,513            optimized_compiler_builtins: build_optimized_compiler_builtins,514            jobs: build_jobs,515            compiletest_diff_tool: build_compiletest_diff_tool,516            // No longer has any effect; kept (for now) to avoid breaking people's configs.517            compiletest_use_stage0_libtest: _,518            tidy_extra_checks: build_tidy_extra_checks,519            ccache: build_ccache,520            exclude: build_exclude,521            compiletest_allow_stage0: build_compiletest_allow_stage0,522        } = toml.build.unwrap_or_default();523524        let Install {525            prefix: install_prefix,526            sysconfdir: install_sysconfdir,527            docdir: install_docdir,528            bindir: install_bindir,529            libdir: install_libdir,530            mandir: install_mandir,531            datadir: install_datadir,532        } = toml.install.unwrap_or_default();533534        let Rust {535            optimize: rust_optimize,536            debug: rust_debug,537            codegen_units: rust_codegen_units,538            codegen_units_std: rust_codegen_units_std,539            rustc_debug_assertions: rust_rustc_debug_assertions,540            std_debug_assertions: rust_std_debug_assertions,541            tools_debug_assertions: rust_tools_debug_assertions,542            overflow_checks: rust_overflow_checks,543            overflow_checks_std: rust_overflow_checks_std,544            debug_logging: rust_debug_logging,545            debuginfo_level: rust_debuginfo_level,546            debuginfo_level_rustc: rust_debuginfo_level_rustc,547            debuginfo_level_std: rust_debuginfo_level_std,548            debuginfo_level_tools: rust_debuginfo_level_tools,549            debuginfo_level_tests: rust_debuginfo_level_tests,550            backtrace: rust_backtrace,551            incremental: rust_incremental,552            randomize_layout: rust_randomize_layout,553            default_linker: rust_default_linker,554            channel: rust_channel,555            musl_root: rust_musl_root,556            rpath: rust_rpath,557            verbose_tests: rust_verbose_tests,558            optimize_tests: rust_optimize_tests,559            codegen_tests: rust_codegen_tests,560            omit_git_hash: rust_omit_git_hash,561            dist_src: rust_dist_src,562            save_toolstates: rust_save_toolstates,563            codegen_backends: rust_codegen_backends,564            lld: rust_lld_enabled,565            llvm_tools: rust_llvm_tools,566            llvm_bitcode_linker: rust_llvm_bitcode_linker,567            deny_warnings: rust_deny_warnings,568            backtrace_on_ice: rust_backtrace_on_ice,569            verify_llvm_ir: rust_verify_llvm_ir,570            thin_lto_import_instr_limit: rust_thin_lto_import_instr_limit,571            parallel_frontend_threads: rust_parallel_frontend_threads,572            remap_debuginfo: rust_remap_debuginfo,573            jemalloc: rust_jemalloc,574            test_compare_mode: rust_test_compare_mode,575            llvm_libunwind: rust_llvm_libunwind,576            control_flow_guard: rust_control_flow_guard,577            ehcont_guard: rust_ehcont_guard,578            new_symbol_mangling: rust_new_symbol_mangling,579            annotate_moves_size_limit: rust_annotate_moves_size_limit,580            profile_generate: rust_profile_generate,581            profile_use: rust_profile_use,582            download_rustc: rust_download_rustc,583            lto: rust_lto,584            validate_mir_opts: rust_validate_mir_opts,585            frame_pointers: rust_frame_pointers,586            stack_protector: rust_stack_protector,587            strip: rust_strip,588            bootstrap_override_lld: rust_bootstrap_override_lld,589            bootstrap_override_lld_legacy: rust_bootstrap_override_lld_legacy,590            std_features: rust_std_features,591            break_on_ice: rust_break_on_ice,592            rustflags: rust_rustflags,593        } = toml.rust.unwrap_or_default();594595        let Llvm {596            optimize: llvm_optimize,597            thin_lto: llvm_thin_lto,598            release_debuginfo: llvm_release_debuginfo,599            assertions: llvm_assertions,600            tests: llvm_tests,601            enzyme: llvm_enzyme,602            plugins: llvm_plugin,603            static_libstdcpp: llvm_static_libstdcpp,604            libzstd: llvm_libzstd,605            ninja: llvm_ninja,606            targets: llvm_targets,607            experimental_targets: llvm_experimental_targets,608            link_jobs: llvm_link_jobs,609            link_shared: llvm_link_shared,610            version_suffix: llvm_version_suffix,611            clang_cl: llvm_clang_cl,612            cflags: llvm_cflags,613            cxxflags: llvm_cxxflags,614            ldflags: llvm_ldflags,615            use_libcxx: llvm_use_libcxx,616            use_linker: llvm_use_linker,617            allow_old_toolchain: llvm_allow_old_toolchain,618            offload: llvm_offload,619            offload_clang_dir: llvm_clang_dir,620            polly: llvm_polly,621            clang: llvm_clang,622            enable_warnings: llvm_enable_warnings,623            download_ci_llvm: llvm_download_ci_llvm,624            build_config: llvm_build_config,625        } = toml.llvm.unwrap_or_default();626627        let Dist {628            sign_folder: dist_sign_folder,629            upload_addr: dist_upload_addr,630            src_tarball: dist_src_tarball,631            compression_formats: dist_compression_formats,632            compression_profile: dist_compression_profile,633            include_mingw_linker: dist_include_mingw_linker,634            vendor: dist_vendor,635        } = toml.dist.unwrap_or_default();636637        let Gcc {638            download_ci_gcc: gcc_download_ci_gcc,639            libgccjit_libs_dir: gcc_libgccjit_libs_dir,640        } = toml.gcc.unwrap_or_default();641642        if rust_bootstrap_override_lld.is_some() && rust_bootstrap_override_lld_legacy.is_some() {643            panic!(644                "Cannot use both `rust.use-lld` and `rust.bootstrap-override-lld`. Please use only `rust.bootstrap-override-lld`"645            );646        }647648        let bootstrap_override_lld =649            rust_bootstrap_override_lld.or(rust_bootstrap_override_lld_legacy).unwrap_or_default();650651        if rust_optimize.as_ref().is_some_and(|v| matches!(v, RustOptimize::Bool(false))) {652            eprintln!(653                "WARNING: setting `optimize` to `false` is known to cause errors and \654                should be considered unsupported. Refer to `bootstrap.example.toml` \655                for more details."656            );657        }658659        // Prefer CLI verbosity flags if set (`flags_verbose` > 0), otherwise take the value from660        // TOML.661        exec_ctx.set_verbosity(cmp::max(build_verbose.unwrap_or_default() as u8, flags_verbose));662663        let stage0_metadata = build_helper::stage0_parser::parse_stage0_file();664        let path_modification_cache = Arc::new(Mutex::new(HashMap::new()));665666        let host_target = flags_build667            .or(build_build)668            .map(|build| TargetSelection::from_user(&build))669            .unwrap_or_else(get_host_target);670        let hosts = flags_host671            .map(|TargetSelectionList(hosts)| hosts)672            .or_else(|| {673                build_host.map(|h| h.iter().map(|t| TargetSelection::from_user(t)).collect())674            })675            .unwrap_or_else(|| vec![host_target]);676677        let llvm_assertions = llvm_assertions.unwrap_or(false);678        let mut target_config = HashMap::new();679        let mut channel = "dev".to_string();680681        let out = flags_build_dir.or_else(|| build_build_dir.map(PathBuf::from));682        let out = if cfg!(test) {683            out.expect("--build-dir has to be specified in tests")684        } else {685            out.unwrap_or_else(|| PathBuf::from("build"))686        };687688        // NOTE: Bootstrap spawns various commands with different working directories.689        // To avoid writing to random places on the file system, `config.out` needs to be an absolute path.690        let mut out = if !out.is_absolute() {691            // `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead.692            absolute(&out).expect("can't make empty path absolute")693        } else {694            out695        };696697        let default_stage0_rustc_path = |dir: &Path| {698            dir.join(host_target).join("stage0").join("bin").join(exe("rustc", host_target))699        };700701        if cfg!(test) {702            // When configuring bootstrap for tests, make sure to set the rustc and Cargo to the703            // same ones used to call the tests (if custom ones are not defined in the toml). If we704            // don't do that, bootstrap will use its own detection logic to find a suitable rustc705            // and Cargo, which doesn't work when the caller is specìfying a custom local rustc or706            // Cargo in their bootstrap.toml.707            build_rustc = build_rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into()));708            build_cargo = build_cargo.take().or(std::env::var_os("CARGO").map(|p| p.into()));709710            // If we are running only `cargo test` (and not `x test bootstrap`), which is useful711            // e.g. for debugging bootstrap itself, then we won't have RUSTC and CARGO set to the712            // proper paths.713            // We thus "guess" that the build directory is located at <src>/build, and try to load714            // rustc and cargo from there715            let is_test_outside_x = std::env::var("CARGO_TARGET_DIR").is_err();716            if is_test_outside_x && build_rustc.is_none() {717                let stage0_rustc = default_stage0_rustc_path(&default_src_dir.join("build"));718                assert!(719                    stage0_rustc.exists(),720                    "Trying to run cargo test without having a stage0 rustc available in {}",721                    stage0_rustc.display()722                );723                build_rustc = Some(stage0_rustc);724            }725        }726727        if !flags_skip_stage0_validation {728            if let Some(rustc) = &build_rustc {729                check_stage0_version(rustc, "rustc", &src, &exec_ctx);730            }731            if let Some(cargo) = &build_cargo {732                check_stage0_version(cargo, "cargo", &src, &exec_ctx);733            }734        }735736        if build_cargo_clippy.is_some() && build_rustc.is_none() {737            println!(738                "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."739            );740        }741742        let ci_env = match flags_ci {743            Some(true) => CiEnv::GitHubActions,744            Some(false) => CiEnv::None,745            None => CiEnv::current(),746        };747        let dwn_ctx = DownloadContext {748            path_modification_cache: path_modification_cache.clone(),749            src: &src,750            submodules: &build_submodules,751            host_target,752            patch_binaries_for_nix: build_patch_binaries_for_nix,753            exec_ctx: &exec_ctx,754            stage0_metadata: &stage0_metadata,755            llvm_assertions,756            bootstrap_cache_path: &build_bootstrap_cache_path,757            ci_env,758        };759760        let initial_rustc = build_rustc.unwrap_or_else(|| {761            download_beta_toolchain(&dwn_ctx, &out);762            default_stage0_rustc_path(&out)763        });764765        let initial_rustdoc = build_rustdoc766            .unwrap_or_else(|| initial_rustc.with_file_name(exe("rustdoc", host_target)));767768        let initial_sysroot = t!(PathBuf::from_str(769            command(&initial_rustc)770                .args(["--print", "sysroot"])771                .run_in_dry_run()772                .run_capture_stdout(&exec_ctx)773                .stdout()774                .trim()775        ));776777        let initial_cargo = build_cargo.unwrap_or_else(|| {778            download_beta_toolchain(&dwn_ctx, &out);779            initial_sysroot.join("bin").join(exe("cargo", host_target))780        });781782        // NOTE: it's important this comes *after* we set `initial_rustc` just above.783        if exec_ctx.dry_run() {784            out = out.join("tmp-dry-run");785            fs::create_dir_all(&out).expect("Failed to create dry-run directory");786        }787788        let file_content = t!(fs::read_to_string(src.join("src/ci/channel")));789        let ci_channel = file_content.trim_end();790791        let is_user_configured_rust_channel = match rust_channel {792            Some(channel_) if channel_ == "auto-detect" => {793                channel = ci_channel.into();794                true795            }796            Some(channel_) => {797                channel = channel_;798                true799            }800            None => false,801        };802803        let omit_git_hash = rust_omit_git_hash.unwrap_or(channel == "dev");804805        let rust_info = git_info(&exec_ctx, omit_git_hash, &src);806807        if !is_user_configured_rust_channel && rust_info.is_from_tarball() {808            channel = ci_channel.into();809        }810811        // FIXME(#133381): alt rustc builds currently do *not* have rustc debug assertions812        // enabled. We should not download a CI alt rustc if we need rustc to have debug813        // assertions (e.g. for crashes test suite). This can be changed once something like814        // [Enable debug assertions on alt815        // builds](https://github.com/rust-lang/rust/pull/131077) lands.816        //817        // Note that `rust.debug = true` currently implies `rust.debug-assertions = true`!818        //819        // This relies also on the fact that the global default for `download-rustc` will be820        // `false` if it's not explicitly set.821        let debug_assertions_requested = matches!(rust_rustc_debug_assertions, Some(true))822            || (matches!(rust_debug, Some(true))823                && !matches!(rust_rustc_debug_assertions, Some(false)));824825        if debug_assertions_requested826            && let Some(ref opt) = rust_download_rustc827            && opt.is_string_or_true()828        {829            eprintln!(830                "WARN: currently no CI rustc builds have rustc debug assertions \831                        enabled. Please either set `rust.debug-assertions` to `false` if you \832                        want to use download CI rustc or set `rust.download-rustc` to `false`."833            );834        }835836        let mut download_rustc_commit =837            download_ci_rustc_commit(&dwn_ctx, &rust_info, rust_download_rustc, llvm_assertions);838839        if debug_assertions_requested && download_rustc_commit.is_some() {840            eprintln!(841                "WARN: `rust.debug-assertions = true` will prevent downloading CI rustc as alt CI \842                rustc is not currently built with debug assertions."843            );844            // We need to put this later down_ci_rustc_commit.845            download_rustc_commit = None;846        }847848        // We need to override `rust.channel` if it's manually specified when using the CI rustc.849        // This is because if the compiler uses a different channel than the one specified in bootstrap.toml,850        // tests may fail due to using a different channel than the one used by the compiler during tests.851        if let Some(commit) = &download_rustc_commit852            && is_user_configured_rust_channel853        {854            println!(855                "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."856            );857858            channel =859                read_file_by_commit(&dwn_ctx, &rust_info, Path::new("src/ci/channel"), commit)860                    .trim()861                    .to_owned();862        }863864        if build_npm.is_some() {865            println!(866                "WARNING: `build.npm` set in bootstrap.toml, this option no longer has any effect. . Use `build.yarn` instead to provide a path to a `yarn` binary."867            );868        }869870        let mut lld_enabled = rust_lld_enabled.unwrap_or(false);871872        // Linux targets for which the user explicitly overrode the used linker873        let mut targets_with_user_linker_override = HashSet::new();874875        if let Some(t) = toml.target {876            for (triple, cfg) in t {877                let TomlTarget {878                    cc: target_cc,879                    cxx: target_cxx,880                    ar: target_ar,881                    ranlib: target_ranlib,882                    default_linker: target_default_linker,883                    default_linker_linux_override: target_default_linker_linux_override,884                    linker: target_linker,885                    split_debuginfo: target_split_debuginfo,886                    llvm_config: target_llvm_config,887                    llvm_has_rust_patches: target_llvm_has_rust_patches,888                    llvm_filecheck: target_llvm_filecheck,889                    llvm_libunwind: target_llvm_libunwind,890                    sanitizers: target_sanitizers,891                    profiler: target_profiler,892                    rpath: target_rpath,893                    rustflags: target_rustflags,894                    crt_static: target_crt_static,895                    musl_root: target_musl_root,896                    musl_libdir: target_musl_libdir,897                    wasi_root: target_wasi_root,898                    qemu_rootfs: target_qemu_rootfs,899                    no_std: target_no_std,900                    codegen_backends: target_codegen_backends,901                    runner: target_runner,902                    optimized_compiler_builtins: target_optimized_compiler_builtins,903                    jemalloc: target_jemalloc,904                } = cfg;905906                let mut target = Target::from_triple(&triple);907908                if target_default_linker_linux_override.is_some() {909                    targets_with_user_linker_override.insert(triple.clone());910                }911912                let default_linker_linux_override = match target_default_linker_linux_override {913                    Some(DefaultLinuxLinkerOverride::SelfContainedLldCc) => {914                        if rust_default_linker.is_some() {915                            panic!(916                                "cannot set both `default-linker` and `default-linker-linux` for target `{triple}`"917                            );918                        }919                        if !triple.contains("linux-gnu") {920                            panic!(921                                "`default-linker-linux` can only be set for Linux GNU targets, not for `{triple}`"922                            );923                        }924                        if !lld_enabled {925                            panic!(926                                "Trying to override the default Linux linker for `{triple}` to be self-contained LLD, but LLD is not being built. Enable it with rust.lld = true."927                            );928                        }929                        DefaultLinuxLinkerOverride::SelfContainedLldCc930                    }931                    Some(DefaultLinuxLinkerOverride::Off) => DefaultLinuxLinkerOverride::Off,932                    None => DefaultLinuxLinkerOverride::default(),933                };934935                if let Some(ref s) = target_llvm_config {936                    if download_rustc_commit.is_some() && triple == *host_target.triple {937                        panic!(938                            "setting llvm_config for the host is incompatible with download-rustc"939                        );940                    }941                    target.llvm_config = Some(src.join(s));942                }943                if let Some(patches) = target_llvm_has_rust_patches {944                    assert!(945                        build_submodules == Some(false) || target_llvm_config.is_some(),946                        "use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"947                    );948                    target.llvm_has_rust_patches = Some(patches);949                }950                if let Some(ref s) = target_llvm_filecheck {951                    target.llvm_filecheck = Some(src.join(s));952                }953                target.llvm_libunwind = target_llvm_libunwind.as_ref().map(|v| {954                    v.parse().unwrap_or_else(|_| {955                        panic!("failed to parse target.{triple}.llvm-libunwind")956                    })957                });958                if let Some(s) = target_no_std {959                    target.no_std = s;960                }961                target.cc = target_cc.map(PathBuf::from);962                target.cxx = target_cxx.map(PathBuf::from);963                target.ar = target_ar.map(PathBuf::from);964                target.ranlib = target_ranlib.map(PathBuf::from);965                target.linker = target_linker.map(PathBuf::from);966                target.crt_static = target_crt_static;967                target.default_linker = target_default_linker;968                target.default_linker_linux_override = default_linker_linux_override;969                target.musl_root = target_musl_root.map(PathBuf::from);970                target.musl_libdir = target_musl_libdir.map(PathBuf::from);971                target.wasi_root = target_wasi_root.map(PathBuf::from);972                target.qemu_rootfs = target_qemu_rootfs.map(PathBuf::from);973                target.runner = target_runner;974                target.sanitizers = target_sanitizers;975                target.profiler = target_profiler;976                target.rpath = target_rpath;977                target.rustflags = target_rustflags.unwrap_or_default();978                target.optimized_compiler_builtins = target_optimized_compiler_builtins;979                target.jemalloc = target_jemalloc;980                if let Some(backends) = target_codegen_backends {981                    target.codegen_backends =982                        Some(parse_codegen_backends(backends, &format!("target.{triple}")))983                }984985                target.split_debuginfo = target_split_debuginfo.as_ref().map(|v| {986                    v.parse().unwrap_or_else(|_| {987                        panic!("invalid value for target.{triple}.split-debuginfo")988                    })989                });990991                target_config.insert(TargetSelection::from_user(&triple), target);992            }993        }994995        let llvm_from_ci = parse_download_ci_llvm(996            &dwn_ctx,997            &rust_info,998            &download_rustc_commit,999            llvm_download_ci_llvm,1000            llvm_assertions,1001        );1002        let is_host_system_llvm =1003            is_system_llvm(&target_config, llvm_from_ci, host_target, host_target);10041005        if llvm_from_ci {1006            let warn = |option: &str| {1007                println!(1008                    "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."1009                );1010                println!(1011                    "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."1012                );1013            };10141015            if llvm_static_libstdcpp.is_some() {1016                warn("static-libstdcpp");1017            }10181019            if llvm_link_shared.is_some() {1020                warn("link-shared");1021            }10221023            // FIXME(#129153): instead of all the ad-hoc `download-ci-llvm` checks that follow,1024            // use the `builder-config` present in tarballs since #128822 to compare the local1025            // config to the ones used to build the LLVM artifacts on CI, and only notify users1026            // if they've chosen a different value.10271028            if llvm_libzstd.is_some() {1029                println!(1030                    "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \1031                    like almost all `llvm.*` options, will be ignored and set by the LLVM CI \1032                    artifacts builder config."1033                );1034                println!(1035                    "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."1036                );1037            }1038        }10391040        if llvm_from_ci {1041            let triple = &host_target.triple;1042            let ci_llvm_bin = ci_llvm_root(&dwn_ctx, llvm_from_ci, &out).join("bin");1043            let build_target =1044                target_config.entry(host_target).or_insert_with(|| Target::from_triple(triple));1045            check_ci_llvm!(build_target.llvm_config);1046            check_ci_llvm!(build_target.llvm_filecheck);1047            build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", host_target)));1048            build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", host_target)));1049        }10501051        for (target, linker_override) in default_linux_linker_overrides() {1052            // If the user overrode the default Linux linker, do not apply bootstrap defaults1053            if targets_with_user_linker_override.contains(&target) {1054                continue;1055            }10561057            // The rust.lld option is global, and not target specific, so if we enable it, it will1058            // be applied to all targets being built.1059            // So we only apply an override if we're building a compiler/host code for the given1060            // override target.1061            // Note: we could also make the LLD config per-target, but that would complicate things1062            if !hosts.contains(&TargetSelection::from_user(&target)) {1063                continue;1064            }10651066            let default_linux_linker_override = match linker_override {1067                DefaultLinuxLinkerOverride::Off => continue,1068                DefaultLinuxLinkerOverride::SelfContainedLldCc => {1069                    // If we automatically default to the self-contained LLD linker,1070                    // we also need to handle the rust.lld option.1071                    match rust_lld_enabled {1072                        // If LLD was not enabled explicitly, we enable it, unless LLVM config has1073                        // been set1074                        None if !is_host_system_llvm => {1075                            lld_enabled = true;1076                            Some(DefaultLinuxLinkerOverride::SelfContainedLldCc)1077                        }1078                        None => None,1079                        // If it was enabled already, we don't need to do anything1080                        Some(true) => Some(DefaultLinuxLinkerOverride::SelfContainedLldCc),1081                        // If it was explicitly disabled, we do not apply the1082                        // linker override1083                        Some(false) => None,1084                    }1085                }1086            };1087            if let Some(linker_override) = default_linux_linker_override {1088                target_config1089                    .entry(TargetSelection::from_user(&target))1090                    .or_default()1091                    .default_linker_linux_override = linker_override;1092            }1093        }10941095        let initial_rustfmt = build_rustfmt.or_else(|| maybe_download_rustfmt(&dwn_ctx, &out));10961097        if matches!(bootstrap_override_lld, BootstrapOverrideLld::SelfContained)1098            && !lld_enabled1099            && flags_stage.unwrap_or(0) > 01100        {1101            panic!(1102                "Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true."1103            );1104        }11051106        if lld_enabled && is_host_system_llvm {1107            panic!("Cannot enable LLD with `rust.lld = true` when using external llvm-config.");1108        }11091110        let download_rustc = download_rustc_commit.is_some();11111112        let stage = match flags_cmd {1113            Subcommand::Check { .. } => flags_stage.or(build_check_stage).unwrap_or(1),1114            Subcommand::Clippy { .. } | Subcommand::Fix => {1115                flags_stage.or(build_check_stage).unwrap_or(1)1116            }1117            // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden.1118            Subcommand::Doc { .. } => {1119                flags_stage.or(build_doc_stage).unwrap_or(if download_rustc { 2 } else { 1 })1120            }1121            Subcommand::Build { .. } => {1122                flags_stage.or(build_build_stage).unwrap_or(if download_rustc { 2 } else { 1 })1123            }1124            Subcommand::Test { .. } | Subcommand::Miri { .. } => {1125                flags_stage.or(build_test_stage).unwrap_or(if download_rustc { 2 } else { 1 })1126            }1127            Subcommand::Bench { .. } => flags_stage.or(build_bench_stage).unwrap_or(2),1128            Subcommand::Dist => flags_stage.or(build_dist_stage).unwrap_or(2),1129            Subcommand::Install => flags_stage.or(build_install_stage).unwrap_or(2),1130            Subcommand::Perf { .. } => flags_stage.unwrap_or(1),1131            // Most of the run commands execute bootstrap tools, which don't depend on the compiler.1132            // Other commands listed here should always use bootstrap tools.1133            Subcommand::Clean { .. }1134            | Subcommand::Run { .. }1135            | Subcommand::Setup { .. }1136            | Subcommand::Format { .. }1137            | Subcommand::Vendor { .. } => flags_stage.unwrap_or(0),1138        };11391140        let local_rebuild = build_local_rebuild.unwrap_or(false);11411142        let check_stage0 = |kind: &str| {1143            if local_rebuild {1144                eprintln!("WARNING: running {kind} in stage 0. This might not work as expected.");1145            } else {1146                eprintln!(1147                    "ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources."1148                );1149                exit!(1);1150            }1151        };11521153        // Now check that the selected stage makes sense, and if not, print an error and end1154        match (stage, &flags_cmd) {1155            (0, Subcommand::Build { .. }) => {1156                check_stage0("build");1157            }1158            (0, Subcommand::Check { .. }) => {1159                check_stage0("check");1160            }1161            (0, Subcommand::Doc { .. }) => {1162                check_stage0("doc");1163            }1164            (0, Subcommand::Clippy { .. }) => {1165                check_stage0("clippy");1166            }1167            (0, Subcommand::Dist) => {1168                check_stage0("dist");1169            }1170            (0, Subcommand::Install) => {1171                check_stage0("install");1172            }1173            (0, Subcommand::Test { .. }) if build_compiletest_allow_stage0 != Some(true) => {1174                eprintln!(1175                    "ERROR: cannot test anything on stage 0. Use at least stage 1. If you want to run compiletest with an external stage0 toolchain, enable `build.compiletest-allow-stage0`."1176                );1177                exit!(1);1178            }1179            _ => {}1180        }11811182        if flags_compile_time_deps && !matches!(flags_cmd, Subcommand::Check { .. }) {1183            eprintln!("ERROR: Can't use --compile-time-deps with any subcommand other than check.");1184            exit!(1);1185        }11861187        if matches!(flags_cmd, Subcommand::Fix) {1188            eprintln!(1189                "WARNING: `x fix` is provided on a best-effort basis and does not support all `cargo fix` options correctly."1190            );1191        }11921193        // CI should always run stage 2 builds, unless it specifically states otherwise1194        #[cfg(not(test))]1195        if flags_stage.is_none() && ci_env.is_running_in_ci() {1196            match flags_cmd {1197                Subcommand::Test { .. }1198                | Subcommand::Miri { .. }1199                | Subcommand::Doc { .. }1200                | Subcommand::Build { .. }1201                | Subcommand::Bench { .. }1202                | Subcommand::Dist1203                | Subcommand::Install => {1204                    assert_eq!(1205                        stage, 2,1206                        "x.py should be run with `--stage 2` on CI, but was run with `--stage {stage}`",1207                    );1208                }1209                Subcommand::Clean { .. }1210                | Subcommand::Check { .. }1211                | Subcommand::Clippy { .. }1212                | Subcommand::Fix1213                | Subcommand::Run { .. }1214                | Subcommand::Setup { .. }1215                | Subcommand::Format { .. }1216                | Subcommand::Vendor { .. }1217                | Subcommand::Perf { .. } => {}1218            }1219        }12201221        let with_defaults = |debuginfo_level_specific: Option<_>| {1222            debuginfo_level_specific.or(rust_debuginfo_level).unwrap_or(1223                if rust_debug == Some(true) {1224                    DebuginfoLevel::Limited1225                } else {1226                    DebuginfoLevel::None1227                },1228            )1229        };12301231        let ccache = match build_ccache {1232            Some(StringOrBool::String(s)) => Some(s),1233            Some(StringOrBool::Bool(true)) => Some("ccache".to_string()),1234            _ => None,1235        };12361237        let explicit_stage_from_config = build_test_stage.is_some()1238            || build_build_stage.is_some()1239            || build_doc_stage.is_some()1240            || build_dist_stage.is_some()1241            || build_install_stage.is_some()1242            || build_check_stage.is_some()1243            || build_bench_stage.is_some();12441245        let deny_warnings = match flags_warnings {1246            Warnings::Deny => true,1247            Warnings::Warn => false,1248            Warnings::Default => rust_deny_warnings.unwrap_or(true),1249        };12501251        let gcc_ci_mode = match gcc_download_ci_gcc {1252            Some(value) => match value {1253                true => GccCiMode::DownloadFromCi,1254                false => GccCiMode::BuildLocally,1255            },1256            None => GccCiMode::default(),1257        };12581259        let targets = flags_target1260            .map(|TargetSelectionList(targets)| targets)1261            .or_else(|| {1262                build_target.map(|t| t.iter().map(|t| TargetSelection::from_user(t)).collect())1263            })1264            .unwrap_or_else(|| hosts.clone());12651266        #[allow(clippy::map_identity)]1267        let skip = flags_skip1268            .into_iter()1269            .chain(flags_exclude)1270            .chain(build_exclude.unwrap_or_default())1271            .map(|p| {1272                // Never return top-level path here as it would break `--skip`1273                // logic on rustc's internal test framework which is utilized by compiletest.1274                #[cfg(windows)]1275                {1276                    PathBuf::from(p.to_string_lossy().replace('/', "\\"))1277                }1278                #[cfg(not(windows))]1279                {1280                    p1281                }1282            })1283            .collect();12841285        let cargo_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/cargo"));1286        let clippy_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/clippy"));1287        let in_tree_gcc_info = git_info(&exec_ctx, false, &src.join("src/gcc"));1288        let in_tree_llvm_info = git_info(&exec_ctx, false, &src.join("src/llvm-project"));1289        let enzyme_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/enzyme"));1290        let miri_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/miri"));1291        let rust_analyzer_info =1292            git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rust-analyzer"));1293        let rustfmt_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rustfmt"));12941295        let optimized_compiler_builtins =1296            build_optimized_compiler_builtins.unwrap_or(if channel == "dev" {1297                CompilerBuiltins::BuildRustOnly1298            } else {1299                CompilerBuiltins::BuildLLVMFuncs1300            });1301        let vendor = build_vendor.unwrap_or(1302            rust_info.is_from_tarball()1303                && src.join("vendor").exists()1304                && src.join(".cargo/config.toml").exists(),1305        );1306        let verbose_tests = rust_verbose_tests.unwrap_or(exec_ctx.is_verbose());13071308        Config {1309            // tidy-alphabetical-start1310            android_ndk: build_android_ndk,1311            backtrace: rust_backtrace.unwrap_or(true),1312            backtrace_on_ice: rust_backtrace_on_ice.unwrap_or(false),1313            bindir: install_bindir.map(PathBuf::from).unwrap_or("bin".into()),1314            bootstrap_cache_path: build_bootstrap_cache_path,1315            bootstrap_override_lld,1316            bypass_bootstrap_lock: flags_bypass_bootstrap_lock,1317            cargo_info,1318            cargo_native_static: build_cargo_native_static.unwrap_or(false),1319            ccache,1320            change_id: toml.change_id.inner,1321            channel,1322            ci_env,1323            clippy_info,1324            cmd: flags_cmd,1325            codegen_tests: rust_codegen_tests.unwrap_or(true),1326            color: flags_color,1327            compile_time_deps: flags_compile_time_deps,1328            compiler_docs: build_compiler_docs.unwrap_or(false),1329            compiletest_allow_stage0: build_compiletest_allow_stage0.unwrap_or(false),1330            compiletest_diff_tool: build_compiletest_diff_tool,1331            config: toml_path,1332            configure_args: build_configure_args.unwrap_or_default(),1333            control_flow_guard: rust_control_flow_guard.unwrap_or(false),1334            datadir: install_datadir.map(PathBuf::from),1335            deny_warnings,1336            description: build_description,1337            dist_compression_formats,1338            dist_compression_profile: dist_compression_profile.unwrap_or("fast".into()),1339            dist_include_mingw_linker: dist_include_mingw_linker.unwrap_or(true),1340            dist_sign_folder: dist_sign_folder.map(PathBuf::from),1341            dist_upload_addr,1342            dist_vendor: dist_vendor.unwrap_or_else(|| {1343                // If we're building from git or tarball sources, enable it by default.1344                rust_info.is_managed_git_subrepository() || rust_info.is_from_tarball()1345            }),1346            docdir: install_docdir.map(PathBuf::from),1347            docs: build_docs.unwrap_or(true),1348            docs_minification: build_docs_minification.unwrap_or(true),1349            download_rustc_commit,1350            dump_bootstrap_shims: flags_dump_bootstrap_shims,1351            ehcont_guard: rust_ehcont_guard.unwrap_or(false),1352            enable_bolt_settings: flags_enable_bolt_settings,1353            enzyme_info,1354            exec_ctx,1355            explicit_stage_from_cli: flags_stage.is_some(),1356            explicit_stage_from_config,1357            extended: build_extended.unwrap_or(false),1358            free_args: flags_free_args,1359            full_bootstrap: build_full_bootstrap.unwrap_or(false),1360            gcc_ci_mode,1361            gdb: build_gdb.map(PathBuf::from),1362            host_target,1363            hosts,1364            in_tree_gcc_info,1365            in_tree_llvm_info,1366            include_default_paths: flags_include_default_paths,1367            incremental: flags_incremental || rust_incremental == Some(true),1368            initial_cargo,1369            initial_cargo_clippy: build_cargo_clippy,1370            initial_rustc,1371            initial_rustdoc,1372            initial_rustfmt,1373            initial_sysroot,1374            jemalloc: rust_jemalloc.unwrap_or(false),1375            jobs: Some(threads_from_config(flags_jobs.or(build_jobs).unwrap_or(0))),1376            json_output: flags_json_output,1377            keep_stage: flags_keep_stage,1378            keep_stage_std: flags_keep_stage_std,1379            libdir: install_libdir.map(PathBuf::from),1380            libgccjit_libs_dir: gcc_libgccjit_libs_dir,1381            library_docs_private_items: build_library_docs_private_items.unwrap_or(false),1382            lld_enabled,1383            lldb: build_lldb.map(PathBuf::from),1384            llvm_allow_old_toolchain: llvm_allow_old_toolchain.unwrap_or(false),1385            llvm_assertions,1386            llvm_bitcode_linker_enabled: rust_llvm_bitcode_linker.unwrap_or(false),1387            llvm_build_config: llvm_build_config.clone().unwrap_or(Default::default()),1388            llvm_cflags,1389            llvm_clang: llvm_clang.unwrap_or(false),1390            llvm_clang_cl,1391            llvm_clang_dir: llvm_clang_dir.map(PathBuf::from),1392            llvm_cxxflags,1393            llvm_enable_warnings: llvm_enable_warnings.unwrap_or(false),1394            llvm_enzyme: llvm_enzyme.unwrap_or(false),1395            llvm_experimental_targets,1396            llvm_from_ci,1397            llvm_ldflags,1398            llvm_libunwind_default: rust_llvm_libunwind1399                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")),1400            llvm_libzstd: llvm_libzstd.unwrap_or(false),1401            llvm_link_jobs,1402            // If we're building with ThinLTO on, by default we want to link1403            // to LLVM shared, to avoid re-doing ThinLTO (which happens in1404            // the link step) with each stage.1405            llvm_link_shared: Cell::new(1406                llvm_link_shared1407                    .or((!llvm_from_ci && llvm_thin_lto.unwrap_or(false)).then_some(true)),1408            ),1409            llvm_offload: llvm_offload.unwrap_or(false),1410            llvm_optimize: llvm_optimize.unwrap_or(true),1411            llvm_plugins: llvm_plugin.unwrap_or(false),1412            llvm_polly: llvm_polly.unwrap_or(false),1413            llvm_profile_generate: flags_llvm_profile_generate,1414            llvm_profile_use: flags_llvm_profile_use,1415            llvm_release_debuginfo: llvm_release_debuginfo.unwrap_or(false),1416            llvm_static_stdcpp: llvm_static_libstdcpp.unwrap_or(false),1417            llvm_targets,1418            llvm_tests: llvm_tests.unwrap_or(false),1419            llvm_thin_lto: llvm_thin_lto.unwrap_or(false),1420            llvm_tools_enabled: rust_llvm_tools.unwrap_or(true),1421            llvm_use_libcxx: llvm_use_libcxx.unwrap_or(false),1422            llvm_use_linker,1423            llvm_version_suffix,1424            local_rebuild,1425            locked_deps: build_locked_deps.unwrap_or(false),1426            low_priority: build_low_priority.unwrap_or(false),1427            mandir: install_mandir.map(PathBuf::from),1428            miri_info,1429            musl_root: rust_musl_root.map(PathBuf::from),1430            ninja_in_file: llvm_ninja.unwrap_or(true),1431            nodejs: build_nodejs.map(PathBuf::from),1432            omit_git_hash,1433            on_fail: flags_on_fail,1434            optimized_compiler_builtins,1435            out,1436            patch_binaries_for_nix: build_patch_binaries_for_nix,1437            path_modification_cache,1438            paths: flags_paths,1439            prefix: install_prefix.map(PathBuf::from),1440            print_step_rusage: build_print_step_rusage.unwrap_or(false),1441            print_step_timings: build_print_step_timings.unwrap_or(false),1442            profiler: build_profiler.unwrap_or(false),1443            python: build_python.map(PathBuf::from),1444            quiet: flags_quiet,1445            reproducible_artifacts: flags_reproducible_artifact,1446            reuse: build_reuse.map(PathBuf::from),1447            rust_analyzer_info,1448            rust_annotate_moves_size_limit,1449            rust_break_on_ice: rust_break_on_ice.unwrap_or(true),1450            rust_codegen_backends: rust_codegen_backends1451                .map(|backends| parse_codegen_backends(backends, "rust"))1452                .unwrap_or(vec![CodegenBackendKind::Llvm]),1453            rust_codegen_units: rust_codegen_units.map(threads_from_config),1454            rust_codegen_units_std: rust_codegen_units_std.map(threads_from_config),1455            rust_debug_logging: rust_debug_logging1456                .or(rust_rustc_debug_assertions)1457                .unwrap_or(rust_debug == Some(true)),1458            rust_debuginfo_level_rustc: with_defaults(rust_debuginfo_level_rustc),1459            rust_debuginfo_level_std: with_defaults(rust_debuginfo_level_std),1460            rust_debuginfo_level_tests: rust_debuginfo_level_tests.unwrap_or(DebuginfoLevel::None),1461            rust_debuginfo_level_tools: with_defaults(rust_debuginfo_level_tools),1462            rust_dist_src: dist_src_tarball.unwrap_or_else(|| rust_dist_src.unwrap_or(true)),1463            rust_frame_pointers: rust_frame_pointers.unwrap_or(false),1464            rust_info,1465            rust_lto: rust_lto1466                .as_deref()1467                .map(|value| RustcLto::from_str(value).unwrap())1468                .unwrap_or_default(),1469            rust_new_symbol_mangling,1470            rust_optimize: rust_optimize.unwrap_or(RustOptimize::Bool(true)),1471            rust_optimize_tests: rust_optimize_tests.unwrap_or(true),1472            rust_overflow_checks: rust_overflow_checks.unwrap_or(rust_debug == Some(true)),1473            rust_overflow_checks_std: rust_overflow_checks_std1474                .or(rust_overflow_checks)1475                .unwrap_or(rust_debug == Some(true)),1476            rust_parallel_frontend_threads: rust_parallel_frontend_threads.map(threads_from_config),1477            rust_profile_generate: flags_rust_profile_generate.or(rust_profile_generate),1478            rust_profile_use: flags_rust_profile_use.or(rust_profile_use),1479            rust_randomize_layout: rust_randomize_layout.unwrap_or(false),1480            rust_remap_debuginfo: rust_remap_debuginfo.unwrap_or(false),1481            rust_rpath: rust_rpath.unwrap_or(true),1482            rust_rustflags: rust_rustflags.unwrap_or_default(),1483            rust_stack_protector,1484            rust_std_features: rust_std_features1485                .unwrap_or(BTreeSet::from([String::from("panic-unwind")])),1486            rust_strip: rust_strip.unwrap_or(false),1487            rust_thin_lto_import_instr_limit,1488            rust_validate_mir_opts,1489            rust_verify_llvm_ir: rust_verify_llvm_ir.unwrap_or(false),1490            rustc_debug_assertions: rust_rustc_debug_assertions.unwrap_or(rust_debug == Some(true)),1491            rustc_default_linker: rust_default_linker,1492            rustc_error_format: flags_rustc_error_format,1493            rustfmt_info,1494            sanitizers: build_sanitizers.unwrap_or(false),1495            save_toolstates: rust_save_toolstates.map(PathBuf::from),1496            skip,1497            skip_std_check_if_no_download_rustc: flags_skip_std_check_if_no_download_rustc,1498            src,1499            stage,1500            stage0_metadata,1501            std_debug_assertions: rust_std_debug_assertions1502                .or(rust_rustc_debug_assertions)1503                .unwrap_or(rust_debug == Some(true)),1504            stderr_is_tty: std::io::stderr().is_terminal(),1505            stdout_is_tty: std::io::stdout().is_terminal(),1506            submodules: build_submodules,1507            sysconfdir: install_sysconfdir.map(PathBuf::from),1508            target_config,1509            targets,1510            test_compare_mode: rust_test_compare_mode.unwrap_or(false),1511            tidy_extra_checks: build_tidy_extra_checks,1512            tool: build_tool.unwrap_or_default(),1513            tools: build_tools,1514            tools_debug_assertions: rust_tools_debug_assertions1515                .or(rust_rustc_debug_assertions)1516                .unwrap_or(rust_debug == Some(true)),1517            vendor,1518            verbose_tests,1519            windows_rc: build_windows_rc.map(PathBuf::from),1520            yarn: build_yarn.map(PathBuf::from),1521            // tidy-alphabetical-end1522        }1523    }15241525    pub fn dry_run(&self) -> bool {1526        self.exec_ctx.dry_run()1527    }15281529    pub fn is_running_on_ci(&self) -> bool {1530        self.ci_env.is_running_in_ci()1531    }15321533    pub fn is_explicit_stage(&self) -> bool {1534        self.explicit_stage_from_cli || self.explicit_stage_from_config1535    }15361537    pub(crate) fn test_args(&self) -> Vec<&str> {1538        let mut test_args = match self.cmd {1539            Subcommand::Test { ref test_args, .. }1540            | Subcommand::Bench { ref test_args, .. }1541            | Subcommand::Miri { ref test_args, .. } => {1542                test_args.iter().flat_map(|s| s.split_whitespace()).collect()1543            }1544            _ => vec![],1545        };1546        test_args.extend(self.free_args.iter().map(|s| s.as_str()));1547        test_args1548    }15491550    pub(crate) fn args(&self) -> Vec<&str> {1551        let mut args = match self.cmd {1552            Subcommand::Run { ref args, .. } => {1553                args.iter().flat_map(|s| s.split_whitespace()).collect()1554            }1555            _ => vec![],1556        };1557        args.extend(self.free_args.iter().map(|s| s.as_str()));1558        args1559    }15601561    /// Returns the content of the given file at a specific commit.1562    pub(crate) fn read_file_by_commit(&self, file: &Path, commit: &str) -> String {1563        let dwn_ctx = DownloadContext::from(self);1564        read_file_by_commit(dwn_ctx, &self.rust_info, file, commit)1565    }15661567    /// Bootstrap embeds a version number into the name of shared libraries it uploads in CI.1568    /// Return the version it would have used for the given commit.1569    pub(crate) fn artifact_version_part(&self, commit: &str) -> String {1570        let (channel, version) = if self.rust_info.is_managed_git_subrepository() {1571            let channel =1572                self.read_file_by_commit(Path::new("src/ci/channel"), commit).trim().to_owned();1573            let version =1574                self.read_file_by_commit(Path::new("src/version"), commit).trim().to_owned();1575            (channel, version)1576        } else {1577            let channel = fs::read_to_string(self.src.join("src/ci/channel"));1578            let version = fs::read_to_string(self.src.join("src/version"));1579            match (channel, version) {1580                (Ok(channel), Ok(version)) => {1581                    (channel.trim().to_owned(), version.trim().to_owned())1582                }1583                (channel, version) => {1584                    let src = self.src.display();1585                    eprintln!("ERROR: failed to determine artifact channel and/or version");1586                    eprintln!(1587                        "HELP: consider using a git checkout or ensure these files are readable"1588                    );1589                    if let Err(channel) = channel {1590                        eprintln!("reading {src}/src/ci/channel failed: {channel:?}");1591                    }1592                    if let Err(version) = version {1593                        eprintln!("reading {src}/src/version failed: {version:?}");1594                    }1595                    panic!();1596                }1597            }1598        };15991600        match channel.as_str() {1601            "stable" => version,1602            "beta" => channel,1603            "nightly" => channel,1604            other => unreachable!("{:?} is not recognized as a valid channel", other),1605        }1606    }16071608    /// Try to find the relative path of `bindir`, otherwise return it in full.1609    pub fn bindir_relative(&self) -> &Path {1610        let bindir = &self.bindir;1611        if bindir.is_absolute() {1612            // Try to make it relative to the prefix.1613            if let Some(prefix) = &self.prefix1614                && let Ok(stripped) = bindir.strip_prefix(prefix)1615            {1616                return stripped;1617            }1618        }1619        bindir1620    }16211622    /// Try to find the relative path of `libdir`.1623    pub fn libdir_relative(&self) -> Option<&Path> {1624        let libdir = self.libdir.as_ref()?;1625        if libdir.is_relative() {1626            Some(libdir)1627        } else {1628            // Try to make it relative to the prefix.1629            libdir.strip_prefix(self.prefix.as_ref()?).ok()1630        }1631    }16321633    /// The absolute path to the downloaded LLVM artifacts.1634    pub(crate) fn ci_llvm_root(&self) -> PathBuf {1635        let dwn_ctx = DownloadContext::from(self);1636        ci_llvm_root(dwn_ctx, self.llvm_from_ci, &self.out)1637    }16381639    /// Directory where the extracted `rustc-dev` component is stored.1640    pub(crate) fn ci_rustc_dir(&self) -> PathBuf {1641        assert!(self.download_rustc());1642        self.out.join(self.host_target).join("ci-rustc")1643    }16441645    /// Determine whether llvm should be linked dynamically.1646    ///1647    /// If `false`, llvm should be linked statically.1648    /// This is computed on demand since LLVM might have to first be downloaded from CI.1649    pub(crate) fn llvm_link_shared(&self) -> bool {1650        let mut opt = self.llvm_link_shared.get();1651        if opt.is_none() && self.dry_run() {1652            // just assume static for now - dynamic linking isn't supported on all platforms1653            return false;1654        }16551656        let llvm_link_shared = *opt.get_or_insert_with(|| {1657            if self.llvm_from_ci {1658                self.maybe_download_ci_llvm();1659                let ci_llvm = self.ci_llvm_root();1660                let link_type = t!(1661                    std::fs::read_to_string(ci_llvm.join("link-type.txt")),1662                    format!("CI llvm missing: {}", ci_llvm.display())1663                );1664                link_type == "dynamic"1665            } else {1666                // unclear how thought-through this default is, but it maintains compatibility with1667                // previous behavior1668                false1669            }1670        });1671        self.llvm_link_shared.set(opt);1672        llvm_link_shared1673    }16741675    /// Return whether we will use a downloaded, pre-compiled version of rustc, or just build from source.1676    pub(crate) fn download_rustc(&self) -> bool {1677        self.download_rustc_commit().is_some()1678    }16791680    pub(crate) fn download_rustc_commit(&self) -> Option<&str> {1681        static DOWNLOAD_RUSTC: OnceLock<Option<String>> = OnceLock::new();1682        if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() {1683            // avoid trying to actually download the commit1684            return self.download_rustc_commit.as_deref();1685        }16861687        DOWNLOAD_RUSTC1688            .get_or_init(|| match &self.download_rustc_commit {1689                None => None,1690                Some(commit) => {1691                    self.download_ci_rustc(commit);16921693                    // CI-rustc can't be used without CI-LLVM. If `self.llvm_from_ci` is false, it means the "if-unchanged"1694                    // logic has detected some changes in the LLVM submodule (download-ci-llvm=false can't happen here as1695                    // we don't allow it while parsing the configuration).1696                    if !self.llvm_from_ci {1697                        // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error1698                        // to not break CI. For non-CI environments, we should return an error.1699                        if self.is_running_on_ci() {1700                            println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");1701                            return None;1702                        } else {1703                            panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");1704                        }1705                    }17061707                    if let Some(config_path) = &self.config {1708                        let ci_config_toml = match self.get_builder_toml("ci-rustc") {1709                            Ok(ci_config_toml) => ci_config_toml,1710                            Err(e) if e.to_string().contains("unknown field") => {1711                                println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");1712                                println!("HELP: Consider rebasing to a newer commit if available.");1713                                return None;1714                            }1715                            Err(e) => {1716                                eprintln!("ERROR: Failed to parse CI rustc bootstrap.toml: {e}");1717                                exit!(2);1718                            }1719                        };17201721                        let current_config_toml = Self::get_toml(config_path).unwrap();17221723                        // Check the config compatibility1724                        // FIXME: this doesn't cover `--set` flags yet.1725                        let res = check_incompatible_options_for_ci_rustc(1726                            self.host_target,1727                            current_config_toml,1728                            ci_config_toml,1729                        );17301731                        // Primarily used by CI runners to avoid handling download-rustc incompatible1732                        // options one by one on shell scripts.1733                        let disable_ci_rustc_if_incompatible = env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")1734                            .is_some_and(|s| s == "1" || s == "true");17351736                        if disable_ci_rustc_if_incompatible && res.is_err() {1737                            println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");1738                            return None;1739                        }17401741                        res.unwrap();1742                    }17431744                    Some(commit.clone())1745                }1746            })1747            .as_deref()1748    }17491750    /// Runs a function if verbosity is greater than 01751    pub fn do_if_verbose(&self, f: impl Fn()) {1752        self.exec_ctx.do_if_verbose(f);1753    }17541755    pub fn any_sanitizers_to_build(&self) -> bool {1756        self.target_config1757            .iter()1758            .any(|(ts, t)| !ts.is_msvc() && t.sanitizers.unwrap_or(self.sanitizers))1759    }17601761    pub fn any_profiler_enabled(&self) -> bool {1762        self.target_config.values().any(|t| matches!(&t.profiler, Some(p) if p.is_string_or_true()))1763            || self.profiler1764    }17651766    /// Returns whether or not submodules should be managed by bootstrap.1767    pub fn submodules(&self) -> bool {1768        // If not specified in config, the default is to only manage1769        // submodules if we're currently inside a git repository.1770        self.submodules.unwrap_or(self.rust_info.is_managed_git_subrepository())1771    }17721773    pub fn git_config(&self) -> GitConfig<'_> {1774        GitConfig {1775            nightly_branch: &self.stage0_metadata.config.nightly_branch,1776            git_merge_commit_email: &self.stage0_metadata.config.git_merge_commit_email,1777        }1778    }17791780    /// Given a path to the directory of a submodule, update it.1781    ///1782    /// `relative_path` should be relative to the root of the git repository, not an absolute path.1783    ///1784    /// This *does not* update the submodule if `bootstrap.toml` explicitly says1785    /// not to, or if we're not in a git repository (like a plain source1786    /// tarball). Typically [`crate::Build::require_submodule`] should be1787    /// used instead to provide a nice error to the user if the submodule is1788    /// missing.1789    #[cfg_attr(1790        feature = "tracing",1791        instrument(1792            level = "trace",1793            name = "Config::update_submodule",1794            skip_all,1795            fields(relative_path = ?relative_path),1796        ),1797    )]1798    pub(crate) fn update_submodule(&self, relative_path: &str) {1799        let dwn_ctx = DownloadContext::from(self);1800        update_submodule(dwn_ctx, &self.rust_info, relative_path);1801    }18021803    /// Returns true if any of the `paths` have been modified locally.1804    pub fn has_changes_from_upstream(&self, paths: &[&'static str]) -> bool {1805        let dwn_ctx = DownloadContext::from(self);1806        has_changes_from_upstream(dwn_ctx, paths)1807    }18081809    /// Checks whether any of the given paths have been modified w.r.t. upstream.1810    pub fn check_path_modifications(&self, paths: &[&'static str]) -> PathFreshness {1811        // Checking path modifications through git can be relatively expensive (>100ms).1812        // We do not assume that the sources would change during bootstrap's execution,1813        // so we can cache the results here.1814        // Note that we do not use a static variable for the cache, because it would cause problems1815        // in tests that create separate `Config` instances.1816        self.path_modification_cache1817            .lock()1818            .unwrap()1819            .entry(paths.to_vec())1820            .or_insert_with(|| {1821                check_path_modifications(&self.src, &self.git_config(), paths, self.ci_env).unwrap()1822            })1823            .clone()1824    }18251826    pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool {1827        self.target_config.get(&target).and_then(|t| t.sanitizers).unwrap_or(self.sanitizers)1828    }18291830    pub fn needs_sanitizer_runtime_built(&self, target: TargetSelection) -> bool {1831        // MSVC uses the Microsoft-provided sanitizer runtime, but all other runtimes we build.1832        !target.is_msvc() && self.sanitizers_enabled(target)1833    }18341835    pub fn profiler_path(&self, target: TargetSelection) -> Option<&str> {1836        match self.target_config.get(&target)?.profiler.as_ref()? {1837            StringOrBool::String(s) => Some(s),1838            StringOrBool::Bool(_) => None,1839        }1840    }18411842    pub fn profiler_enabled(&self, target: TargetSelection) -> bool {1843        self.target_config1844            .get(&target)1845            .and_then(|t| t.profiler.as_ref())1846            .map(StringOrBool::is_string_or_true)1847            .unwrap_or(self.profiler)1848    }18491850    /// Returns codegen backends that should be:1851    /// - Built and added to the sysroot when we build the compiler.1852    /// - Distributed when `x dist` is executed (if the codegen backend has a dist step).1853    pub fn enabled_codegen_backends(&self, target: TargetSelection) -> &[CodegenBackendKind] {1854        self.target_config1855            .get(&target)1856            .and_then(|cfg| cfg.codegen_backends.as_deref())1857            .unwrap_or(&self.rust_codegen_backends)1858    }18591860    /// Returns the codegen backend that should be configured as the *default* codegen backend1861    /// for a rustc compiled by bootstrap.1862    pub fn default_codegen_backend(&self, target: TargetSelection) -> &CodegenBackendKind {1863        // We're guaranteed to have always at least one codegen backend listed.1864        self.enabled_codegen_backends(target).first().unwrap()1865    }18661867    pub fn jemalloc(&self, target: TargetSelection) -> bool {1868        self.target_config.get(&target).and_then(|cfg| cfg.jemalloc).unwrap_or(self.jemalloc)1869    }18701871    pub fn rpath_enabled(&self, target: TargetSelection) -> bool {1872        self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)1873    }18741875    pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> &CompilerBuiltins {1876        self.target_config1877            .get(&target)1878            .and_then(|t| t.optimized_compiler_builtins.as_ref())1879            .unwrap_or(&self.optimized_compiler_builtins)1880    }18811882    pub fn llvm_enabled(&self, target: TargetSelection) -> bool {1883        self.enabled_codegen_backends(target).contains(&CodegenBackendKind::Llvm)1884    }18851886    pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {1887        self.target_config1888            .get(&target)1889            .and_then(|t| t.llvm_libunwind)1890            .or(self.llvm_libunwind_default)1891            .unwrap_or(1892                if target.contains("fuchsia")1893                    || (target.contains("hexagon") && !target.contains("qurt"))1894                {1895                    // Fuchsia and Hexagon Linux use in-tree llvm-libunwind.1896                    // Hexagon QuRT uses libc_eh from the Hexagon SDK instead.1897                    LlvmLibunwind::InTree1898                } else {1899                    LlvmLibunwind::No1900                },1901            )1902    }19031904    pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {1905        self.target_config1906            .get(&target)1907            .and_then(|t| t.split_debuginfo)1908            .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))1909    }19101911    /// Checks if the given target is the same as the host target.1912    pub fn is_host_target(&self, target: TargetSelection) -> bool {1913        self.host_target == target1914    }19151916    /// Returns `true` if this is an external version of LLVM not managed by bootstrap.1917    /// In particular, we expect llvm sources to be available when this is false.1918    ///1919    /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set.1920    pub fn is_system_llvm(&self, target: TargetSelection) -> bool {1921        is_system_llvm(&self.target_config, self.llvm_from_ci, self.host_target, target)1922    }19231924    /// Returns `true` if this is our custom, patched, version of LLVM.1925    ///1926    /// This does not necessarily imply that we're managing the `llvm-project` submodule.1927    pub fn is_rust_llvm(&self, target: TargetSelection) -> bool {1928        match self.target_config.get(&target) {1929            // We're using a user-controlled version of LLVM. The user has explicitly told us whether the version has our patches.1930            // (They might be wrong, but that's not a supported use-case.)1931            // In particular, this tries to support `submodules = false` and `patches = false`, for using a newer version of LLVM that's not through `rust-lang/llvm-project`.1932            Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched,1933            // The user hasn't promised the patches match.1934            // This only has our patches if it's downloaded from CI or built from source.1935            _ => !self.is_system_llvm(target),1936        }1937    }19381939    pub fn exec_ctx(&self) -> &ExecutionContext {1940        &self.exec_ctx1941    }19421943    pub fn git_info(&self, omit_git_hash: bool, dir: &Path) -> GitInfo {1944        GitInfo::new(omit_git_hash, dir, self)1945    }1946}19471948impl AsRef<ExecutionContext> for Config {1949    fn as_ref(&self) -> &ExecutionContext {1950        &self.exec_ctx1951    }1952}19531954fn compute_src_directory(src_dir: Option<PathBuf>, exec_ctx: &ExecutionContext) -> Option<PathBuf> {1955    if let Some(src) = src_dir {1956        return Some(src);1957    } else {1958        // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,1959        // running on a completely different machine from where it was compiled.1960        let mut cmd = helpers::git(None);1961        // NOTE: we cannot support running from outside the repository because the only other path we have available1962        // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.1963        // We still support running outside the repository if we find we aren't in a git directory.19641965        // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,1966        // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap1967        // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.1968        cmd.arg("rev-parse").arg("--show-cdup");1969        // Discard stderr because we expect this to fail when building from a tarball.1970        let output = cmd.allow_failure().run_capture_stdout(exec_ctx);1971        if output.is_success() {1972            let git_root_relative = output.stdout();1973            // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,1974            // and to resolve any relative components.1975            let git_root = env::current_dir()1976                .unwrap()1977                .join(PathBuf::from(git_root_relative.trim()))1978                .canonicalize()1979                .unwrap();1980            let s = git_root.to_str().unwrap();19811982            // Bootstrap is quite bad at handling /? in front of paths1983            let git_root = match s.strip_prefix("\\\\?\\") {1984                Some(p) => PathBuf::from(p),1985                None => git_root,1986            };1987            // If this doesn't have at least `stage0`, we guessed wrong. This can happen when,1988            // for example, the build directory is inside of another unrelated git directory.1989            // In that case keep the original `CARGO_MANIFEST_DIR` handling.1990            //1991            // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside1992            // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.1993            if git_root.join("src").join("stage0").exists() {1994                return Some(git_root);1995            }1996        } else {1997            // We're building from a tarball, not git sources.1998            // We don't support pre-downloaded bootstrap in this case.1999        }2000    };

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.