Skip to content

Commit fbc1214

Browse files
authored
Use a search list to find a compatible toolchain (#521)
* cross-compile: add find_working_gnu_prefix to detect compiler Add `find_working_gnu_prefix()` to iterate through a slice of potential compiler prefixes, and return the first one that succeeds. This is useful when there is not yet a single clear toolchain prefix, for example with riscv (riscv64-unknown-none-elf vs riscv32-unknown-none-elf vs riscv-none-embed). Signed-off-by: Sean Cross <[email protected]> * cross-compile: riscv: look through whitelist of compilers riscv currently has several competing compiler toolchain prefixes. If a toolchain supports multilib, then an "incorrect" target triple may be used. For example, many distributions ship multilib toolchains with a `riscv64` prefix, so a riscv32imac-unknown-none-elf target can successfully use a toolchain with a triple of `riscv64-unknown-none`. Signed-off-by: Sean Cross <[email protected]>
1 parent ad78c15 commit fbc1214

File tree

1 file changed

+57
-5
lines changed

1 file changed

+57
-5
lines changed

src/lib.rs

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,11 +2291,31 @@ impl Build {
22912291
"powerpc-unknown-netbsd" => Some("powerpc--netbsd"),
22922292
"powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"),
22932293
"powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"),
2294-
"riscv32i-unknown-none-elf" => Some("riscv32-unknown-elf"),
2295-
"riscv32imac-unknown-none-elf" => Some("riscv32-unknown-elf"),
2296-
"riscv32imc-unknown-none-elf" => Some("riscv32-unknown-elf"),
2297-
"riscv64gc-unknown-none-elf" => Some("riscv64-unknown-elf"),
2298-
"riscv64imac-unknown-none-elf" => Some("riscv64-unknown-elf"),
2294+
"riscv32i-unknown-none-elf" => self.find_working_gnu_prefix(&[
2295+
"riscv32-unknown-elf",
2296+
"riscv64-unknown-elf",
2297+
"riscv-none-embed",
2298+
]),
2299+
"riscv32imac-unknown-none-elf" => self.find_working_gnu_prefix(&[
2300+
"riscv32-unknown-elf",
2301+
"riscv64-unknown-elf",
2302+
"riscv-none-embed",
2303+
]),
2304+
"riscv32imc-unknown-none-elf" => self.find_working_gnu_prefix(&[
2305+
"riscv32-unknown-elf",
2306+
"riscv64-unknown-elf",
2307+
"riscv-none-embed",
2308+
]),
2309+
"riscv64gc-unknown-none-elf" => self.find_working_gnu_prefix(&[
2310+
"riscv64-unknown-elf",
2311+
"riscv32-unknown-elf",
2312+
"riscv-none-embed",
2313+
]),
2314+
"riscv64imac-unknown-none-elf" => self.find_working_gnu_prefix(&[
2315+
"riscv64-unknown-elf",
2316+
"riscv32-unknown-elf",
2317+
"riscv-none-embed",
2318+
]),
22992319
"riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"),
23002320
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
23012321
"sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"),
@@ -2325,6 +2345,38 @@ impl Build {
23252345
.map(|x| x.to_owned()))
23262346
}
23272347

2348+
/// Some platforms have multiple, compatible, canonical prefixes. Look through
2349+
/// each possible prefix for a compiler that exists and return it. The prefixes
2350+
/// should be ordered from most-likely to least-likely.
2351+
fn find_working_gnu_prefix(&self, prefixes: &[&'static str]) -> Option<&'static str> {
2352+
let suffix = if self.cpp { "-g++" } else { "-gcc" };
2353+
let extension = std::env::consts::EXE_SUFFIX;
2354+
2355+
// Loop through PATH entries searching for each toolchain. This ensures that we
2356+
// are more likely to discover the toolchain early on, because chances are good
2357+
// that the desired toolchain is in one of the higher-priority paths.
2358+
env::var_os("PATH")
2359+
.as_ref()
2360+
.and_then(|path_entries| {
2361+
env::split_paths(path_entries).find_map(|path_entry| {
2362+
for prefix in prefixes {
2363+
let target_compiler = format!("{}{}{}", prefix, suffix, extension);
2364+
if path_entry.join(&target_compiler).exists() {
2365+
return Some(prefix);
2366+
}
2367+
}
2368+
None
2369+
})
2370+
})
2371+
.map(|prefix| *prefix)
2372+
.or_else(||
2373+
// If no toolchain was found, provide the first toolchain that was passed in.
2374+
// This toolchain has been shown not to exist, however it will appear in the
2375+
// error that is shown to the user which should make it easier to search for
2376+
// where it should be obtained.
2377+
prefixes.first().map(|prefix| *prefix))
2378+
}
2379+
23282380
fn get_target(&self) -> Result<String, Error> {
23292381
match self.target.clone() {
23302382
Some(t) => Ok(t),

0 commit comments

Comments
 (0)