Skip to main content

bootstrap/core/config/toml/
target.rs

1//! This module defines the structures and logic for handling target-specific configuration
2//! within the `bootstrap.toml` file. This allows you to customize build settings, tools,
3//! and flags for individual compilation targets.
4//!
5//! It includes:
6//!
7//! * [`TomlTarget`]: This struct directly mirrors the `[target.<triple>]` sections in your
8//!   `bootstrap.toml`. It's used for deserializing raw TOML data for a specific target.
9//! * [`Target`]: This struct represents the processed and validated configuration for a
10//!   build target, which is is stored in the main `Config` structure.
11
12use std::collections::HashMap;
13
14use serde::de::Error;
15use serde::{Deserialize, Deserializer};
16
17use crate::core::config::{
18    CompilerBuiltins, CompressDebuginfo, LlvmLibunwind, Merge, OverrideAllocator, ReplaceOpt,
19    SplitDebuginfo, StringOrBool,
20};
21use crate::{CodegenBackendKind, HashSet, PathBuf, define_config, exit};
22
23define_config! {
24    /// TOML representation of how each build target is configured.
25    struct TomlTarget {
26        cc: Option<String> = "cc",
27        cxx: Option<String> = "cxx",
28        ar: Option<String> = "ar",
29        ranlib: Option<String> = "ranlib",
30        default_linker: Option<PathBuf> = "default-linker",
31        default_linker_linux_override: Option<DefaultLinuxLinkerOverride> = "default-linker-linux-override",
32        linker: Option<String> = "linker",
33        split_debuginfo: Option<String> = "split-debuginfo",
34        llvm_config: Option<String> = "llvm-config",
35        llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
36        llvm_filecheck: Option<String> = "llvm-filecheck",
37        llvm_libunwind: Option<String> = "llvm-libunwind",
38        sanitizers: Option<bool> = "sanitizers",
39        profiler: Option<StringOrBool> = "profiler",
40        rpath: Option<bool> = "rpath",
41        rustflags: Option<Vec<String>> = "rustflags",
42        crt_static: Option<bool> = "crt-static",
43        musl_root: Option<String> = "musl-root",
44        musl_libdir: Option<String> = "musl-libdir",
45        wasi_root: Option<String> = "wasi-root",
46        qemu_rootfs: Option<String> = "qemu-rootfs",
47        no_std: Option<bool> = "no-std",
48        codegen_backends: Option<Vec<String>> = "codegen-backends",
49        runner: Option<String> = "runner",
50        optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
51        override_allocator: Option<OverrideAllocator> = "override-allocator",
52        jemalloc: Option<bool> = "jemalloc",
53    }
54}
55
56/// Per-target configuration stored in the global configuration structure.
57#[derive(Debug, Default, Clone, PartialEq, Eq)]
58pub struct Target {
59    /// Some(path to llvm-config) if using an external LLVM.
60    pub llvm_config: Option<PathBuf>,
61    pub llvm_has_rust_patches: Option<bool>,
62    /// Some(path to FileCheck) if one was specified.
63    pub llvm_filecheck: Option<PathBuf>,
64    pub llvm_libunwind: Option<LlvmLibunwind>,
65    pub cc: Option<PathBuf>,
66    pub cxx: Option<PathBuf>,
67    pub ar: Option<PathBuf>,
68    pub ranlib: Option<PathBuf>,
69    pub default_linker: Option<PathBuf>,
70    pub default_linker_linux_override: DefaultLinuxLinkerOverride,
71    pub linker: Option<PathBuf>,
72    pub split_debuginfo: Option<SplitDebuginfo>,
73    pub compress_debuginfo: Option<CompressDebuginfo>,
74    pub sanitizers: Option<bool>,
75    pub profiler: Option<StringOrBool>,
76    pub rpath: Option<bool>,
77    pub rustflags: Vec<String>,
78    pub crt_static: Option<bool>,
79    pub musl_root: Option<PathBuf>,
80    pub musl_libdir: Option<PathBuf>,
81    pub wasi_root: Option<PathBuf>,
82    pub qemu_rootfs: Option<PathBuf>,
83    pub runner: Option<String>,
84    pub no_std: bool,
85    pub codegen_backends: Option<Vec<CodegenBackendKind>>,
86    pub optimized_compiler_builtins: Option<CompilerBuiltins>,
87    pub override_allocator: Option<OverrideAllocator>,
88}
89
90impl Target {
91    pub fn from_triple(triple: &str) -> Self {
92        let mut target: Self = Default::default();
93        if !build_helper::targets::target_supports_std(triple) {
94            target.no_std = true;
95        }
96        if triple.contains("emscripten") {
97            target.runner = Some("node".into());
98        }
99        target
100    }
101}
102
103/// Overrides the default linker used on a Linux target.
104/// On Linux, the linker is usually invoked through `cc`, therefore this exists as a separate
105/// configuration from simply setting `default-linker`, which corresponds to `-Clinker`.
106#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
107pub enum DefaultLinuxLinkerOverride {
108    /// Do not apply any override and use the default linker for the given target.
109    #[default]
110    Off,
111    /// Use the self-contained `rust-lld` linker, invoked through `cc`.
112    /// Corresponds to `-Clinker-features=+lld -Clink-self-contained=+linker`.
113    SelfContainedLldCc,
114}
115
116impl<'de> Deserialize<'de> for DefaultLinuxLinkerOverride {
117    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118    where
119        D: Deserializer<'de>,
120    {
121        let name = String::deserialize(deserializer)?;
122        match name.as_str() {
123            "off" => Ok(Self::Off),
124            "self-contained-lld-cc" => Ok(Self::SelfContainedLldCc),
125            other => Err(D::Error::unknown_variant(other, &["off", "self-contained-lld-cc"])),
126        }
127    }
128}
129
130/// Set of linker overrides for selected Linux targets.
131#[cfg(not(test))]
132pub fn default_linux_linker_overrides() -> HashMap<String, DefaultLinuxLinkerOverride> {
133    [("x86_64-unknown-linux-gnu".to_string(), DefaultLinuxLinkerOverride::SelfContainedLldCc)]
134        .into()
135}
136
137#[cfg(test)]
138thread_local! {
139    static TEST_LINUX_LINKER_OVERRIDES: std::cell::RefCell<Option<HashMap<String, DefaultLinuxLinkerOverride>>> = std::cell::RefCell::new(None);
140}
141
142#[cfg(test)]
143pub fn default_linux_linker_overrides() -> HashMap<String, DefaultLinuxLinkerOverride> {
144    TEST_LINUX_LINKER_OVERRIDES.with(|cell| cell.borrow().clone()).unwrap_or_default()
145}
146
147#[cfg(test)]
148pub fn with_default_linux_linker_overrides<R>(
149    targets: HashMap<String, DefaultLinuxLinkerOverride>,
150    f: impl FnOnce() -> R,
151) -> R {
152    TEST_LINUX_LINKER_OVERRIDES.with(|cell| {
153        let prev = cell.replace(Some(targets));
154        let result = f();
155        cell.replace(prev);
156        result
157    })
158}