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}