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