bootstrap/core/config/toml/
llvm.rs

1//! This module defines the `Llvm` struct, which represents the `[llvm]` table
2//! in the `bootstrap.toml` configuration file.
3
4use serde::{Deserialize, Deserializer};
5
6use crate::core::config::StringOrBool;
7use crate::core::config::toml::{Merge, ReplaceOpt, TomlConfig};
8use crate::{HashMap, HashSet, PathBuf, define_config, exit};
9
10define_config! {
11    /// TOML representation of how the LLVM build is configured.
12    #[derive(Default)]
13    struct Llvm {
14        optimize: Option<bool> = "optimize",
15        thin_lto: Option<bool> = "thin-lto",
16        release_debuginfo: Option<bool> = "release-debuginfo",
17        assertions: Option<bool> = "assertions",
18        tests: Option<bool> = "tests",
19        enzyme: Option<bool> = "enzyme",
20        plugins: Option<bool> = "plugins",
21        static_libstdcpp: Option<bool> = "static-libstdcpp",
22        libzstd: Option<bool> = "libzstd",
23        ninja: Option<bool> = "ninja",
24        targets: Option<String> = "targets",
25        experimental_targets: Option<String> = "experimental-targets",
26        link_jobs: Option<u32> = "link-jobs",
27        link_shared: Option<bool> = "link-shared",
28        version_suffix: Option<String> = "version-suffix",
29        clang_cl: Option<String> = "clang-cl",
30        cflags: Option<String> = "cflags",
31        cxxflags: Option<String> = "cxxflags",
32        ldflags: Option<String> = "ldflags",
33        use_libcxx: Option<bool> = "use-libcxx",
34        use_linker: Option<String> = "use-linker",
35        allow_old_toolchain: Option<bool> = "allow-old-toolchain",
36        offload: Option<bool> = "offload",
37        polly: Option<bool> = "polly",
38        offload_clang_dir: Option<String> = "offload-clang-dir",
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/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
47/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing.
48#[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        static_libstdcpp: _,
101        libzstd,
102        ninja: _,
103        targets,
104        experimental_targets,
105        link_jobs: _,
106        link_shared: _,
107        version_suffix,
108        clang_cl,
109        cflags,
110        cxxflags,
111        ldflags,
112        use_libcxx,
113        use_linker,
114        allow_old_toolchain,
115        offload,
116        offload_clang_dir: _,
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}