Skip to content

Commit a1faddd

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 fba7fed commit a1faddd

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.
@@ -2533,6 +2533,21 @@ impl Build {
25332533
}
25342534
None => default_ar,
25352535
}
2536+
} else if target.starts_with("wasm32") {
2537+
// Formally speaking one should be able to use this approach,
2538+
// parsing -print-search-dirs output, to cover all clang targets,
2539+
// including Android SDKs and other cross-compilation scenarios...
2540+
// And even extend it to gcc targets by seaching for "ar" instead
2541+
// of "llvm-ar"...
2542+
let compiler = self.get_base_compiler()?;
2543+
if compiler.family == ToolFamily::Clang {
2544+
match search_programs(&mut self.cmd(&compiler.path), "llvm-ar") {
2545+
Some(ar) => ar.to_str().unwrap().to_owned(),
2546+
None => default_ar,
2547+
}
2548+
} else {
2549+
default_ar
2550+
}
25362551
} else {
25372552
default_ar
25382553
};
@@ -3280,7 +3295,7 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
32803295
}
32813296
}
32823297

3283-
fn which(tool: &Path) -> Option<PathBuf> {
3298+
fn which(tool: &Path, path_entries: Option<OsString>) -> Option<PathBuf> {
32843299
fn check_exe(exe: &mut PathBuf) -> bool {
32853300
let exe_ext = std::env::consts::EXE_EXTENSION;
32863301
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
@@ -3293,9 +3308,23 @@ fn which(tool: &Path) -> Option<PathBuf> {
32933308
}
32943309

32953310
// Loop through PATH entries searching for the |tool|.
3296-
let path_entries = env::var_os("PATH")?;
3311+
let path_entries = path_entries.or(env::var_os("PATH"))?;
32973312
env::split_paths(&path_entries).find_map(|path_entry| {
32983313
let mut exe = path_entry.join(tool);
32993314
return if check_exe(&mut exe) { Some(exe) } else { None };
33003315
})
33013316
}
3317+
3318+
// search for |prog| on 'programs' path in '|cc| -print-search-dirs' output
3319+
fn search_programs(cc: &mut Command, prog: &str) -> Option<PathBuf> {
3320+
let search_dirs = run_output(cc.arg("-print-search-dirs"), "cc").ok()?;
3321+
// clang driver appears to be forcing UTF-8 output even on Windows,
3322+
// hence from_utf8 is assumed to be usable in all cases.
3323+
let search_dirs = std::str::from_utf8(&search_dirs).ok()?;
3324+
for dirs in search_dirs.split(|c| c == '\r' || c == '\n') {
3325+
if dirs.starts_with("programs: =") {
3326+
return which(Path::new(prog), Some(OsString::from(&dirs[11..])));
3327+
}
3328+
}
3329+
None
3330+
}

0 commit comments

Comments
 (0)