bootstrap/core/config/toml/
target.rs1use std::collections::HashMap;
16
17use serde::{Deserialize, Deserializer};
18
19use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
20use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool};
21use crate::{Config, HashSet, PathBuf, TargetSelection, define_config, exit};
22
23define_config! {
24 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 linker: Option<String> = "linker",
32 split_debuginfo: Option<String> = "split-debuginfo",
33 llvm_config: Option<String> = "llvm-config",
34 llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
35 llvm_filecheck: Option<String> = "llvm-filecheck",
36 llvm_libunwind: Option<String> = "llvm-libunwind",
37 sanitizers: Option<bool> = "sanitizers",
38 profiler: Option<StringOrBool> = "profiler",
39 rpath: Option<bool> = "rpath",
40 crt_static: Option<bool> = "crt-static",
41 musl_root: Option<String> = "musl-root",
42 musl_libdir: Option<String> = "musl-libdir",
43 wasi_root: Option<String> = "wasi-root",
44 qemu_rootfs: Option<String> = "qemu-rootfs",
45 no_std: Option<bool> = "no-std",
46 codegen_backends: Option<Vec<String>> = "codegen-backends",
47 runner: Option<String> = "runner",
48 optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
49 jemalloc: Option<bool> = "jemalloc",
50 }
51}
52
53#[derive(Debug, Default, Clone, PartialEq, Eq)]
55pub struct Target {
56 pub llvm_config: Option<PathBuf>,
58 pub llvm_has_rust_patches: Option<bool>,
59 pub llvm_filecheck: Option<PathBuf>,
61 pub llvm_libunwind: Option<LlvmLibunwind>,
62 pub cc: Option<PathBuf>,
63 pub cxx: Option<PathBuf>,
64 pub ar: Option<PathBuf>,
65 pub ranlib: Option<PathBuf>,
66 pub default_linker: Option<PathBuf>,
67 pub linker: Option<PathBuf>,
68 pub split_debuginfo: Option<SplitDebuginfo>,
69 pub sanitizers: Option<bool>,
70 pub profiler: Option<StringOrBool>,
71 pub rpath: Option<bool>,
72 pub crt_static: Option<bool>,
73 pub musl_root: Option<PathBuf>,
74 pub musl_libdir: Option<PathBuf>,
75 pub wasi_root: Option<PathBuf>,
76 pub qemu_rootfs: Option<PathBuf>,
77 pub runner: Option<String>,
78 pub no_std: bool,
79 pub codegen_backends: Option<Vec<String>>,
80 pub optimized_compiler_builtins: Option<bool>,
81 pub jemalloc: Option<bool>,
82}
83
84impl Target {
85 pub fn from_triple(triple: &str) -> Self {
86 let mut target: Self = Default::default();
87 if !build_helper::targets::target_supports_std(triple) {
88 target.no_std = true;
89 }
90 if triple.contains("emscripten") {
91 target.runner = Some("node".into());
92 }
93 target
94 }
95}
96
97impl Config {
98 pub fn apply_target_config(&mut self, toml_target: Option<HashMap<String, TomlTarget>>) {
99 if let Some(t) = toml_target {
100 for (triple, cfg) in t {
101 let mut target = Target::from_triple(&triple);
102
103 if let Some(ref s) = cfg.llvm_config {
104 if self.download_rustc_commit.is_some() && triple == *self.host_target.triple {
105 panic!(
106 "setting llvm_config for the host is incompatible with download-rustc"
107 );
108 }
109 target.llvm_config = Some(self.src.join(s));
110 }
111 if let Some(patches) = cfg.llvm_has_rust_patches {
112 assert!(
113 self.submodules == Some(false) || cfg.llvm_config.is_some(),
114 "use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
115 );
116 target.llvm_has_rust_patches = Some(patches);
117 }
118 if let Some(ref s) = cfg.llvm_filecheck {
119 target.llvm_filecheck = Some(self.src.join(s));
120 }
121 target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| {
122 v.parse().unwrap_or_else(|_| {
123 panic!("failed to parse target.{triple}.llvm-libunwind")
124 })
125 });
126 if let Some(s) = cfg.no_std {
127 target.no_std = s;
128 }
129 target.cc = cfg.cc.map(PathBuf::from);
130 target.cxx = cfg.cxx.map(PathBuf::from);
131 target.ar = cfg.ar.map(PathBuf::from);
132 target.ranlib = cfg.ranlib.map(PathBuf::from);
133 target.linker = cfg.linker.map(PathBuf::from);
134 target.crt_static = cfg.crt_static;
135 target.musl_root = cfg.musl_root.map(PathBuf::from);
136 target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
137 target.wasi_root = cfg.wasi_root.map(PathBuf::from);
138 target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
139 target.runner = cfg.runner;
140 target.sanitizers = cfg.sanitizers;
141 target.profiler = cfg.profiler;
142 target.rpath = cfg.rpath;
143 target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
144 target.jemalloc = cfg.jemalloc;
145
146 if let Some(ref backends) = cfg.codegen_backends {
147 let available_backends = ["llvm", "cranelift", "gcc"];
148
149 target.codegen_backends = Some(backends.iter().map(|s| {
150 if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) {
151 if available_backends.contains(&backend) {
152 panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
153 } else {
154 println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
155 Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
156 In this case, it would be referred to as '{backend}'.");
157 }
158 }
159
160 s.clone()
161 }).collect());
162 }
163
164 target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| {
165 v.parse().unwrap_or_else(|_| {
166 panic!("invalid value for target.{triple}.split-debuginfo")
167 })
168 });
169
170 self.target_config.insert(TargetSelection::from_user(&triple), target);
171 }
172 }
173 }
174}