@@ -460,33 +460,85 @@ mod c_vendor {
460
460
#[ cfg( feature = "c-system" ) ]
461
461
mod c_system {
462
462
use std:: env;
463
- use std:: process:: Command ;
463
+ use std:: process:: { Command , Output } ;
464
464
use std:: str;
465
+ use std:: path:: Path ;
465
466
use sources;
466
467
467
- /// Link against system clang runtime libraries
468
- pub fn compile ( llvm_target : & [ & str ] ) {
469
- let target_os = env:: var ( "CARGO_CFG_TARGET_OS" ) . unwrap ( ) ;
470
-
471
- let llvm_config = env:: var ( "LLVM_CONFIG" ) . expect ( "LLVM_CONFIG not set" ) ;
472
- let ( subpath, libname) = match target_os. as_str ( ) {
473
- "linux" => ( "linux" , format ! ( "clang_rt.builtins-{}" , llvm_target[ 0 ] ) ) ,
474
- "macos" => ( "darwin" , "clang_rt.builtins_osx_dynamic" . to_string ( ) ) ,
475
- _ => panic ! ( "unsupported target os: {}" , target_os) ,
476
- } ;
477
- let cmd = format ! ( "ls -1d $({} --libdir)/clang/*/lib/{}" , llvm_config, subpath) ;
478
- let output = Command :: new ( "sh" )
479
- . args ( & [ "-ec" , & cmd] )
480
- . output ( )
481
- . expect ( "failed to find clang lib dir" ) ;
468
+ fn success_output ( err : & str , cmd : & mut Command ) -> Output {
469
+ let output = cmd. output ( ) . expect ( err) ;
482
470
let status = output. status ;
483
471
if !status. success ( ) {
484
- panic ! ( format! ( "failed to find clang lib dir : {:?}", status. code( ) ) ) ;
472
+ panic ! ( "{} : {:?}", err , status. code( ) ) ;
485
473
}
486
- for search_dir in str:: from_utf8 ( & output. stdout ) . unwrap ( ) . lines ( ) {
487
- println ! ( "cargo:rustc-link-search=native={}" , search_dir) ;
474
+ output
475
+ }
476
+
477
+ // This function recreates the logic of getArchNameForCompilerRTLib,
478
+ // defined in clang/lib/Driver/ToolChain.cpp.
479
+ fn get_arch_name_for_compiler_rtlib ( ) -> String {
480
+ let target = env:: var ( "TARGET" ) . unwrap ( ) ;
481
+ let target_arch = env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
482
+ let target_os = env:: var ( "CARGO_CFG_TARGET_OS" ) . unwrap ( ) ;
483
+ let r = match target_arch. as_str ( ) {
484
+ "arm" => if target. ends_with ( "eabihf" ) && target_os != "windows" {
485
+ "armhf"
486
+ } else {
487
+ "arm"
488
+ } ,
489
+ "x86" => if target_os == "android" {
490
+ "i686"
491
+ } else {
492
+ "i386"
493
+ } ,
494
+ _ => target_arch. as_str ( ) ,
495
+ } ;
496
+ r. to_string ( )
497
+ }
498
+
499
+ /// Link against system clang runtime libraries
500
+ pub fn compile ( llvm_target : & [ & str ] ) {
501
+ let target = env:: var ( "TARGET" ) . unwrap ( ) ;
502
+ let target_os = env:: var ( "CARGO_CFG_TARGET_OS" ) . unwrap ( ) ;
503
+ let compiler_rt_arch = get_arch_name_for_compiler_rtlib ( ) ;
504
+
505
+ if let Ok ( clang) = env:: var ( "CLANG" ) {
506
+ let output = success_output (
507
+ "failed to find clang's compiler-rt" ,
508
+ Command :: new ( clang)
509
+ . arg ( format ! ( "--target={}" , target) )
510
+ . arg ( "--rtlib=compiler-rt" )
511
+ . arg ( "--print-libgcc-file-name" ) ,
512
+ ) ;
513
+ let fullpath = Path :: new ( str:: from_utf8 ( & output. stdout ) . unwrap ( ) ) ;
514
+ let libpath = fullpath. parent ( ) . unwrap ( ) . display ( ) ;
515
+ let libname = fullpath
516
+ . file_stem ( )
517
+ . unwrap ( )
518
+ . to_str ( )
519
+ . unwrap ( )
520
+ . trim_start_matches ( "lib" ) ;
521
+ println ! ( "cargo:rustc-link-search=native={}" , libpath) ;
522
+ println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
523
+ } else if let Ok ( llvm_config) = env:: var ( "LLVM_CONFIG" ) {
524
+ // fallback if clang is not installed
525
+ let ( subpath, libname) = match target_os. as_str ( ) {
526
+ "linux" => ( "linux" , format ! ( "clang_rt.builtins-{}" , & compiler_rt_arch) ) ,
527
+ "macos" => ( "darwin" , "clang_rt.builtins_osx_dynamic" . to_string ( ) ) ,
528
+ _ => panic ! ( "unsupported target os: {}" , target_os) ,
529
+ } ;
530
+ let cmd = format ! ( "ls -1d $({} --libdir)/clang/*/lib/{}" , llvm_config, subpath) ;
531
+ let output = success_output (
532
+ "failed to find clang's lib dir" ,
533
+ Command :: new ( "sh" ) . args ( & [ "-ec" , & cmd] ) ,
534
+ ) ;
535
+ for search_dir in str:: from_utf8 ( & output. stdout ) . unwrap ( ) . lines ( ) {
536
+ println ! ( "cargo:rustc-link-search=native={}" , search_dir) ;
537
+ }
538
+ println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
539
+ } else {
540
+ panic ! ( "neither CLANG nor LLVM_CONFIG could be read" ) ;
488
541
}
489
- println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
490
542
491
543
let sources = sources:: get_sources ( llvm_target) ;
492
544
for ( sym, _src) in sources. map . iter ( ) {
0 commit comments