Skip to content

Commit ec70931

Browse files
committed
Support using clang as well
1 parent 2965a3c commit ec70931

File tree

2 files changed

+74
-21
lines changed

2 files changed

+74
-21
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ default = ["compiler-builtins"]
4444
# implementations and also filling in unimplemented intrinsics
4545
c-vendor = ["cc"]
4646

47-
# Link against system clang_rt.* libraries. LLVM_CONFIG must be set.
47+
# Link against system clang_rt.* libraries.
48+
# LLVM_CONFIG or CLANG (more reliable) must be set.
4849
c-system = []
4950

5051
c = ["c-vendor"]

build.rs

+72-20
Original file line numberDiff line numberDiff line change
@@ -460,33 +460,85 @@ mod c_vendor {
460460
#[cfg(feature = "c-system")]
461461
mod 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

Comments
 (0)