Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default-host argument #12

Merged
merged 9 commits into from
Oct 17, 2022
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
42 changes: 42 additions & 0 deletions src/host_triple.rs
Original file line number Diff line number Diff line change
@@ -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,))
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod emoji;
pub mod host_triple;
pub mod targets;
pub mod toolchain;
pub mod logging {
Expand Down
23 changes: 18 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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: {:?}
Expand All @@ -156,6 +165,7 @@ fn install(args: InstallOpts) -> Result<()> {
- Profile Minimal: {:?}
- Toolchain version: {:?}",
emoji::INFO,
host_triple,
targets,
&args.espidf_version,
export_file,
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -248,18 +258,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);
Expand Down
29 changes: 12 additions & 17 deletions src/targets.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand All @@ -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);
Expand All @@ -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)
Expand Down
52 changes: 27 additions & 25 deletions src/toolchain/gcc_toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::{
emoji,
host_triple::HostTriple,
targets::Target,
toolchain::{download_file, espidf::get_tool_path},
};
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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",
}
}

Expand Down Expand Up @@ -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)]
Expand Down
Loading