bootstrap/core/config/toml/
llvm.rs1use serde::{Deserialize, Deserializer};
5
6use crate::core::config::toml::{Merge, ReplaceOpt, TomlConfig};
7use crate::core::config::{StringOrBool, set};
8use crate::{Config, HashMap, HashSet, PathBuf, define_config, exit};
9
10define_config! {
11 struct Llvm {
13 optimize: Option<bool> = "optimize",
14 thin_lto: Option<bool> = "thin-lto",
15 release_debuginfo: Option<bool> = "release-debuginfo",
16 assertions: Option<bool> = "assertions",
17 tests: Option<bool> = "tests",
18 enzyme: Option<bool> = "enzyme",
19 plugins: Option<bool> = "plugins",
20 ccache: Option<StringOrBool> = "ccache",
22 static_libstdcpp: Option<bool> = "static-libstdcpp",
23 libzstd: Option<bool> = "libzstd",
24 ninja: Option<bool> = "ninja",
25 targets: Option<String> = "targets",
26 experimental_targets: Option<String> = "experimental-targets",
27 link_jobs: Option<u32> = "link-jobs",
28 link_shared: Option<bool> = "link-shared",
29 version_suffix: Option<String> = "version-suffix",
30 clang_cl: Option<String> = "clang-cl",
31 cflags: Option<String> = "cflags",
32 cxxflags: Option<String> = "cxxflags",
33 ldflags: Option<String> = "ldflags",
34 use_libcxx: Option<bool> = "use-libcxx",
35 use_linker: Option<String> = "use-linker",
36 allow_old_toolchain: Option<bool> = "allow-old-toolchain",
37 offload: Option<bool> = "offload",
38 polly: Option<bool> = "polly",
39 clang: Option<bool> = "clang",
40 enable_warnings: Option<bool> = "enable-warnings",
41 download_ci_llvm: Option<StringOrBool> = "download-ci-llvm",
42 build_config: Option<HashMap<String, String>> = "build-config",
43 }
44}
45
46#[cfg(not(test))]
49pub fn check_incompatible_options_for_ci_llvm(
50 current_config_toml: TomlConfig,
51 ci_config_toml: TomlConfig,
52) -> Result<(), String> {
53 macro_rules! err {
54 ($current:expr, $expected:expr) => {
55 if let Some(current) = &$current {
56 if Some(current) != $expected.as_ref() {
57 return Err(format!(
58 "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \
59 Current value: {:?}, Expected value(s): {}{:?}",
60 stringify!($expected).replace("_", "-"),
61 $current,
62 if $expected.is_some() { "None/" } else { "" },
63 $expected,
64 ));
65 };
66 };
67 };
68 }
69
70 macro_rules! warn {
71 ($current:expr, $expected:expr) => {
72 if let Some(current) = &$current {
73 if Some(current) != $expected.as_ref() {
74 println!(
75 "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
76 Current value: {:?}, Expected value(s): {}{:?}",
77 stringify!($expected).replace("_", "-"),
78 $current,
79 if $expected.is_some() { "None/" } else { "" },
80 $expected,
81 );
82 };
83 };
84 };
85 }
86
87 let (Some(current_llvm_config), Some(ci_llvm_config)) =
88 (current_config_toml.llvm, ci_config_toml.llvm)
89 else {
90 return Ok(());
91 };
92
93 let Llvm {
94 optimize,
95 thin_lto,
96 release_debuginfo,
97 assertions: _,
98 tests: _,
99 plugins,
100 ccache: _,
101 static_libstdcpp: _,
102 libzstd,
103 ninja: _,
104 targets,
105 experimental_targets,
106 link_jobs: _,
107 link_shared: _,
108 version_suffix,
109 clang_cl,
110 cflags,
111 cxxflags,
112 ldflags,
113 use_libcxx,
114 use_linker,
115 allow_old_toolchain,
116 offload,
117 polly,
118 clang,
119 enable_warnings,
120 download_ci_llvm: _,
121 build_config,
122 enzyme,
123 } = ci_llvm_config;
124
125 err!(current_llvm_config.optimize, optimize);
126 err!(current_llvm_config.thin_lto, thin_lto);
127 err!(current_llvm_config.release_debuginfo, release_debuginfo);
128 err!(current_llvm_config.libzstd, libzstd);
129 err!(current_llvm_config.targets, targets);
130 err!(current_llvm_config.experimental_targets, experimental_targets);
131 err!(current_llvm_config.clang_cl, clang_cl);
132 err!(current_llvm_config.version_suffix, version_suffix);
133 err!(current_llvm_config.cflags, cflags);
134 err!(current_llvm_config.cxxflags, cxxflags);
135 err!(current_llvm_config.ldflags, ldflags);
136 err!(current_llvm_config.use_libcxx, use_libcxx);
137 err!(current_llvm_config.use_linker, use_linker);
138 err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain);
139 err!(current_llvm_config.offload, offload);
140 err!(current_llvm_config.polly, polly);
141 err!(current_llvm_config.clang, clang);
142 err!(current_llvm_config.build_config, build_config);
143 err!(current_llvm_config.plugins, plugins);
144 err!(current_llvm_config.enzyme, enzyme);
145
146 warn!(current_llvm_config.enable_warnings, enable_warnings);
147
148 Ok(())
149}
150
151impl Config {
152 pub fn apply_llvm_config(
153 &mut self,
154 toml_llvm: Option<Llvm>,
155 ccache: &mut Option<StringOrBool>,
156 ) {
157 let mut llvm_tests = None;
158 let mut llvm_enzyme = None;
159 let mut llvm_offload = None;
160 let mut llvm_plugins = None;
161
162 if let Some(llvm) = toml_llvm {
163 let Llvm {
164 optimize: optimize_toml,
165 thin_lto,
166 release_debuginfo,
167 assertions: _,
168 tests,
169 enzyme,
170 plugins,
171 ccache: llvm_ccache,
172 static_libstdcpp,
173 libzstd,
174 ninja,
175 targets,
176 experimental_targets,
177 link_jobs,
178 link_shared,
179 version_suffix,
180 clang_cl,
181 cflags,
182 cxxflags,
183 ldflags,
184 use_libcxx,
185 use_linker,
186 allow_old_toolchain,
187 offload,
188 polly,
189 clang,
190 enable_warnings,
191 download_ci_llvm,
192 build_config,
193 } = llvm;
194 if llvm_ccache.is_some() {
195 eprintln!("Warning: llvm.ccache is deprecated. Use build.ccache instead.");
196 }
197
198 if ccache.is_none() {
199 *ccache = llvm_ccache;
200 }
201 set(&mut self.ninja_in_file, ninja);
202 llvm_tests = tests;
203 llvm_enzyme = enzyme;
204 llvm_offload = offload;
205 llvm_plugins = plugins;
206 set(&mut self.llvm_optimize, optimize_toml);
207 set(&mut self.llvm_thin_lto, thin_lto);
208 set(&mut self.llvm_release_debuginfo, release_debuginfo);
209 set(&mut self.llvm_static_stdcpp, static_libstdcpp);
210 set(&mut self.llvm_libzstd, libzstd);
211 if let Some(v) = link_shared {
212 self.llvm_link_shared.set(Some(v));
213 }
214 self.llvm_targets.clone_from(&targets);
215 self.llvm_experimental_targets.clone_from(&experimental_targets);
216 self.llvm_link_jobs = link_jobs;
217 self.llvm_version_suffix.clone_from(&version_suffix);
218 self.llvm_clang_cl.clone_from(&clang_cl);
219
220 self.llvm_cflags.clone_from(&cflags);
221 self.llvm_cxxflags.clone_from(&cxxflags);
222 self.llvm_ldflags.clone_from(&ldflags);
223 set(&mut self.llvm_use_libcxx, use_libcxx);
224 self.llvm_use_linker.clone_from(&use_linker);
225 self.llvm_allow_old_toolchain = allow_old_toolchain.unwrap_or(false);
226 self.llvm_offload = offload.unwrap_or(false);
227 self.llvm_polly = polly.unwrap_or(false);
228 self.llvm_clang = clang.unwrap_or(false);
229 self.llvm_enable_warnings = enable_warnings.unwrap_or(false);
230 self.llvm_build_config = build_config.clone().unwrap_or(Default::default());
231
232 self.llvm_from_ci = self.parse_download_ci_llvm(download_ci_llvm, self.llvm_assertions);
233
234 if self.llvm_from_ci {
235 let warn = |option: &str| {
236 println!(
237 "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
238 );
239 println!(
240 "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
241 );
242 };
243
244 if static_libstdcpp.is_some() {
245 warn("static-libstdcpp");
246 }
247
248 if link_shared.is_some() {
249 warn("link-shared");
250 }
251
252 if libzstd.is_some() {
258 println!(
259 "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
260 like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
261 artifacts builder config."
262 );
263 println!(
264 "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
265 );
266 }
267 }
268
269 if !self.llvm_from_ci && self.llvm_thin_lto && link_shared.is_none() {
270 self.llvm_link_shared.set(Some(true));
274 }
275 } else {
276 self.llvm_from_ci = self.parse_download_ci_llvm(None, false);
277 }
278
279 self.llvm_tests = llvm_tests.unwrap_or(false);
280 self.llvm_enzyme = llvm_enzyme.unwrap_or(false);
281 self.llvm_offload = llvm_offload.unwrap_or(false);
282 self.llvm_plugins = llvm_plugins.unwrap_or(false);
283 }
284}