@@ -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" ,
@@ -238,31 +262,28 @@ impl Step for Llvm {
238262 cfg. define ( "LLVM_LINK_LLVM_DYLIB" , "ON" ) ;
239263 }
240264
241- // For distribution we want the LLVM tools to be *statically* linked to libstdc++
242- if builder. config . llvm_tools_enabled {
243- if !target. contains ( "msvc" ) {
265+ // For distribution we want the LLVM tools to be *statically* linked to libstdc++.
266+ // We also do this if the user explicitly requested static libstdc++.
267+ if builder. config . llvm_tools_enabled || builder. config . llvm_static_stdcpp {
268+ if !target. contains ( "msvc" ) && !target. contains ( "netbsd" ) {
244269 if target. contains ( "apple" ) {
245- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , "-static-libstdc++" ) ;
270+ ldflags . push_all ( "-static-libstdc++" ) ;
246271 } else {
247- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , "-Wl,-Bsymbolic -static-libstdc++" ) ;
272+ ldflags . push_all ( "-Wl,-Bsymbolic -static-libstdc++" ) ;
248273 }
249274 }
250275 }
251276
252- if ! target. contains ( "freebsd ") && target. starts_with ( "riscv ") {
277+ if target. starts_with ( "riscv ") && ! target. contains ( "freebsd ") {
253278 // RISC-V GCC erroneously requires linking against
254279 // `libatomic` when using 1-byte and 2-byte C++
255280 // atomics but the LLVM build system check cannot
256281 // detect this. Therefore it is set manually here.
257282 // FreeBSD uses Clang as its system compiler and
258283 // provides no libatomic in its base system so does
259284 // not want this.
260- if !builder. config . llvm_tools_enabled {
261- cfg. define ( "CMAKE_EXE_LINKER_FLAGS" , "-latomic" ) ;
262- } else {
263- cfg. define ( "CMAKE_EXE_LINKER_FLAGS" , "-latomic -static-libstdc++" ) ;
264- }
265- cfg. define ( "CMAKE_SHARED_LINKER_FLAGS" , "-latomic" ) ;
285+ ldflags. exe . push ( " -latomic" ) ;
286+ ldflags. shared . push ( " -latomic" ) ;
266287 }
267288
268289 if target. contains ( "msvc" ) {
@@ -309,7 +330,7 @@ impl Step for Llvm {
309330
310331 // Workaround for ppc32 lld limitation
311332 if target == "powerpc-unknown-freebsd" {
312- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -fuse-ld=bfd") ;
333+ ldflags . exe . push ( " -fuse-ld=bfd") ;
313334 }
314335
315336 // https://llvm.org/docs/HowToCrossCompileLLVM.html
@@ -351,7 +372,7 @@ impl Step for Llvm {
351372 cfg. define ( "LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN" , "YES" ) ;
352373 }
353374
354- configure_cmake ( builder, target, & mut cfg, true ) ;
375+ configure_cmake ( builder, target, & mut cfg, true , ldflags ) ;
355376
356377 for ( key, val) in & builder. config . llvm_build_config {
357378 cfg. define ( key, val) ;
@@ -399,6 +420,7 @@ fn configure_cmake(
399420 target : TargetSelection ,
400421 cfg : & mut cmake:: Config ,
401422 use_compiler_launcher : bool ,
423+ mut ldflags : LdFlags ,
402424) {
403425 // Do not print installation messages for up-to-date files.
404426 // LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -507,31 +529,38 @@ fn configure_cmake(
507529 }
508530
509531 cfg. build_arg ( "-j" ) . build_arg ( builder. jobs ( ) . to_string ( ) ) ;
510- let mut cflags = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) ;
532+ let mut cflags: OsString = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) . into ( ) ;
511533 if let Some ( ref s) = builder. config . llvm_cflags {
512- cflags. push_str ( & format ! ( " {}" , s) ) ;
534+ cflags. push ( " " ) ;
535+ cflags. push ( s) ;
513536 }
514537 // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10.
515538 if target. contains ( "apple-ios" ) {
516539 if target. contains ( "86-" ) {
517- cflags. push_str ( " -miphonesimulator-version-min=10.0" ) ;
540+ cflags. push ( " -miphonesimulator-version-min=10.0" ) ;
518541 } else {
519- cflags. push_str ( " -miphoneos-version-min=10.0" ) ;
542+ cflags. push ( " -miphoneos-version-min=10.0" ) ;
520543 }
521544 }
522545 if builder. config . llvm_clang_cl . is_some ( ) {
523- cflags. push_str ( & format ! ( " --target={}" , target) )
546+ cflags. push ( & format ! ( " --target={}" , target) ) ;
524547 }
525- cfg. define ( "CMAKE_C_FLAGS" , cflags) ;
526- let mut cxxflags = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) ;
527- if builder. config . llvm_static_stdcpp && !target. contains ( "msvc" ) && !target. contains ( "netbsd" ) {
528- cxxflags. push_str ( " -static-libstdc++" ) ;
548+ if let Some ( flags) = env:: var_os ( "CFLAGS" ) {
549+ cflags. push ( " " ) ;
550+ cflags. push ( flags) ;
529551 }
552+ cfg. define ( "CMAKE_C_FLAGS" , cflags) ;
553+ let mut cxxflags: OsString = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) . into ( ) ;
530554 if let Some ( ref s) = builder. config . llvm_cxxflags {
531- cxxflags. push_str ( & format ! ( " {}" , s) ) ;
555+ cxxflags. push ( " " ) ;
556+ cxxflags. push ( s) ;
532557 }
533558 if builder. config . llvm_clang_cl . is_some ( ) {
534- cxxflags. push_str ( & format ! ( " --target={}" , target) )
559+ cxxflags. push ( & format ! ( " --target={}" , target) ) ;
560+ }
561+ if let Some ( flags) = env:: var_os ( "CXXFLAGS" ) {
562+ cxxflags. push ( " " ) ;
563+ cxxflags. push ( flags) ;
535564 }
536565 cfg. define ( "CMAKE_CXX_FLAGS" , cxxflags) ;
537566 if let Some ( ar) = builder. ar ( target) {
@@ -550,12 +579,18 @@ fn configure_cmake(
550579 }
551580 }
552581
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) ;
582+ if let Some ( ref flags) = builder. config . llvm_ldflags {
583+ ldflags. push_all ( flags) ;
557584 }
558585
586+ if let Some ( flags) = env:: var_os ( "LDFLAGS" ) {
587+ ldflags. push_all ( & flags) ;
588+ }
589+
590+ cfg. define ( "CMAKE_SHARED_LINKER_FLAGS" , & ldflags. shared ) ;
591+ cfg. define ( "CMAKE_MODULE_LINKER_FLAGS" , & ldflags. module ) ;
592+ cfg. define ( "CMAKE_EXE_LINKER_FLAGS" , & ldflags. exe ) ;
593+
559594 if env:: var_os ( "SCCACHE_ERROR_LOG" ) . is_some ( ) {
560595 cfg. env ( "RUSTC_LOG" , "sccache=warn" ) ;
561596 }
@@ -598,7 +633,7 @@ impl Step for Lld {
598633 t ! ( fs:: create_dir_all( & out_dir) ) ;
599634
600635 let mut cfg = cmake:: Config :: new ( builder. src . join ( "src/llvm-project/lld" ) ) ;
601- configure_cmake ( builder, target, & mut cfg, true ) ;
636+ configure_cmake ( builder, target, & mut cfg, true , LdFlags :: default ( ) ) ;
602637
603638 // This is an awful, awful hack. Discovered when we migrated to using
604639 // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
@@ -788,7 +823,7 @@ impl Step for Sanitizers {
788823 // Unfortunately sccache currently lacks support to build them successfully.
789824 // Disable compiler launcher on Darwin targets to avoid potential issues.
790825 let use_compiler_launcher = !self . target . contains ( "apple-darwin" ) ;
791- configure_cmake ( builder, self . target , & mut cfg, use_compiler_launcher) ;
826+ configure_cmake ( builder, self . target , & mut cfg, use_compiler_launcher, LdFlags :: default ( ) ) ;
792827
793828 t ! ( fs:: create_dir_all( & out_dir) ) ;
794829 cfg. out_dir ( out_dir) ;
0 commit comments