@@ -457,33 +457,85 @@ mod c_vendor {
457457#[ cfg( feature = "c-system" ) ]
458458mod c_system {
459459 use std:: env;
460- use std:: process:: Command ;
460+ use std:: process:: { Command , Output } ;
461461 use std:: str;
462+ use std:: path:: Path ;
462463 use sources;
463464
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) ;
479467 let status = output. status ;
480468 if !status. success ( ) {
481- panic ! ( format! ( "failed to find clang lib dir : {:?}", status. code( ) ) ) ;
469+ panic ! ( "{} : {:?}", err , status. code( ) ) ;
482470 }
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" ) ;
485538 }
486- println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
487539
488540 let sources = sources:: get_sources ( llvm_target) ;
489541 for ( sym, _src) in sources. map . iter ( ) {
0 commit comments