Change:
} } <ins> #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct LibcxxVersionTool { pub target: TargetSelection, } #[allow(dead_code)] #[derive(Debug, Clone)] pub enum LibcxxVersion { Gnu(usize), Llvm(usize), } impl Step for LibcxxVersionTool { type Output = LibcxxVersion; const DEFAULT: bool = false; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() } fn run(self, builder: &Builder<'_>) -> LibcxxVersion { let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version"); let _ = fs::remove_dir_all(&out_dir); t!(fs::create_dir_all(&out_dir)); let compiler = builder.cxx(self.target).unwrap(); let mut cmd = Command::new(compiler); let executable = out_dir.join("libcxx-version"); cmd.arg("-o").arg(&executable).arg(builder.src.join("src/tools/libcxx-version/main.cpp")); builder.run_cmd(&mut cmd); if !executable.exists() { panic!("Something went wrong. {} is not present", executable.display()); } let version_output = output(&mut Command::new(executable)); let version_str = version_output.split_once("version:").unwrap().1; let version = version_str.trim().parse::<usize>().unwrap(); if version_output.starts_with("libstdc++") { LibcxxVersion::Gnu(version) } else if version_output.starts_with("libc++") { LibcxxVersion::Llvm(version) } else { panic!("Coudln't recognize the standard library version."); } } } </ins> macro_rules! tool_extended { (($sel:ident, $builder:ident), $($name:ident,

Discussion:
Spawned off of I'm not 100% sure what would be involved in such a check here, but it seems like a good thing to investigate, because the nature of the resulting bootstrap failures is super frustrating. (I'll admit, I don't know if the right thing would be to hard error out of all uses of download-ci-llvm for potentially-incompatible libstdc++, or only to hard error out for defaulting uses... but a warning seems warranted in any such cases.
I guess the problem here is that we're compiling the locally and linking that against the downloaded toolchain. A check like suggested here makes sense to me in the meantime, but I suppose long-term the "right" fix here is to get rid of any C++ code we need to separately compile by upstreaming C bindings into LLVM proper, and then we can just call those on the Rust side without any ABI issues. (FWIW, I was initially confused since we explicitly statically link in the stdcpp in the distributed I guess maybe we could also fix this by skipping linking to a local stdcpp while compiling the Rust wrapper code? Not sure if that works out.)
This is the particular line which leads to failure with download-ci-llvm when there is an ABI mismatch. In my experiment removing it resulted in linking errors on rustcdriver. I agree, this solves the problem completely without applying hacks (in my opinion, there is no simple or clean way of comparing ABI or libstd versions) on bootstrap. Maybe, for now, we should just print a warning when downloading ci llvm?
You mean always print a warning? I don't think that's a good idea, it's noisy and we generally expect that people are happy using download CI LLVM. I don't think a warning is helpful here if we can't scope it down to where it matters (in which case it can probably be an error).
Not always, only once while downloading it.
I think that falls in the same "not particularly helpful" case. Most users will miss the message, and even if they don't it's not clear how they should respond. I at least don't know how to check whether my machine has everything setup right. If we could check then we could limit the warning, in which case I'm broadly in favor of making it perhaps even a hard error.