Skip to content

Commit 2965a3c

Browse files
committed
Support linking against system clang libs
1 parent 1ac3970 commit 2965a3c

File tree

3 files changed

+99
-40
lines changed

3 files changed

+99
-40
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ default = ["compiler-builtins"]
4242

4343
# Enable compilation of C code in compiler-rt, filling in some more optimized
4444
# implementations and also filling in unimplemented intrinsics
45-
c = ["cc"]
45+
c-vendor = ["cc"]
46+
47+
# Link against system clang_rt.* libraries. LLVM_CONFIG must be set.
48+
c-system = []
49+
50+
c = ["c-vendor"]
4651

4752
# Flag this library as the unstable compiler-builtins lib
4853
compiler-builtins = []

build.rs

Lines changed: 91 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

testcrate/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ utest-macros = { git = "https://github.com/japaric/utest" }
2323

2424
[features]
2525
c = ["compiler_builtins/c"]
26+
c-vendor = ["compiler_builtins/c-vendor"]
27+
c-system = ["compiler_builtins/c-system"]
2628
mem = ["compiler_builtins/mem"]
2729
mangled-names = ["compiler_builtins/mangled-names"]
2830
default = ["mangled-names"]

0 commit comments

Comments
 (0)