Skip to content

Commit 6aa82fe

Browse files
infinity0Ximin Luo
authored and
Ximin Luo
committed
Support using clang as well
1 parent 30001f7 commit 6aa82fe

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
@@ -457,33 +457,85 @@ mod c_vendor {
457457
#[cfg(feature = "c-system")]
458458
mod c_system {
459459
use std::env;
460-
use std::process::Command;
460+
use std::process::{Command, Output};
461461
use std::str;
462+
use std::path::Path;
462463
use sources;
463464

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");
465+
fn success_output(err: &str, cmd: &mut Command) -> Output {
466+
let output = cmd.output().expect(err);
479467
let status = output.status;
480468
if !status.success() {
481-
panic!(format!("failed to find clang lib dir: {:?}", status.code()));
469+
panic!("{}: {:?}", err, status.code());
482470
}
483-
for search_dir in str::from_utf8(&output.stdout).unwrap().lines() {
484-
println!("cargo:rustc-link-search=native={}", search_dir);
471+
output
472+
}
473+
474+
// This function recreates the logic of getArchNameForCompilerRTLib,
475+
// defined in clang/lib/Driver/ToolChain.cpp.
476+
fn get_arch_name_for_compiler_rtlib() -> String {
477+
let target = env::var("TARGET").unwrap();
478+
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
479+
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
480+
let r = match target_arch.as_str() {
481+
"arm" => if target.ends_with("eabihf") && target_os != "windows" {
482+
"armhf"
483+
} else {
484+
"arm"
485+
},
486+
"x86" => if target_os == "android" {
487+
"i686"
488+
} else {
489+
"i386"
490+
},
491+
_ => target_arch.as_str(),
492+
};
493+
r.to_string()
494+
}
495+
496+
/// Link against system clang runtime libraries
497+
pub fn compile(llvm_target: &[&str]) {
498+
let target = env::var("TARGET").unwrap();
499+
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
500+
let compiler_rt_arch = get_arch_name_for_compiler_rtlib();
501+
502+
if let Ok(clang) = env::var("CLANG") {
503+
let output = success_output(
504+
"failed to find clang's compiler-rt",
505+
Command::new(clang)
506+
.arg(format!("--target={}", target))
507+
.arg("--rtlib=compiler-rt")
508+
.arg("--print-libgcc-file-name"),
509+
);
510+
let fullpath = Path::new(str::from_utf8(&output.stdout).unwrap());
511+
let libpath = fullpath.parent().unwrap().display();
512+
let libname = fullpath
513+
.file_stem()
514+
.unwrap()
515+
.to_str()
516+
.unwrap()
517+
.trim_start_matches("lib");
518+
println!("cargo:rustc-link-search=native={}", libpath);
519+
println!("cargo:rustc-link-lib=static={}", libname);
520+
} else if let Ok(llvm_config) = env::var("LLVM_CONFIG") {
521+
// fallback if clang is not installed
522+
let (subpath, libname) = match target_os.as_str() {
523+
"linux" => ("linux", format!("clang_rt.builtins-{}", &compiler_rt_arch)),
524+
"macos" => ("darwin", "clang_rt.builtins_osx_dynamic".to_string()),
525+
_ => panic!("unsupported target os: {}", target_os),
526+
};
527+
let cmd = format!("ls -1d $({} --libdir)/clang/*/lib/{}", llvm_config, subpath);
528+
let output = success_output(
529+
"failed to find clang's lib dir",
530+
Command::new("sh").args(&["-ec", &cmd]),
531+
);
532+
for search_dir in str::from_utf8(&output.stdout).unwrap().lines() {
533+
println!("cargo:rustc-link-search=native={}", search_dir);
534+
}
535+
println!("cargo:rustc-link-lib=static={}", libname);
536+
} else {
537+
panic!("neither CLANG nor LLVM_CONFIG could be read");
485538
}
486-
println!("cargo:rustc-link-lib=static={}", libname);
487539

488540
let sources = sources::get_sources(llvm_target);
489541
for (sym, _src) in sources.map.iter() {

0 commit comments

Comments
 (0)