From 928855bdd5a054ee884bf1de9351e8009dcdffe3 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 15 Dec 2022 14:26:25 +0100 Subject: [PATCH 01/12] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Initial?= =?UTF-8?q?=20async?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 123 ++++++++++++++++++------- Cargo.toml | 4 +- src/main.rs | 62 ++++++++----- src/toolchain/espidf.rs | 47 +++++----- src/toolchain/gcc.rs | 41 +++++---- src/toolchain/llvm.rs | 72 ++++++++------- src/toolchain/mod.rs | 34 ++++--- src/toolchain/rust.rs | 197 ++++++++++++++++++++-------------------- 8 files changed, 342 insertions(+), 238 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e1a7c1..cc88fa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -83,6 +83,17 @@ dependencies = [ "tempfile", ] +[[package]] +name = "async-trait" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atty" version = "0.2.14" @@ -102,15 +113,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.5.4", + "miniz_oxide", "object", "rustc-demangle", ] @@ -527,11 +538,12 @@ dependencies = [ [[package]] name = "espup" -version = "0.2.4" +version = "0.2.5-dev" dependencies = [ "anyhow", "assert_cmd", "assert_fs", + "async-trait", "clap", "console", "directories-next", @@ -552,6 +564,7 @@ dependencies = [ "tar", "tempfile", "thiserror", + "tokio", "toml", "update-informer", "xz2", @@ -586,7 +599,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] @@ -634,12 +647,6 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" -[[package]] -name = "futures-io" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" - [[package]] name = "futures-sink" version = "0.3.25" @@ -659,12 +666,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", - "futures-io", "futures-task", - "memchr", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -690,9 +694,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "globset" @@ -996,9 +1000,19 @@ checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "linux-raw-sys" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] [[package]] name = "log" @@ -1072,15 +1086,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1132,9 +1137,9 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" dependencies = [ "memchr", ] @@ -1218,6 +1223,29 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.42.0", +] + [[package]] name = "password-hash" version = "0.4.2" @@ -1658,6 +1686,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.7" @@ -1667,6 +1704,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + [[package]] name = "smawk" version = "0.3.1" @@ -1906,11 +1949,25 @@ dependencies = [ "memchr", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.42.0", ] +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.0" @@ -1937,9 +1994,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index d9e108d..805161d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ clap = { version = "4.0.29", features = ["derive"] } dirs = "4.0.0" flate2 = "1.0.25" guess_host_triple = "0.1.3" -reqwest = { version = "0.11.12", features = ["blocking"] } +reqwest = "0.11.12" tar = "0.4.37" zip = "0.6.3" xz2 = "0.1.6" @@ -38,6 +38,8 @@ regex = "1.7.0" serde_json = "1.0.89" thiserror = "1.0.37" update-informer = "0.6.0" +tokio = { version = "1.21.2", features = ["full"] } +async-trait = "0.1.58" [dev-dependencies] assert_fs = "1.0.10" diff --git a/src/main.rs b/src/main.rs index 3eaf018..87dedbe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,9 +17,8 @@ use espup::{ }, gcc::{get_toolchain_name, install_gcc_targets}, llvm::Llvm, - rust::{ - check_rust_installation, install_extra_crates, install_riscv_target, Crate, XtensaRust, - }, + rust::{check_rust_installation, install_riscv_target, Crate, XtensaRust}, + Installable, }, update::check_for_update, }; @@ -31,6 +30,7 @@ use std::{ io::Write, path::PathBuf, }; +use tokio::sync::mpsc; #[cfg(windows)] const DEFAULT_EXPORT_FILE: &str = "export-esp.ps1"; @@ -128,7 +128,7 @@ pub struct UninstallOpts { } /// Installs the Rust for ESP chips environment -fn install(args: InstallOpts) -> Result<()> { +async fn install(args: InstallOpts) -> Result<()> { initialize_logger(&args.log_level); check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); info!("{} Installing esp-rs", emoji::DISC); @@ -143,7 +143,7 @@ fn install(args: InstallOpts) -> Result<()> { let xtensa_rust: XtensaRust = if let Some(toolchain_version) = &args.toolchain_version { XtensaRust::new(toolchain_version, &host_triple) } else { - let latest_version = XtensaRust::get_latest_version()?; + let latest_version = XtensaRust::get_latest_version().await?; XtensaRust::new(&latest_version, &host_triple) }; Some(xtensa_rust) @@ -152,6 +152,7 @@ fn install(args: InstallOpts) -> Result<()> { }; let export_file = get_export_file(args.export_file)?; let llvm = Llvm::new(args.llvm_version, args.profile_minimal, &host_triple); + let llvm_path = Some(llvm.path.clone()); debug!( "{} Arguments: @@ -171,7 +172,7 @@ fn install(args: InstallOpts) -> Result<()> { &args.esp_idf_version, &export_file, &extra_crates, - llvm, + &llvm, &args.nightly_version, xtensa_rust, args.profile_minimal, @@ -181,21 +182,24 @@ fn install(args: InstallOpts) -> Result<()> { #[cfg(windows)] check_arguments(&targets, &args.esp_idf_version)?; - check_rust_installation(&args.nightly_version, &host_triple)?; + check_rust_installation(&args.nightly_version, &host_triple).await?; + + // Build up a vector of installable applications, all of which implement the + // `Installable` async trait. + let mut to_install = Vec::>::new(); if let Some(ref xtensa_rust) = xtensa_rust { - xtensa_rust.install()?; + to_install.push(Box::new(xtensa_rust.to_owned())); } - exports.extend(llvm.install()?); - + // TODO: can we convert this to a struct which implements `Installable`? if targets.contains(&Target::ESP32C3) { install_riscv_target(&args.nightly_version)?; } if let Some(esp_idf_version) = &args.esp_idf_version { let repo = EspIdfRepo::new(esp_idf_version, args.profile_minimal, &targets); - exports.extend(repo.install()?); + to_install.push(Box::new(repo)); if let Some(ref mut extra_crates) = extra_crates { extra_crates.insert(Crate::new("ldproxy")); } else { @@ -204,11 +208,23 @@ fn install(args: InstallOpts) -> Result<()> { extra_crates = Some(crates); }; } else { - exports.extend(install_gcc_targets(&targets, &host_triple)?); + // FIXME: parallelize! + exports.extend(install_gcc_targets(&targets, &host_triple).await?); } if let Some(ref extra_crates) = &extra_crates { - install_extra_crates(extra_crates)?; + // TODO: should we consolidate this into a single `cargo install`? + for krate in extra_crates { + to_install.push(Box::new(krate.to_owned())); + } + } + + // With a list of applications to install, install them all in parallel. + let (tx, mut rx) = mpsc::channel::<()>(32); + + for app in to_install { + // FIXME: parallelize! + exports.extend(app.install().await?); } if args.profile_minimal { @@ -228,7 +244,7 @@ fn install(args: InstallOpts) -> Result<()> { .collect::>() }), host_triple, - llvm_path: Some(llvm.path), + llvm_path, nightly_version: args.nightly_version, targets, xtensa_rust, @@ -240,11 +256,12 @@ fn install(args: InstallOpts) -> Result<()> { "{} Please, source the export file, as state above, to properly setup the environment!", emoji::WARN ); + Ok(()) } /// Uninstalls the Rust for ESP chips environment -fn uninstall(args: UninstallOpts) -> Result<()> { +async fn uninstall(args: UninstallOpts) -> Result<()> { initialize_logger(&args.log_level); check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); @@ -333,7 +350,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> { } /// Updates Xtensa Rust toolchain. -fn update(args: UpdateOpts) -> Result<()> { +async fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); @@ -343,7 +360,7 @@ fn update(args: UpdateOpts) -> Result<()> { let xtensa_rust: XtensaRust = if let Some(toolchain_version) = args.toolchain_version { XtensaRust::new(&toolchain_version, &host_triple) } else { - let latest_version = XtensaRust::get_latest_version()?; + let latest_version = XtensaRust::get_latest_version().await?; XtensaRust::new(&latest_version, &host_triple) }; @@ -368,7 +385,7 @@ fn update(args: UpdateOpts) -> Result<()> { return Ok(()); } config_xtensa_rust.uninstall()?; - xtensa_rust.install()?; + xtensa_rust.install().await?; config.xtensa_rust = Some(xtensa_rust); } @@ -378,11 +395,12 @@ fn update(args: UpdateOpts) -> Result<()> { Ok(()) } -fn main() -> Result<()> { +#[tokio::main] +async fn main() -> Result<()> { match Cli::parse().subcommand { - SubCommand::Install(args) => install(*args), - SubCommand::Update(args) => update(args), - SubCommand::Uninstall(args) => uninstall(args), + SubCommand::Install(args) => install(*args).await, + SubCommand::Update(args) => update(args).await, + SubCommand::Uninstall(args) => uninstall(args).await, } } diff --git a/src/toolchain/espidf.rs b/src/toolchain/espidf.rs index 2d4ecec..b102874 100644 --- a/src/toolchain/espidf.rs +++ b/src/toolchain/espidf.rs @@ -1,4 +1,5 @@ //! GCC Toolchain source and installation tools +use super::Installable; use crate::{ emoji, error::Error, @@ -8,6 +9,7 @@ use crate::{ get_home_dir, }, }; +use async_trait::async_trait; use embuild::{espidf, espidf::EspIdfRemote, git}; use log::{debug, info}; use miette::Result; @@ -63,11 +65,31 @@ pub struct EspIdfRepo { } impl EspIdfRepo { - /// Installs esp-idf. - pub fn install(self) -> Result, Error> { + /// Create a new instance with the proper arguments. + pub fn new(version: &str, minified: bool, targets: &HashSet) -> EspIdfRepo { + let install_path = PathBuf::from(get_tools_path()); + debug!( + "{} ESP-IDF install path: '{}'", + emoji::DEBUG, + install_path.display() + ); + + Self { + repository_url: DEFAULT_GIT_REPOSITORY.to_string(), + version: version.to_string(), + minified, + install_path, + targets: targets.clone(), + } + } +} + +#[async_trait] +impl Installable for EspIdfRepo { + async fn install(&self) -> Result, Error> { let cmake_generator = DEFAULT_CMAKE_GENERATOR; let mut exports: Vec = Vec::new(); - + let targets = self.targets.clone(); // A closure to specify which tools `idf-tools.py` should install. let make_tools = move |repo: &git::Repository, version: &anyhow::Result| @@ -85,7 +107,7 @@ impl EspIdfRepo { let mut tools = vec![]; let mut subtools = Vec::new(); - for target in self.targets { + for target in targets { let gcc_toolchain_name = get_toolchain_name(&target); subtools.push(gcc_toolchain_name); @@ -167,23 +189,6 @@ impl EspIdfRepo { Ok(exports) } - - /// Create a new instance with the proper arguments. - pub fn new(version: &str, minified: bool, targets: &HashSet) -> EspIdfRepo { - let install_path = PathBuf::from(get_tools_path()); - debug!( - "{} ESP-IDF install path: '{}'", - emoji::DEBUG, - install_path.display() - ); - Self { - repository_url: DEFAULT_GIT_REPOSITORY.to_string(), - version: version.to_string(), - minified, - install_path, - targets: targets.clone(), - } - } } /// Gets the esp-idf installation path. diff --git a/src/toolchain/gcc.rs b/src/toolchain/gcc.rs index 3b61543..f574fde 100644 --- a/src/toolchain/gcc.rs +++ b/src/toolchain/gcc.rs @@ -1,5 +1,6 @@ //! GCC Toolchain source and installation tools +use super::Installable; use crate::{ emoji, error::Error, @@ -7,6 +8,7 @@ use crate::{ targets::Target, toolchain::{download_file, espidf::get_tool_path}, }; +use async_trait::async_trait; use embuild::espidf::EspIdfVersion; use log::{debug, info, warn}; use miette::Result; @@ -43,8 +45,21 @@ impl Gcc { get_tool_path(&toolchain_path) } - /// Installs the gcc toolchain. - pub fn install(&self) -> Result<(), Error> { + /// Create a new instance with default values and proper toolchain name. + pub fn new(target: &Target, host_triple: &HostTriple) -> Self { + Self { + host_triple: host_triple.clone(), + release: DEFAULT_GCC_RELEASE.to_string(), + repository_url: DEFAULT_GCC_REPOSITORY.to_string(), + toolchain_name: get_toolchain_name(target), + version: DEFAULT_GCC_VERSION.to_string(), + } + } +} + +#[async_trait] +impl Installable for Gcc { + async fn install(&self) -> Result, Error> { let target_dir = format!("{}/{}-{}", self.toolchain_name, self.release, self.version); let gcc_path = get_tool_path(&target_dir); let extension = get_artifact_extension(&self.host_triple); @@ -55,7 +70,7 @@ impl Gcc { emoji::WARN, &gcc_path ); - return Ok(()); + return Ok(vec![]); // No exports } let gcc_file = format!( "{}-gcc{}-{}-{}.{}", @@ -71,19 +86,9 @@ impl Gcc { &format!("{}.{}", &self.toolchain_name, extension), &gcc_path, true, - )?; - Ok(()) - } - - /// Create a new instance with default values and proper toolchain name. - pub fn new(target: &Target, host_triple: &HostTriple) -> Self { - Self { - host_triple: host_triple.clone(), - release: DEFAULT_GCC_RELEASE.to_string(), - repository_url: DEFAULT_GCC_REPOSITORY.to_string(), - toolchain_name: get_toolchain_name(target), - version: DEFAULT_GCC_VERSION.to_string(), - } + ) + .await?; + Ok(vec![]) // No exports } } @@ -138,7 +143,7 @@ pub fn get_ulp_toolchain_name(target: Target, version: Option<&EspIdfVersion>) - } /// Installs GCC toolchain the selected targets. -pub fn install_gcc_targets( +pub async fn install_gcc_targets( targets: &HashSet, host_triple: &HostTriple, ) -> Result, Error> { @@ -146,7 +151,7 @@ pub fn install_gcc_targets( let mut exports: Vec = Vec::new(); for target in targets { let gcc = Gcc::new(target, host_triple); - gcc.install()?; + gcc.install().await?; #[cfg(windows)] exports.push(format!("$Env:PATH += \";{}\"", gcc.get_bin_path())); diff --git a/src/toolchain/llvm.rs b/src/toolchain/llvm.rs index 60d1b17..a3eb2d8 100644 --- a/src/toolchain/llvm.rs +++ b/src/toolchain/llvm.rs @@ -1,10 +1,13 @@ //! LLVM Toolchain source and installation tools +use super::Installable; use crate::{ emoji, + error::Error, host_triple::HostTriple, toolchain::{download_file, espidf::get_tool_path}, }; +use async_trait::async_trait; use log::{info, warn}; use miette::Result; use std::path::{Path, PathBuf}; @@ -47,39 +50,6 @@ impl Llvm { llvm_path } - /// Installs the LLVM toolchain. - pub fn install(&self) -> Result> { - let mut exports: Vec = Vec::new(); - - if Path::new(&self.path).exists() { - warn!( - "{} Previous installation of LLVM exist in: '{}'. Reusing this installation.", - emoji::WARN, - self.path.to_str().unwrap() - ); - } else { - info!("{} Installing Xtensa elf Clang", emoji::WRENCH); - download_file( - self.repository_url.clone(), - "idf_tool_xtensa_elf_clang.tar.xz", - self.path.to_str().unwrap(), - true, - )?; - } - // Set environment variables. - #[cfg(windows)] - exports.push(format!( - "$Env:LIBCLANG_PATH=\"{}/libclang.dll\"", - self.get_lib_path() - )); - #[cfg(windows)] - exports.push(format!("$Env:PATH+=\";{}\"", self.get_lib_path())); - #[cfg(unix)] - exports.push(format!("export LIBCLANG_PATH=\"{}\"", self.get_lib_path())); - - Ok(exports) - } - /// Create a new instance with default values and proper toolchain version. pub fn new(version: String, minified: bool, host_triple: &HostTriple) -> Self { let mut file_name = format!( @@ -109,3 +79,39 @@ impl Llvm { } } } + +#[async_trait] +impl Installable for Llvm { + async fn install(&self) -> Result, Error> { + let mut exports: Vec = Vec::new(); + + if Path::new(&self.path).exists() { + warn!( + "{} Previous installation of LLVM exist in: '{}'. Reusing this installation.", + emoji::WARN, + self.path.to_str().unwrap() + ); + } else { + info!("{} Installing Xtensa elf Clang", emoji::WRENCH); + download_file( + self.repository_url.clone(), + "idf_tool_xtensa_elf_clang.tar.xz", + self.path.to_str().unwrap(), + true, + ) + .await?; + } + // Set environment variables. + #[cfg(windows)] + exports.push(format!( + "$Env:LIBCLANG_PATH=\"{}/libclang.dll\"", + self.get_lib_path() + )); + #[cfg(windows)] + exports.push(format!("$Env:PATH+=\";{}\"", self.get_lib_path())); + #[cfg(unix)] + exports.push(format!("export LIBCLANG_PATH=\"{}\"", self.get_lib_path())); + + Ok(exports) + } +} diff --git a/src/toolchain/mod.rs b/src/toolchain/mod.rs index fd25b64..9edb939 100644 --- a/src/toolchain/mod.rs +++ b/src/toolchain/mod.rs @@ -1,11 +1,12 @@ use crate::{emoji, error::Error}; +use async_trait::async_trait; use dirs::home_dir; use flate2::bufread::GzDecoder; use log::info; use miette::Result; use std::{ fs::{create_dir_all, File}, - io::{copy, BufReader}, + io::Write, path::Path, }; use tar::Archive; @@ -16,13 +17,19 @@ pub mod gcc; pub mod llvm; pub mod rust; +#[async_trait] +pub trait Installable { + /// Install some application, returning a vector of any required exports + async fn install(&self) -> Result, Error>; +} + /// Returns the path to the home directory. pub fn get_home_dir() -> String { home_dir().unwrap().display().to_string() } /// Downloads a file from a URL and uncompresses it, if necesary, to the output directory. -pub fn download_file( +pub async fn download_file( url: String, file_name: &str, output_directory: &str, @@ -48,14 +55,14 @@ pub fn download_file( file_name, url ); - let mut resp = reqwest::blocking::get(&url).unwrap(); - + let resp = reqwest::get(&url).await?; + let bytes = resp.bytes().await?; if uncompress { let extension = Path::new(file_name).extension().unwrap().to_str().unwrap(); match extension { "zip" => { - let mut tmpfile = tempfile::tempfile().unwrap(); - resp.copy_to(&mut tmpfile)?; + let mut tmpfile = tempfile::tempfile()?; + tmpfile.write_all(&bytes)?; let mut zipfile = zip::ZipArchive::new(tmpfile).unwrap(); zipfile.extract(output_directory).unwrap(); } @@ -65,10 +72,11 @@ pub fn download_file( emoji::WRENCH, output_directory ); - let content_br = BufReader::new(resp); - let tarfile = GzDecoder::new(content_br); + + let bytes = bytes.to_vec(); + let tarfile = GzDecoder::new(bytes.as_slice()); let mut archive = Archive::new(tarfile); - archive.unpack(output_directory).unwrap(); + archive.unpack(output_directory)?; } "xz" => { info!( @@ -76,10 +84,10 @@ pub fn download_file( emoji::WRENCH, output_directory ); - let content_br = BufReader::new(resp); - let tarfile = XzDecoder::new(content_br); + let bytes = bytes.to_vec(); + let tarfile = XzDecoder::new(bytes.as_slice()); let mut archive = Archive::new(tarfile); - archive.unpack(output_directory).unwrap(); + archive.unpack(output_directory)?; } _ => { return Err(Error::UnsuportedFileExtension(extension.to_string())); @@ -88,7 +96,7 @@ pub fn download_file( } else { info!("{} Creating file: '{}'", emoji::WRENCH, file_path); let mut out = File::create(file_path)?; - copy(&mut resp, &mut out)?; + out.write_all(&bytes)?; } Ok(format!("{}/{}", output_directory, file_name)) } diff --git a/src/toolchain/rust.rs b/src/toolchain/rust.rs index 3757813..413c32d 100644 --- a/src/toolchain/rust.rs +++ b/src/toolchain/rust.rs @@ -1,11 +1,13 @@ //! Xtensa Rust Toolchain source and installation tools +use super::Installable; use crate::{ emoji, error::Error, host_triple::HostTriple, toolchain::{download_file, espidf::get_dist_path, get_home_dir}, }; +use async_trait::async_trait; use embuild::cmd; use log::{debug, info, warn}; use miette::{IntoDiagnostic, Result}; @@ -49,11 +51,10 @@ pub struct XtensaRust { impl XtensaRust { /// Get the latest version of Xtensa Rust toolchain. - pub fn get_latest_version() -> Result { + pub async fn get_latest_version() -> Result { let mut headers = header::HeaderMap::new(); headers.insert("Accept", "application/vnd.github.v3+json".parse().unwrap()); - - let client = reqwest::blocking::Client::builder() + let client = reqwest::Client::builder() .redirect(reqwest::redirect::Policy::none()) .user_agent("espup") .build() @@ -62,8 +63,10 @@ impl XtensaRust { .get(XTENSA_RUST_API_URL) .headers(headers) .send() + .await .into_diagnostic()? .text() + .await .into_diagnostic()?; let json: serde_json::Value = serde_json::from_str(&res).map_err(|_| Error::FailedToSerializeJson)?; @@ -75,70 +78,6 @@ impl XtensaRust { Ok(version) } - /// Installs the Xtensa Rust toolchain. - pub fn install(&self) -> Result<(), Error> { - #[cfg(unix)] - let toolchain_path = self.toolchain_destination.clone(); - #[cfg(windows)] - let toolchain_path = self.toolchain_destination.clone().join("esp"); - if toolchain_path.exists() { - return Err(Error::XtensaToolchainAlreadyInstalled( - toolchain_path.display().to_string(), - )); - } - info!( - "{} Installing Xtensa Rust {} toolchain", - emoji::WRENCH, - self.version - ); - - #[cfg(unix)] - if cfg!(unix) { - download_file( - self.dist_url.clone(), - "rust.tar.xz", - &get_dist_path("rust"), - true, - )?; - - info!("{} Installing rust esp toolchain", emoji::WRENCH); - let arguments = format!( - "{}/rust-nightly-{}/install.sh --destdir={} --prefix='' --without=rust-docs-json-preview,rust-docs", - get_dist_path("rust"), - &self.host_triple, - self.toolchain_destination.display() - ); - cmd!("/bin/bash", "-c", arguments).run()?; - - download_file( - self.src_dist_url.clone(), - "rust-src.tar.xz", - &get_dist_path("rust-src"), - true, - )?; - info!("{} Installing rust-src for esp toolchain", emoji::WRENCH); - let arguments = format!( - "{}/rust-src-nightly/install.sh --destdir={} --prefix='' --without=rust-docs-json-preview,rust-docs", - get_dist_path("rust-src"), - self.toolchain_destination.display() - ); - cmd!("/bin/bash", "-c", arguments).run()?; - } - // Some platfroms like Windows are available in single bundle rust + src, because install - // script in dist is not available for the plaform. It's sufficient to extract the toolchain - #[cfg(windows)] - if cfg!(windows) { - download_file( - self.dist_url.clone(), - "rust.zip", - &self.toolchain_destination.display().to_string(), - true, - )?; - } - - Ok(()) - } - /// Create a new instance. pub fn new(toolchain_version: &str, host_triple: &HostTriple) -> Self { let artifact_extension = get_artifact_extension(host_triple); @@ -201,6 +140,74 @@ impl XtensaRust { } } +#[async_trait] +impl Installable for XtensaRust { + async fn install(&self) -> Result, Error> { + #[cfg(unix)] + let toolchain_path = self.toolchain_destination.clone(); + #[cfg(windows)] + let toolchain_path = self.toolchain_destination.clone().join("esp"); + if toolchain_path.exists() { + return Err(Error::XtensaToolchainAlreadyInstalled( + toolchain_path.display().to_string(), + )); + } + info!( + "{} Installing Xtensa Rust {} toolchain", + emoji::WRENCH, + self.version + ); + + #[cfg(unix)] + if cfg!(unix) { + download_file( + self.dist_url.clone(), + "rust.tar.xz", + &get_dist_path("rust"), + true, + ) + .await?; + + info!("{} Installing rust esp toolchain", emoji::WRENCH); + let arguments = format!( + "{}/rust-nightly-{}/install.sh --destdir={} --prefix='' --without=rust-docs-json-preview,rust-docs", + get_dist_path("rust"), + &self.host_triple, + self.toolchain_destination.display() + ); + cmd!("/bin/bash", "-c", arguments).run()?; + + download_file( + self.src_dist_url.clone(), + "rust-src.tar.xz", + &get_dist_path("rust-src"), + true, + ) + .await?; + info!("{} Installing rust-src for esp toolchain", emoji::WRENCH); + let arguments = format!( + "{}/rust-src-nightly/install.sh --destdir={} --prefix='' --without=rust-docs-json-preview,rust-docs", + get_dist_path("rust-src"), + self.toolchain_destination.display() + ); + cmd!("/bin/bash", "-c", arguments).run()?; + } + // Some platfroms like Windows are available in single bundle rust + src, because install + // script in dist is not available for the plaform. It's sufficient to extract the toolchain + #[cfg(windows)] + if cfg!(windows) { + download_file( + self.dist_url.clone(), + "rust.zip", + &self.toolchain_destination.display().to_string(), + true, + )?; + } + + Ok(vec![]) // No exports + } +} + #[derive(Hash, Eq, PartialEq, Debug, Clone, Serialize, Deserialize, Default)] pub struct Crate { /// Crate name. @@ -208,23 +215,6 @@ pub struct Crate { } impl Crate { - /// Installs a crate. - pub fn install(&self) -> Result<()> { - #[cfg(unix)] - let crate_path = format!("{}/bin/{}", get_cargo_home().display(), self.name); - #[cfg(windows)] - let crate_path = format!("{}/bin/{}.exe", get_cargo_home().display(), self.name); - if PathBuf::from(crate_path).exists() { - warn!("{} {} is already installed", emoji::WARN, self.name); - Ok(()) - } else { - cmd!("cargo", "install", &self.name) - .run() - .into_diagnostic()?; - Ok(()) - } - } - /// Create a crate instance. pub fn new(name: &str) -> Self { Crate { @@ -238,17 +228,26 @@ impl Crate { } } -pub fn install_extra_crates(crates: &HashSet) -> Result<()> { - debug!( - "{} Installing the following crates: {:#?}", - emoji::DEBUG, - crates - ); - for c in crates { - c.install()?; +#[async_trait] +impl Installable for Crate { + async fn install(&self) -> Result, Error> { + debug!("{} Installing crate: {}", emoji::DEBUG, self.name); + + #[cfg(unix)] + let crate_path = format!("{}/bin/{}", get_cargo_home().display(), self.name); + #[cfg(windows)] + let crate_path = format!("{}/bin/{}.exe", get_cargo_home().display(), self.name); + + if PathBuf::from(crate_path).exists() { + warn!("{} {} is already installed", emoji::WARN, self.name); + } else { + cmd!("cargo", "install", &self.name).run()?; + } + + Ok(vec![]) // No exports } - Ok(()) } + /// Gets the artifact extension based on the host architecture. fn get_artifact_extension(host_triple: &HostTriple) -> &str { match host_triple { @@ -269,7 +268,10 @@ pub fn get_rustup_home() -> PathBuf { /// Checks if rustup and the proper nightly version are installed. If rustup is not installed, /// it returns an error. If nigthly version is not installed, proceed to install it. -pub fn check_rust_installation(nightly_version: &str, host_triple: &HostTriple) -> Result<()> { +pub async fn check_rust_installation( + nightly_version: &str, + host_triple: &HostTriple, +) -> Result<()> { info!("{} Checking existing Rust installation", emoji::WRENCH); match cmd!("rustup", "toolchain", "list") @@ -287,7 +289,7 @@ pub fn check_rust_installation(nightly_version: &str, host_triple: &HostTriple) Err(e) => { if let std::io::ErrorKind::NotFound = e.kind() { warn!("{} rustup was not found.", emoji::WARN); - install_rustup(nightly_version, host_triple)?; + install_rustup(nightly_version, host_triple).await?; } else { return Err(Error::RustupDetectionError(e.to_string())).into_diagnostic(); } @@ -298,7 +300,7 @@ pub fn check_rust_installation(nightly_version: &str, host_triple: &HostTriple) } /// Installs rustup -fn install_rustup(nightly_version: &str, host_triple: &HostTriple) -> Result<(), Error> { +async fn install_rustup(nightly_version: &str, host_triple: &HostTriple) -> Result<(), Error> { #[cfg(windows)] let rustup_init_path = download_file( "https://win.rustup.rs/x86_64".to_string(), @@ -312,7 +314,8 @@ fn install_rustup(nightly_version: &str, host_triple: &HostTriple) -> Result<(), "rustup-init.sh", &get_dist_path("rustup"), false, - )?; + ) + .await?; info!( "{} Installing rustup with {} toolchain", emoji::WRENCH, From fd529e3f6aa7f140ee6a4a6b2fcf004bfb5d9726 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Tue, 20 Dec 2022 14:59:41 +0000 Subject: [PATCH 02/12] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Use=20st?= =?UTF-8?q?ruct=20to=20store=20RiscV=20Target=20info=20so=20we=20can=20imp?= =?UTF-8?q?l=20Installaable=20for=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 8 ++++-- src/toolchain/rust.rs | 67 ++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index 87dedbe..2dca1ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use espup::{ }, gcc::{get_toolchain_name, install_gcc_targets}, llvm::Llvm, - rust::{check_rust_installation, install_riscv_target, Crate, XtensaRust}, + rust::{check_rust_installation, Crate, RiscVTarget, XtensaRust}, Installable, }, update::check_for_update, @@ -192,9 +192,11 @@ async fn install(args: InstallOpts) -> Result<()> { to_install.push(Box::new(xtensa_rust.to_owned())); } - // TODO: can we convert this to a struct which implements `Installable`? if targets.contains(&Target::ESP32C3) { - install_riscv_target(&args.nightly_version)?; + let riscv_target = RiscVTarget { + nightly_version: args.nightly_version.clone(), + }; + to_install.push(Box::new(riscv_target)); } if let Some(esp_idf_version) = &args.esp_idf_version { diff --git a/src/toolchain/rust.rs b/src/toolchain/rust.rs index 413c32d..12b7354 100644 --- a/src/toolchain/rust.rs +++ b/src/toolchain/rust.rs @@ -248,6 +248,47 @@ impl Installable for Crate { } } +pub struct RiscVTarget { + /// Nightly version. + pub nightly_version: String, +} + +impl RiscVTarget { + /// Create a crate instance. + pub fn new(nightly_version: &str) -> Self { + RiscVTarget { + nightly_version: nightly_version.to_string(), + } + } +} + +#[async_trait] +impl Installable for RiscVTarget { + async fn install(&self) -> Result, Error> { + info!("{} Installing RiscV target", emoji::WRENCH); + cmd!( + "rustup", + "component", + "add", + "rust-src", + "--toolchain", + &self.nightly_version + ) + .run()?; + cmd!( + "rustup", + "target", + "add", + "--toolchain", + &self.nightly_version, + "riscv32imac-unknown-none-elf" + ) + .run()?; + + Ok(vec![]) // No exports + } +} + /// Gets the artifact extension based on the host architecture. fn get_artifact_extension(host_triple: &HostTriple) -> &str { match host_triple { @@ -370,32 +411,6 @@ async fn install_rustup(nightly_version: &str, host_triple: &HostTriple) -> Resu Ok(()) } -/// Installs the RiscV target. -pub fn install_riscv_target(nightly_version: &str) -> Result<()> { - info!("{} Installing Riscv target", emoji::WRENCH); - cmd!( - "rustup", - "component", - "add", - "rust-src", - "--toolchain", - nightly_version - ) - .run() - .into_diagnostic()?; - cmd!( - "rustup", - "target", - "add", - "--toolchain", - nightly_version, - "riscv32imac-unknown-none-elf" - ) - .run() - .into_diagnostic()?; - Ok(()) -} - /// Installs the desired version of the nightly toolchain. fn install_rust_nightly(version: &str) -> Result<()> { info!("{} Installing {} toolchain", emoji::WRENCH, version); From c8390adad52cd27a049a6b11844f479e09c35c1f Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Tue, 20 Dec 2022 15:10:23 +0000 Subject: [PATCH 03/12] =?UTF-8?q?refactor:=20=E2=9A=A1=EF=B8=8F=20Use=20Ri?= =?UTF-8?q?scVTarget=20constructor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2dca1ae..d110c1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -193,9 +193,7 @@ async fn install(args: InstallOpts) -> Result<()> { } if targets.contains(&Target::ESP32C3) { - let riscv_target = RiscVTarget { - nightly_version: args.nightly_version.clone(), - }; + let riscv_target = RiscVTarget::new(&args.nightly_version); to_install.push(Box::new(riscv_target)); } From 17de2492f7cc97ac36f36dfd98735833313b8d6e Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Tue, 20 Dec 2022 16:24:16 +0000 Subject: [PATCH 04/12] =?UTF-8?q?chore:=20=E2=9C=A8=20Initial=20attemp=20t?= =?UTF-8?q?o=20paralelize=20installations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index d110c1e..eaa8900 100644 --- a/src/main.rs +++ b/src/main.rs @@ -220,13 +220,24 @@ async fn install(args: InstallOpts) -> Result<()> { } // With a list of applications to install, install them all in parallel. - let (tx, mut rx) = mpsc::channel::<()>(32); + let (tx, mut rx) = mpsc::channel::>(32); for app in to_install { - // FIXME: parallelize! exports.extend(app.install().await?); + + // let tx = tx.clone(); + // tokio::spawn(async move { + // let res = app.install().await; + // let res = res.unwrap(); + // tx.send(res).await.unwrap(); + // }); } + // let mut exports = Vec::new(); + // while let Some(name) = rx.recv().await { + // exports.extend(name); + // } + if args.profile_minimal { clear_dist_folder()?; } From c151489b14442310c8afb0883f7c9771c8838f06 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Wed, 21 Dec 2022 11:06:23 +0000 Subject: [PATCH 05/12] =?UTF-8?q?feat:=20=E2=9C=A8=20Spawn=20a=20task=20fo?= =?UTF-8?q?r=20every=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index eaa8900..44c3040 100644 --- a/src/main.rs +++ b/src/main.rs @@ -186,7 +186,7 @@ async fn install(args: InstallOpts) -> Result<()> { // Build up a vector of installable applications, all of which implement the // `Installable` async trait. - let mut to_install = Vec::>::new(); + let mut to_install = Vec::>::new(); if let Some(ref xtensa_rust) = xtensa_rust { to_install.push(Box::new(xtensa_rust.to_owned())); @@ -223,20 +223,18 @@ async fn install(args: InstallOpts) -> Result<()> { let (tx, mut rx) = mpsc::channel::>(32); for app in to_install { - exports.extend(app.install().await?); - - // let tx = tx.clone(); - // tokio::spawn(async move { - // let res = app.install().await; - // let res = res.unwrap(); - // tx.send(res).await.unwrap(); - // }); + let tx = tx.clone(); + tokio::spawn(async move { + let res = app.install().await; + let res = res.unwrap(); + tx.send(res).await.unwrap(); + }); } - // let mut exports = Vec::new(); - // while let Some(name) = rx.recv().await { - // exports.extend(name); - // } + let mut exports = Vec::new(); + while let Some(name) = rx.recv().await { + exports.extend(name); + } if args.profile_minimal { clear_dist_folder()?; From cd2a326bf4bcf1119592af7ae9b3ea0de9f22df1 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Wed, 21 Dec 2022 11:43:08 +0000 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20=E2=9C=A8=20Await=20only=20the=20?= =?UTF-8?q?len=20of=20to=5Finstall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 44c3040..4234888 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ use espup::{ }; use log::{debug, info, warn}; use miette::{IntoDiagnostic, Result}; +use std::time::Instant; use std::{ collections::HashSet, fs::{remove_dir_all, remove_file, File}, @@ -129,6 +130,8 @@ pub struct UninstallOpts { /// Installs the Rust for ESP chips environment async fn install(args: InstallOpts) -> Result<()> { + let start = Instant::now(); + initialize_logger(&args.log_level); check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); info!("{} Installing esp-rs", emoji::DISC); @@ -221,7 +224,7 @@ async fn install(args: InstallOpts) -> Result<()> { // With a list of applications to install, install them all in parallel. let (tx, mut rx) = mpsc::channel::>(32); - + let installable_items = to_install.len(); for app in to_install { let tx = tx.clone(); tokio::spawn(async move { @@ -231,9 +234,10 @@ async fn install(args: InstallOpts) -> Result<()> { }); } - let mut exports = Vec::new(); - while let Some(name) = rx.recv().await { - exports.extend(name); + // Read the results of the install tasks as they complete. + for _ in 0..installable_items { + let names = rx.recv().await.unwrap(); + exports.extend(names); } if args.profile_minimal { @@ -265,7 +269,8 @@ async fn install(args: InstallOpts) -> Result<()> { "{} Please, source the export file, as state above, to properly setup the environment!", emoji::WARN ); - + let duration = start.elapsed(); + println!("Time elapsed in expensive_function() is: {:?}", duration); Ok(()) } From ca41f9c682aad497a48a1fdd448c5b7d86860917 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Wed, 21 Dec 2022 12:02:20 +0000 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Add=20llvm=20to=20t?= =?UTF-8?q?o=5Finstall?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.rs b/src/main.rs index 4234888..e44632b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -195,6 +195,8 @@ async fn install(args: InstallOpts) -> Result<()> { to_install.push(Box::new(xtensa_rust.to_owned())); } + to_install.push(Box::new(llvm)); + if targets.contains(&Target::ESP32C3) { let riscv_target = RiscVTarget::new(&args.nightly_version); to_install.push(Box::new(riscv_target)); From bfc678ec690f742417810938c8ce6594875d3eb7 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Wed, 21 Dec 2022 16:25:24 +0000 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20=E2=9C=A8=20Paralelize=20gcc=20in?= =?UTF-8?q?stallation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 10 ++++++---- src/toolchain/gcc.rs | 35 ++++++++++------------------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index e44632b..761f754 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ use espup::{ espidf::{ get_dist_path, get_install_path, get_tool_path, EspIdfRepo, DEFAULT_GIT_REPOSITORY, }, - gcc::{get_toolchain_name, install_gcc_targets}, + gcc::{get_toolchain_name, Gcc}, llvm::Llvm, rust::{check_rust_installation, Crate, RiscVTarget, XtensaRust}, Installable, @@ -213,8 +213,10 @@ async fn install(args: InstallOpts) -> Result<()> { extra_crates = Some(crates); }; } else { - // FIXME: parallelize! - exports.extend(install_gcc_targets(&targets, &host_triple).await?); + for target in &targets { + let gcc = Gcc::new(target, &host_triple); + to_install.push(Box::new(gcc)); + } } if let Some(ref extra_crates) = &extra_crates { @@ -237,7 +239,7 @@ async fn install(args: InstallOpts) -> Result<()> { } // Read the results of the install tasks as they complete. - for _ in 0..installable_items { + for _ in 0..installable_items - 1 { let names = rx.recv().await.unwrap(); exports.extend(names); } diff --git a/src/toolchain/gcc.rs b/src/toolchain/gcc.rs index f574fde..c567a43 100644 --- a/src/toolchain/gcc.rs +++ b/src/toolchain/gcc.rs @@ -10,12 +10,9 @@ use crate::{ }; use async_trait::async_trait; use embuild::espidf::EspIdfVersion; -use log::{debug, info, warn}; +use log::{debug, warn}; use miette::Result; -use std::{ - collections::HashSet, - path::{Path, PathBuf}, -}; +use std::path::{Path, PathBuf}; const DEFAULT_GCC_REPOSITORY: &str = "https://github.com/espressif/crosstool-NG/releases/download"; const DEFAULT_GCC_RELEASE: &str = "esp-2021r2-patch5"; @@ -88,7 +85,14 @@ impl Installable for Gcc { true, ) .await?; - Ok(vec![]) // No exports + let mut exports: Vec = Vec::new(); + + #[cfg(windows)] + exports.push(format!("$Env:PATH += \";{}\"", &self.get_bin_path())); + #[cfg(unix)] + exports.push(format!("export PATH={}:$PATH", &self.get_bin_path())); + + Ok(exports) } } @@ -141,22 +145,3 @@ pub fn get_ulp_toolchain_name(target: Target, version: Option<&EspIdfVersion>) - _ => None, } } - -/// Installs GCC toolchain the selected targets. -pub async fn install_gcc_targets( - targets: &HashSet, - host_triple: &HostTriple, -) -> Result, Error> { - info!("{} Installing gcc for build targets", emoji::WRENCH); - let mut exports: Vec = Vec::new(); - for target in targets { - let gcc = Gcc::new(target, host_triple); - gcc.install().await?; - - #[cfg(windows)] - exports.push(format!("$Env:PATH += \";{}\"", gcc.get_bin_path())); - #[cfg(unix)] - exports.push(format!("export PATH={}:$PATH", gcc.get_bin_path())); - } - Ok(exports) -} From 73b7785aac25a557fe228db9f8c81cce8c34f464 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 22 Dec 2022 10:37:07 +0000 Subject: [PATCH 09/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Fix=20receiving?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 761f754..c4bbdca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -239,7 +239,7 @@ async fn install(args: InstallOpts) -> Result<()> { } // Read the results of the install tasks as they complete. - for _ in 0..installable_items - 1 { + for _ in 0..installable_items { let names = rx.recv().await.unwrap(); exports.extend(names); } From e42f74dcfcb18728703c403f5cdd14fed4ab3f3f Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 22 Dec 2022 10:38:14 +0000 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Remove=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index c4bbdca..e896419 100644 --- a/src/main.rs +++ b/src/main.rs @@ -220,7 +220,6 @@ async fn install(args: InstallOpts) -> Result<()> { } if let Some(ref extra_crates) = &extra_crates { - // TODO: should we consolidate this into a single `cargo install`? for krate in extra_crates { to_install.push(Box::new(krate.to_owned())); } From f96ad318424c5aaa77795434d95e002a0536ffd7 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 22 Dec 2022 10:51:37 +0000 Subject: [PATCH 11/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Remove=20stopwatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index e896419..497d10c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,6 @@ use espup::{ }; use log::{debug, info, warn}; use miette::{IntoDiagnostic, Result}; -use std::time::Instant; use std::{ collections::HashSet, fs::{remove_dir_all, remove_file, File}, @@ -130,8 +129,6 @@ pub struct UninstallOpts { /// Installs the Rust for ESP chips environment async fn install(args: InstallOpts) -> Result<()> { - let start = Instant::now(); - initialize_logger(&args.log_level); check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); info!("{} Installing esp-rs", emoji::DISC); @@ -272,8 +269,6 @@ async fn install(args: InstallOpts) -> Result<()> { "{} Please, source the export file, as state above, to properly setup the environment!", emoji::WARN ); - let duration = start.elapsed(); - println!("Time elapsed in expensive_function() is: {:?}", duration); Ok(()) } From 6eb0b53dd99530473b2ce22e37b40ed5df1b6f40 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Thu, 22 Dec 2022 11:09:21 +0000 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Fix=20Windows=20bui?= =?UTF-8?q?ld?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/toolchain/rust.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/toolchain/rust.rs b/src/toolchain/rust.rs index 12b7354..e62b799 100644 --- a/src/toolchain/rust.rs +++ b/src/toolchain/rust.rs @@ -201,7 +201,8 @@ impl Installable for XtensaRust { "rust.zip", &self.toolchain_destination.display().to_string(), true, - )?; + ) + .await?; } Ok(vec![]) // No exports @@ -348,7 +349,8 @@ async fn install_rustup(nightly_version: &str, host_triple: &HostTriple) -> Resu "rustup-init.exe", &get_dist_path("rustup"), false, - )?; + ) + .await?; #[cfg(unix)] let rustup_init_path = download_file( "https://sh.rustup.rs".to_string(),