@@ -40,7 +40,7 @@ fn main() {
4040 // mangling names though we assume that we're also in test mode so we don't
4141 // build anything and we rely on the upstream implementation of compiler-rt
4242 // functions
43- if !cfg ! ( feature = "mangled-names" ) && cfg ! ( feature = "c" ) {
43+ if !cfg ! ( feature = "mangled-names" ) && cfg ! ( any ( feature = "c-vendor" , feature = "c-system" ) ) {
4444 // Don't use a C compiler for these targets:
4545 //
4646 // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's
@@ -50,8 +50,10 @@ fn main() {
5050 // compiler nor is cc-rs ready for compilation to riscv (at this
5151 // time). This can probably be removed in the future
5252 if !target. contains ( "wasm32" ) && !target. contains ( "nvptx" ) && !target. starts_with ( "riscv" ) {
53- #[ cfg( feature = "c" ) ]
54- c:: compile ( & llvm_target) ;
53+ #[ cfg( feature = "c-vendor" ) ]
54+ c_vendor:: compile ( & llvm_target) ;
55+ #[ cfg( feature = "c-system" ) ]
56+ c_system:: compile ( & llvm_target) ;
5557 }
5658 }
5759
@@ -73,17 +75,14 @@ fn main() {
7375 }
7476}
7577
76- #[ cfg( feature = "c" ) ]
77- mod c {
78- extern crate cc;
79-
78+ #[ cfg( any( feature = "c-vendor" , feature = "c-system" ) ) ]
79+ mod sources {
8080 use std:: collections:: BTreeMap ;
8181 use std:: env;
82- use std:: path:: PathBuf ;
8382
84- struct Sources {
83+ pub struct Sources {
8584 // SYMBOL -> PATH TO SOURCE
86- map : BTreeMap < & ' static str , & ' static str > ,
85+ pub map : BTreeMap < & ' static str , & ' static str > ,
8786 }
8887
8988 impl Sources {
@@ -120,39 +119,11 @@ mod c {
120119 }
121120 }
122121
123- /// Compile intrinsics from the compiler-rt C source code
124- pub fn compile ( llvm_target : & [ & str ] ) {
122+ pub fn get_sources ( llvm_target : & [ & str ] ) -> Sources {
125123 let target_arch = env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
126124 let target_env = env:: var ( "CARGO_CFG_TARGET_ENV" ) . unwrap ( ) ;
127125 let target_os = env:: var ( "CARGO_CFG_TARGET_OS" ) . unwrap ( ) ;
128126 let target_vendor = env:: var ( "CARGO_CFG_TARGET_VENDOR" ) . unwrap ( ) ;
129- let cfg = & mut cc:: Build :: new ( ) ;
130-
131- cfg. warnings ( false ) ;
132-
133- if target_env == "msvc" {
134- // Don't pull in extra libraries on MSVC
135- cfg. flag ( "/Zl" ) ;
136-
137- // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
138- cfg. define ( "__func__" , Some ( "__FUNCTION__" ) ) ;
139- } else {
140- // Turn off various features of gcc and such, mostly copying
141- // compiler-rt's build system already
142- cfg. flag ( "-fno-builtin" ) ;
143- cfg. flag ( "-fvisibility=hidden" ) ;
144- cfg. flag ( "-ffreestanding" ) ;
145- // Avoid the following warning appearing once **per file**:
146- // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
147- //
148- // Note that compiler-rt's build system also checks
149- //
150- // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
151- //
152- // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
153- cfg. flag_if_supported ( "-fomit-frame-pointer" ) ;
154- cfg. define ( "VISIBILITY_HIDDEN" , None ) ;
155- }
156127
157128 let mut sources = Sources :: new ( ) ;
158129 sources. extend ( & [
@@ -414,6 +385,48 @@ mod c {
414385 sources. remove ( & [ "__aeabi_cdcmp" , "__aeabi_cfcmp" ] ) ;
415386 }
416387
388+ sources
389+ }
390+ }
391+
392+ #[ cfg( feature = "c-vendor" ) ]
393+ mod c_vendor {
394+ extern crate cc;
395+
396+ use std:: env;
397+ use std:: path:: PathBuf ;
398+ use sources;
399+
400+ /// Compile intrinsics from the compiler-rt C source code
401+ pub fn compile ( llvm_target : & [ & str ] ) {
402+ let target_env = env:: var ( "CARGO_CFG_TARGET_ENV" ) . unwrap ( ) ;
403+ let cfg = & mut cc:: Build :: new ( ) ;
404+ cfg. warnings ( false ) ;
405+
406+ if target_env == "msvc" {
407+ // Don't pull in extra libraries on MSVC
408+ cfg. flag ( "/Zl" ) ;
409+
410+ // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
411+ cfg. define ( "__func__" , Some ( "__FUNCTION__" ) ) ;
412+ } else {
413+ // Turn off various features of gcc and such, mostly copying
414+ // compiler-rt's build system already
415+ cfg. flag ( "-fno-builtin" ) ;
416+ cfg. flag ( "-fvisibility=hidden" ) ;
417+ cfg. flag ( "-ffreestanding" ) ;
418+ // Avoid the following warning appearing once **per file**:
419+ // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
420+ //
421+ // Note that compiler-rt's build system also checks
422+ //
423+ // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
424+ //
425+ // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
426+ cfg. flag_if_supported ( "-fomit-frame-pointer" ) ;
427+ cfg. define ( "VISIBILITY_HIDDEN" , None ) ;
428+ }
429+
417430 // When compiling the C code we require the user to tell us where the
418431 // source code is, and this is largely done so when we're compiling as
419432 // part of rust-lang/rust we can use the same llvm-project repository as
@@ -431,6 +444,7 @@ mod c {
431444 // use of that macro in lib/builtins/int_util.h in compiler-rt.
432445 cfg. flag_if_supported ( & format ! ( "-ffile-prefix-map={}=." , root. display( ) ) ) ;
433446
447+ let sources = sources:: get_sources ( llvm_target) ;
434448 let src_dir = root. join ( "lib/builtins" ) ;
435449 for ( sym, src) in sources. map . iter ( ) {
436450 let src = src_dir. join ( src) ;
@@ -442,3 +456,41 @@ mod c {
442456 cfg. compile ( "libcompiler-rt.a" ) ;
443457 }
444458}
459+
460+ #[ cfg( feature = "c-system" ) ]
461+ mod c_system {
462+ use std:: env;
463+ use std:: process:: Command ;
464+ use std:: str;
465+ use sources;
466+
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" ) ;
482+ let status = output. status ;
483+ if !status. success ( ) {
484+ panic ! ( format!( "failed to find clang lib dir: {:?}" , status. code( ) ) ) ;
485+ }
486+ for search_dir in str:: from_utf8 ( & output. stdout ) . unwrap ( ) . lines ( ) {
487+ println ! ( "cargo:rustc-link-search=native={}" , search_dir) ;
488+ }
489+ println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
490+
491+ let sources = sources:: get_sources ( llvm_target) ;
492+ for ( sym, _src) in sources. map . iter ( ) {
493+ println ! ( "cargo:rustc-cfg={}=\" optimized-c\" " , sym) ;
494+ }
495+ }
496+ }
0 commit comments