From 6f43319cf60ca4078dfbbe07d004b7de04bb1735 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 17:11:57 +0200 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20default-host=20ar?= =?UTF-8?q?gument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 30 +++++++++++++++++++++++++----- src/toolchain/gcc_toolchain.rs | 26 ++++++++++++++------------ src/toolchain/llvm_toolchain.rs | 22 ++++++++++++---------- src/toolchain/rust_toolchain.rs | 23 ++++++++++++----------- 4 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/main.rs b/src/main.rs index 676f6fea..209035f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ use espup::{ }, }, }; +use guess_host_triple::guess_host_triple; use log::{debug, info}; use std::{ collections::HashSet, @@ -56,6 +57,9 @@ pub enum SubCommand { #[derive(Debug, Parser)] pub struct InstallOpts { + /// Target triple of the host. + #[arg(short = 'd', long, required = false)] + pub defautl_host: Option, /// ESP-IDF version to install. If empty, no esp-idf is installed. Version format: /// /// - `commit:`: Uses the commit `` of the `esp-idf` repository. @@ -95,6 +99,9 @@ pub struct InstallOpts { #[derive(Debug, Parser)] pub struct UpdateOpts { + /// Target triple of the host. + #[arg(short = 'd', long, required = false)] + pub defautl_host: Option, /// Verbosity level of the logs. #[arg(short = 'l', long, default_value = "info", value_parser = ["debug", "info", "warn", "error"])] pub log_level: String, @@ -132,20 +139,25 @@ fn install(args: InstallOpts) -> Result<()> { info!("{} Installing esp-rs", emoji::DISC); let targets: HashSet = parse_targets(&args.targets).unwrap(); + // TODO: Check the provided host triple. + let host_triple = args + .defautl_host + .unwrap_or_else(|| guess_host_triple().unwrap().to_string()); let mut extra_crates: HashSet = args.extra_crates.split(',').map(RustCrate::new).collect(); let mut exports: Vec = Vec::new(); let export_file = args.export_file.clone(); - let rust_toolchain = RustToolchain::new(args.toolchain_version.clone()); + let rust_toolchain = RustToolchain::new(&args.toolchain_version, &host_triple); // Complete LLVM is failing for Windows, aarch64 MacOs, and aarch64 Linux, so we are using always minified. #[cfg(all(target_arch = "x86_64", target_os = "linux"))] - let llvm = LlvmToolchain::new(args.profile_minimal); + let llvm = LlvmToolchain::new(args.profile_minimal, &host_triple); #[cfg(any(not(target_arch = "x86_64"), not(target_os = "linux")))] - let llvm = LlvmToolchain::new(true); + let llvm = LlvmToolchain::new(true, &host_triple); debug!( "{} Arguments: + - Host triple: {} - Targets: {:?} - ESP-IDF version: {:?} - Export file: {:?} @@ -156,6 +168,7 @@ fn install(args: InstallOpts) -> Result<()> { - Profile Minimal: {:?} - Toolchain version: {:?}", emoji::INFO, + host_triple, targets, &args.espidf_version, export_file, @@ -185,7 +198,7 @@ fn install(args: InstallOpts) -> Result<()> { exports.extend(repo.install()?); extra_crates.insert(RustCrate::new("ldproxy")); } else { - exports.extend(install_gcc_targets(targets)?); + exports.extend(install_gcc_targets(targets, &host_triple)?); } debug!( @@ -249,17 +262,24 @@ fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); info!("{} Updating Xtensa Rust toolchain", emoji::DISC); + // TODO: Check the provided host triple. + let host_triple = args + .defautl_host + .unwrap_or_else(|| guess_host_triple().unwrap().to_string()); + debug!( "{} Arguments: + - Host triple: {} - Toolchain version: {}", emoji::INFO, + host_triple, &args.toolchain_version, ); info!("{} Deleting previous Xtensa Rust toolchain", emoji::WRENCH); remove_dir_all(get_rustup_home().join("toolchains").join("esp"))?; - let rust_toolchain = RustToolchain::new(args.toolchain_version); + let rust_toolchain = RustToolchain::new(&args.toolchain_version, &host_triple); rust_toolchain.install_xtensa_rust()?; info!("{} Update suscesfully completed!", emoji::CHECK); diff --git a/src/toolchain/gcc_toolchain.rs b/src/toolchain/gcc_toolchain.rs index a1e1ef69..b0c0d37f 100644 --- a/src/toolchain/gcc_toolchain.rs +++ b/src/toolchain/gcc_toolchain.rs @@ -16,14 +16,16 @@ const DEFAULT_GCC_VERSION: &str = "8_4_0"; #[derive(Debug)] pub struct GccToolchain { - /// The repository containing GCC sources. - pub repository_url: String, + /// Host triple. + pub host_triple: String, /// Repository release version to use. pub release: String, - /// GCC Version. - pub version: String, + /// The repository containing GCC sources. + pub repository_url: String, /// GCC Toolchain target. pub toolchain_name: String, + /// GCC Version. + pub version: String, } impl GccToolchain { @@ -41,15 +43,14 @@ impl GccToolchain { let target_dir = format!("{}/{}-{}", self.toolchain_name, self.release, self.version); let gcc_path = get_tool_path(&target_dir); - let host_triple = guess_host_triple::guess_host_triple().unwrap(); - let extension = get_artifact_extension(host_triple); + let extension = get_artifact_extension(&self.host_triple); debug!("{} GCC path: {}", emoji::DEBUG, gcc_path); let gcc_file = format!( "{}-gcc{}-{}-{}.{}", self.toolchain_name, self.version, self.release, - get_arch(host_triple).unwrap(), + get_arch(&self.host_triple).unwrap(), extension ); let gcc_dist_url = format!("{}/{}/{}", self.repository_url, self.release, gcc_file); @@ -63,12 +64,13 @@ impl GccToolchain { } /// Create a new instance with default values and proper toolchain name. - pub fn new(target: Target) -> Self { + pub fn new(target: Target, host_triple: &str) -> Self { Self { - repository_url: DEFAULT_GCC_REPOSITORY.to_string(), + host_triple: host_triple.to_string(), release: DEFAULT_GCC_RELEASE.to_string(), - version: DEFAULT_GCC_VERSION.to_string(), + repository_url: DEFAULT_GCC_REPOSITORY.to_string(), toolchain_name: get_toolchain_name(target), + version: DEFAULT_GCC_VERSION.to_string(), } } } @@ -128,11 +130,11 @@ pub fn get_ulp_toolchain_name(target: Target, version: Option<&EspIdfVersion>) - } /// Installs GCC toolchain the selected targets. -pub fn install_gcc_targets(targets: HashSet) -> Result> { +pub fn install_gcc_targets(targets: HashSet, host_triple: &str) -> Result> { info!("{} Installing gcc for build targets", emoji::WRENCH); let mut exports: Vec = Vec::new(); for target in targets { - let gcc = GccToolchain::new(target); + let gcc = GccToolchain::new(target, host_triple); gcc.install()?; #[cfg(windows)] diff --git a/src/toolchain/llvm_toolchain.rs b/src/toolchain/llvm_toolchain.rs index 8c826773..cc0f1e63 100644 --- a/src/toolchain/llvm_toolchain.rs +++ b/src/toolchain/llvm_toolchain.rs @@ -16,14 +16,16 @@ const DEFAULT_LLVM_VERSION: &str = "esp-14.0.0-20220415"; #[derive(Debug)] pub struct LlvmToolchain { - /// The repository containing LVVM sources. - pub repository_url: String, - /// Repository release version to use. - pub version: String, /// LLVM Toolchain file name. pub file_name: String, + /// Host triple. + pub host_triple: String, /// LLVM Toolchain path. pub path: PathBuf, + /// The repository containing LVVM sources. + pub repository_url: String, + /// Repository release version to use. + pub version: String, } impl LlvmToolchain { @@ -74,7 +76,7 @@ impl LlvmToolchain { self.repository_url.clone(), &format!( "idf_tool_xtensa_elf_clang.{}", - Self::get_artifact_extension(guess_host_triple::guess_host_triple().unwrap()) + Self::get_artifact_extension(&self.host_triple) ), self.path.to_str().unwrap(), true, @@ -95,10 +97,9 @@ impl LlvmToolchain { } /// Create a new instance with default values and proper toolchain version. - pub fn new(minified: bool) -> Self { - let host_triple = guess_host_triple::guess_host_triple().unwrap(); - let version = DEFAULT_LLVM_VERSION.to_string(); + pub fn new(minified: bool, host_triple: &str) -> Self { let file_name: String; + let version = DEFAULT_LLVM_VERSION.to_string(); let repository_url: String; if minified { file_name = format!( @@ -130,10 +131,11 @@ impl LlvmToolchain { ) .into(); Self { - repository_url, - version, file_name, + host_triple: host_triple.to_string(), path, + repository_url, + version, } } } diff --git a/src/toolchain/rust_toolchain.rs b/src/toolchain/rust_toolchain.rs index 56ff92a1..484e025f 100644 --- a/src/toolchain/rust_toolchain.rs +++ b/src/toolchain/rust_toolchain.rs @@ -15,20 +15,22 @@ const DEFAULT_XTENSA_RUST_REPOSITORY: &str = #[derive(Debug)] pub struct RustToolchain { + /// Path to the cargo home directory. + pub cargo_home: PathBuf, /// Xtensa Rust toolchain file. pub dist_file: String, /// Xtensa Rust toolchain URL. pub dist_url: String, + /// Host triple. + pub host_triple: String, + /// Path to the rustup home directory. + pub rustup_home: PathBuf, #[cfg(unix)] /// Xtensa Src Rust toolchain file. pub src_dist_file: String, #[cfg(unix)] /// Xtensa Src Rust toolchain URL. pub src_dist_url: String, - /// Path to the cargo home directory. - pub cargo_home: PathBuf, - /// Path to the rustup home directory. - pub rustup_home: PathBuf, /// Xtensa Rust toolchain destination path. pub toolchain_destination: PathBuf, /// Xtensa Rust Toolchain version. @@ -57,7 +59,6 @@ impl RustToolchain { #[cfg(unix)] if cfg!(unix) { - let host_triple = guess_host_triple::guess_host_triple().unwrap(); download_file( self.dist_url.clone(), "rust.tar.xz", @@ -69,7 +70,7 @@ impl RustToolchain { let arguments = format!( "{}/rust-nightly-{}/install.sh --destdir={} --prefix='' --without=rust-docs", get_dist_path("rust"), - host_triple, + &self.host_triple, self.toolchain_destination.display() ); cmd!("/bin/bash", "-c", arguments).run()?; @@ -104,10 +105,9 @@ impl RustToolchain { } /// Create a new instance. - pub fn new(toolchain_version: String) -> Self { - let host_triple = guess_host_triple::guess_host_triple().unwrap(); + pub fn new(toolchain_version: &str, host_triple: &str) -> Self { let artifact_extension = get_artifact_extension(host_triple); - let version = toolchain_version; + let version = toolchain_version.to_string(); let dist = format!("rust-{}-{}", version, host_triple); let dist_file = format!("{}.{}", dist, artifact_extension); let dist_url = format!( @@ -130,14 +130,15 @@ impl RustToolchain { #[cfg(windows)] let toolchain_destination = rustup_home.join("toolchains"); Self { + cargo_home, dist_file, dist_url, + host_triple: host_triple.to_string(), + rustup_home, #[cfg(unix)] src_dist_file, #[cfg(unix)] src_dist_url, - cargo_home, - rustup_home, toolchain_destination, version, } From 2e4b590bdbf1299cdb6c1fb790ce44f59be581de Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 17:26:40 +0200 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20function=20to=20c?= =?UTF-8?q?heck=20the=20introduced=20default-host?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 209035f6..6989f350 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #[cfg(windows)] use anyhow::bail; -use anyhow::Result; +use anyhow::{bail, Result}; use clap::Parser; use embuild::espidf::{parse_esp_idf_git_ref, EspIdfRemote}; use espup::{ @@ -139,10 +139,7 @@ fn install(args: InstallOpts) -> Result<()> { info!("{} Installing esp-rs", emoji::DISC); let targets: HashSet = parse_targets(&args.targets).unwrap(); - // TODO: Check the provided host triple. - let host_triple = args - .defautl_host - .unwrap_or_else(|| guess_host_triple().unwrap().to_string()); + let host_triple = get_host_triple(args.defautl_host)?; let mut extra_crates: HashSet = args.extra_crates.split(',').map(RustCrate::new).collect(); let mut exports: Vec = Vec::new(); @@ -261,11 +258,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> { fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); info!("{} Updating Xtensa Rust toolchain", emoji::DISC); - - // TODO: Check the provided host triple. - let host_triple = args - .defautl_host - .unwrap_or_else(|| guess_host_triple().unwrap().to_string()); + let host_triple = get_host_triple(args.defautl_host)?; debug!( "{} Arguments: @@ -345,3 +338,23 @@ pub fn check_arguments(targets: &HashSet, espidf_version: &Option) -> Result { + match host_triple_arg { + Some(host_triple) => { + if !matches!( + host_triple.as_str(), + "x86_64-unknown-linux-gnu" + | "aarch64-unknown-linux-gnu" + | "x86_64-pc-windows-msvc" + | "x86_64-pc-windows-gnu" + | "x86_64-apple-darwin" + | "aarch64-apple-darwin" + ) { + bail!("{} Invalid host triple: {}", emoji::ERROR, host_triple); + } + Ok(host_triple) + } + None => Ok(guess_host_triple().unwrap().to_string()), + } +} From b89d56ffe7627954a6b8ee7860a7ec738757c0c4 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 17:39:05 +0200 Subject: [PATCH 3/9] =?UTF-8?q?test:=20=F0=9F=A7=AA=20Add=20tests=20for=20?= =?UTF-8?q?get=5Fhost=5Ftriple?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6989f350..5046e770 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #[cfg(windows)] use anyhow::bail; -use anyhow::{bail, Result}; +use anyhow::Result; use clap::Parser; use embuild::espidf::{parse_esp_idf_git_ref, EspIdfRemote}; use espup::{ @@ -139,7 +139,7 @@ fn install(args: InstallOpts) -> Result<()> { info!("{} Installing esp-rs", emoji::DISC); let targets: HashSet = parse_targets(&args.targets).unwrap(); - let host_triple = get_host_triple(args.defautl_host)?; + let host_triple = get_host_triple(args.defautl_host).unwrap(); let mut extra_crates: HashSet = args.extra_crates.split(',').map(RustCrate::new).collect(); let mut exports: Vec = Vec::new(); @@ -258,7 +258,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> { fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); info!("{} Updating Xtensa Rust toolchain", emoji::DISC); - let host_triple = get_host_triple(args.defautl_host)?; + let host_triple = get_host_triple(args.defautl_host).unwrap(); debug!( "{} Arguments: @@ -339,7 +339,7 @@ pub fn check_arguments(targets: &HashSet, espidf_version: &Option) -> Result { +pub fn get_host_triple(host_triple_arg: Option) -> Result { match host_triple_arg { Some(host_triple) => { if !matches!( @@ -351,10 +351,59 @@ pub fn get_host_triple(host_triple_arg: Option) -> Result { | "x86_64-apple-darwin" | "aarch64-apple-darwin" ) { - bail!("{} Invalid host triple: {}", emoji::ERROR, host_triple); + return Err(format!( + "{} Host triple '{}' is not supported.", + emoji::ERROR, + host_triple + )); } Ok(host_triple) } None => Ok(guess_host_triple().unwrap().to_string()), } } + +#[cfg(test)] +mod tests { + use crate::emoji; + use crate::get_host_triple; + + #[test] + fn test_get_host_triple() { + assert_eq!( + get_host_triple(Some("x86_64-unknown-linux-gnu".to_string())), + Ok("x86_64-unknown-linux-gnu".to_string()) + ); + assert_eq!( + get_host_triple(Some("aarch64-unknown-linux-gnu".to_string())), + Ok("aarch64-unknown-linux-gnu".to_string()) + ); + assert_eq!( + get_host_triple(Some("x86_64-pc-windows-msvc".to_string())), + Ok("x86_64-pc-windows-msvc".to_string()) + ); + assert_eq!( + get_host_triple(Some("x86_64-pc-windows-gnu".to_string())), + Ok("x86_64-pc-windows-gnu".to_string()) + ); + assert_eq!( + get_host_triple(Some("x86_64-apple-darwin".to_string())), + Ok("x86_64-apple-darwin".to_string()) + ); + assert_eq!( + get_host_triple(Some("aarch64-apple-darwin".to_string())), + Ok("aarch64-apple-darwin".to_string()) + ); + assert_eq!( + get_host_triple(Some("non-existing-triple".to_string())), + Err(format!( + "{} Host triple 'non-existing-triple' is not supported.", + emoji::ERROR + )) + ); + assert_eq!( + get_host_triple(Some("".to_string())), + Err(format!("{} Host triple '' is not supported.", emoji::ERROR)) + ); + } +} From 4ad1b398074deaf0c3bcfc3de4e5942f1478af9c Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 17:55:08 +0200 Subject: [PATCH 4/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Fix=20typo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5046e770..11f6bacf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ pub enum SubCommand { pub struct InstallOpts { /// Target triple of the host. #[arg(short = 'd', long, required = false)] - pub defautl_host: Option, + pub default_host: Option, /// ESP-IDF version to install. If empty, no esp-idf is installed. Version format: /// /// - `commit:`: Uses the commit `` of the `esp-idf` repository. @@ -101,7 +101,7 @@ pub struct InstallOpts { pub struct UpdateOpts { /// Target triple of the host. #[arg(short = 'd', long, required = false)] - pub defautl_host: Option, + pub default_host: Option, /// Verbosity level of the logs. #[arg(short = 'l', long, default_value = "info", value_parser = ["debug", "info", "warn", "error"])] pub log_level: String, @@ -139,7 +139,7 @@ fn install(args: InstallOpts) -> Result<()> { info!("{} Installing esp-rs", emoji::DISC); let targets: HashSet = parse_targets(&args.targets).unwrap(); - let host_triple = get_host_triple(args.defautl_host).unwrap(); + let host_triple = get_host_triple(args.default_host).unwrap(); let mut extra_crates: HashSet = args.extra_crates.split(',').map(RustCrate::new).collect(); let mut exports: Vec = Vec::new(); @@ -258,7 +258,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> { fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); info!("{} Updating Xtensa Rust toolchain", emoji::DISC); - let host_triple = get_host_triple(args.defautl_host).unwrap(); + let host_triple = get_host_triple(args.default_host).unwrap(); debug!( "{} Arguments: From 1eeebc1ca594829489ac5715bae5e3708b2d4251 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 19:31:39 +0200 Subject: [PATCH 5/9] =?UTF-8?q?perf:=20=F0=9F=8E=A8=20Improve=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/targets.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/targets.rs b/src/targets.rs index 6a39e6dc..fb64a6aa 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -6,7 +6,6 @@ use std::{collections::HashSet, str::FromStr}; use strum::Display; #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Display)] - pub enum Target { /// Xtensa LX7 based dual core #[strum(serialize = "esp32")] @@ -23,7 +22,7 @@ pub enum Target { } impl FromStr for Target { - type Err = (); + type Err = String; fn from_str(s: &str) -> Result { match s { @@ -31,7 +30,7 @@ impl FromStr for Target { "esp32s2" => Ok(Target::ESP32S2), "esp32s3" => Ok(Target::ESP32S3), "esp32c3" => Ok(Target::ESP32C3), - _ => Err(()), + _ => Err(format!("{} Target '{}' is not supported", emoji::ERROR, s)), } } } From cb52c6800e738c98cfe8fe3d5283b36ec724791a Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 19:32:04 +0200 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20host=5Ftriple=20m?= =?UTF-8?q?od?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/host_triple.rs | 56 ++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 75 ++------------------------------- src/toolchain/gcc_toolchain.rs | 34 +++++++-------- src/toolchain/llvm_toolchain.rs | 23 +++++----- src/toolchain/rust_toolchain.rs | 7 +-- 6 files changed, 93 insertions(+), 103 deletions(-) create mode 100644 src/host_triple.rs diff --git a/src/host_triple.rs b/src/host_triple.rs new file mode 100644 index 00000000..395510bd --- /dev/null +++ b/src/host_triple.rs @@ -0,0 +1,56 @@ +use crate::emoji; +use anyhow::Result; +use guess_host_triple::guess_host_triple; +use std::str::FromStr; +use strum::Display; + +#[derive(Display, Debug, Clone)] +pub enum HostTriple { + /// 64-bit Linux + #[strum(serialize = "x86_64-unknown-linux-gnu")] + X86_64UnknownLinuxGnu = 0, + /// ARM64 Linux + #[strum(serialize = "aarch64-unknown-linux-gnu")] + Aarch64UnknownLinuxGnu, + /// 64-bit MSVC + #[strum(serialize = "x86_64-pc-windows-msvc")] + X86_64PcWindowsMsvc, + /// 64-bit MinGW + #[strum(serialize = "x86_64-pc-windows-gnu")] + X86_64PcWindowsGnu, + /// 64-bit macOS + #[strum(serialize = "x86_64-apple-darwin")] + X86_64AppleDarwin, + /// ARM64 macOS + #[strum(serialize = "aarch64-apple-darwin")] + Aarch64AppleDarwin, +} + +impl FromStr for HostTriple { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "x86_64-unknown-linux-gnu" => Ok(HostTriple::X86_64UnknownLinuxGnu), + "aarch64-unknown-linux-gnu" => Ok(HostTriple::Aarch64UnknownLinuxGnu), + "x86_64-pc-windows-msvc" => Ok(HostTriple::X86_64PcWindowsMsvc), + "x86_64-pc-windows-gnu" => Ok(HostTriple::X86_64PcWindowsGnu), + "x86_64-apple-darwin" => Ok(HostTriple::X86_64AppleDarwin), + "aarch64-apple-darwin" => Ok(HostTriple::Aarch64AppleDarwin), + _ => Err(format!( + "{} Host triple '{}' is not supported.", + emoji::ERROR, + s + )), + } + } +} + +/// Parse the host triple if specified, otherwise guess it. +pub fn get_host_triple(host_triple_arg: Option) -> Result { + let host_triple = match host_triple_arg { + Some(host_triple) => HostTriple::from_str(&host_triple).unwrap(), + None => HostTriple::from_str(guess_host_triple().unwrap()).unwrap(), + }; + Ok(host_triple) +} diff --git a/src/lib.rs b/src/lib.rs index 8c9c467f..106ebee1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod emoji; +pub mod host_triple; pub mod targets; pub mod toolchain; pub mod logging { diff --git a/src/main.rs b/src/main.rs index 11f6bacf..a3a1579e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use clap::Parser; use embuild::espidf::{parse_esp_idf_git_ref, EspIdfRemote}; use espup::{ emoji, + host_triple::get_host_triple, logging::initialize_logger, targets::{parse_targets, Target}, toolchain::{ @@ -19,7 +20,6 @@ use espup::{ }, }, }; -use guess_host_triple::guess_host_triple; use log::{debug, info}; use std::{ collections::HashSet, @@ -139,7 +139,7 @@ fn install(args: InstallOpts) -> Result<()> { info!("{} Installing esp-rs", emoji::DISC); let targets: HashSet = parse_targets(&args.targets).unwrap(); - let host_triple = get_host_triple(args.default_host).unwrap(); + let host_triple = get_host_triple(args.default_host)?; let mut extra_crates: HashSet = args.extra_crates.split(',').map(RustCrate::new).collect(); let mut exports: Vec = Vec::new(); @@ -258,7 +258,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> { fn update(args: UpdateOpts) -> Result<()> { initialize_logger(&args.log_level); info!("{} Updating Xtensa Rust toolchain", emoji::DISC); - let host_triple = get_host_triple(args.default_host).unwrap(); + let host_triple = get_host_triple(args.default_host)?; debug!( "{} Arguments: @@ -338,72 +338,3 @@ pub fn check_arguments(targets: &HashSet, espidf_version: &Option) -> Result { - match host_triple_arg { - Some(host_triple) => { - if !matches!( - host_triple.as_str(), - "x86_64-unknown-linux-gnu" - | "aarch64-unknown-linux-gnu" - | "x86_64-pc-windows-msvc" - | "x86_64-pc-windows-gnu" - | "x86_64-apple-darwin" - | "aarch64-apple-darwin" - ) { - return Err(format!( - "{} Host triple '{}' is not supported.", - emoji::ERROR, - host_triple - )); - } - Ok(host_triple) - } - None => Ok(guess_host_triple().unwrap().to_string()), - } -} - -#[cfg(test)] -mod tests { - use crate::emoji; - use crate::get_host_triple; - - #[test] - fn test_get_host_triple() { - assert_eq!( - get_host_triple(Some("x86_64-unknown-linux-gnu".to_string())), - Ok("x86_64-unknown-linux-gnu".to_string()) - ); - assert_eq!( - get_host_triple(Some("aarch64-unknown-linux-gnu".to_string())), - Ok("aarch64-unknown-linux-gnu".to_string()) - ); - assert_eq!( - get_host_triple(Some("x86_64-pc-windows-msvc".to_string())), - Ok("x86_64-pc-windows-msvc".to_string()) - ); - assert_eq!( - get_host_triple(Some("x86_64-pc-windows-gnu".to_string())), - Ok("x86_64-pc-windows-gnu".to_string()) - ); - assert_eq!( - get_host_triple(Some("x86_64-apple-darwin".to_string())), - Ok("x86_64-apple-darwin".to_string()) - ); - assert_eq!( - get_host_triple(Some("aarch64-apple-darwin".to_string())), - Ok("aarch64-apple-darwin".to_string()) - ); - assert_eq!( - get_host_triple(Some("non-existing-triple".to_string())), - Err(format!( - "{} Host triple 'non-existing-triple' is not supported.", - emoji::ERROR - )) - ); - assert_eq!( - get_host_triple(Some("".to_string())), - Err(format!("{} Host triple '' is not supported.", emoji::ERROR)) - ); - } -} diff --git a/src/toolchain/gcc_toolchain.rs b/src/toolchain/gcc_toolchain.rs index b0c0d37f..39928d76 100644 --- a/src/toolchain/gcc_toolchain.rs +++ b/src/toolchain/gcc_toolchain.rs @@ -2,6 +2,7 @@ use crate::{ emoji, + host_triple::HostTriple, targets::Target, toolchain::{download_file, espidf::get_tool_path}, }; @@ -17,7 +18,7 @@ const DEFAULT_GCC_VERSION: &str = "8_4_0"; #[derive(Debug)] pub struct GccToolchain { /// Host triple. - pub host_triple: String, + pub host_triple: HostTriple, /// Repository release version to use. pub release: String, /// The repository containing GCC sources. @@ -64,9 +65,9 @@ impl GccToolchain { } /// Create a new instance with default values and proper toolchain name. - pub fn new(target: Target, host_triple: &str) -> Self { + pub fn new(target: Target, host_triple: &HostTriple) -> Self { Self { - host_triple: host_triple.to_string(), + host_triple: host_triple.clone(), release: DEFAULT_GCC_RELEASE.to_string(), repository_url: DEFAULT_GCC_REPOSITORY.to_string(), toolchain_name: get_toolchain_name(target), @@ -76,24 +77,20 @@ impl GccToolchain { } /// Gets the name of the GCC arch based on the host triple. -fn get_arch(host_triple: &str) -> Result<&str, String> { +fn get_arch(host_triple: &HostTriple) -> Result<&str> { match host_triple { - "aarch64-apple-darwin" | "x86_64-apple-darwin" => Ok("macos"), - "aarch64-unknown-linux-gnu" => Ok("linux-arm64"), - "x86_64-unknown-linux-gnu" => Ok("linux-amd64"), - "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => Ok("win64"), - _ => Err(format!( - "No GCC arch found for the host triple: {}", - host_triple - )), + HostTriple::Aarch64AppleDarwin | HostTriple::X86_64AppleDarwin => Ok("macos"), + HostTriple::X86_64UnknownLinuxGnu => Ok("linux-amd64"), + HostTriple::Aarch64UnknownLinuxGnu => Ok("linux-arm64"), + HostTriple::X86_64PcWindowsMsvc | HostTriple::X86_64PcWindowsGnu => Ok("win64"), } } -/// Gets the artifact extension based on the host architecture. -fn get_artifact_extension(host_triple: &str) -> &str { +/// Gets the artifact extension based on the host triple. +fn get_artifact_extension(host_triple: &HostTriple) -> &str { match host_triple { - "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "zip", - _ => "tar.gz", + HostTriple::X86_64PcWindowsMsvc | HostTriple::X86_64PcWindowsGnu => "zip", + _ => "tar.xz", } } @@ -130,7 +127,10 @@ pub fn get_ulp_toolchain_name(target: Target, version: Option<&EspIdfVersion>) - } /// Installs GCC toolchain the selected targets. -pub fn install_gcc_targets(targets: HashSet, host_triple: &str) -> Result> { +pub fn install_gcc_targets( + targets: HashSet, + host_triple: &HostTriple, +) -> Result> { info!("{} Installing gcc for build targets", emoji::WRENCH); let mut exports: Vec = Vec::new(); for target in targets { diff --git a/src/toolchain/llvm_toolchain.rs b/src/toolchain/llvm_toolchain.rs index cc0f1e63..80953ac8 100644 --- a/src/toolchain/llvm_toolchain.rs +++ b/src/toolchain/llvm_toolchain.rs @@ -2,6 +2,7 @@ use crate::{ emoji, + host_triple::HostTriple, toolchain::{download_file, espidf::get_tool_path}, }; use anyhow::{bail, Ok, Result}; @@ -19,7 +20,7 @@ pub struct LlvmToolchain { /// LLVM Toolchain file name. pub file_name: String, /// Host triple. - pub host_triple: String, + pub host_triple: HostTriple, /// LLVM Toolchain path. pub path: PathBuf, /// The repository containing LVVM sources. @@ -30,23 +31,23 @@ pub struct LlvmToolchain { impl LlvmToolchain { /// Gets the name of the LLVM arch based on the host triple. - fn get_arch(host_triple: &str) -> Result { + fn get_arch(host_triple: &HostTriple) -> Result<&str> { match host_triple { - "aarch64-apple-darwin" | "x86_64-apple-darwin" => Ok("macos".to_string()), - "x86_64-unknown-linux-gnu" => Ok("linux-amd64".to_string()), - "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => Ok("win64".to_string()), + HostTriple::Aarch64AppleDarwin | HostTriple::X86_64AppleDarwin => Ok("macos"), + HostTriple::X86_64UnknownLinuxGnu => Ok("linux-amd64"), + HostTriple::X86_64PcWindowsMsvc | HostTriple::X86_64PcWindowsGnu => Ok("win64"), _ => bail!( - "{} No LLVM arch found for the host triple: {}", + "{} No LLVM arch found for the host triple: '{}'", emoji::ERROR, host_triple ), } } - /// Gets the artifact extension based on the host architecture. - fn get_artifact_extension(host_triple: &str) -> &str { + /// Gets the artifact extension based on the host triple. + fn get_artifact_extension(host_triple: &HostTriple) -> &str { match host_triple { - "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "zip", + HostTriple::X86_64PcWindowsMsvc | HostTriple::X86_64PcWindowsGnu => "zip", _ => "tar.xz", } } @@ -97,7 +98,7 @@ impl LlvmToolchain { } /// Create a new instance with default values and proper toolchain version. - pub fn new(minified: bool, host_triple: &str) -> Self { + pub fn new(minified: bool, host_triple: &HostTriple) -> Self { let file_name: String; let version = DEFAULT_LLVM_VERSION.to_string(); let repository_url: String; @@ -132,7 +133,7 @@ impl LlvmToolchain { .into(); Self { file_name, - host_triple: host_triple.to_string(), + host_triple: host_triple.clone(), path, repository_url, version, diff --git a/src/toolchain/rust_toolchain.rs b/src/toolchain/rust_toolchain.rs index 484e025f..b9ca2bc8 100644 --- a/src/toolchain/rust_toolchain.rs +++ b/src/toolchain/rust_toolchain.rs @@ -2,6 +2,7 @@ use crate::{ emoji, + host_triple::HostTriple, toolchain::{download_file, espidf::get_dist_path, get_home_dir}, }; use anyhow::{bail, Result}; @@ -105,7 +106,7 @@ impl RustToolchain { } /// Create a new instance. - pub fn new(toolchain_version: &str, host_triple: &str) -> Self { + pub fn new(toolchain_version: &str, host_triple: &HostTriple) -> Self { let artifact_extension = get_artifact_extension(host_triple); let version = toolchain_version.to_string(); let dist = format!("rust-{}-{}", version, host_triple); @@ -176,9 +177,9 @@ impl RustCrate { } /// Gets the artifact extension based on the host architecture. -fn get_artifact_extension(host_triple: &str) -> &str { +fn get_artifact_extension(host_triple: &HostTriple) -> &str { match host_triple { - "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "zip", + HostTriple::X86_64PcWindowsMsvc | HostTriple::X86_64PcWindowsGnu => "zip", _ => "tar.xz", } } From ffc2611d41be7cffb8c63426cca4f35733a1280f Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Fri, 7 Oct 2022 20:44:50 +0200 Subject: [PATCH 7/9] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Use=20stru?= =?UTF-8?q?m-macros=20to=20avoid=20reimplementing=20from=5Fstr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + Cargo.toml | 1 + src/host_triple.rs | 34 +++++++++++----------------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd5fd57f..65c26446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -409,6 +409,7 @@ dependencies = [ "openssl", "reqwest", "strum", + "strum_macros", "tar", "tempfile", "xz2", diff --git a/Cargo.toml b/Cargo.toml index 047ad009..5d18d670 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ log = "0.4.17" env_logger = "0.9.0" embuild = { version = "0.30.4", features = ["espidf", "git"] } strum = { version = "0.24", features = ["derive"] } +strum_macros = "0.24.3" [target.aarch64-unknown-linux-gnu.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/src/host_triple.rs b/src/host_triple.rs index 395510bd..696672a3 100644 --- a/src/host_triple.rs +++ b/src/host_triple.rs @@ -1,10 +1,11 @@ use crate::emoji; -use anyhow::Result; +use anyhow::{bail, Result}; use guess_host_triple::guess_host_triple; use std::str::FromStr; use strum::Display; +use strum_macros::EnumString; -#[derive(Display, Debug, Clone)] +#[derive(Display, Debug, Clone, EnumString)] pub enum HostTriple { /// 64-bit Linux #[strum(serialize = "x86_64-unknown-linux-gnu")] @@ -26,30 +27,17 @@ pub enum HostTriple { Aarch64AppleDarwin, } -impl FromStr for HostTriple { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "x86_64-unknown-linux-gnu" => Ok(HostTriple::X86_64UnknownLinuxGnu), - "aarch64-unknown-linux-gnu" => Ok(HostTriple::Aarch64UnknownLinuxGnu), - "x86_64-pc-windows-msvc" => Ok(HostTriple::X86_64PcWindowsMsvc), - "x86_64-pc-windows-gnu" => Ok(HostTriple::X86_64PcWindowsGnu), - "x86_64-apple-darwin" => Ok(HostTriple::X86_64AppleDarwin), - "aarch64-apple-darwin" => Ok(HostTriple::Aarch64AppleDarwin), - _ => Err(format!( - "{} Host triple '{}' is not supported.", - emoji::ERROR, - s - )), - } - } -} - /// Parse the host triple if specified, otherwise guess it. pub fn get_host_triple(host_triple_arg: Option) -> Result { let host_triple = match host_triple_arg { - Some(host_triple) => HostTriple::from_str(&host_triple).unwrap(), + Some(host_triple_string) => match FromStr::from_str(&host_triple_string) { + Ok(host_triple) => host_triple, + Err(_) => bail!( + "{} Host triple '{}' is not supported.", + emoji::ERROR, + host_triple_string + ), + }, None => HostTriple::from_str(guess_host_triple().unwrap()).unwrap(), }; Ok(host_triple) From 6a13fec1b97cc0975102b32eef395d83a546011e Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Mon, 10 Oct 2022 08:52:01 +0200 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20=E2=9A=A1=EF=B8=8F=20Use=20anyh?= =?UTF-8?q?ow::context=20to=20improve=20err=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/host_triple.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/host_triple.rs b/src/host_triple.rs index 696672a3..44e533ff 100644 --- a/src/host_triple.rs +++ b/src/host_triple.rs @@ -1,5 +1,5 @@ use crate::emoji; -use anyhow::{bail, Result}; +use anyhow::{Context, Result}; use guess_host_triple::guess_host_triple; use std::str::FromStr; use strum::Display; @@ -29,16 +29,14 @@ pub enum HostTriple { /// Parse the host triple if specified, otherwise guess it. pub fn get_host_triple(host_triple_arg: Option) -> Result { - let host_triple = match host_triple_arg { - Some(host_triple_string) => match FromStr::from_str(&host_triple_string) { - Ok(host_triple) => host_triple, - Err(_) => bail!( - "{} Host triple '{}' is not supported.", - emoji::ERROR, - host_triple_string - ), - }, - None => HostTriple::from_str(guess_host_triple().unwrap()).unwrap(), - }; - Ok(host_triple) + if let Some(host_triple_arg) = host_triple_arg { + HostTriple::from_str(&host_triple_arg).context(format!( + "{} Host triple '{}' is not supported.", + emoji::ERROR, + host_triple_arg, + )) + } else { + HostTriple::from_str(guess_host_triple().unwrap()) + .context(format!("{} Unable to guess host triple.", emoji::ERROR,)) + } } From 2da07d9c5f5b3e15195036673ee741822b389938 Mon Sep 17 00:00:00 2001 From: Sergio Gasquez Date: Mon, 10 Oct 2022 09:19:20 +0200 Subject: [PATCH 9/9] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Use=20stru?= =?UTF-8?q?m-macros=20to=20avoid=20reimplementing=20from=5Fstr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/targets.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/targets.rs b/src/targets.rs index fb64a6aa..d1f84340 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -1,11 +1,13 @@ //! ESP32 chip variants support. use crate::emoji; +use anyhow::Context; use log::debug; use std::{collections::HashSet, str::FromStr}; use strum::Display; +use strum_macros::EnumString; -#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Display)] +#[derive(Clone, Copy, EnumString, PartialEq, Hash, Eq, Debug, Display)] pub enum Target { /// Xtensa LX7 based dual core #[strum(serialize = "esp32")] @@ -21,20 +23,6 @@ pub enum Target { ESP32C3, } -impl FromStr for Target { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "esp32" => Ok(Target::ESP32), - "esp32s2" => Ok(Target::ESP32S2), - "esp32s3" => Ok(Target::ESP32S3), - "esp32c3" => Ok(Target::ESP32C3), - _ => Err(format!("{} Target '{}' is not supported", emoji::ERROR, s)), - } - } -} - /// Returns a vector of Chips from a comma or space separated string. pub fn parse_targets(targets_str: &str) -> Result, String> { debug!("{} Parsing targets: {}", emoji::DEBUG, targets_str); @@ -53,7 +41,15 @@ pub fn parse_targets(targets_str: &str) -> Result, String> { }; for target in targets_str { - targets.insert(FromStr::from_str(target).unwrap()); + targets.insert( + Target::from_str(target) + .context(format!( + "{} Target '{}' is not supported", + emoji::ERROR, + target + )) + .unwrap(), + ); } debug!("{} Parsed targets: {:?}", emoji::DEBUG, targets); Ok(targets)