@@ -31,6 +31,29 @@ pub struct Meta {
3131 root : String ,
3232}
3333
34+ // Linker flags to pass to LLVM's CMake invocation.
35+ #[ derive( Debug , Clone , Default ) ]
36+ struct LdFlags {
37+ // CMAKE_EXE_LINKER_FLAGS
38+ exe : OsString ,
39+ // CMAKE_SHARED_LINKER_FLAGS
40+ shared : OsString ,
41+ // CMAKE_MODULE_LINKER_FLAGS
42+ module : OsString ,
43+ }
44+
45+ impl LdFlags {
46+ fn push_all ( & mut self , s : impl AsRef < OsStr > ) {
47+ let s = s. as_ref ( ) ;
48+ self . exe . push ( " " ) ;
49+ self . exe . push ( s) ;
50+ self . shared . push ( " " ) ;
51+ self . shared . push ( s) ;
52+ self . module . push ( " " ) ;
53+ self . module . push ( s) ;
54+ }
55+ }
56+
3457// This returns whether we've already previously built LLVM.
3558//
3659// It's used to avoid busting caches during x.py check -- if we've already built
@@ -146,6 +169,7 @@ impl Step for Llvm {
146169
147170 // https://llvm.org/docs/CMake.html
148171 let mut cfg = cmake:: Config :: new ( builder. src . join ( root) ) ;
172+ let mut ldflags = LdFlags :: default ( ) ;
149173
150174 let profile = match ( builder. config . llvm_optimize , builder. config . llvm_release_debuginfo ) {
151175 ( false , _) => "Debug" ,
@@ -242,9 +266,9 @@ impl Step for Llvm {
242266 if builder. config . llvm_tools_enabled {
243267 if !target. contains ( "msvc" ) {
244268 if target. contains ( "apple" ) {
245- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -static-libstdc++") ;
269+ ldflags . exe . push ( " -static-libstdc++") ;
246270 } else {
247- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -Wl,-Bsymbolic -static-libstdc++") ;
271+ ldflags . exe . push ( " -Wl,-Bsymbolic -static-libstdc++") ;
248272 }
249273 }
250274 }
@@ -258,11 +282,11 @@ impl Step for Llvm {
258282 // provides no libatomic in its base system so does
259283 // not want this.
260284 if !builder. config . llvm_tools_enabled {
261- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -latomic") ;
285+ ldflags . exe . push ( " -latomic") ;
262286 } else {
263- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -latomic -static-libstdc++") ;
287+ ldflags . exe . push ( " -latomic -static-libstdc++") ;
264288 }
265- cfg . define ( "CMAKE_SHARED_LINKER_FLAGS" , " -latomic") ;
289+ ldflags . shared . push ( " -latomic") ;
266290 }
267291
268292 if target. contains ( "msvc" ) {
@@ -309,7 +333,7 @@ impl Step for Llvm {
309333
310334 // Workaround for ppc32 lld limitation
311335 if target == "powerpc-unknown-freebsd" {
312- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -fuse-ld=bfd") ;
336+ ldflags . exe . push ( " -fuse-ld=bfd") ;
313337 }
314338
315339 // https://llvm.org/docs/HowToCrossCompileLLVM.html
@@ -351,7 +375,7 @@ impl Step for Llvm {
351375 cfg. define ( "LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN" , "YES" ) ;
352376 }
353377
354- configure_cmake ( builder, target, & mut cfg, true ) ;
378+ configure_cmake ( builder, target, & mut cfg, true , ldflags ) ;
355379
356380 for ( key, val) in & builder. config . llvm_build_config {
357381 cfg. define ( key, val) ;
@@ -399,6 +423,7 @@ fn configure_cmake(
399423 target : TargetSelection ,
400424 cfg : & mut cmake:: Config ,
401425 use_compiler_launcher : bool ,
426+ mut ldflags : LdFlags ,
402427) {
403428 // Do not print installation messages for up-to-date files.
404429 // LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -507,31 +532,41 @@ fn configure_cmake(
507532 }
508533
509534 cfg. build_arg ( "-j" ) . build_arg ( builder. jobs ( ) . to_string ( ) ) ;
510- let mut cflags = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) ;
535+ let mut cflags: OsString = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) . into ( ) ;
511536 if let Some ( ref s) = builder. config . llvm_cflags {
512- cflags. push_str ( & format ! ( " {}" , s) ) ;
537+ cflags. push ( " " ) ;
538+ cflags. push ( s) ;
513539 }
514540 // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10.
515541 if target. contains ( "apple-ios" ) {
516542 if target. contains ( "86-" ) {
517- cflags. push_str ( " -miphonesimulator-version-min=10.0" ) ;
543+ cflags. push ( " -miphonesimulator-version-min=10.0" ) ;
518544 } else {
519- cflags. push_str ( " -miphoneos-version-min=10.0" ) ;
545+ cflags. push ( " -miphoneos-version-min=10.0" ) ;
520546 }
521547 }
522548 if builder. config . llvm_clang_cl . is_some ( ) {
523- cflags. push_str ( & format ! ( " --target={}" , target) )
549+ cflags. push ( & format ! ( " --target={}" , target) ) ;
550+ }
551+ if let Some ( flags) = env:: var_os ( "CFLAGS" ) {
552+ cflags. push ( " " ) ;
553+ cflags. push ( flags) ;
524554 }
525555 cfg. define ( "CMAKE_C_FLAGS" , cflags) ;
526- let mut cxxflags = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) ;
556+ let mut cxxflags: OsString = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) . into ( ) ;
527557 if builder. config . llvm_static_stdcpp && !target. contains ( "msvc" ) && !target. contains ( "netbsd" ) {
528- cxxflags. push_str ( " -static-libstdc++" ) ;
558+ cxxflags. push ( " -static-libstdc++" ) ;
529559 }
530560 if let Some ( ref s) = builder. config . llvm_cxxflags {
531- cxxflags. push_str ( & format ! ( " {}" , s) ) ;
561+ cxxflags. push ( " " ) ;
562+ cxxflags. push ( s) ;
532563 }
533564 if builder. config . llvm_clang_cl . is_some ( ) {
534- cxxflags. push_str ( & format ! ( " --target={}" , target) )
565+ cxxflags. push ( & format ! ( " --target={}" , target) ) ;
566+ }
567+ if let Some ( flags) = env:: var_os ( "CXXFLAGS" ) {
568+ cxxflags. push ( " " ) ;
569+ cxxflags. push ( flags) ;
535570 }
536571 cfg. define ( "CMAKE_CXX_FLAGS" , cxxflags) ;
537572 if let Some ( ar) = builder. ar ( target) {
@@ -550,12 +585,18 @@ fn configure_cmake(
550585 }
551586 }
552587
553- if let Some ( ref s) = builder. config . llvm_ldflags {
554- cfg. define ( "CMAKE_SHARED_LINKER_FLAGS" , s) ;
555- cfg. define ( "CMAKE_MODULE_LINKER_FLAGS" , s) ;
556- cfg. define ( "CMAKE_EXE_LINKER_FLAGS" , s) ;
588+ if let Some ( ref flags) = builder. config . llvm_ldflags {
589+ ldflags. push_all ( flags) ;
557590 }
558591
592+ if let Some ( flags) = env:: var_os ( "LDFLAGS" ) {
593+ ldflags. push_all ( & flags) ;
594+ }
595+
596+ cfg. define ( "CMAKE_SHARED_LINKER_FLAGS" , & ldflags. shared ) ;
597+ cfg. define ( "CMAKE_MODULE_LINKER_FLAGS" , & ldflags. module ) ;
598+ cfg. define ( "CMAKE_EXE_LINKER_FLAGS" , & ldflags. exe ) ;
599+
559600 if env:: var_os ( "SCCACHE_ERROR_LOG" ) . is_some ( ) {
560601 cfg. env ( "RUSTC_LOG" , "sccache=warn" ) ;
561602 }
@@ -598,7 +639,7 @@ impl Step for Lld {
598639 t ! ( fs:: create_dir_all( & out_dir) ) ;
599640
600641 let mut cfg = cmake:: Config :: new ( builder. src . join ( "src/llvm-project/lld" ) ) ;
601- configure_cmake ( builder, target, & mut cfg, true ) ;
642+ configure_cmake ( builder, target, & mut cfg, true , LdFlags :: default ( ) ) ;
602643
603644 // This is an awful, awful hack. Discovered when we migrated to using
604645 // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
@@ -788,7 +829,7 @@ impl Step for Sanitizers {
788829 // Unfortunately sccache currently lacks support to build them successfully.
789830 // Disable compiler launcher on Darwin targets to avoid potential issues.
790831 let use_compiler_launcher = !self . target . contains ( "apple-darwin" ) ;
791- configure_cmake ( builder, self . target , & mut cfg, use_compiler_launcher) ;
832+ configure_cmake ( builder, self . target , & mut cfg, use_compiler_launcher, LdFlags :: default ( ) ) ;
792833
793834 t ! ( fs:: create_dir_all( & out_dir) ) ;
794835 cfg. out_dir ( out_dir) ;
0 commit comments