@@ -24,9 +24,18 @@ use crate::util::get_clang_cl_resource_dir;
2424use crate :: util:: { self , exe, output, t, up_to_date} ;
2525use crate :: { CLang , GitRepo } ;
2626
27+ #[ derive( Clone ) ]
28+ pub struct LlvmResult {
29+ /// Path to llvm-config binary.
30+ /// NB: This is always the host llvm-config!
31+ pub llvm_config : PathBuf ,
32+ /// Path to LLVM cmake directory for the target.
33+ pub llvm_cmake_dir : PathBuf ,
34+ }
35+
2736pub struct Meta {
2837 stamp : HashStamp ,
29- build_llvm_config : PathBuf ,
38+ res : LlvmResult ,
3039 out_dir : PathBuf ,
3140 root : String ,
3241}
@@ -64,15 +73,22 @@ impl LdFlags {
6473pub fn prebuilt_llvm_config (
6574 builder : & Builder < ' _ > ,
6675 target : TargetSelection ,
67- ) -> Result < PathBuf , Meta > {
76+ ) -> Result < LlvmResult , Meta > {
6877 builder. config . maybe_download_ci_llvm ( ) ;
6978
7079 // If we're using a custom LLVM bail out here, but we can only use a
7180 // custom LLVM for the build triple.
7281 if let Some ( config) = builder. config . target_config . get ( & target) {
7382 if let Some ( ref s) = config. llvm_config {
7483 check_llvm_version ( builder, s) ;
75- return Ok ( s. to_path_buf ( ) ) ;
84+ let llvm_config = s. to_path_buf ( ) ;
85+ let mut llvm_cmake_dir = llvm_config. clone ( ) ;
86+ llvm_cmake_dir. pop ( ) ;
87+ llvm_cmake_dir. pop ( ) ;
88+ llvm_cmake_dir. push ( "lib" ) ;
89+ llvm_cmake_dir. push ( "cmake" ) ;
90+ llvm_cmake_dir. push ( "llvm" ) ;
91+ return Ok ( LlvmResult { llvm_config, llvm_cmake_dir } ) ;
7692 }
7793 }
7894
@@ -84,8 +100,9 @@ pub fn prebuilt_llvm_config(
84100 llvm_config_ret_dir. push ( "build" ) ;
85101 }
86102 llvm_config_ret_dir. push ( "bin" ) ;
87-
88103 let build_llvm_config = llvm_config_ret_dir. join ( exe ( "llvm-config" , builder. config . build ) ) ;
104+ let llvm_cmake_dir = out_dir. join ( "lib/cmake/llvm" ) ;
105+ let res = LlvmResult { llvm_config : build_llvm_config, llvm_cmake_dir } ;
89106
90107 let stamp = out_dir. join ( "llvm-finished-building" ) ;
91108 let stamp = HashStamp :: new ( stamp, builder. in_tree_llvm_info . sha ( ) ) ;
@@ -96,7 +113,7 @@ pub fn prebuilt_llvm_config(
96113 Using a potentially stale build of LLVM; \
97114 This may not behave well.",
98115 ) ;
99- return Ok ( build_llvm_config ) ;
116+ return Ok ( res ) ;
100117 }
101118
102119 if stamp. is_done ( ) {
@@ -110,10 +127,10 @@ pub fn prebuilt_llvm_config(
110127 stamp. path. display( )
111128 ) ) ;
112129 }
113- return Ok ( build_llvm_config ) ;
130+ return Ok ( res ) ;
114131 }
115132
116- Err ( Meta { stamp, build_llvm_config , out_dir, root : root. into ( ) } )
133+ Err ( Meta { stamp, res , out_dir, root : root. into ( ) } )
117134}
118135
119136/// This retrieves the LLVM sha we *want* to use, according to git history.
@@ -223,7 +240,7 @@ pub struct Llvm {
223240}
224241
225242impl Step for Llvm {
226- type Output = PathBuf ; // path to llvm-config
243+ type Output = LlvmResult ;
227244
228245 const ONLY_HOSTS : bool = true ;
229246
@@ -236,7 +253,7 @@ impl Step for Llvm {
236253 }
237254
238255 /// Compile LLVM for `target`.
239- fn run ( self , builder : & Builder < ' _ > ) -> PathBuf {
256+ fn run ( self , builder : & Builder < ' _ > ) -> LlvmResult {
240257 let target = self . target ;
241258 let target_native = if self . target . starts_with ( "riscv" ) {
242259 // RISC-V target triples in Rust is not named the same as C compiler target triples.
@@ -252,11 +269,10 @@ impl Step for Llvm {
252269 target. to_string ( )
253270 } ;
254271
255- let Meta { stamp, build_llvm_config, out_dir, root } =
256- match prebuilt_llvm_config ( builder, target) {
257- Ok ( p) => return p,
258- Err ( m) => m,
259- } ;
272+ let Meta { stamp, res, out_dir, root } = match prebuilt_llvm_config ( builder, target) {
273+ Ok ( p) => return p,
274+ Err ( m) => m,
275+ } ;
260276
261277 builder. update_submodule ( & Path :: new ( "src" ) . join ( "llvm-project" ) ) ;
262278 if builder. llvm_link_shared ( ) && target. contains ( "windows" ) {
@@ -430,7 +446,8 @@ impl Step for Llvm {
430446
431447 // https://llvm.org/docs/HowToCrossCompileLLVM.html
432448 if target != builder. config . build {
433- let llvm_config = builder. ensure ( Llvm { target : builder. config . build } ) ;
449+ let LlvmResult { llvm_config, .. } =
450+ builder. ensure ( Llvm { target : builder. config . build } ) ;
434451 if !builder. config . dry_run ( ) {
435452 let llvm_bindir = output ( Command :: new ( & llvm_config) . arg ( "--bindir" ) ) ;
436453 let host_bin = Path :: new ( llvm_bindir. trim ( ) ) ;
@@ -480,7 +497,7 @@ impl Step for Llvm {
480497 // tools and libs on all platforms.
481498
482499 if builder. config . dry_run ( ) {
483- return build_llvm_config ;
500+ return res ;
484501 }
485502
486503 cfg. build ( ) ;
@@ -490,7 +507,7 @@ impl Step for Llvm {
490507 // for a versioned path like libLLVM-14.dylib. Manually create a symbolic
491508 // link to make llvm-config happy.
492509 if builder. llvm_link_shared ( ) && target. contains ( "apple-darwin" ) {
493- let mut cmd = Command :: new ( & build_llvm_config ) ;
510+ let mut cmd = Command :: new ( & res . llvm_config ) ;
494511 let version = output ( cmd. arg ( "--version" ) ) ;
495512 let major = version. split ( '.' ) . next ( ) . unwrap ( ) ;
496513 let lib_name = match llvm_version_suffix {
@@ -509,18 +526,18 @@ impl Step for Llvm {
509526 // LLVM after a configuration change, so to rebuild it the build files have to be removed,
510527 // which will also remove these modified files.
511528 if builder. config . llvm_bolt_profile_generate {
512- instrument_with_bolt_inplace ( & get_built_llvm_lib_path ( & build_llvm_config ) ) ;
529+ instrument_with_bolt_inplace ( & get_built_llvm_lib_path ( & res . llvm_config ) ) ;
513530 }
514531 if let Some ( path) = & builder. config . llvm_bolt_profile_use {
515532 optimize_library_with_bolt_inplace (
516- & get_built_llvm_lib_path ( & build_llvm_config ) ,
533+ & get_built_llvm_lib_path ( & res . llvm_config ) ,
517534 & Path :: new ( path) ,
518535 ) ;
519536 }
520537
521538 t ! ( stamp. write( ) ) ;
522539
523- build_llvm_config
540+ res
524541 }
525542}
526543
@@ -803,7 +820,8 @@ impl Step for Lld {
803820 }
804821 let target = self . target ;
805822
806- let llvm_config = builder. ensure ( Llvm { target : self . target } ) ;
823+ let LlvmResult { llvm_config, llvm_cmake_dir } =
824+ builder. ensure ( Llvm { target : self . target } ) ;
807825
808826 let out_dir = builder. lld_out ( target) ;
809827 let done_stamp = out_dir. join ( "lld-finished-building" ) ;
@@ -834,22 +852,6 @@ impl Step for Lld {
834852 configure_cmake ( builder, target, & mut cfg, true , ldflags) ;
835853 configure_llvm ( builder, target, & mut cfg) ;
836854
837- // This is an awful, awful hack. Discovered when we migrated to using
838- // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
839- // tree, will execute `llvm-config --cmakedir` and then tell CMake about
840- // that directory for later processing. Unfortunately if this path has
841- // forward slashes in it (which it basically always does on Windows)
842- // then CMake will hit a syntax error later on as... something isn't
843- // escaped it seems?
844- //
845- // Instead of attempting to fix this problem in upstream CMake and/or
846- // LLVM/LLD we just hack around it here. This thin wrapper will take the
847- // output from llvm-config and replace all instances of `\` with `/` to
848- // ensure we don't hit the same bugs with escaping. It means that you
849- // can't build on a system where your paths require `\` on Windows, but
850- // there's probably a lot of reasons you can't do that other than this.
851- let llvm_config_shim = env:: current_exe ( ) . unwrap ( ) . with_file_name ( "llvm-config-wrapper" ) ;
852-
853855 // Re-use the same flags as llvm to control the level of debug information
854856 // generated for lld.
855857 let profile = match ( builder. config . llvm_optimize , builder. config . llvm_release_debuginfo ) {
@@ -860,30 +862,15 @@ impl Step for Lld {
860862
861863 cfg. out_dir ( & out_dir)
862864 . profile ( profile)
863- . env ( "LLVM_CONFIG_REAL" , & llvm_config)
864- . define ( "LLVM_CONFIG_PATH" , llvm_config_shim)
865+ . define ( "LLVM_CMAKE_DIR" , llvm_cmake_dir)
865866 . define ( "LLVM_INCLUDE_TESTS" , "OFF" ) ;
866867
867- // While we're using this horrible workaround to shim the execution of
868- // llvm-config, let's just pile on more. I can't seem to figure out how
869- // to build LLD as a standalone project and also cross-compile it at the
870- // same time. It wants a natively executable `llvm-config` to learn
871- // about LLVM, but then it learns about all the host configuration of
872- // LLVM and tries to link to host LLVM libraries.
873- //
874- // To work around that we tell our shim to replace anything with the
875- // build target with the actual target instead. This'll break parts of
876- // LLD though which try to execute host tools, such as llvm-tblgen, so
877- // we specifically tell it where to find those. This is likely super
878- // brittle and will break over time. If anyone knows better how to
879- // cross-compile LLD it would be much appreciated to fix this!
880868 if target != builder. config . build {
881- cfg. env ( "LLVM_CONFIG_SHIM_REPLACE" , & builder. config . build . triple )
882- . env ( "LLVM_CONFIG_SHIM_REPLACE_WITH" , & target. triple )
883- . define (
884- "LLVM_TABLEGEN_EXE" ,
885- llvm_config. with_file_name ( "llvm-tblgen" ) . with_extension ( EXE_EXTENSION ) ,
886- ) ;
869+ // Use the host llvm-tblgen binary.
870+ cfg. define (
871+ "LLVM_TABLEGEN_EXE" ,
872+ llvm_config. with_file_name ( "llvm-tblgen" ) . with_extension ( EXE_EXTENSION ) ,
873+ ) ;
887874 }
888875
889876 cfg. build ( ) ;
@@ -987,7 +974,7 @@ impl Step for Sanitizers {
987974 return runtimes;
988975 }
989976
990- let llvm_config = builder. ensure ( Llvm { target : builder. config . build } ) ;
977+ let LlvmResult { llvm_config, .. } = builder. ensure ( Llvm { target : builder. config . build } ) ;
991978 if builder. config . dry_run ( ) {
992979 return runtimes;
993980 }
0 commit comments