Skip to main content

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 std::collections::HashMap;
5
6use serde::{Deserialize, Deserializer};
7
8use crate::core::config::StringOrBool;
9use crate::core::config::toml::{Merge, ReplaceOpt, TomlConfig};
10use crate::define_config;
11
12define_config! {
13    /// TOML representation of how the LLVM build is configured.
14    #[derive(Default)]
15    struct Llvm {
16        optimize: Option<bool> = "optimize",
17        thin_lto: Option<bool> = "thin-lto",
18        release_debuginfo: Option<bool> = "release-debuginfo",
19        assertions: Option<bool> = "assertions",
20        tests: Option<bool> = "tests",
21        enzyme: Option<bool> = "enzyme",
22        plugins: Option<bool> = "plugins",
23        static_libstdcpp: Option<bool> = "static-libstdcpp",
24        libzstd: Option<bool> = "libzstd",
25        ninja: Option<bool> = "ninja",
26        targets: Option<String> = "targets",
27        experimental_targets: Option<String> = "experimental-targets",
28        link_jobs: Option<u32> = "link-jobs",
29        link_shared: Option<bool> = "link-shared",
30        version_suffix: Option<String> = "version-suffix",
31        clang_cl: Option<String> = "clang-cl",
32        cflags: Option<String> = "cflags",
33        cxxflags: Option<String> = "cxxflags",
34        ldflags: Option<String> = "ldflags",
35        use_libcxx: Option<bool> = "use-libcxx",
36        use_linker: Option<String> = "use-linker",
37        allow_old_toolchain: Option<bool> = "allow-old-toolchain",
38        offload: Option<bool> = "offload",
39        polly: Option<bool> = "polly",
40        offload_clang_dir: Option<String> = "offload-clang-dir",
41        clang: Option<bool> = "clang",
42        enable_warnings: Option<bool> = "enable-warnings",
43        download_ci_llvm: Option<StringOrBool> = "download-ci-llvm",
44        build_config: Option<HashMap<String, String>> = "build-config",
45    }
46}
47
48/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
49/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing.
50pub fn check_incompatible_options_for_ci_llvm(
51    current_config_toml: TomlConfig,
52    ci_config_toml: TomlConfig,
53) -> Result<(), String> {
54    macro_rules! err {
55        ($current:expr, $expected:expr) => {
56            if let Some(current) = &$current {
57                if Some(current) != $expected.as_ref() {
58                    return Err(format!(
59                        "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \
60                        Current value: {:?}, Expected value(s): {}{:?}",
61                        stringify!($expected).replace("_", "-"),
62                        $current,
63                        if $expected.is_some() { "None/" } else { "" },
64                        $expected,
65                    ));
66                };
67            };
68        };
69    }
70
71    macro_rules! warn {
72        ($current:expr, $expected:expr) => {
73            if let Some(current) = &$current {
74                if Some(current) != $expected.as_ref() {
75                    println!(
76                        "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
77                        Current value: {:?}, Expected value(s): {}{:?}",
78                        stringify!($expected).replace("_", "-"),
79                        $current,
80                        if $expected.is_some() { "None/" } else { "" },
81                        $expected,
82                    );
83                };
84            };
85        };
86    }
87
88    let (Some(current_llvm_config), Some(ci_llvm_config)) =
89        (current_config_toml.llvm, ci_config_toml.llvm)
90    else {
91        return Ok(());
92    };
93
94    let Llvm {
95        optimize,
96        thin_lto,
97        release_debuginfo,
98        assertions: _,
99        tests: _,
100        plugins,
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        offload_clang_dir: _,
118        polly,
119        clang,
120        enable_warnings,
121        download_ci_llvm: _,
122        build_config,
123        enzyme,
124    } = ci_llvm_config;
125
126    err!(current_llvm_config.optimize, optimize);
127    err!(current_llvm_config.thin_lto, thin_lto);
128    err!(current_llvm_config.release_debuginfo, release_debuginfo);
129    err!(current_llvm_config.libzstd, libzstd);
130    err!(current_llvm_config.targets, targets);
131    err!(current_llvm_config.experimental_targets, experimental_targets);
132    err!(current_llvm_config.clang_cl, clang_cl);
133    err!(current_llvm_config.version_suffix, version_suffix);
134    err!(current_llvm_config.cflags, cflags);
135    err!(current_llvm_config.cxxflags, cxxflags);
136    err!(current_llvm_config.ldflags, ldflags);
137    err!(current_llvm_config.use_libcxx, use_libcxx);
138    err!(current_llvm_config.use_linker, use_linker);
139    err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain);
140    err!(current_llvm_config.offload, offload);
141    err!(current_llvm_config.polly, polly);
142    err!(current_llvm_config.clang, clang);
143    err!(current_llvm_config.build_config, build_config);
144    err!(current_llvm_config.plugins, plugins);
145    err!(current_llvm_config.enzyme, enzyme);
146
147    warn!(current_llvm_config.enable_warnings, enable_warnings);
148
149    Ok(())
150}