diff --git a/src/gcc_toolchain.rs b/src/gcc_toolchain.rs index 3b503e6..0d5af73 100644 --- a/src/gcc_toolchain.rs +++ b/src/gcc_toolchain.rs @@ -1,4 +1,4 @@ -//! GCC Toolchain source and tools installation +//! GCC Toolchain source and installation tools use crate::chip::Chip; use crate::emoji; @@ -39,8 +39,7 @@ impl GccToolchain { /// Gets the artifact extension based on the host architecture. fn get_artifact_extension(host_triple: &str) -> &str { match host_triple { - "x86_64-pc-windows-msvc" => "zip", - "x86_64-pc-windows-gnu" => "zip", + "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "zip", _ => "tar.gz", } } @@ -83,7 +82,7 @@ impl GccToolchain { Ok(()) } - /// Create a new instance with default values and proper toolchain_name. + /// Create a new instance with default values and proper toolchain name. pub fn new(chip: Chip) -> Self { Self { repository_url: DEFAULT_GCC_REPOSITORY.to_string(), diff --git a/src/llvm_toolchain.rs b/src/llvm_toolchain.rs index 6f5f9e7..169a773 100644 --- a/src/llvm_toolchain.rs +++ b/src/llvm_toolchain.rs @@ -1,4 +1,4 @@ -//! LLVM Toolchain source and tools installation +//! LLVM Toolchain source and installation tools use crate::emoji; use crate::utils::{download_file, get_tool_path}; @@ -6,8 +6,7 @@ use anyhow::Result; use log::{info, warn}; use std::path::{Path, PathBuf}; -const DEFAULT_LLVM_REPOSITORY: &str = - "https://github.com/espressif/llvm-project/releases/download/"; +const DEFAULT_LLVM_REPOSITORY: &str = "https://github.com/espressif/llvm-project/releases/download"; pub struct LlvmToolchain { /// The repository containing LVVM sources. @@ -104,10 +103,7 @@ impl LlvmToolchain { Self::get_arch(host_triple).unwrap(), Self::get_artifact_extension(host_triple) ); - let repository_url = format!( - "https://github.com/espressif/llvm-project/releases/download/{}/{}", - &release, file_name - ); + let repository_url = format!("{}/{}/{}", DEFAULT_LLVM_REPOSITORY, &release, file_name); let path = format!( "{}/{}-{}", get_tool_path("xtensa-esp32-elf-clang"), diff --git a/src/main.rs b/src/main.rs index b01e970..a19fe17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ use crate::chip::*; use crate::llvm_toolchain::LlvmToolchain; +use crate::rust_toolchain::RustToolchain; use crate::toolchain::*; use crate::utils::*; use anyhow::Result; use clap::Parser; use clap_verbosity_flag::{InfoLevel, Verbosity}; -use embuild::cmd; use log::{info, warn}; use std::fs::File; use std::io::Write; @@ -15,8 +15,10 @@ mod chip; mod emoji; mod gcc_toolchain; mod llvm_toolchain; +mod rust_toolchain; mod toolchain; mod utils; + #[derive(Parser)] struct Opts { #[clap(subcommand)] @@ -105,20 +107,7 @@ fn install(args: InstallOpts) -> Result<()> { let targets: Vec = parse_targets(&args.build_target).unwrap(); print_arguments(&args, arch, &targets); - let artifact_file_extension = get_artifact_llvm_extension(arch).to_string(); - - let rust_dist = format!("rust-{}-{}", args.toolchain_version, arch); - let rust_src_dist = format!("rust-src-{}", args.toolchain_version); - let rust_dist_file = format!("{}.{}", rust_dist, artifact_file_extension); - let rust_src_dist_file = format!("{}.{}", rust_src_dist, artifact_file_extension); - let rust_dist_url = format!( - "https://github.com/esp-rs/rust-build/releases/download/v{}/{}", - args.toolchain_version, rust_dist_file - ); - let rust_src_dist_url = format!( - "https://github.com/esp-rs/rust-build/releases/download/v{}/{}", - args.toolchain_version, rust_src_dist_file - ); + let rust_toolchain = RustToolchain::new(&args, arch, &targets); let mut exports: Vec = Vec::new(); @@ -134,49 +123,15 @@ fn install(args: InstallOpts) -> Result<()> { ); return Ok(()); } else { - // install_rust_xtensa_toolchain - // 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 info!("{} Installing Xtensa Rust toolchain", emoji::WRENCH); - if get_rust_installer(arch).to_string().is_empty() { - download_file( - rust_dist_url, - "rust.zip", - &args.toolchain_destination.display().to_string(), - true, - )?; - } else { - download_file(rust_dist_url, "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", - get_dist_path("rust"), - arch, - args.toolchain_destination.display() - ); - cmd!("/bin/bash", "-c", arguments).run()?; - - download_file( - rust_src_dist_url, - "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", - get_dist_path("rust-src"), - args.toolchain_destination.display() - ); - cmd!("/bin/bash", "-c", arguments).run()?; - } + rust_toolchain.install_xtensa()?; } llvm.install()?; exports.push(format!("export LIBCLANG_PATH=\"{}\"", &llvm.get_lib_path())); if targets.contains(&Chip::ESP32C3) { - install_riscv_target(&args.nightly_version)?; + rust_toolchain.install_riscv_target()?; } if args.espidf_version.is_some() { diff --git a/src/rust_toolchain.rs b/src/rust_toolchain.rs new file mode 100644 index 0000000..d78d134 --- /dev/null +++ b/src/rust_toolchain.rs @@ -0,0 +1,160 @@ +//! Xtensa Rust Toolchain source and installation tools + +use super::InstallOpts; +use crate::chip::Chip; +use crate::emoji; +use crate::utils::{download_file, get_dist_path}; +use anyhow::Result; +use embuild::cmd; +use log::info; +use std::path::PathBuf; + +const DEFAULT_XTENSA_RUST_REPOSITORY: &str = + "https://github.com/esp-rs/rust-build/releases/download"; + +pub struct RustToolchain { + /// Xtensa Rust toolchain file. + pub dist_file: String, + /// Xtensa Rust toolchain url. + pub dist_url: String, + /// Xtensa Src Rust toolchain file. + pub src_dist_file: String, + /// Xtensa Src Rust toolchain url. + pub src_dist_url: String, + /// ESP targets. + pub targets: Vec, + /// Extra crates to install. + pub extra_crates: String, + /// Nightly version to install. + pub nightly_version: 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. + pub version: String, +} + +impl RustToolchain { + /// Gets the artifact extension based on the host architecture. + fn get_artifact_extension(host_triple: &str) -> &str { + match host_triple { + "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "zip", + _ => "tar.xz", + } + } + + /// Gets the installer file. + pub fn get_installer(host_triple: &str) -> &str { + match host_triple { + "x86_64-pc-windows-msvc" | "x86_64-pc-windows-gnu" => "", + _ => "./install.sh", + } + } + + /// Installs the RiscV target. + pub fn install_riscv_target(&self) -> Result<()> { + info!("{} Installing Riscv target", emoji::WRENCH); + cmd!( + "rustup", + "component", + "add", + "rust-src", + "--toolchain", + self.version.clone() + ) + .run()?; + cmd!( + "rustup", + "target", + "add", + "--toolchain", + self.version.clone(), + "riscv32imac-unknown-none-elf" + ) + .run()?; + Ok(()) + } + + /// Installs the Xtensa Rust toolchain. + pub fn install_xtensa(&self) -> Result<()> { + let host_triple = guess_host_triple::guess_host_triple().unwrap(); + + // 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 + if Self::get_installer(host_triple).to_string().is_empty() { + download_file( + self.dist_url.clone(), + "rust.zip", + &self.toolchain_destination.display().to_string(), + true, + )?; + } else { + 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", + get_dist_path("rust"), + 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", + get_dist_path("rust-src"), + self.toolchain_destination.display() + ); + cmd!("/bin/bash", "-c", arguments).run()?; + } + Ok(()) + } + + // TODO: Some fields are not needed in Windows + /// Create a new instance. + pub fn new(args: &InstallOpts, arch: &str, targets: &[Chip]) -> Self { + let artifact_extension = Self::get_artifact_extension(arch); + let version = args.toolchain_version.clone(); + + let dist = format!("rust-{}-{}", args.toolchain_version, arch); + let dist_file = format!("{}.{}", dist, artifact_extension); + let dist_url = format!( + "{}/v{}/{}", + DEFAULT_XTENSA_RUST_REPOSITORY, version, dist_file + ); + let src_dist = format!("rust-src-{}", args.toolchain_version); + let src_dist_file = format!("{}.{}", src_dist, artifact_extension); + let src_dist_url = format!( + "{}/v{}/{}", + DEFAULT_XTENSA_RUST_REPOSITORY, version, src_dist_file + ); + + Self { + dist_file, + dist_url, + src_dist_file, + src_dist_url, + targets: targets.to_vec(), + extra_crates: args.extra_crates.clone(), + nightly_version: args.nightly_version.clone(), + cargo_home: args.cargo_home.clone(), + rustup_home: args.rustup_home.clone(), + toolchain_destination: args.toolchain_destination.clone(), + version, + } + } +} diff --git a/src/toolchain.rs b/src/toolchain.rs index e9cae30..a3fc050 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -34,29 +34,6 @@ pub fn check_rust_installation(nightly_version: &str) -> Result<()> { Ok(()) } -pub fn install_riscv_target(version: &str) -> Result<()> { - info!("{} Installing Riscv target", emoji::WRENCH); - cmd!( - "rustup", - "component", - "add", - "rust-src", - "--toolchain", - version - ) - .run()?; - cmd!( - "rustup", - "target", - "add", - "--toolchain", - version, - "riscv32imac-unknown-none-elf" - ) - .run()?; - Ok(()) -} - pub fn install_rustup(nightly_version: &str) -> Result<()> { #[cfg(windows)] let rustup_init_path = download_file( diff --git a/src/utils.rs b/src/utils.rs index 11544b6..8231a21 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,22 +44,6 @@ pub fn parse_targets(build_target: &str) -> Result, String> { Ok(chips) } -pub fn get_artifact_llvm_extension(arch: &str) -> &str { - match arch { - "x86_64-pc-windows-msvc" => "zip", - "x86_64-pc-windows-gnu" => "zip", - _ => "tar.xz", - } -} - -pub fn get_rust_installer(arch: &str) -> &str { - match arch { - "x86_64-pc-windows-msvc" => "", - "x86_64-pc-windows-gnu" => "", - _ => "./install.sh", - } -} - pub fn get_home_dir() -> String { home_dir().unwrap().display().to_string() }