Skip to content

Commit 239b632

Browse files
committed
Default to llvm-ar when compiling with clang --target=wasm32.
Generalization of the method would facilitate cases when system ar(1) doesn't support any given cross-compile target. This is because accompanying llvm-ar is known to match targets supported by the clang installation at hand.
1 parent 0e51f6d commit 239b632

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

src/lib.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ impl Build {
11061106
None => "none",
11071107
};
11081108
if cudart != "none" {
1109-
if let Some(nvcc) = which(&self.get_compiler().path) {
1109+
if let Some(nvcc) = which(&self.get_compiler().path, None) {
11101110
// Try to figure out the -L search path. If it fails,
11111111
// it's on user to specify one by passing it through
11121112
// RUSTFLAGS environment variable.
@@ -2664,6 +2664,21 @@ impl Build {
26642664
}
26652665

26662666
"emar".to_string()
2667+
} else if target.starts_with("wasm32") {
2668+
// Formally speaking one should be able to use this approach,
2669+
// parsing -print-search-dirs output, to cover all clang targets,
2670+
// including Android SDKs and other cross-compilation scenarios...
2671+
// And even extend it to gcc targets by seaching for "ar" instead
2672+
// of "llvm-ar"...
2673+
let compiler = self.get_base_compiler()?;
2674+
if compiler.family == ToolFamily::Clang {
2675+
match search_programs(&mut self.cmd(&compiler.path), "llvm-ar") {
2676+
Some(ar) => ar.to_str().unwrap().to_owned(),
2677+
None => default_ar,
2678+
}
2679+
} else {
2680+
default_ar
2681+
}
26672682
} else if target.contains("msvc") {
26682683
let compiler = self.get_base_compiler()?;
26692684
let mut lib = String::new();
@@ -2673,10 +2688,10 @@ impl Build {
26732688
// next to 'clang-cl' and use 'search_programs()' to locate
26742689
// 'llvm-lib'. This is because 'clang-cl' doesn't support
26752690
// the -print-search-dirs option.
2676-
if let Some(mut cmd) = which(&compiler.path) {
2691+
if let Some(mut cmd) = which(&compiler.path, None) {
26772692
cmd.pop();
26782693
cmd.push("llvm-lib.exe");
2679-
if let Some(llvm_lib) = which(&cmd) {
2694+
if let Some(llvm_lib) = which(&cmd, None) {
26802695
lib = llvm_lib.to_str().unwrap().to_owned();
26812696
}
26822697
}
@@ -3522,7 +3537,7 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
35223537
}
35233538
}
35243539

3525-
fn which(tool: &Path) -> Option<PathBuf> {
3540+
fn which(tool: &Path, path_entries: Option<OsString>) -> Option<PathBuf> {
35263541
fn check_exe(exe: &mut PathBuf) -> bool {
35273542
let exe_ext = std::env::consts::EXE_EXTENSION;
35283543
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
@@ -3535,7 +3550,7 @@ fn which(tool: &Path) -> Option<PathBuf> {
35353550
}
35363551

35373552
// Loop through PATH entries searching for the |tool|.
3538-
let path_entries = env::var_os("PATH")?;
3553+
let path_entries = path_entries.or(env::var_os("PATH"))?;
35393554
env::split_paths(&path_entries).find_map(|path_entry| {
35403555
let mut exe = path_entry.join(tool);
35413556
return if check_exe(&mut exe) { Some(exe) } else { None };
@@ -3566,3 +3581,17 @@ impl AsmFileExt {
35663581
None
35673582
}
35683583
}
3584+
3585+
// search for |prog| on 'programs' path in '|cc| -print-search-dirs' output
3586+
fn search_programs(cc: &mut Command, prog: &str) -> Option<PathBuf> {
3587+
let search_dirs = run_output(cc.arg("-print-search-dirs"), "cc").ok()?;
3588+
// clang driver appears to be forcing UTF-8 output even on Windows,
3589+
// hence from_utf8 is assumed to be usable in all cases.
3590+
let search_dirs = std::str::from_utf8(&search_dirs).ok()?;
3591+
for dirs in search_dirs.split(|c| c == '\r' || c == '\n') {
3592+
if dirs.starts_with("programs: =") {
3593+
return which(Path::new(prog), Some(OsString::from(&dirs[11..])));
3594+
}
3595+
}
3596+
None
3597+
}

0 commit comments

Comments
 (0)