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

#41, #36 #42

Merged
merged 7 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pio = ["embuild/pio"]
paste = "1"

[build-dependencies]
embuild = { version = "0.28.4", features = ["glob"] }
embuild = { version = "0.29.0", features = ["glob"] }
anyhow = "1"
strum = { version = "0.23", features = ["derive"], optional = true }
strum = { version = "0.24", features = ["derive"], optional = true }
regex = "1.5"
bindgen = "0.59"
37 changes: 25 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,40 @@ The following environment variables are used by the build script:

- `ESP_IDF_TOOLS_INSTALL_DIR`:

The location where the ESP-IDF framework tooling is assumed to be/will be installed.
The framework tooling is either PlatformIO (when the `pio` builder is used), or the ESP-IDF native toolset (when the `native` builder is used).
The location where the ESP-IDF framework tooling is assumed to be/will be installed. The
framework tooling is either PlatformIO (when the `pio` builder is used), or the ESP-IDF
native toolset (when the `native` builder is used).

This variable can take one of the following values:
This variable can take one of the following values:
- `workspace` (default) - the tooling will be installed/used in
`<crate-workspace-dir>/.embuild/platformio` for `pio`, and `<crate-workspace-dir>/.embuild/espressif` for the `native` builder;
- `out` - the tooling will be installed/used inside the crate's build output directory, and will be deleted when `cargo clean` is invoked;
- `global` - the tooling will be installed/used in its standard directory (`~/.platformio` for PlatformIO, and `~./espressif` for the native ESP-IDF toolset);
- `custom:<dir>` - the tooling will be installed/used in the directory specified by `<dir>`. If this directory is a relative location, it is assumed to be
relative to the crate's workspace dir.

**ATTENTION**: Please be extra careful with the `custom:<dir>` setting when switching from `pio` to `native` and the other way around, because
the builder will install the tooling in `<dir>` without using any additional `platformio` or `espressif` subdirectories, so if you are not careful, you might end up with
both PlatformIO, as well as the ESP-IDF native tooling intermingled together in a single folder.


Note that both builders (`native` and `pio`) clone the ESP-IDF GIT repository *inside* the tooling directory as well. This restriction might be lifted soon for the `native` builder, whereas the user would be able to point the build to a custom ESP-IDF repository location.
relative to the crate's workspace dir;
- `fromenv` - use the build framework from the environment
- *native* builder: use activated esp-idf environment (see esp-idf docs
[unix](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html#step-4-set-up-the-environment-variables)
/
[windows](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup.html#using-the-command-prompt))
- *pio* builder: use `platformio` from the environment (i.e. `$PATH`)

and error if this is not possible.

**ATTENTION**: Please be extra careful with the `custom:<dir>` setting when switching from `pio` to `native` and the other way around, because
the builder will install the tooling in `<dir>` without using any additional `platformio` or `espressif` subdirectories, so if you are not careful, you might end up with
both PlatformIO, as well as the ESP-IDF native tooling intermingled together in a single folder.


Note that both builders (`native` and `pio`) clone the ESP-IDF GIT repository *inside* the tooling directory as well. This restriction might be lifted soon for the `native` builder, whereas the user would be able to point the build to a custom ESP-IDF repository location.

- `IDF_PATH` (*native* builder only):
A path to a user-provided local clone of the [`esp-idf`](https://github.com/espressif/esp-idf),
that will be used instead of the one downloaded by the build script.

- `ESP_IDF_VERSION` (*native* builder only):

The version used for the `esp-idf` can be one of the following:
The version used for the `esp-idf`, can be one of the following:
- `commit:<hash>`: Uses the commit `<hash>` of the `esp-idf` repository.
Note that this will clone the whole `esp-idf` not just one commit.
- `tag:<tag>`: Uses the tag `<tag>` of the `esp-idf` repository.
Expand Down
103 changes: 77 additions & 26 deletions build/common.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::collections::HashSet;
use std::fmt::Display;
use std::iter::once;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{env, error, fs};

use anyhow::*;
use anyhow::{anyhow, bail, Result};
use embuild::cargo::{self, IntoWarning};
use embuild::utils::{OsStrExt, PathExt};
use embuild::{bindgen, build, kconfig};
Expand All @@ -24,9 +25,6 @@ pub const V_4_3_2_PATCHES: &[&str] = &[
"patches/pthread_destructor_fix.diff",
];

#[allow(unused)]
pub const NO_PATCHES: &[&str] = &[];

const TOOLS_WORKSPACE_INSTALL_DIR: &str = ".embuild";

const ALL_COMPONENTS: &[&str] = &[
Expand Down Expand Up @@ -207,32 +205,85 @@ pub fn list_specific_sdkconfigs(
})
}

pub fn get_install_dir(builder_name: impl AsRef<str>) -> Result<Option<PathBuf>> {
let location = match env::var(ESP_IDF_TOOLS_INSTALL_DIR_VAR) {
Err(env::VarError::NotPresent) => None,
var => Some(var?.to_lowercase()),
};

let dir = match location.as_deref() {
None | Some("workspace") => Some(
workspace_dir()?
.join(TOOLS_WORKSPACE_INSTALL_DIR)
.join(builder_name.as_ref()),
),
Some("global") => None,
Some("out") => Some(cargo::out_dir().join(builder_name.as_ref())),
Some(custom) => {
if let Some(suffix) = custom.strip_prefix("custom:") {
Some(PathBuf::from(suffix).abspath_relative_to(&workspace_dir()?))
} else {
bail!("Invalid installation directory format. Should be one of `global`, `workspace`, `out` or `custom:<dir>`");
#[derive(Clone, Debug)]
pub enum InstallDir {
Global,
Workspace(PathBuf),
Out(PathBuf),
Custom(PathBuf),
FromEnv,
}

impl InstallDir {
/// Get the install directory from the [`ESP_IDF_TOOLS_INSTALL_DIR_VAR`] env variable.
///
/// If this env variable is unset or empty uses `default_install_dir` instead.
/// On success returns `(install_dir as InstallDir, is_default as bool)`.
pub fn from_env_or(
default_install_dir: &str,
builder_name: &str,
) -> Result<(InstallDir, bool)> {
let location = env::var_os(ESP_IDF_TOOLS_INSTALL_DIR_VAR);
let (location, is_default) = match &location {
None => (default_install_dir, true),
Some(val) => {
let val = val.try_to_str()?.trim();
if val.is_empty() {
(default_install_dir, true)
} else {
(val, false)
}
}
};
let install_dir = match location.to_lowercase().as_str() {
"global" => Self::Global,
"workspace" => Self::Workspace(
workspace_dir()?
.join(TOOLS_WORKSPACE_INSTALL_DIR)
.join(builder_name),
),
"out" => Self::Out(cargo::out_dir().join(builder_name)),
"fromenv" => Self::FromEnv,
_ => Self::Custom({
if let Some(suffix) = location.strip_prefix("custom:") {
Path::new(suffix).abspath_relative_to(&workspace_dir()?)
} else {
bail!(
"Invalid installation directory format. \
Should be one of `global`, `workspace`, `out`, `fromenv` or `custom:<dir>`."
);
}
}),
};
Ok((install_dir, is_default))
}

pub fn is_from_env(&self) -> bool {
matches!(self, Self::FromEnv)
}

pub fn path(&self) -> Option<&Path> {
match self {
Self::Global | Self::FromEnv => None,
Self::Workspace(ref path) => Some(path.as_ref()),
Self::Out(ref path) => Some(path.as_ref()),
Self::Custom(ref path) => Some(path.as_ref()),
}
};
}
}

Ok(dir)
impl Display for InstallDir {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Global => write!(f, "global"),
Self::Workspace(ref path) => write!(f, "workspace ({})", path.display()),
Self::Out(ref path) => write!(f, "out ({})", path.display()),
Self::Custom(ref path) => write!(f, "custom ({})", path.display()),
Self::FromEnv => write!(f, "fromenv"),
}
}
}

pub fn workspace_dir() -> Result<PathBuf> {
Ok(cargo::workspace_dir().ok_or_else(|| anyhow!("Cannot fetch crate's workspace dir"))?)
cargo::workspace_dir().ok_or_else(|| anyhow!("Cannot fetch crate's workspace dir"))
}
Loading