Skip to content

Commit de870dc

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 f2e1b1c commit de870dc

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.
@@ -2517,6 +2517,21 @@ impl Build {
25172517
}
25182518

25192519
"emar".to_string()
2520+
} else if target.starts_with("wasm32") {
2521+
// Formally speaking one should be able to use this approach,
2522+
// parsing -print-search-dirs output, to cover all clang targets,
2523+
// including Android SDKs and other cross-compilation scenarios...
2524+
// And even extend it to gcc targets by seaching for "ar" instead
2525+
// of "llvm-ar"...
2526+
let compiler = self.get_base_compiler()?;
2527+
if compiler.family == ToolFamily::Clang {
2528+
match search_programs(&mut self.cmd(&compiler.path), "llvm-ar") {
2529+
Some(ar) => ar.to_str().unwrap().to_owned(),
2530+
None => default_ar,
2531+
}
2532+
} else {
2533+
default_ar
2534+
}
25202535
} else if target.contains("msvc") {
25212536
match windows_registry::find(&target, "lib.exe") {
25222537
Some(t) => return Ok((t, "lib.exe".to_string())),
@@ -3287,7 +3302,7 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<
32873302
}
32883303
}
32893304

3290-
fn which(tool: &Path) -> Option<PathBuf> {
3305+
fn which(tool: &Path, path_entries: Option<OsString>) -> Option<PathBuf> {
32913306
fn check_exe(exe: &mut PathBuf) -> bool {
32923307
let exe_ext = std::env::consts::EXE_EXTENSION;
32933308
exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists())
@@ -3300,9 +3315,23 @@ fn which(tool: &Path) -> Option<PathBuf> {
33003315
}
33013316

33023317
// Loop through PATH entries searching for the |tool|.
3303-
let path_entries = env::var_os("PATH")?;
3318+
let path_entries = path_entries.or(env::var_os("PATH"))?;
33043319
env::split_paths(&path_entries).find_map(|path_entry| {
33053320
let mut exe = path_entry.join(tool);
33063321
return if check_exe(&mut exe) { Some(exe) } else { None };
33073322
})
33083323
}
3324+
3325+
// search for |prog| on 'programs' path in '|cc| -print-search-dirs' output
3326+
fn search_programs(cc: &mut Command, prog: &str) -> Option<PathBuf> {
3327+
let search_dirs = run_output(cc.arg("-print-search-dirs"), "cc").ok()?;
3328+
// clang driver appears to be forcing UTF-8 output even on Windows,
3329+
// hence from_utf8 is assumed to be usable in all cases.
3330+
let search_dirs = std::str::from_utf8(&search_dirs).ok()?;
3331+
for dirs in search_dirs.split(|c| c == '\r' || c == '\n') {
3332+
if dirs.starts_with("programs: =") {
3333+
return which(Path::new(prog), Some(OsString::from(&dirs[11..])));
3334+
}
3335+
}
3336+
None
3337+
}

0 commit comments

Comments
 (0)