@@ -31,6 +31,29 @@ pub struct Meta {
31
31
root : String ,
32
32
}
33
33
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
+
34
57
// This returns whether we've already previously built LLVM.
35
58
//
36
59
// It's used to avoid busting caches during x.py check -- if we've already built
@@ -146,6 +169,7 @@ impl Step for Llvm {
146
169
147
170
// https://llvm.org/docs/CMake.html
148
171
let mut cfg = cmake:: Config :: new ( builder. src . join ( root) ) ;
172
+ let mut ldflags = LdFlags :: default ( ) ;
149
173
150
174
let profile = match ( builder. config . llvm_optimize , builder. config . llvm_release_debuginfo ) {
151
175
( false , _) => "Debug" ,
@@ -238,31 +262,28 @@ impl Step for Llvm {
238
262
cfg. define ( "LLVM_LINK_LLVM_DYLIB" , "ON" ) ;
239
263
}
240
264
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" ) {
244
269
if target. contains ( "apple" ) {
245
- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , "-static-libstdc++" ) ;
270
+ ldflags . push_all ( "-static-libstdc++" ) ;
246
271
} else {
247
- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , "-Wl,-Bsymbolic -static-libstdc++" ) ;
272
+ ldflags . push_all ( "-Wl,-Bsymbolic -static-libstdc++" ) ;
248
273
}
249
274
}
250
275
}
251
276
252
- if ! target. contains ( "freebsd ") && target. starts_with ( "riscv ") {
277
+ if target. starts_with ( "riscv ") && ! target. contains ( "freebsd ") {
253
278
// RISC-V GCC erroneously requires linking against
254
279
// `libatomic` when using 1-byte and 2-byte C++
255
280
// atomics but the LLVM build system check cannot
256
281
// detect this. Therefore it is set manually here.
257
282
// FreeBSD uses Clang as its system compiler and
258
283
// provides no libatomic in its base system so does
259
284
// 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" ) ;
266
287
}
267
288
268
289
if target. contains ( "msvc" ) {
@@ -309,7 +330,7 @@ impl Step for Llvm {
309
330
310
331
// Workaround for ppc32 lld limitation
311
332
if target == "powerpc-unknown-freebsd" {
312
- cfg . define ( "CMAKE_EXE_LINKER_FLAGS" , " -fuse-ld=bfd") ;
333
+ ldflags . exe . push ( " -fuse-ld=bfd") ;
313
334
}
314
335
315
336
// https://llvm.org/docs/HowToCrossCompileLLVM.html
@@ -351,7 +372,7 @@ impl Step for Llvm {
351
372
cfg. define ( "LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN" , "YES" ) ;
352
373
}
353
374
354
- configure_cmake ( builder, target, & mut cfg, true ) ;
375
+ configure_cmake ( builder, target, & mut cfg, true , ldflags ) ;
355
376
356
377
for ( key, val) in & builder. config . llvm_build_config {
357
378
cfg. define ( key, val) ;
@@ -399,6 +420,7 @@ fn configure_cmake(
399
420
target : TargetSelection ,
400
421
cfg : & mut cmake:: Config ,
401
422
use_compiler_launcher : bool ,
423
+ mut ldflags : LdFlags ,
402
424
) {
403
425
// Do not print installation messages for up-to-date files.
404
426
// LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -507,31 +529,38 @@ fn configure_cmake(
507
529
}
508
530
509
531
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 ( ) ;
511
533
if let Some ( ref s) = builder. config . llvm_cflags {
512
- cflags. push_str ( & format ! ( " {}" , s) ) ;
534
+ cflags. push ( " " ) ;
535
+ cflags. push ( s) ;
513
536
}
514
537
// Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10.
515
538
if target. contains ( "apple-ios" ) {
516
539
if target. contains ( "86-" ) {
517
- cflags. push_str ( " -miphonesimulator-version-min=10.0" ) ;
540
+ cflags. push ( " -miphonesimulator-version-min=10.0" ) ;
518
541
} else {
519
- cflags. push_str ( " -miphoneos-version-min=10.0" ) ;
542
+ cflags. push ( " -miphoneos-version-min=10.0" ) ;
520
543
}
521
544
}
522
545
if builder. config . llvm_clang_cl . is_some ( ) {
523
- cflags. push_str ( & format ! ( " --target={}" , target) )
546
+ cflags. push ( & format ! ( " --target={}" , target) ) ;
524
547
}
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) ;
529
551
}
552
+ cfg. define ( "CMAKE_C_FLAGS" , cflags) ;
553
+ let mut cxxflags: OsString = builder. cflags ( target, GitRepo :: Llvm ) . join ( " " ) . into ( ) ;
530
554
if let Some ( ref s) = builder. config . llvm_cxxflags {
531
- cxxflags. push_str ( & format ! ( " {}" , s) ) ;
555
+ cxxflags. push ( " " ) ;
556
+ cxxflags. push ( s) ;
532
557
}
533
558
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) ;
535
564
}
536
565
cfg. define ( "CMAKE_CXX_FLAGS" , cxxflags) ;
537
566
if let Some ( ar) = builder. ar ( target) {
@@ -550,12 +579,18 @@ fn configure_cmake(
550
579
}
551
580
}
552
581
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) ;
557
584
}
558
585
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
+
559
594
if env:: var_os ( "SCCACHE_ERROR_LOG" ) . is_some ( ) {
560
595
cfg. env ( "RUSTC_LOG" , "sccache=warn" ) ;
561
596
}
@@ -598,7 +633,7 @@ impl Step for Lld {
598
633
t ! ( fs:: create_dir_all( & out_dir) ) ;
599
634
600
635
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 ( ) ) ;
602
637
603
638
// This is an awful, awful hack. Discovered when we migrated to using
604
639
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
@@ -788,7 +823,7 @@ impl Step for Sanitizers {
788
823
// Unfortunately sccache currently lacks support to build them successfully.
789
824
// Disable compiler launcher on Darwin targets to avoid potential issues.
790
825
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 ( ) ) ;
792
827
793
828
t ! ( fs:: create_dir_all( & out_dir) ) ;
794
829
cfg. out_dir ( out_dir) ;
0 commit comments