From 69f2a56595ab7b3d7b083ec11f90b511fd583d0c Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:00:01 +1000 Subject: [PATCH 01/27] Move `TARGET` in `lib.rs` into new mod `target.rs` Signed-off-by: Jiahao XU --- src/lib.rs | 4 ++-- src/target.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/target.rs diff --git a/src/lib.rs b/src/lib.rs index 2a823625..ef3cfbaf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,8 +15,8 @@ pub use helpers::*; pub mod bins; pub mod fetchers; -/// Compiled target triple, used as default for binary fetching -pub const TARGET: &str = env!("TARGET"); +mod target; +pub use target::TARGET; /// Default package path template (may be overridden in package Cargo.toml) pub const DEFAULT_PKG_URL: &str = diff --git a/src/target.rs b/src/target.rs new file mode 100644 index 00000000..94bfe775 --- /dev/null +++ b/src/target.rs @@ -0,0 +1,2 @@ +/// Compiled target triple, used as default for binary fetching +pub const TARGET: &str = env!("TARGET"); From 8bd4b9b6a1362f53d48be1ee58bf751b1ac34e55 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:32:15 +1000 Subject: [PATCH 02/27] Impl `detect_targets` for linux Signed-off-by: Jiahao XU --- src/lib.rs | 2 +- src/target.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ef3cfbaf..0a6c1437 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ pub mod bins; pub mod fetchers; mod target; -pub use target::TARGET; +pub use target::{detect_targets, TARGET}; /// Default package path template (may be overridden in package Cargo.toml) pub const DEFAULT_PKG_URL: &str = diff --git a/src/target.rs b/src/target.rs index 94bfe775..4c6f8f57 100644 --- a/src/target.rs +++ b/src/target.rs @@ -1,2 +1,97 @@ /// Compiled target triple, used as default for binary fetching pub const TARGET: &str = env!("TARGET"); + +/// 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> { + #[cfg(target_os = "linux")] + { + return linux::detect_targets_linux().await; + } + + todo!() +} + +#[cfg(target_os = "linux")] +mod linux { + use super::TARGET; + use std::process::Output; + use tokio::process::Command; + + async fn detect_targets_linux() -> Vec> { + let abi = parse_abi(); + + if let Ok(Output { + status: _, + stdout, + stderr, + }) = Command::new("ldd").arg("--version").output().await + { + let libc_version = if let Some(libc_version) = parse_libc_version(stdout) { + libc_version + } else if let Some(libc_version) = parse_libc_version(stderr) { + libc_version + } else { + return vec![create_target_str("musl", abi)]; + }; + + if libc_version == "gnu" { + return vec![ + create_target_str("gnu", abi), + create_target_str("musl", abi), + ]; + } + } + + // Fallback to using musl + vec![create_target_str("musl", abi)] + } + + fn parse_libc_version(output: &[u8]) -> Option<&'static str> { + let s = String::from_utf8_lossy(output); + if s.contains("musl libc") { + Some("musl") + } else if s.contains("GLIBC") { + Some("gnu") + } else { + None + } + } + + const fn parse_abi() -> &'static str { + if TARGET.endswith("abi64") { + "abi64" + } else if TARGET.endswith("eabi") { + "eabi" + } else if TARGET.endswith("eabihf") { + "eabihf" + } else if TARGET.endswith("gnu") || TARGET.endswith("musl") { + "" + } else { + panic!("Unknown abi") + } + } + + fn create_target_str(libc_version: &str, abi: &str) -> Box { + let prefix = TARGET.rsplit_once('-').unwrap().0; + + let mut target = String::with_capacity(prefix.len() + 1 + libc_version.len() + abi.len()); + target.push_str(prefix); + target.push('-'); + target.push_str(libc_version); + target.push_str(abi); + + target.into_boxed_str() + } +} From ca5c9b7c239f067443e6de51c86af478a1f2b176 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:35:51 +1000 Subject: [PATCH 03/27] Add dep `guess_host_triple` for target_os `macos` Signed-off-by: Jiahao XU --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e4888364..9532caf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,9 @@ zip = { version = "0.6.2", default-features = false, features = [ "deflate", "bz # Enable feature zstdmt to enable multithreading in libzstd. zstd = { version = "0.10.0", features = [ "bindgen", "zstdmt" ], default-features = false } +[target.'cfg(target_os = "macos")'.dependencies] +guess_host_triple = "0.1.3" + [dev-dependencies] env_logger = "0.9.0" From 4157f20b99c29681531f25a2c161b76bf4103366 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:40:52 +1000 Subject: [PATCH 04/27] Support for macos in `detect_targets` Signed-off-by: Jiahao XU --- src/target.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/target.rs b/src/target.rs index 4c6f8f57..24b0e3e9 100644 --- a/src/target.rs +++ b/src/target.rs @@ -19,8 +19,10 @@ pub async fn detect_targets() -> Vec> { { return linux::detect_targets_linux().await; } - - todo!() + #[cfg(target_os = "macos")] + { + macos::detect_targets_macos() + } } #[cfg(target_os = "linux")] @@ -95,3 +97,19 @@ mod linux { target.into_boxed_str() } } + +#[cfg(target_os = "macos")] +mod macos { + use guess_host_triple::guess_host_triple; + + const AARCH64: &str = "aarch64-apple-darwin"; + const X86: &str = "x86_64-apple-darwin"; + + pub(super) fn detect_targets_macos() -> Vec> { + if guess_host_triple() == Some(AARCH64) { + vec![AARCH64.into(), X86.into()] + } else { + vec![X86.into()] + } + } +} From 9a8b28afcfe80e9dce7f64537e3752829e0eeeed Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:41:15 +1000 Subject: [PATCH 05/27] Fix invocation of `linux::detect_targets_linux` in `detect_targets` Signed-off-by: Jiahao XU --- src/target.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target.rs b/src/target.rs index 24b0e3e9..03c02a56 100644 --- a/src/target.rs +++ b/src/target.rs @@ -17,7 +17,7 @@ pub const TARGET: &str = env!("TARGET"); pub async fn detect_targets() -> Vec> { #[cfg(target_os = "linux")] { - return linux::detect_targets_linux().await; + linux::detect_targets_linux().await } #[cfg(target_os = "macos")] { @@ -31,7 +31,7 @@ mod linux { use std::process::Output; use tokio::process::Command; - async fn detect_targets_linux() -> Vec> { + pub(super) async fn detect_targets_linux() -> Vec> { let abi = parse_abi(); if let Ok(Output { From b74139f457b5eb135d1e3c84f369b141a4f7bed2 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:42:43 +1000 Subject: [PATCH 06/27] Support for other platforms in `detect_targets` Signed-off-by: Jiahao XU --- src/target.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/target.rs b/src/target.rs index 03c02a56..79eb32ab 100644 --- a/src/target.rs +++ b/src/target.rs @@ -23,6 +23,10 @@ pub async fn detect_targets() -> Vec> { { macos::detect_targets_macos() } + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { + vec![TARGET.into()] + } } #[cfg(target_os = "linux")] From 1ebc759b17352458cfc5f65ff07882cda095b079 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:45:06 +1000 Subject: [PATCH 07/27] Add dep `arrayvec` v0.7.2 Signed-off-by: Jiahao XU --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9532caf5..d98eadd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,8 @@ zip = { version = "0.6.2", default-features = false, features = [ "deflate", "bz # Enable feature zstdmt to enable multithreading in libzstd. zstd = { version = "0.10.0", features = [ "bindgen", "zstdmt" ], default-features = false } +arrayvec = "0.7.2" + [target.'cfg(target_os = "macos")'.dependencies] guess_host_triple = "0.1.3" From c50e9491701555e4bf4a11f56ccd6227f7b7a738 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:45:21 +1000 Subject: [PATCH 08/27] Update `Cargo.lock` Signed-off-by: Jiahao XU --- Cargo.lock | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 56719108..3bfbedd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "async-trait" version = "0.1.53" @@ -141,6 +147,7 @@ dependencies = [ name = "cargo-binstall" version = "0.8.0" dependencies = [ + "arrayvec", "async-trait", "cargo_metadata", "cargo_toml", @@ -148,6 +155,7 @@ dependencies = [ "dirs", "env_logger", "flate2", + "guess_host_triple", "log", "miette", "reqwest", @@ -355,6 +363,27 @@ dependencies = [ "termcolor", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" version = "1.7.0" @@ -509,6 +538,18 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "guess_host_triple" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35a8ce923c7490629d84e12fa2f75e1733f1ec692a47c264f9b7fd632855afc" +dependencies = [ + "errno", + "libc", + "log", + "winapi", +] + [[package]] name = "h2" version = "0.3.13" From 7232f32428b95a73ec66d586845f0b4a89a224e7 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:52:11 +1000 Subject: [PATCH 09/27] Use `ArrayVec` to avoid heap alloc in `detect_targets` Signed-off-by: Jiahao XU --- src/target.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/target.rs b/src/target.rs index 79eb32ab..da0f3794 100644 --- a/src/target.rs +++ b/src/target.rs @@ -1,3 +1,5 @@ +use arrayvec::ArrayVec; + /// Compiled target triple, used as default for binary fetching pub const TARGET: &str = env!("TARGET"); @@ -14,7 +16,7 @@ pub const TARGET: &str = env!("TARGET"); /// /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// for more information. -pub async fn detect_targets() -> Vec> { +pub async fn detect_targets() -> ArrayVec, 2> { #[cfg(target_os = "linux")] { linux::detect_targets_linux().await @@ -29,13 +31,23 @@ pub async fn detect_targets() -> Vec> { } } +fn from_array(arr: [T; LEN]) -> ArrayVec { + let mut v = ArrayVec::new(); + + for elem in arr { + v.push(elem); + } + + v +} + #[cfg(target_os = "linux")] mod linux { - use super::TARGET; + use super::{from_array, ArrayVec, TARGET}; use std::process::Output; use tokio::process::Command; - pub(super) async fn detect_targets_linux() -> Vec> { + pub(super) async fn detect_targets_linux() -> ArrayVec, 2> { let abi = parse_abi(); if let Ok(Output { @@ -49,19 +61,19 @@ mod linux { } else if let Some(libc_version) = parse_libc_version(stderr) { libc_version } else { - return vec![create_target_str("musl", abi)]; + return from_array([create_target_str("musl", abi)]); }; if libc_version == "gnu" { - return vec![ + return from_array([ create_target_str("gnu", abi), create_target_str("musl", abi), - ]; + ]); } } // Fallback to using musl - vec![create_target_str("musl", abi)] + from_array([create_target_str("musl", abi)]) } fn parse_libc_version(output: &[u8]) -> Option<&'static str> { @@ -104,16 +116,17 @@ mod linux { #[cfg(target_os = "macos")] mod macos { + use super::{from_array, ArrayVec}; use guess_host_triple::guess_host_triple; const AARCH64: &str = "aarch64-apple-darwin"; const X86: &str = "x86_64-apple-darwin"; - pub(super) fn detect_targets_macos() -> Vec> { + pub(super) fn detect_targets_macos() -> ArrayVec, 2> { if guess_host_triple() == Some(AARCH64) { - vec![AARCH64.into(), X86.into()] + from_array([AARCH64.into(), X86.into()]) } else { - vec![X86.into()] + from_array([X86.into()]) } } } From 8bf4d187eee77caa0217ebb88d532970fa6a5178 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 22:53:12 +1000 Subject: [PATCH 10/27] Rename `parse_libc_version` to `parse_libc_version_from_ldd_output` Signed-off-by: Jiahao XU --- src/target.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/target.rs b/src/target.rs index da0f3794..17cbc185 100644 --- a/src/target.rs +++ b/src/target.rs @@ -56,13 +56,14 @@ mod linux { stderr, }) = Command::new("ldd").arg("--version").output().await { - let libc_version = if let Some(libc_version) = parse_libc_version(stdout) { - libc_version - } else if let Some(libc_version) = parse_libc_version(stderr) { - libc_version - } else { - return from_array([create_target_str("musl", abi)]); - }; + let libc_version = + if let Some(libc_version) = parse_libc_version_from_ldd_output(stdout) { + libc_version + } else if let Some(libc_version) = parse_libc_version(stderr) { + libc_version + } else { + return from_array([create_target_str("musl", abi)]); + }; if libc_version == "gnu" { return from_array([ @@ -76,7 +77,7 @@ mod linux { from_array([create_target_str("musl", abi)]) } - fn parse_libc_version(output: &[u8]) -> Option<&'static str> { + fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> { let s = String::from_utf8_lossy(output); if s.contains("musl libc") { Some("musl") From cce378e2c5f0a442c0b9af04c1bd7a578b0ac6fa Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 23:00:33 +1000 Subject: [PATCH 11/27] Add `get_targets_from_rustc` to `detect_targets` Signed-off-by: Jiahao XU --- src/target.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/target.rs b/src/target.rs index 17cbc185..acaccf6d 100644 --- a/src/target.rs +++ b/src/target.rs @@ -1,4 +1,7 @@ use arrayvec::ArrayVec; +use std::io::{BufRead, Cursor}; +use std::process::Output; +use tokio::process::Command; /// Compiled target triple, used as default for binary fetching pub const TARGET: &str = env!("TARGET"); @@ -17,6 +20,10 @@ pub const TARGET: &str = env!("TARGET"); /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// for more information. pub async fn detect_targets() -> ArrayVec, 2> { + if let Some(target) = get_targets_from_rustc().await { + return from_array([target]); + } + #[cfg(target_os = "linux")] { linux::detect_targets_linux().await @@ -31,6 +38,20 @@ pub async fn detect_targets() -> ArrayVec, 2> { } } +// Figure out what the host target is, from rustc or from this program's own build target +async fn get_targets_from_rustc() -> Option> { + match Command::new("rustc").arg("-vV").output().await { + Ok(Output { status, stdout, .. }) if status.success() => Cursor::new(stdout) + .lines() + .filter_map(|line| line.ok()) + .find_map(|line| { + line.strip_prefix("host: ") + .map(|host| host.to_owned().into_boxed_str()) + }), + _ => None, + } +} + fn from_array(arr: [T; LEN]) -> ArrayVec { let mut v = ArrayVec::new(); @@ -43,9 +64,7 @@ fn from_array(arr: [T; LEN]) -> ArrayVec< #[cfg(target_os = "linux")] mod linux { - use super::{from_array, ArrayVec, TARGET}; - use std::process::Output; - use tokio::process::Command; + use super::{from_array, ArrayVec, Command, Output, TARGET}; pub(super) async fn detect_targets_linux() -> ArrayVec, 2> { let abi = parse_abi(); From 6b764b0b3fe2c3ea75fa84044ea951a307522630 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 23:07:25 +1000 Subject: [PATCH 12/27] Add fallbacks for `get_targets_from_rustc` Signed-off-by: Jiahao XU --- src/target.rs | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/target.rs b/src/target.rs index acaccf6d..66b4504c 100644 --- a/src/target.rs +++ b/src/target.rs @@ -21,20 +21,32 @@ pub const TARGET: &str = env!("TARGET"); /// for more information. pub async fn detect_targets() -> ArrayVec, 2> { if let Some(target) = get_targets_from_rustc().await { - return from_array([target]); - } + let mut v = from_array([target]); - #[cfg(target_os = "linux")] - { - linux::detect_targets_linux().await - } - #[cfg(target_os = "macos")] - { - macos::detect_targets_macos() - } - #[cfg(not(any(target_os = "linux", target_os = "macos")))] - { - vec![TARGET.into()] + #[cfg(target_os = "linux")] + if v[0].contains("gnu") { + v.push(target.replace("gnu", "musl").into_boxed_str()); + } + + #[cfg(target_os = "macos")] + if &*v[0] == macos::AARCH64 { + v.push(macos::X86.into()); + } + + v + } else { + #[cfg(target_os = "linux")] + { + linux::detect_targets_linux().await + } + #[cfg(target_os = "macos")] + { + macos::detect_targets_macos() + } + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { + vec![TARGET.into()] + } } } @@ -139,8 +151,8 @@ mod macos { use super::{from_array, ArrayVec}; use guess_host_triple::guess_host_triple; - const AARCH64: &str = "aarch64-apple-darwin"; - const X86: &str = "x86_64-apple-darwin"; + pub(super) const AARCH64: &str = "aarch64-apple-darwin"; + pub(super) const X86: &str = "x86_64-apple-darwin"; pub(super) fn detect_targets_macos() -> ArrayVec, 2> { if guess_host_triple() == Some(AARCH64) { From c9c3cffb25494ae7c161f64d766dde5ec4cf86b8 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 23:08:00 +1000 Subject: [PATCH 13/27] Fix `detect_targets` for win and other targets Signed-off-by: Jiahao XU --- src/target.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target.rs b/src/target.rs index 66b4504c..bfd715ba 100644 --- a/src/target.rs +++ b/src/target.rs @@ -45,7 +45,7 @@ pub async fn detect_targets() -> ArrayVec, 2> { } #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - vec![TARGET.into()] + from_array([TARGET.into()]) } } } From 3f7f293b789582dfa4e00c68643538c6cafc1e18 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 23:17:07 +1000 Subject: [PATCH 14/27] Fix bugs Signed-off-by: Jiahao XU --- src/target.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target.rs b/src/target.rs index bfd715ba..6a24d98f 100644 --- a/src/target.rs +++ b/src/target.rs @@ -25,7 +25,7 @@ pub async fn detect_targets() -> ArrayVec, 2> { #[cfg(target_os = "linux")] if v[0].contains("gnu") { - v.push(target.replace("gnu", "musl").into_boxed_str()); + v.push(v[0].replace("gnu", "musl").into_boxed_str()); } #[cfg(target_os = "macos")] @@ -88,9 +88,9 @@ mod linux { }) = Command::new("ldd").arg("--version").output().await { let libc_version = - if let Some(libc_version) = parse_libc_version_from_ldd_output(stdout) { + if let Some(libc_version) = parse_libc_version_from_ldd_output(&stdout) { libc_version - } else if let Some(libc_version) = parse_libc_version(stderr) { + } else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) { libc_version } else { return from_array([create_target_str("musl", abi)]); From 44b1bdbfe57ef8caa795c9bc5d966305638cafe8 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 Jun 2022 23:20:09 +1000 Subject: [PATCH 15/27] Fix use of `ends_with` Signed-off-by: Jiahao XU --- src/target.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target.rs b/src/target.rs index 6a24d98f..0794546f 100644 --- a/src/target.rs +++ b/src/target.rs @@ -120,13 +120,13 @@ mod linux { } const fn parse_abi() -> &'static str { - if TARGET.endswith("abi64") { + if TARGET.ends_with("abi64") { "abi64" - } else if TARGET.endswith("eabi") { + } else if TARGET.ends_with("eabi") { "eabi" - } else if TARGET.endswith("eabihf") { + } else if TARGET.ends_with("eabihf") { "eabihf" - } else if TARGET.endswith("gnu") || TARGET.endswith("musl") { + } else if TARGET.ends_with("gnu") || TARGET.ends_with("musl") { "" } else { panic!("Unknown abi") From 1df135f4c0b1de0f755e99e01994f68ca8c95f0c Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 00:20:52 +1000 Subject: [PATCH 16/27] Fix `target::linux::parse_abi`: Remove `const` Signed-off-by: Jiahao XU --- src/target.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target.rs b/src/target.rs index 0794546f..d4456244 100644 --- a/src/target.rs +++ b/src/target.rs @@ -119,7 +119,7 @@ mod linux { } } - const fn parse_abi() -> &'static str { + fn parse_abi() -> &'static str { if TARGET.ends_with("abi64") { "abi64" } else if TARGET.ends_with("eabi") { From 11fe943a11a2752b3fc743416777bb26f24a8a86 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 11:30:00 +1000 Subject: [PATCH 17/27] Fix `parse_abi` for `gnu_ilp32` and `gnuspe` Signed-off-by: Jiahao XU --- src/target.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/target.rs b/src/target.rs index d4456244..af3f02d2 100644 --- a/src/target.rs +++ b/src/target.rs @@ -120,16 +120,14 @@ mod linux { } fn parse_abi() -> &'static str { - if TARGET.ends_with("abi64") { - "abi64" - } else if TARGET.ends_with("eabi") { - "eabi" - } else if TARGET.ends_with("eabihf") { - "eabihf" - } else if TARGET.ends_with("gnu") || TARGET.ends_with("musl") { - "" + let last = TARGET.rsplit_once('-').unwrap().1; + + if let Some(libc_version) = last.strip_prefix("musl") { + libc_version + } else if let Some(libc_version) = last.strip_prefix("gnu") { + libc_version } else { - panic!("Unknown abi") + panic!("Unrecognized libc") } } From efc8119c45875c4d3cce7fd1f0b3ae79da81b1c6 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 11:45:53 +1000 Subject: [PATCH 18/27] Add opaque newtype `Targets` over `ArrayVec, 2>` Signed-off-by: Jiahao XU --- src/target.rs | 72 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/src/target.rs b/src/target.rs index af3f02d2..6c8d9f09 100644 --- a/src/target.rs +++ b/src/target.rs @@ -1,11 +1,49 @@ use arrayvec::ArrayVec; use std::io::{BufRead, Cursor}; +use std::iter::IntoIterator; +use std::ops::Deref; use std::process::Output; use tokio::process::Command; /// Compiled target triple, used as default for binary fetching pub const TARGET: &str = env!("TARGET"); +#[derive(Debug, Clone)] +pub struct Targets(ArrayVec, 2>); + +impl Targets { + fn from_array(arr: [Box; LEN]) -> Self { + let mut v = ArrayVec::new(); + + for elem in arr { + v.push(elem); + } + + Self(v) + } + + fn push(&mut self, s: Box) { + self.0.push(s) + } +} + +impl Deref for Targets { + type Target = [Box]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl IntoIterator for Targets { + type Item = Box; + type IntoIter = arrayvec::IntoIter, 2>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + /// Detect the targets supported at runtime, /// which might be different from `TARGET` which is detected /// at compile-time. @@ -19,9 +57,9 @@ pub const TARGET: &str = env!("TARGET"); /// /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// for more information. -pub async fn detect_targets() -> ArrayVec, 2> { +pub async fn detect_targets() -> Targets { if let Some(target) = get_targets_from_rustc().await { - let mut v = from_array([target]); + let mut v = Targets::from_array([target]); #[cfg(target_os = "linux")] if v[0].contains("gnu") { @@ -45,7 +83,7 @@ pub async fn detect_targets() -> ArrayVec, 2> { } #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - from_array([TARGET.into()]) + Targets::from_array([TARGET.into()]) } } } @@ -64,21 +102,11 @@ async fn get_targets_from_rustc() -> Option> { } } -fn from_array(arr: [T; LEN]) -> ArrayVec { - let mut v = ArrayVec::new(); - - for elem in arr { - v.push(elem); - } - - v -} - #[cfg(target_os = "linux")] mod linux { - use super::{from_array, ArrayVec, Command, Output, TARGET}; + use super::{Command, Output, Targets, TARGET}; - pub(super) async fn detect_targets_linux() -> ArrayVec, 2> { + pub(super) async fn detect_targets_linux() -> Targets { let abi = parse_abi(); if let Ok(Output { @@ -93,11 +121,11 @@ mod linux { } else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) { libc_version } else { - return from_array([create_target_str("musl", abi)]); + return Targets::from_array([create_target_str("musl", abi)]); }; if libc_version == "gnu" { - return from_array([ + return Targets::from_array([ create_target_str("gnu", abi), create_target_str("musl", abi), ]); @@ -105,7 +133,7 @@ mod linux { } // Fallback to using musl - from_array([create_target_str("musl", abi)]) + Targets::from_array([create_target_str("musl", abi)]) } fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> { @@ -146,17 +174,17 @@ mod linux { #[cfg(target_os = "macos")] mod macos { - use super::{from_array, ArrayVec}; + use super::Targets; use guess_host_triple::guess_host_triple; pub(super) const AARCH64: &str = "aarch64-apple-darwin"; pub(super) const X86: &str = "x86_64-apple-darwin"; - pub(super) fn detect_targets_macos() -> ArrayVec, 2> { + pub(super) fn detect_targets_macos() -> Targets { if guess_host_triple() == Some(AARCH64) { - from_array([AARCH64.into(), X86.into()]) + Targets::from_array([AARCH64.into(), X86.into()]) } else { - from_array([X86.into()]) + Targets::from_array([X86.into()]) } } } From 7a244176b4f7abfc566a49818415fec1c1cb16f0 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 11:48:19 +1000 Subject: [PATCH 19/27] Reorder dep in `Cargo.toml` Signed-off-by: Jiahao XU --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d98eadd0..b3dc9387 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ pkg-fmt = "zip" pkg-fmt = "zip" [dependencies] +arrayvec = "0.7.2" async-trait = "0.1.52" cargo_metadata = "0.14.2" cargo_toml = "0.11.4" @@ -62,8 +63,6 @@ zip = { version = "0.6.2", default-features = false, features = [ "deflate", "bz # Enable feature zstdmt to enable multithreading in libzstd. zstd = { version = "0.10.0", features = [ "bindgen", "zstdmt" ], default-features = false } -arrayvec = "0.7.2" - [target.'cfg(target_os = "macos")'.dependencies] guess_host_triple = "0.1.3" From bd224f7186f62dc84c49898cb5d25e66a4fd9476 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 11:49:02 +1000 Subject: [PATCH 20/27] Use star re-export for mod `targets` Signed-off-by: Jiahao XU --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0a6c1437..d83d7887 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ pub mod bins; pub mod fetchers; mod target; -pub use target::{detect_targets, TARGET}; +pub use target::*; /// Default package path template (may be overridden in package Cargo.toml) pub const DEFAULT_PKG_URL: &str = From 1d71f92ee6e9d436b96cfda57b886adc4e8a6492 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:10:05 +1000 Subject: [PATCH 21/27] Impl `IntoIterator` for `&Targets` Signed-off-by: Jiahao XU --- src/target.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target.rs b/src/target.rs index 6c8d9f09..2bd52a6e 100644 --- a/src/target.rs +++ b/src/target.rs @@ -3,6 +3,7 @@ use std::io::{BufRead, Cursor}; use std::iter::IntoIterator; use std::ops::Deref; use std::process::Output; +use std::slice; use tokio::process::Command; /// Compiled target triple, used as default for binary fetching @@ -44,6 +45,15 @@ impl IntoIterator for Targets { } } +impl<'a> IntoIterator for &'a Targets { + type Item = &'a Box; + type IntoIter = slice::Iter<'a, Box>; + + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter() + } +} + /// Detect the targets supported at runtime, /// which might be different from `TARGET` which is detected /// at compile-time. From 95b7c4f771dfd546c8c6e5dd37631e8d196f01d0 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:11:04 +1000 Subject: [PATCH 22/27] Rename `get_targets_from_rustc` to `get_target_from_rustc` Signed-off-by: Jiahao XU --- src/target.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target.rs b/src/target.rs index 2bd52a6e..ad91ffc5 100644 --- a/src/target.rs +++ b/src/target.rs @@ -68,7 +68,7 @@ impl<'a> IntoIterator for &'a Targets { /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// for more information. pub async fn detect_targets() -> Targets { - if let Some(target) = get_targets_from_rustc().await { + if let Some(target) = get_target_from_rustc().await { let mut v = Targets::from_array([target]); #[cfg(target_os = "linux")] @@ -99,7 +99,7 @@ pub async fn detect_targets() -> Targets { } // Figure out what the host target is, from rustc or from this program's own build target -async fn get_targets_from_rustc() -> Option> { +async fn get_target_from_rustc() -> Option> { match Command::new("rustc").arg("-vV").output().await { Ok(Output { status, stdout, .. }) if status.success() => Cursor::new(stdout) .lines() From 96336e4dd903880cd251cb9ff6689f0ef5f29458 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:11:49 +1000 Subject: [PATCH 23/27] Update doc of `get_target_from_rustc` Signed-off-by: Jiahao XU --- src/target.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target.rs b/src/target.rs index ad91ffc5..f64175eb 100644 --- a/src/target.rs +++ b/src/target.rs @@ -98,7 +98,8 @@ pub async fn detect_targets() -> Targets { } } -// Figure out what the host target is, from rustc or from this program's own build target +/// Figure out what the host target is using `rustc`. +/// If `rustc` is absent, then it would return `None`. async fn get_target_from_rustc() -> Option> { match Command::new("rustc").arg("-vV").output().await { Ok(Output { status, stdout, .. }) if status.success() => Cursor::new(stdout) From 9ee2609b2541000b117ddef1b2a1bdeba19b1c3e Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:14:27 +1000 Subject: [PATCH 24/27] Refactor `get_target_from_rustc` impl Signed-off-by: Jiahao XU --- src/target.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/target.rs b/src/target.rs index f64175eb..cb274ec3 100644 --- a/src/target.rs +++ b/src/target.rs @@ -101,16 +101,18 @@ pub async fn detect_targets() -> Targets { /// Figure out what the host target is using `rustc`. /// If `rustc` is absent, then it would return `None`. async fn get_target_from_rustc() -> Option> { - match Command::new("rustc").arg("-vV").output().await { - Ok(Output { status, stdout, .. }) if status.success() => Cursor::new(stdout) - .lines() - .filter_map(|line| line.ok()) - .find_map(|line| { - line.strip_prefix("host: ") - .map(|host| host.to_owned().into_boxed_str()) - }), - _ => None, + let Output { status, stdout, .. } = Command::new("rustc").arg("-vV").output().await.ok()?; + if !status.success() { + return None; } + + Cursor::new(stdout) + .lines() + .filter_map(|line| line.ok()) + .find_map(|line| { + line.strip_prefix("host: ") + .map(|host| host.to_owned().into_boxed_str()) + }) } #[cfg(target_os = "linux")] From ecf6fdbab58cc1549a65cb4ddb4ec6cb9993882a Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:20:46 +1000 Subject: [PATCH 25/27] Revert back to using `Vec>` for targets Signed-off-by: Jiahao XU --- src/target.rs | 74 +++++++++------------------------------------------ 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/src/target.rs b/src/target.rs index cb274ec3..7f5e4f7b 100644 --- a/src/target.rs +++ b/src/target.rs @@ -1,59 +1,10 @@ -use arrayvec::ArrayVec; use std::io::{BufRead, Cursor}; -use std::iter::IntoIterator; -use std::ops::Deref; use std::process::Output; -use std::slice; use tokio::process::Command; /// Compiled target triple, used as default for binary fetching pub const TARGET: &str = env!("TARGET"); -#[derive(Debug, Clone)] -pub struct Targets(ArrayVec, 2>); - -impl Targets { - fn from_array(arr: [Box; LEN]) -> Self { - let mut v = ArrayVec::new(); - - for elem in arr { - v.push(elem); - } - - Self(v) - } - - fn push(&mut self, s: Box) { - self.0.push(s) - } -} - -impl Deref for Targets { - type Target = [Box]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl IntoIterator for Targets { - type Item = Box; - type IntoIter = arrayvec::IntoIter, 2>; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl<'a> IntoIterator for &'a Targets { - type Item = &'a Box; - type IntoIter = slice::Iter<'a, Box>; - - fn into_iter(self) -> Self::IntoIter { - (&self.0).into_iter() - } -} - /// Detect the targets supported at runtime, /// which might be different from `TARGET` which is detected /// at compile-time. @@ -67,9 +18,9 @@ impl<'a> IntoIterator for &'a Targets { /// /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// for more information. -pub async fn detect_targets() -> Targets { +pub async fn detect_targets() -> Vec> { if let Some(target) = get_target_from_rustc().await { - let mut v = Targets::from_array([target]); + let mut v = vec![target]; #[cfg(target_os = "linux")] if v[0].contains("gnu") { @@ -93,7 +44,7 @@ pub async fn detect_targets() -> Targets { } #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - Targets::from_array([TARGET.into()]) + vec![TARGET.into()] } } } @@ -117,9 +68,9 @@ async fn get_target_from_rustc() -> Option> { #[cfg(target_os = "linux")] mod linux { - use super::{Command, Output, Targets, TARGET}; + use super::{Command, Output, TARGET}; - pub(super) async fn detect_targets_linux() -> Targets { + pub(super) async fn detect_targets_linux() -> Vec> { let abi = parse_abi(); if let Ok(Output { @@ -134,19 +85,19 @@ mod linux { } else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) { libc_version } else { - return Targets::from_array([create_target_str("musl", abi)]); + return vec![create_target_str("musl", abi)]; }; if libc_version == "gnu" { - return Targets::from_array([ + return vec![ create_target_str("gnu", abi), create_target_str("musl", abi), - ]); + ]; } } // Fallback to using musl - Targets::from_array([create_target_str("musl", abi)]) + vec![create_target_str("musl", abi)] } fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> { @@ -187,17 +138,16 @@ mod linux { #[cfg(target_os = "macos")] mod macos { - use super::Targets; use guess_host_triple::guess_host_triple; pub(super) const AARCH64: &str = "aarch64-apple-darwin"; pub(super) const X86: &str = "x86_64-apple-darwin"; - pub(super) fn detect_targets_macos() -> Targets { + pub(super) fn detect_targets_macos() -> Vec> { if guess_host_triple() == Some(AARCH64) { - Targets::from_array([AARCH64.into(), X86.into()]) + vec![AARCH64.into(), X86.into()] } else { - Targets::from_array([X86.into()]) + vec![X86.into()] } } } From 9c818e0e9553ad1964e2465a991ce1ff324b035c Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:21:03 +1000 Subject: [PATCH 26/27] Remove dep `arrayvec` Signed-off-by: Jiahao XU --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b3dc9387..9532caf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ pkg-fmt = "zip" pkg-fmt = "zip" [dependencies] -arrayvec = "0.7.2" async-trait = "0.1.52" cargo_metadata = "0.14.2" cargo_toml = "0.11.4" From 0819b653089b4640b619b38fb2fb91fbb49bf671 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jun 2022 12:21:50 +1000 Subject: [PATCH 27/27] Update `Cargo.lock` Signed-off-by: Jiahao XU --- Cargo.lock | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bfbedd2..429675c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - [[package]] name = "async-trait" version = "0.1.53" @@ -147,7 +141,6 @@ dependencies = [ name = "cargo-binstall" version = "0.8.0" dependencies = [ - "arrayvec", "async-trait", "cargo_metadata", "cargo_toml",