@@ -460,33 +460,85 @@ mod c_vendor {
460460#[ cfg( feature = "c-system" ) ]
461461mod c_system {
462462 use std:: env;
463- use std:: process:: Command ;
463+ use std:: process:: { Command , Output } ;
464464 use std:: str;
465+ use std:: path:: Path ;
465466 use sources;
466467
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) ;
482470 let status = output. status ;
483471 if !status. success ( ) {
484- panic ! ( format! ( "failed to find clang lib dir : {:?}", status. code( ) ) ) ;
472+ panic ! ( "{} : {:?}", err , status. code( ) ) ;
485473 }
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" ) ;
488541 }
489- println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
490542
491543 let sources = sources:: get_sources ( llvm_target) ;
492544 for ( sym, _src) in sources. map . iter ( ) {
0 commit comments