Skip to content

Commit 30001f7

Browse files
infinity0Ximin Luo
authored and
Ximin Luo
committed
Support linking against system clang libs
1 parent 44dc22f commit 30001f7

File tree

3 files changed

+99
-40
lines changed

3 files changed

+99
-40
lines changed

Diff for: Cargo.toml

+6-1
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 = []

Diff for: build.rs

+91-39
Original file line numberDiff line numberDiff line change
@@ -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+
}

Diff for: testcrate/Cargo.toml

+2
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)