@@ -16,7 +16,8 @@ use std::path::PathBuf;
1616use std:: process:: Command ;
1717use walkdir:: WalkDir ;
1818
19- use crate :: builder:: Kind ;
19+ use crate :: core:: build_steps:: tool;
20+ use crate :: builder:: { Kind , Builder } ;
2021use crate :: core:: config:: Target ;
2122use crate :: utils:: helpers:: output;
2223use crate :: Build ;
@@ -35,6 +36,10 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[
3536 // just a dummy comment so the list doesn't get onelined
3637] ;
3738
39+ /// Minimum version threshold for libstdc++ required when using prebuilt LLVM
40+ /// from CI (with`llvm.download-ci-llvm` option).
41+ const LIBSTDCXX_MIN_VERSION_THRESHOLD : usize = 8 ;
42+
3843impl Finder {
3944 pub fn new ( ) -> Self {
4045 Self { cache : HashMap :: new ( ) , path : env:: var_os ( "PATH" ) . unwrap_or_default ( ) }
@@ -99,6 +104,35 @@ pub fn check(build: &mut Build) {
99104 cmd_finder. must_have ( "git" ) ;
100105 }
101106
107+ // Ensure that a compatible version of libstdc++ is available on the system when using `llvm.download-ci-llvm`.
108+ if !build. config . dry_run ( ) && build. config . llvm_from_ci {
109+ let builder = Builder :: new ( build) ;
110+ let libcxx_version = builder. ensure ( tool:: LibcxxVersionTool { target : build. build } ) ;
111+
112+ match libcxx_version {
113+ tool:: LibcxxVersion :: Gnu ( version) => {
114+ if LIBSTDCXX_MIN_VERSION_THRESHOLD > version {
115+ eprintln ! (
116+ "\n Your system's libstdc++ version is too old for the `llvm.download-ci-llvm` option."
117+ ) ;
118+ eprintln ! ( "Current version detected: '{}'" , version) ;
119+ eprintln ! ( "Minimum required version: '{}'" , LIBSTDCXX_MIN_VERSION_THRESHOLD ) ;
120+ eprintln ! (
121+ "Consider upgrading libstdc++ or disabling the `llvm.download-ci-llvm` option."
122+ ) ;
123+ crate :: exit!( 1 ) ;
124+ }
125+ }
126+ tool:: LibcxxVersion :: Llvm ( _) => {
127+ eprintln ! (
128+ "\n Your system is using libc++, which is incompatible with the `llvm.download-ci-llvm` option."
129+ ) ;
130+ eprintln ! ( "Disable `llvm.download-ci-llvm` or switch to libstdc++." ) ;
131+ crate :: exit!( 1 ) ;
132+ }
133+ }
134+ }
135+
102136 // We need cmake, but only if we're actually building LLVM or sanitizers.
103137 let building_llvm = build
104138 . hosts
@@ -199,11 +233,15 @@ than building it.
199233 if ![ "A-A" , "B-B" , "C-C" ] . contains ( & target_str. as_str ( ) ) {
200234 let mut has_target = false ;
201235
202- let missing_targets_hashset: HashSet < _ > = STAGE0_MISSING_TARGETS . iter ( ) . map ( |t| t. to_string ( ) ) . collect ( ) ;
203- let duplicated_targets: Vec < _ > = stage0_supported_target_list. intersection ( & missing_targets_hashset) . collect ( ) ;
236+ let missing_targets_hashset: HashSet < _ > =
237+ STAGE0_MISSING_TARGETS . iter ( ) . map ( |t| t. to_string ( ) ) . collect ( ) ;
238+ let duplicated_targets: Vec < _ > =
239+ stage0_supported_target_list. intersection ( & missing_targets_hashset) . collect ( ) ;
204240
205241 if !duplicated_targets. is_empty ( ) {
206- println ! ( "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list." ) ;
242+ println ! (
243+ "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
244+ ) ;
207245 for duplicated_target in duplicated_targets {
208246 println ! ( " {duplicated_target}" ) ;
209247 }
0 commit comments