diff --git a/xtask/src/bin_install.rs b/xtask/src/bin_install.rs new file mode 100644 index 00000000..ad01e052 --- /dev/null +++ b/xtask/src/bin_install.rs @@ -0,0 +1,87 @@ +use xshell::{cmd, Shell}; + +use crate::{local_bin, CARGO, LOCAL_CARGO_ROOT}; + +pub struct CargoPackage { + pub name: &'static str, + pub binary_name: &'static str, + pub version: &'static str, +} + +impl CargoPackage { + pub const fn new(name: &'static str, version: &'static str) -> Self { + Self { + name, + binary_name: name, + version, + } + } + + pub const fn with_binary_name(self, name: &'static str) -> Self { + Self { + binary_name: name, + ..self + } + } +} + +pub fn cargo_install(sh: &Shell, package: &CargoPackage) -> anyhow::Result<()> { + let package_name = package.name; + let package_version = package.version; + + if is_installed(sh, package) { + trace!("{package_name} is already installed"); + return Ok(()); + } + + if cargo_binstall_is_available(sh) { + trace!("cargo-binstall is available"); + cmd!( + sh, + "{CARGO} binstall --no-confirm --root {LOCAL_CARGO_ROOT} {package_name}@{package_version}" + ) + .run()?; + } else { + trace!("Install {package_name} using cargo install"); + // Install in debug because it's faster to compile and we typically don't need execution speed anyway. + cmd!( + sh, + "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} {package_name}@{package_version}" + ) + .run()?; + } + + Ok(()) +} + +fn cargo_binstall_is_available(sh: &Shell) -> bool { + cmd!(sh, "{CARGO} binstall -h") + .quiet() + .ignore_stderr() + .ignore_stdout() + .run() + .is_ok() +} + +/// Checks if a binary is installed in local root +pub fn is_installed(sh: &Shell, package: impl GetBinaryName) -> bool { + let path = local_bin().join(package.binary_name()); + sh.path_exists(&path) || sh.path_exists(path.with_extension("exe")) +} + +#[doc(hidden)] +pub trait GetBinaryName { + fn binary_name(self) -> &'static str; +} + +impl GetBinaryName for &CargoPackage { + fn binary_name(self) -> &'static str { + self.binary_name + } +} + +impl GetBinaryName for &'static str { + fn binary_name(self) -> &'static str { + self + } +} diff --git a/xtask/src/bin_version.rs b/xtask/src/bin_version.rs index 259e7456..325dc26b 100644 --- a/xtask/src/bin_version.rs +++ b/xtask/src/bin_version.rs @@ -1,8 +1,12 @@ -// Hash of this file is used in CI for caching +// We pin the binaries to specific versions so we use the same artifact everywhere. +// Hash of this file is used in CI for caching. + +use crate::bin_install::CargoPackage; + +pub const CARGO_FUZZ: CargoPackage = CargoPackage::new("cargo-fuzz", "0.11.2"); +pub const CARGO_LLVM_COV: CargoPackage = CargoPackage::new("cargo-llvm-cov", "0.5.37"); +pub const GRCOV: CargoPackage = CargoPackage::new("grcov", "0.8.19"); +pub const WASM_PACK: CargoPackage = CargoPackage::new("wasm-pack", "0.12.1"); +pub const TYPOS_CLI: CargoPackage = CargoPackage::new("typos-cli", "1.16.23").with_binary_name("typos"); -pub const CARGO_FUZZ_VERSION: &str = "0.11.2"; -pub const CARGO_LLVM_COV_VERSION: &str = "0.5.19"; -pub const GRCOV_VERSION: &str = "0.8.18"; -pub const WASM_PACK_VERSION: &str = "0.11.1"; pub const WABT_VERSION: &str = "1.0.33"; -pub const TYPOS_CLI_VERSION: &str = "1.14.9"; diff --git a/xtask/src/check.rs b/xtask/src/check.rs index f553afbe..8399e98c 100644 --- a/xtask/src/check.rs +++ b/xtask/src/check.rs @@ -119,15 +119,7 @@ pub fn typos(sh: &Shell) -> anyhow::Result<()> { pub fn install(sh: &Shell) -> anyhow::Result<()> { let _s = Section::new("TYPOS-CLI-INSTALL"); - if !is_installed(sh, "typos") { - // Install in debug because it's faster to compile and we don't need execution speed anyway. - // typos-cli version is pinned so we don’t get different versions without intervention. - cmd!( - sh, - "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} typos-cli@{TYPOS_CLI_VERSION}" - ) - .run()?; - } + cargo_install(sh, &TYPOS_CLI)?; Ok(()) } diff --git a/xtask/src/cov.rs b/xtask/src/cov.rs index 25aa6250..56a3283f 100644 --- a/xtask/src/cov.rs +++ b/xtask/src/cov.rs @@ -8,13 +8,7 @@ const COV_IGNORE_REGEX: &str = pub fn install(sh: &Shell) -> anyhow::Result<()> { let _s = Section::new("COV-INSTALL"); - if !is_installed(sh, "cargo-llvm-cov") { - cmd!( - sh, - "{CARGO} install --locked --root {LOCAL_CARGO_ROOT} cargo-llvm-cov@{CARGO_LLVM_COV_VERSION}" - ) - .run()?; - } + cargo_install(sh, &CARGO_LLVM_COV)?; Ok(()) } @@ -170,21 +164,8 @@ pub fn grcov(sh: &Shell) -> anyhow::Result<()> { cmd!(sh, "rustup component add --toolchain nightly llvm-tools-preview").run()?; cmd!(sh, "rustup component add llvm-tools-preview").run()?; - if !is_installed(sh, "cargo-fuzz") { - cmd!( - sh, - "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} cargo-fuzz@{CARGO_FUZZ_VERSION}" - ) - .run()?; - } - - if !is_installed(sh, "grcov") { - cmd!( - sh, - "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} grcov@{GRCOV_VERSION}" - ) - .run()?; - } + cargo_install(sh, &CARGO_FUZZ)?; + cargo_install(sh, &GRCOV)?; println!("Remove leftovers"); sh.remove_path("./fuzz/coverage/")?; diff --git a/xtask/src/fuzz.rs b/xtask/src/fuzz.rs index 8eeaf689..29a731c5 100644 --- a/xtask/src/fuzz.rs +++ b/xtask/src/fuzz.rs @@ -61,15 +61,7 @@ pub fn install(sh: &Shell) -> anyhow::Result<()> { let _s = Section::new("FUZZ-INSTALL"); windows_skip!(); - if !is_installed(sh, "cargo-fuzz") { - // Install in debug because it's faster to compile and we don't need execution speed anyway. - // cargo-fuzz version is pinned so we don’t get different versions without intervention. - cmd!( - sh, - "{CARGO} install --debug --locked --root {LOCAL_CARGO_ROOT} cargo-fuzz@{CARGO_FUZZ_VERSION}" - ) - .run()?; - } + cargo_install(sh, &CARGO_FUZZ)?; cmd!(sh, "rustup install nightly --profile=minimal").run()?; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 5a4f1476..f22e9f9d 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -6,6 +6,7 @@ #[macro_use] mod macros; +mod bin_install; mod bin_version; mod check; mod clean; @@ -19,11 +20,21 @@ mod web; use std::path::{Path, PathBuf}; -use prelude::LOCAL_CARGO_ROOT; use xshell::Shell; use crate::cli::Action; +#[cfg(target_os = "windows")] +pub const LOCAL_CARGO_ROOT: &str = ".cargo\\local_root\\"; +#[cfg(not(target_os = "windows"))] +pub const LOCAL_CARGO_ROOT: &str = ".cargo/local_root/"; + +pub const CARGO: &str = env!("CARGO"); + +pub const WASM_PACKAGES: &[&str] = &["ironrdp-web"]; + +pub const FUZZ_TARGETS: &[&str] = &["pdu_decoding", "rle_decompression", "bitmap_stream"]; + fn main() -> anyhow::Result<()> { let args = match cli::parse_args() { Ok(args) => args, @@ -47,7 +58,7 @@ fn main() -> anyhow::Result<()> { web::install(&sh)?; if is_verbose() { - list_files(&sh, local_cargo_root().join("bin"))?; + list_files(&sh, local_bin())?; } } Action::CheckFmt => check::fmt(&sh)?, @@ -177,12 +188,6 @@ pub fn is_verbose() -> bool { VERBOSE.load(std::sync::atomic::Ordering::Acquire) } -/// Checks if a binary is installed in local root -pub fn is_installed(sh: &Shell, name: &str) -> bool { - let path = local_bin().join(name); - sh.path_exists(&path) || sh.path_exists(path.with_extension("exe")) -} - pub fn list_files(sh: &Shell, path: impl AsRef) -> anyhow::Result<()> { let path = path.as_ref(); diff --git a/xtask/src/prelude.rs b/xtask/src/prelude.rs index 28233dc7..4dbac942 100644 --- a/xtask/src/prelude.rs +++ b/xtask/src/prelude.rs @@ -1,16 +1,7 @@ pub use anyhow::Context as _; pub use xshell::{cmd, Shell}; +pub use crate::bin_install::{cargo_install, is_installed}; pub use crate::bin_version::*; pub use crate::section::Section; -pub use crate::{is_installed, is_verbose, list_files, local_bin, local_cargo_root, set_verbose}; - -pub const CARGO: &str = env!("CARGO"); -#[cfg(target_os = "windows")] -pub const LOCAL_CARGO_ROOT: &str = ".cargo\\local_root\\"; -#[cfg(not(target_os = "windows"))] -pub const LOCAL_CARGO_ROOT: &str = ".cargo/local_root/"; - -pub const WASM_PACKAGES: &[&str] = &["ironrdp-web"]; - -pub const FUZZ_TARGETS: &[&str] = &["pdu_decoding", "rle_decompression", "bitmap_stream"]; +pub use crate::{is_verbose, list_files, CARGO, FUZZ_TARGETS, WASM_PACKAGES}; diff --git a/xtask/src/wasm.rs b/xtask/src/wasm.rs index 48a1d88a..89a6938c 100644 --- a/xtask/src/wasm.rs +++ b/xtask/src/wasm.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use crate::{local_bin, prelude::*}; pub fn check(sh: &Shell) -> anyhow::Result<()> { let _s = Section::new("WASM-CHECK"); @@ -53,7 +53,7 @@ pub fn install(sh: &Shell) -> anyhow::Result<()> { fn install_wasm2wat(sh: &Shell) -> anyhow::Result<()> { println!("Installing wasm2wat in local root..."); - let _guard = sh.push_dir(LOCAL_CARGO_ROOT); + let _guard = sh.push_dir(crate::LOCAL_CARGO_ROOT); let platform_suffix = if cfg!(target_os = "windows") { "windows" diff --git a/xtask/src/web.rs b/xtask/src/web.rs index 7d60dc05..575bfc63 100644 --- a/xtask/src/web.rs +++ b/xtask/src/web.rs @@ -15,37 +15,7 @@ pub fn install(sh: &Shell) -> anyhow::Result<()> { run_cmd_in!(sh, IRON_REMOTE_GUI_PATH, "{NPM} install")?; run_cmd_in!(sh, IRON_SVELTE_CLIENT_PATH, "{NPM} install")?; - if !is_installed(sh, "wasm-pack") { - if cfg!(target_os = "windows") { - let _guard = sh.push_dir(LOCAL_CARGO_ROOT); - - cmd!(sh, "{NPM} install wasm-pack@{WASM_PACK_VERSION}").run()?; - - sh.copy_file( - "./node_modules/binary-install/node_modules/.bin/wasm-pack.exe", - "./bin/wasm-pack.exe", - )?; - - sh.remove_path("./node_modules")?; - sh.remove_path("./package-lock.json")?; - sh.remove_path("./package.json")?; - } else { - // WORKAROUND: https://github.com/rustwasm/wasm-pack/issues/1203 - - // NOTE: Install in debug because it's faster to compile and we don't need execution speed anyway. - // NOTE: cargo-fuzz version is pinned so we don’t get different versions without intervention. - cmd!( - sh, - "{CARGO} install - --debug --locked - --root {LOCAL_CARGO_ROOT} - --no-default-features - --features sys-openssl - wasm-pack@{WASM_PACK_VERSION}" - ) - .run()?; - } - } + cargo_install(sh, &WASM_PACK)?; Ok(()) }