run_make_support/
linker.rs

1use regex::Regex;
2
3use crate::{Rustc, is_msvc};
4
5/// Asserts that `rustc` uses LLD for linking when executed.
6pub fn assert_rustc_uses_lld(rustc: &mut Rustc) {
7    let stderr = get_stderr_with_linker_messages(rustc);
8    assert!(
9        has_lld_version_in_logs(&stderr),
10        "LLD version should be present in rustc stderr:\n{stderr}"
11    );
12}
13
14/// Asserts that `rustc` doesn't use LLD for linking when executed.
15pub fn assert_rustc_doesnt_use_lld(rustc: &mut Rustc) {
16    let stderr = get_stderr_with_linker_messages(rustc);
17    assert!(
18        !has_lld_version_in_logs(&stderr),
19        "LLD version should NOT be present in rustc stderr:\n{stderr}"
20    );
21}
22
23fn get_stderr_with_linker_messages(rustc: &mut Rustc) -> String {
24    // lld-link is used if msvc, otherwise a gnu-compatible lld is used.
25    let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" };
26
27    let output = rustc.arg("-Wlinker-messages").link_arg(linker_version_flag).run();
28    output.stderr_utf8()
29}
30
31fn has_lld_version_in_logs(stderr: &str) -> bool {
32    // Strip the `-Wlinker-messages` wrappers prefixing the linker output.
33    let stderr = Regex::new(r"warning: linker std(out|err):").unwrap().replace_all(&stderr, "");
34    let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
35    stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
36}