Skip to content

Commit dd2909c

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 53fb72c commit dd2909c

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

src/lib.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ impl Build {
10291029
None => "none",
10301030
};
10311031
if cudart != "none" {
1032-
if let Some(nvcc) = which(&self.get_compiler().path) {
1032+
if let Some(nvcc) = which(&self.get_compiler().path, None) {
10331033
// Try to figure out the -L search path. If it fails,
10341034
// it's on user to specify one by passing it through
10351035
// RUSTFLAGS environment variable.
@@ -2565,6 +2565,21 @@ impl Build {
25652565
}
25662566

25672567
"emar".to_string()
2568+
} else if target.starts_with("wasm32") {
2569+
// Formally speaking one should be able to use this approach,
2570+
// parsing -print-search-dirs output, to cover all clang targets,
2571+
// including Android SDKs and other cross-compilation scenarios...
2572+
// And even extend it to gcc targets by seaching for "ar" instead
2573+
// of "llvm-ar"...
2574+
let compiler = self.get_base_compiler()?;
2575+
if compiler.family == ToolFamily::Clang {
2576+
match search_programs(&mut self.cmd(&compiler.path), "llvm-ar") {
2577+
Some(ar) => ar.to_str().unwrap().to_owned(),
2578+
None => default_ar,
2579+
}
2580+
} else {
2581+
default_ar
2582+
}
25682583
} else if target.contains("msvc") {
25692584
match windows_registry::find(&target, "lib.exe") {
25702585
Some(t) => return Ok((t, "lib.exe".to_string())),
@@ -3335,7 +3350,7 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
33353350
}
33363351
}
33373352

3338-
fn which(tool: &Path) -> Option<PathBuf> {
3353+
fn which(tool: &Path, path_entries: Option<OsString>) -> Option<PathBuf> {
33393354
fn check_exe(exe: &mut PathBuf) -> bool {
33403355
let exe_ext = std::env::consts::EXE_EXTENSION;
33413356
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
@@ -3348,9 +3363,23 @@ fn which(tool: &Path) -> Option<PathBuf> {
33483363
}
33493364

33503365
// Loop through PATH entries searching for the |tool|.
3351-
let path_entries = env::var_os("PATH")?;
3366+
let path_entries = path_entries.or(env::var_os("PATH"))?;
33523367
env::split_paths(&path_entries).find_map(|path_entry| {
33533368
let mut exe = path_entry.join(tool);
33543369
return if check_exe(&mut exe) { Some(exe) } else { None };
33553370
})
33563371
}
3372+
3373+
// search for |prog| on 'programs' path in '|cc| -print-search-dirs' output
3374+
fn search_programs(cc: &mut Command, prog: &str) -> Option<PathBuf> {
3375+
let search_dirs = run_output(cc.arg("-print-search-dirs"), "cc").ok()?;
3376+
// clang driver appears to be forcing UTF-8 output even on Windows,
3377+
// hence from_utf8 is assumed to be usable in all cases.
3378+
let search_dirs = std::str::from_utf8(&search_dirs).ok()?;
3379+
for dirs in search_dirs.split(|c| c == '\r' || c == '\n') {
3380+
if dirs.starts_with("programs: =") {
3381+
return which(Path::new(prog), Some(OsString::from(&dirs[11..])));
3382+
}
3383+
}
3384+
None
3385+
}

0 commit comments

Comments
 (0)