@@ -37,7 +37,7 @@ fn main() {
3737 // mangling names though we assume that we're also in test mode so we don't
3838 // build anything and we rely on the upstream implementation of compiler-rt
3939 // functions
40- if !cfg ! ( feature = "mangled-names" ) && cfg ! ( feature = "c" ) {
40+ if !cfg ! ( feature = "mangled-names" ) && cfg ! ( any ( feature = "c-vendor" , feature = "c-system" ) ) {
4141 // Don't use a C compiler for these targets:
4242 //
4343 // * wasm32 - clang 8 for wasm is somewhat hard to come by and it's
@@ -47,8 +47,10 @@ fn main() {
4747 // compiler nor is cc-rs ready for compilation to riscv (at this
4848 // time). This can probably be removed in the future
4949 if !target. contains ( "wasm32" ) && !target. contains ( "nvptx" ) && !target. starts_with ( "riscv" ) {
50- #[ cfg( feature = "c" ) ]
51- c:: compile ( & llvm_target) ;
50+ #[ cfg( feature = "c-vendor" ) ]
51+ c_vendor:: compile ( & llvm_target) ;
52+ #[ cfg( feature = "c-system" ) ]
53+ c_system:: compile ( & llvm_target) ;
5254 }
5355 }
5456
@@ -70,17 +72,14 @@ fn main() {
7072 }
7173}
7274
73- #[ cfg( feature = "c" ) ]
74- mod c {
75- extern crate cc;
76-
75+ #[ cfg( any( feature = "c-vendor" , feature = "c-system" ) ) ]
76+ mod sources {
7777 use std:: collections:: BTreeMap ;
7878 use std:: env;
79- use std:: path:: PathBuf ;
8079
81- struct Sources {
80+ pub struct Sources {
8281 // SYMBOL -> PATH TO SOURCE
83- map : BTreeMap < & ' static str , & ' static str > ,
82+ pub map : BTreeMap < & ' static str , & ' static str > ,
8483 }
8584
8685 impl Sources {
@@ -117,39 +116,11 @@ mod c {
117116 }
118117 }
119118
120- /// Compile intrinsics from the compiler-rt C source code
121- pub fn compile ( llvm_target : & [ & str ] ) {
119+ pub fn get_sources ( llvm_target : & [ & str ] ) -> Sources {
122120 let target_arch = env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
123121 let target_env = env:: var ( "CARGO_CFG_TARGET_ENV" ) . unwrap ( ) ;
124122 let target_os = env:: var ( "CARGO_CFG_TARGET_OS" ) . unwrap ( ) ;
125123 let target_vendor = env:: var ( "CARGO_CFG_TARGET_VENDOR" ) . unwrap ( ) ;
126- let cfg = & mut cc:: Build :: new ( ) ;
127-
128- cfg. warnings ( false ) ;
129-
130- if target_env == "msvc" {
131- // Don't pull in extra libraries on MSVC
132- cfg. flag ( "/Zl" ) ;
133-
134- // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
135- cfg. define ( "__func__" , Some ( "__FUNCTION__" ) ) ;
136- } else {
137- // Turn off various features of gcc and such, mostly copying
138- // compiler-rt's build system already
139- cfg. flag ( "-fno-builtin" ) ;
140- cfg. flag ( "-fvisibility=hidden" ) ;
141- cfg. flag ( "-ffreestanding" ) ;
142- // Avoid the following warning appearing once **per file**:
143- // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
144- //
145- // Note that compiler-rt's build system also checks
146- //
147- // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
148- //
149- // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
150- cfg. flag_if_supported ( "-fomit-frame-pointer" ) ;
151- cfg. define ( "VISIBILITY_HIDDEN" , None ) ;
152- }
153124
154125 let mut sources = Sources :: new ( ) ;
155126 sources. extend ( & [
@@ -411,6 +382,48 @@ mod c {
411382 sources. remove ( & [ "__aeabi_cdcmp" , "__aeabi_cfcmp" ] ) ;
412383 }
413384
385+ sources
386+ }
387+ }
388+
389+ #[ cfg( feature = "c-vendor" ) ]
390+ mod c_vendor {
391+ extern crate cc;
392+
393+ use std:: env;
394+ use std:: path:: PathBuf ;
395+ use sources;
396+
397+ /// Compile intrinsics from the compiler-rt C source code
398+ pub fn compile ( llvm_target : & [ & str ] ) {
399+ let target_env = env:: var ( "CARGO_CFG_TARGET_ENV" ) . unwrap ( ) ;
400+ let cfg = & mut cc:: Build :: new ( ) ;
401+ cfg. warnings ( false ) ;
402+
403+ if target_env == "msvc" {
404+ // Don't pull in extra libraries on MSVC
405+ cfg. flag ( "/Zl" ) ;
406+
407+ // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
408+ cfg. define ( "__func__" , Some ( "__FUNCTION__" ) ) ;
409+ } else {
410+ // Turn off various features of gcc and such, mostly copying
411+ // compiler-rt's build system already
412+ cfg. flag ( "-fno-builtin" ) ;
413+ cfg. flag ( "-fvisibility=hidden" ) ;
414+ cfg. flag ( "-ffreestanding" ) ;
415+ // Avoid the following warning appearing once **per file**:
416+ // clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
417+ //
418+ // Note that compiler-rt's build system also checks
419+ //
420+ // `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
421+ //
422+ // in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
423+ cfg. flag_if_supported ( "-fomit-frame-pointer" ) ;
424+ cfg. define ( "VISIBILITY_HIDDEN" , None ) ;
425+ }
426+
414427 // When compiling the C code we require the user to tell us where the
415428 // source code is, and this is largely done so when we're compiling as
416429 // part of rust-lang/rust we can use the same llvm-project repository as
@@ -428,6 +441,7 @@ mod c {
428441 // use of that macro in lib/builtins/int_util.h in compiler-rt.
429442 cfg. flag_if_supported ( & format ! ( "-ffile-prefix-map={}=." , root. display( ) ) ) ;
430443
444+ let sources = sources:: get_sources ( llvm_target) ;
431445 let src_dir = root. join ( "lib/builtins" ) ;
432446 for ( sym, src) in sources. map . iter ( ) {
433447 let src = src_dir. join ( src) ;
@@ -439,3 +453,41 @@ mod c {
439453 cfg. compile ( "libcompiler-rt.a" ) ;
440454 }
441455}
456+
457+ #[ cfg( feature = "c-system" ) ]
458+ mod c_system {
459+ use std:: env;
460+ use std:: process:: Command ;
461+ use std:: str;
462+ use sources;
463+
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" ) ;
479+ let status = output. status ;
480+ if !status. success ( ) {
481+ panic ! ( format!( "failed to find clang lib dir: {:?}" , status. code( ) ) ) ;
482+ }
483+ for search_dir in str:: from_utf8 ( & output. stdout ) . unwrap ( ) . lines ( ) {
484+ println ! ( "cargo:rustc-link-search=native={}" , search_dir) ;
485+ }
486+ println ! ( "cargo:rustc-link-lib=static={}" , libname) ;
487+
488+ let sources = sources:: get_sources ( llvm_target) ;
489+ for ( sym, _src) in sources. map . iter ( ) {
490+ println ! ( "cargo:rustc-cfg={}=\" optimized-c\" " , sym) ;
491+ }
492+ }
493+ }
0 commit comments