Merge pull request #12 from esp-rs/feature/default-host-arg

Add `default-host` argument
This commit is contained in:
Sergio Gasquez Arcos 2022-10-17 08:33:11 +02:00 committed by GitHub
commit 2bbb89fead
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 138 additions and 78 deletions

1
Cargo.lock generated
View File

@ -409,6 +409,7 @@ dependencies = [
"openssl",
"reqwest",
"strum",
"strum_macros",
"tar",
"tempfile",
"xz2",

View File

@ -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"] }

42
src/host_triple.rs Normal file
View File

@ -0,0 +1,42 @@
use crate::emoji;
use anyhow::{Context, Result};
use guess_host_triple::guess_host_triple;
use std::str::FromStr;
use strum::Display;
use strum_macros::EnumString;
#[derive(Display, Debug, Clone, EnumString)]
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,
}
/// Parse the host triple if specified, otherwise guess it.
pub fn get_host_triple(host_triple_arg: Option<String>) -> Result<HostTriple> {
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,))
}
}

View File

@ -1,4 +1,5 @@
pub mod emoji;
pub mod host_triple;
pub mod targets;
pub mod toolchain;
pub mod logging {

View File

@ -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::{
@ -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 default_host: Option<String>,
/// ESP-IDF version to install. If empty, no esp-idf is installed. Version format:
///
/// - `commit:<hash>`: Uses the commit `<hash>` 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 default_host: Option<String>,
/// 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,22 @@ fn install(args: InstallOpts) -> Result<()> {
info!("{} Installing esp-rs", emoji::DISC);
let targets: HashSet<Target> = parse_targets(&args.targets).unwrap();
let host_triple = get_host_triple(args.default_host)?;
let mut extra_crates: HashSet<RustCrate> =
args.extra_crates.split(',').map(RustCrate::new).collect();
let mut exports: Vec<String> = 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 +165,7 @@ fn install(args: InstallOpts) -> Result<()> {
- Profile Minimal: {:?}
- Toolchain version: {:?}",
emoji::INFO,
host_triple,
targets,
&args.espidf_version,
export_file,
@ -185,7 +195,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!(
@ -252,18 +262,21 @@ 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)?;
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);

View File

@ -1,12 +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")]
@ -22,20 +23,6 @@ pub enum Target {
ESP32C3,
}
impl FromStr for Target {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"esp32" => Ok(Target::ESP32),
"esp32s2" => Ok(Target::ESP32S2),
"esp32s3" => Ok(Target::ESP32S3),
"esp32c3" => Ok(Target::ESP32C3),
_ => Err(()),
}
}
}
/// Returns a vector of Chips from a comma or space separated string.
pub fn parse_targets(targets_str: &str) -> Result<HashSet<Target>, String> {
debug!("{} Parsing targets: {}", emoji::DEBUG, targets_str);
@ -54,7 +41,15 @@ pub fn parse_targets(targets_str: &str) -> Result<HashSet<Target>, 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)

View File

@ -2,6 +2,7 @@
use crate::{
emoji,
host_triple::HostTriple,
targets::Target,
toolchain::{download_file, espidf::get_tool_path},
};
@ -16,14 +17,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: HostTriple,
/// 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 +44,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,35 +65,32 @@ 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: &HostTriple) -> Self {
Self {
repository_url: DEFAULT_GCC_REPOSITORY.to_string(),
host_triple: host_triple.clone(),
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(),
}
}
}
/// 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",
}
}
@ -128,11 +127,14 @@ pub fn get_ulp_toolchain_name(target: Target, version: Option<&EspIdfVersion>) -
}
/// Installs GCC toolchain the selected targets.
pub fn install_gcc_targets(targets: HashSet<Target>) -> Result<Vec<String>> {
pub fn install_gcc_targets(
targets: HashSet<Target>,
host_triple: &HostTriple,
) -> Result<Vec<String>> {
info!("{} Installing gcc for build targets", emoji::WRENCH);
let mut exports: Vec<String> = Vec::new();
for target in targets {
let gcc = GccToolchain::new(target);
let gcc = GccToolchain::new(target, host_triple);
gcc.install()?;
#[cfg(windows)]

View File

@ -2,6 +2,7 @@
use crate::{
emoji,
host_triple::HostTriple,
toolchain::{download_file, espidf::get_tool_path},
};
use anyhow::{bail, Ok, Result};
@ -16,35 +17,37 @@ const DEFAULT_LLVM_VERSION: &str = "esp-14.0.0-20220415";
#[derive(Debug)]
pub struct LlvmToolchain {
/// LLVM Toolchain file name.
pub file_name: String,
/// Host triple.
pub host_triple: HostTriple,
/// LLVM Toolchain path.
pub path: PathBuf,
/// 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,
/// LLVM Toolchain path.
pub path: PathBuf,
}
impl LlvmToolchain {
/// Gets the name of the LLVM arch based on the host triple.
fn get_arch(host_triple: &str) -> Result<String> {
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",
}
}
@ -74,7 +77,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 +98,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: &HostTriple) -> Self {
let file_name: String;
let version = DEFAULT_LLVM_VERSION.to_string();
let repository_url: String;
if minified {
file_name = format!(
@ -130,10 +132,11 @@ impl LlvmToolchain {
)
.into();
Self {
file_name,
host_triple: host_triple.clone(),
path,
repository_url,
version,
file_name,
path,
}
}
}

View File

@ -2,6 +2,7 @@
use crate::{
emoji,
host_triple::HostTriple,
toolchain::{download_file, espidf::get_dist_path, get_home_dir},
};
use anyhow::{bail, Result};
@ -15,20 +16,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 +60,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 +71,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 +106,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: &HostTriple) -> 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 +131,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,
}
@ -175,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",
}
}