cargo-binstall/crates/detect-targets/src/detect.rs
Jiahao XU 76a692224d
Fix detect-targets on Linux and add CI testing (#1344)
* Testing: Add `detect-targets/src/main.rs`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `detect-targets` linux: `guess_host_triple` could return wrong libc info

so it has to check it manually instead of simply providing alternatives
like other OSes.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `get_ld_flavor` for Alpine's gcompat glibc

Its output is different from regular glibc, so we need to hardcode that
particular cases.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix detection of alpine specific musl target

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add ci testing for Alpine

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add CI test for detect-targets on ubuntu

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Refactor `get_ld_flavor`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix shellcheck

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add more CI test for ubuntu

and fixed typo in it

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Rm distro specific target as it breaks `cargo-install` fallback

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Make sure all binaries are built in CI

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add `package.metadata.binstall` for `detect-targets`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix justfile

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `detect-targets-{alpine, ubuntu}-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `detect-targets-ubuntu-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `debug-targets-ubuntu-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* `set -exuo pipefail` in `detect-targets-ubuntu-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Simplify `detect-targets-*-test`: Use `Swatinem/rust-cache@v2` directly

instead of using `just-setup`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Rm dup steps in `detect-targets-ubuntu-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add `ls` to detect-targets-alpine-test for debugging

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* FIx `detect-targets-alpine-test`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `get_ld_flavor`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `linux::detect_targets` on ubuntu & glibc system

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* FIx `linux::detect_targets` glibc checking

Check dynlib suffix

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

---------

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
2023-09-06 14:17:43 +00:00

107 lines
3.2 KiB
Rust

use std::{
borrow::Cow,
env,
ffi::OsStr,
process::{Output, Stdio},
};
use cfg_if::cfg_if;
use tokio::process::Command;
cfg_if! {
if #[cfg(target_os = "linux")] {
mod linux;
} else if #[cfg(target_os = "macos")] {
mod macos;
} else if #[cfg(target_os = "windows")] {
mod windows;
}
}
/// Detect the targets supported at runtime,
/// which might be different from `TARGET` which is detected
/// at compile-time.
///
/// Return targets supported in the order of preference.
/// If target_os is linux and it support gnu, then it is preferred
/// to musl.
///
/// If target_os is mac and it is aarch64, then aarch64 is preferred
/// to x86_64.
///
/// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155)
/// for more information.
pub async fn detect_targets() -> Vec<String> {
let target = get_target_from_rustc().await.unwrap_or_else(|| {
guess_host_triple::guess_host_triple()
.unwrap_or(crate::TARGET)
.to_string()
});
cfg_if! {
if #[cfg(target_os = "macos")] {
let mut targets = vec![target];
targets.extend(macos::detect_alternative_targets(&targets[0]).await);
targets
} else if #[cfg(target_os = "windows")] {
let mut targets = vec![target];
targets.extend(windows::detect_alternative_targets(&targets[0]));
targets
} else if #[cfg(target_os = "linux")] {
// Linux is a bit special, since the result from `guess_host_triple`
// might be wrong about whether glibc or musl is used.
linux::detect_targets(target).await
}
}
}
/// Figure out what the host target is using `rustc`.
/// If `rustc` is absent, then it would return `None`.
///
/// If environment variable `CARGO` is present, then
/// `$CARGO -vV` will be run instead.
///
/// Otherwise, it will run `rustc -vV` to detect target.
async fn get_target_from_rustc() -> Option<String> {
let cmd = env::var_os("CARGO")
.map(Cow::Owned)
.unwrap_or_else(|| Cow::Borrowed(OsStr::new("rustc")));
let Output { status, stdout, .. } = Command::new(cmd)
.arg("-vV")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.ok()?
.wait_with_output()
.await
.ok()?;
if !status.success() {
return None;
}
let stdout = String::from_utf8_lossy(&stdout);
let target = stdout
.lines()
.find_map(|line| line.strip_prefix("host: "))?;
// The target triplets have the form of 'arch-vendor-system'.
//
// When building for Linux (e.g. the 'system' part is
// 'linux-something'), replace the vendor with 'unknown'
// so that mapping to rust standard targets happens correctly.
//
// For example, alpine set `rustc` host triple to
// `x86_64-alpine-linux-musl`.
//
// Here we use splitn with n=4 since we just need to check
// the third part to see if it equals to "linux" and verify
// that we have at least three parts.
let mut parts: Vec<&str> = target.splitn(4, '-').collect();
if *parts.get(2)? == "linux" {
parts[1] = "unknown";
}
Some(parts.join("-"))
}