mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-21 13:08:42 +00:00
Fix detect_targets_linux
: Detect arch/libc at runtime using guess_host_triple
(#649)
- Enable `guess_host_triple` on all targets - Fix `detect_targets_linux`: Detect runtime arch/libc using `guess_host_triple` instead of using the one specified in `TARGET`. - Add support for android in `detect_targets` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
49f60d37fe
commit
42672ccf40
3 changed files with 47 additions and 58 deletions
|
@ -12,8 +12,6 @@ license = "Apache-2.0 OR MIT"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.23.0", features = ["rt", "process", "sync"], default-features = false }
|
tokio = { version = "1.23.0", features = ["rt", "process", "sync"], default-features = false }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
|
||||||
guess_host_triple = "0.1.3"
|
guess_host_triple = "0.1.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -42,6 +42,8 @@ pub async fn detect_targets() -> Vec<String> {
|
||||||
|
|
||||||
if targets[0].contains("gnu") {
|
if targets[0].contains("gnu") {
|
||||||
targets.push(targets[0].replace("gnu", "musl"));
|
targets.push(targets[0].replace("gnu", "musl"));
|
||||||
|
} else if targets[0].contains("android") {
|
||||||
|
targets.push(targets[0].replace("android", "musl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
targets
|
targets
|
||||||
|
|
|
@ -2,43 +2,58 @@ use crate::TARGET;
|
||||||
|
|
||||||
use std::process::{Output, Stdio};
|
use std::process::{Output, Stdio};
|
||||||
|
|
||||||
|
use guess_host_triple::guess_host_triple;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
pub(super) async fn detect_targets_linux() -> Vec<String> {
|
pub(super) async fn detect_targets_linux() -> Vec<String> {
|
||||||
let (abi, libc) = parse_abi_and_libc();
|
let target = guess_host_triple().unwrap_or(TARGET);
|
||||||
|
|
||||||
if let Libc::Glibc = libc {
|
let (prefix, postfix) = target
|
||||||
// Glibc can only be dynamically linked.
|
.rsplit_once('-')
|
||||||
// If we can run this binary, then it means that the target
|
.expect("unwrap: target always has a -");
|
||||||
// supports both glibc and musl.
|
|
||||||
return create_targets_str(&["gnu", "musl"], abi);
|
let (abi, libc) = if let Some(abi) = postfix.strip_prefix("musl") {
|
||||||
|
(abi, Libc::Musl)
|
||||||
|
} else if let Some(abi) = postfix.strip_prefix("gnu") {
|
||||||
|
(abi, Libc::Gnu)
|
||||||
|
} else if let Some(abi) = postfix.strip_prefix("android") {
|
||||||
|
(abi, Libc::Android)
|
||||||
|
} else {
|
||||||
|
(postfix, Libc::Unknown)
|
||||||
|
};
|
||||||
|
|
||||||
|
let musl_fallback_target = || format!("{prefix}-{}{abi}", "musl");
|
||||||
|
|
||||||
|
match libc {
|
||||||
|
Libc::Gnu => {
|
||||||
|
// guess_host_triple cannot detect whether the system is using glibc,
|
||||||
|
// musl libc or other libc.
|
||||||
|
//
|
||||||
|
// As such, we need to launch the test ourselves.
|
||||||
|
if supports_gnu().await {
|
||||||
|
vec![target.to_string(), musl_fallback_target()]
|
||||||
|
} else {
|
||||||
|
vec![musl_fallback_target()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Libc::Android => vec![target.to_string(), musl_fallback_target()],
|
||||||
|
|
||||||
|
_ => vec![target.to_string()],
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(Output {
|
async fn supports_gnu() -> bool {
|
||||||
status: _,
|
Command::new("ldd")
|
||||||
stdout,
|
|
||||||
stderr,
|
|
||||||
}) = Command::new("ldd")
|
|
||||||
.arg("--version")
|
.arg("--version")
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.output()
|
.output()
|
||||||
.await
|
.await
|
||||||
{
|
.ok()
|
||||||
let libc_version = if let Some(libc_version) = parse_libc_version_from_ldd_output(&stdout) {
|
.and_then(|Output { stdout, stderr, .. }| {
|
||||||
libc_version
|
parse_libc_version_from_ldd_output(&stdout)
|
||||||
} else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) {
|
.or_else(|| parse_libc_version_from_ldd_output(&stderr))
|
||||||
libc_version
|
})
|
||||||
} else {
|
== Some("gnu")
|
||||||
return vec![create_target_str("musl", abi)];
|
|
||||||
};
|
|
||||||
|
|
||||||
if libc_version == "gnu" {
|
|
||||||
return create_targets_str(&["gnu", "musl"], abi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to using musl
|
|
||||||
vec![create_target_str("musl", abi)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> {
|
fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> {
|
||||||
|
@ -53,34 +68,8 @@ fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Libc {
|
enum Libc {
|
||||||
Glibc,
|
Gnu,
|
||||||
Musl,
|
Musl,
|
||||||
}
|
Android,
|
||||||
|
Unknown,
|
||||||
fn parse_abi_and_libc() -> (&'static str, Libc) {
|
|
||||||
let last = TARGET.rsplit_once('-').unwrap().1;
|
|
||||||
|
|
||||||
if let Some(libc_version) = last.strip_prefix("musl") {
|
|
||||||
(libc_version, Libc::Musl)
|
|
||||||
} else if let Some(libc_version) = last.strip_prefix("gnu") {
|
|
||||||
(libc_version, Libc::Glibc)
|
|
||||||
} else {
|
|
||||||
panic!("Unrecognized libc")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_target_str(libc_version: &str, abi: &str) -> String {
|
|
||||||
let prefix = TARGET
|
|
||||||
.rsplit_once('-')
|
|
||||||
.expect("unwrap: TARGET always has a -")
|
|
||||||
.0;
|
|
||||||
|
|
||||||
format!("{prefix}-{libc_version}{abi}")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_targets_str(libc_versions: &[&str], abi: &str) -> Vec<String> {
|
|
||||||
libc_versions
|
|
||||||
.iter()
|
|
||||||
.map(|libc_version| create_target_str(libc_version, abi))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue