mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-03 15:15:01 +00:00
Add the esp-build
package, update esp-hal
and esp-lp-hal
to use it in their build scripts (#1325)
* Create the `esp-build` package * Update `esp-hal` and `esp-lp-hal` to use `esp-build`
This commit is contained in:
parent
4e5020f83f
commit
0cb5e4e82d
@ -2,6 +2,7 @@
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["xtask"]
|
members = ["xtask"]
|
||||||
exclude = [
|
exclude = [
|
||||||
|
"esp-build",
|
||||||
"esp-hal",
|
"esp-hal",
|
||||||
"esp-hal-procmacros",
|
"esp-hal-procmacros",
|
||||||
"esp-hal-smartled",
|
"esp-hal-smartled",
|
||||||
|
16
esp-build/Cargo.toml
Normal file
16
esp-build/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "esp-build"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.60.0"
|
||||||
|
description = "Build utilities for esp-hal"
|
||||||
|
repository = "https://github.com/esp-rs/esp-hal"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.35"
|
||||||
|
syn = { version = "2.0.52", features = ["fold", "full"] }
|
||||||
|
termcolor = "1.4.1"
|
30
esp-build/README.md
Normal file
30
esp-build/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# esp-build
|
||||||
|
|
||||||
|
[](https://crates.io/crates/esp-build)
|
||||||
|
[](https://docs.rs/esp-build)
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
Build utilities for `esp-hal`.
|
||||||
|
|
||||||
|
## [Documentation](https://docs.rs/crate/esp-build)
|
||||||
|
|
||||||
|
## Minimum Supported Rust Version (MSRV)
|
||||||
|
|
||||||
|
This crate is guaranteed to compile on stable Rust 1.60 and up. It _might_
|
||||||
|
compile with older versions but that may change in any new patch release.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Licensed under either of:
|
||||||
|
|
||||||
|
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
|
||||||
|
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
|
||||||
|
any additional terms or conditions.
|
222
esp-build/src/lib.rs
Normal file
222
esp-build/src/lib.rs
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
//! Build utilities for esp-hal.
|
||||||
|
|
||||||
|
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||||
|
|
||||||
|
use std::{io::Write as _, process};
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use syn::{parse_macro_input, punctuated::Punctuated, LitStr, Token};
|
||||||
|
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||||
|
|
||||||
|
/// Print a build error and terminate the process.
|
||||||
|
///
|
||||||
|
/// It should be noted that the error will be printed BEFORE the main function
|
||||||
|
/// is called, and as such this should NOT be thought analogous to `println!` or
|
||||||
|
/// similar utilities.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// esp_build::error! {"
|
||||||
|
/// ERROR: something really bad has happened!
|
||||||
|
/// "}
|
||||||
|
/// // Process exits with exit code 1
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn error(input: TokenStream) -> TokenStream {
|
||||||
|
do_alert(Color::Red, input);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Print a build warning.
|
||||||
|
///
|
||||||
|
/// It should be noted that the warning will be printed BEFORE the main function
|
||||||
|
/// is called, and as such this should NOT be thought analogous to `println!` or
|
||||||
|
/// similar utilities.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// esp_build::warning! {"
|
||||||
|
/// WARNING: something unpleasant has happened!
|
||||||
|
/// "};
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn warning(input: TokenStream) -> TokenStream {
|
||||||
|
do_alert(Color::Yellow, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given some features, assert that **at most** one of the features is enabled.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```rust
|
||||||
|
/// assert_unique_features!("foo", "bar", "baz");
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn assert_unique_features(input: TokenStream) -> TokenStream {
|
||||||
|
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pairs = unique_pairs(&features);
|
||||||
|
let unique_cfgs = pairs
|
||||||
|
.iter()
|
||||||
|
.map(|(a, b)| quote::quote! { all(feature = #a, feature = #b) });
|
||||||
|
|
||||||
|
let message = format!(
|
||||||
|
r#"
|
||||||
|
ERROR: expected exactly zero or one enabled feature from feature group:
|
||||||
|
{:?}
|
||||||
|
"#,
|
||||||
|
features.iter().map(|lit| lit.value()).collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
quote::quote! {
|
||||||
|
#[cfg(any(#(#unique_cfgs),*))]
|
||||||
|
::esp_build::error! { #message }
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given some features, assert that **at least** one of the features is
|
||||||
|
/// enabled.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```rust
|
||||||
|
/// assert_used_features!("foo", "bar", "baz");
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn assert_used_features(input: TokenStream) -> TokenStream {
|
||||||
|
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let message = format!(
|
||||||
|
r#"
|
||||||
|
ERROR: expected at least one enabled feature from feature group:
|
||||||
|
{:?}
|
||||||
|
"#,
|
||||||
|
features.iter().map(|lit| lit.value()).collect::<Vec<_>>()
|
||||||
|
);
|
||||||
|
|
||||||
|
quote::quote! {
|
||||||
|
#[cfg(not(any(#(feature = #features),*)))]
|
||||||
|
::esp_build::error! { #message }
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given some features, assert that **exactly** one of the features is enabled.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```rust
|
||||||
|
/// assert_unique_used_features!("foo", "bar", "baz");
|
||||||
|
/// ```
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn assert_unique_used_features(input: TokenStream) -> TokenStream {
|
||||||
|
let features = parse_macro_input!(input with Punctuated<LitStr, Token![,]>::parse_terminated)
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pairs = unique_pairs(&features);
|
||||||
|
let unique_cfgs = pairs
|
||||||
|
.iter()
|
||||||
|
.map(|(a, b)| quote::quote! { all(feature = #a, feature = #b) });
|
||||||
|
|
||||||
|
let message = format!(
|
||||||
|
r#"
|
||||||
|
ERROR: expected exactly one enabled feature from feature group:
|
||||||
|
{:?}
|
||||||
|
"#,
|
||||||
|
features.iter().map(|lit| lit.value()).collect::<Vec<_>>()
|
||||||
|
);
|
||||||
|
|
||||||
|
quote::quote! {
|
||||||
|
#[cfg(any(any(#(#unique_cfgs),*), not(any(#(feature = #features),*))))]
|
||||||
|
::esp_build::error! { #message }
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helper Functions
|
||||||
|
|
||||||
|
// Adapted from:
|
||||||
|
// https://github.com/dtolnay/build-alert/blob/49d060e/src/lib.rs#L54-L93
|
||||||
|
fn do_alert(color: Color, input: TokenStream) -> TokenStream {
|
||||||
|
let message = parse_macro_input!(input as LitStr).value();
|
||||||
|
|
||||||
|
let ref mut stderr = StandardStream::stderr(ColorChoice::Auto);
|
||||||
|
let color_spec = ColorSpec::new().set_fg(Some(color)).clone();
|
||||||
|
|
||||||
|
let mut has_nonspace = false;
|
||||||
|
|
||||||
|
for mut line in message.lines() {
|
||||||
|
if !has_nonspace {
|
||||||
|
let (maybe_heading, rest) = split_heading(line);
|
||||||
|
|
||||||
|
if let Some(heading) = maybe_heading {
|
||||||
|
stderr.set_color(color_spec.clone().set_bold(true)).ok();
|
||||||
|
write!(stderr, "\n{}", heading).ok();
|
||||||
|
has_nonspace = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if line.is_empty() {
|
||||||
|
writeln!(stderr).ok();
|
||||||
|
} else {
|
||||||
|
stderr.set_color(&color_spec).ok();
|
||||||
|
writeln!(stderr, "{}", line).ok();
|
||||||
|
|
||||||
|
has_nonspace = has_nonspace || line.contains(|ch: char| ch != ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stderr.reset().ok();
|
||||||
|
writeln!(stderr).ok();
|
||||||
|
|
||||||
|
TokenStream::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from:
|
||||||
|
// https://github.com/dtolnay/build-alert/blob/49d060e/src/lib.rs#L95-L114
|
||||||
|
fn split_heading(s: &str) -> (Option<&str>, &str) {
|
||||||
|
let mut end = 0;
|
||||||
|
while end < s.len() && s[end..].starts_with(|ch: char| ch.is_ascii_uppercase()) {
|
||||||
|
end += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if end >= 3 && (end == s.len() || s[end..].starts_with(':')) {
|
||||||
|
let (heading, rest) = s.split_at(end);
|
||||||
|
(Some(heading), rest)
|
||||||
|
} else {
|
||||||
|
(None, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unique_pairs(features: &Vec<LitStr>) -> Vec<(&LitStr, &LitStr)> {
|
||||||
|
let mut pairs = Vec::new();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
let mut j = 0;
|
||||||
|
|
||||||
|
while i < features.len() {
|
||||||
|
let a = &features[i];
|
||||||
|
let b = &features[j];
|
||||||
|
|
||||||
|
if a.value() != b.value() {
|
||||||
|
pairs.push((a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
j += 1;
|
||||||
|
|
||||||
|
if j >= features.len() {
|
||||||
|
i += 1;
|
||||||
|
j = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pairs
|
||||||
|
}
|
@ -70,6 +70,7 @@ xtensa-lx-rt = { version = "0.16.0", optional = true }
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
basic-toml = "0.1.8"
|
basic-toml = "0.1.8"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
esp-build = { version = "0.1.0", path = "../esp-build" }
|
||||||
esp-metadata = { version = "0.1.0", path = "../esp-metadata" }
|
esp-metadata = { version = "0.1.0", path = "../esp-metadata" }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
|
|
||||||
|
105
esp-hal/build.rs
105
esp-hal/build.rs
@ -7,45 +7,9 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use esp_build::assert_unique_used_features;
|
||||||
use esp_metadata::{Chip, Config};
|
use esp_metadata::{Chip, Config};
|
||||||
|
|
||||||
// Macros taken from:
|
|
||||||
// https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110
|
|
||||||
|
|
||||||
// Given some features, assert that AT MOST one of the features is enabled.
|
|
||||||
macro_rules! assert_unique_features {
|
|
||||||
() => {};
|
|
||||||
|
|
||||||
( $first:tt $(,$rest:tt)* ) => {
|
|
||||||
$(
|
|
||||||
#[cfg(all(feature = $first, feature = $rest))]
|
|
||||||
compile_error!(concat!("Features \"", $first, "\" and \"", $rest, "\" cannot be used together"));
|
|
||||||
)*
|
|
||||||
assert_unique_features!($($rest),*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given some features, assert that AT LEAST one of the features is enabled.
|
|
||||||
macro_rules! assert_used_features {
|
|
||||||
( $all:tt ) => {
|
|
||||||
#[cfg(not(feature = $all))]
|
|
||||||
compile_error!(concat!("The feature flag must be provided: ", $all));
|
|
||||||
};
|
|
||||||
|
|
||||||
( $($all:tt),+ ) => {
|
|
||||||
#[cfg(not(any($(feature = $all),*)))]
|
|
||||||
compile_error!(concat!("One of the feature flags must be provided: ", $($all, ", "),*));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given some features, assert that EXACTLY one of the features is enabled.
|
|
||||||
macro_rules! assert_unique_used_features {
|
|
||||||
( $($all:tt),* ) => {
|
|
||||||
assert_unique_features!($($all),*);
|
|
||||||
assert_used_features!($($all),*);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
// NOTE: update when adding new device support!
|
// NOTE: update when adding new device support!
|
||||||
// Ensure that exactly one chip has been specified:
|
// Ensure that exactly one chip has been specified:
|
||||||
@ -56,7 +20,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
// If the `embassy` feature is enabled, ensure that a time driver implementation
|
// If the `embassy` feature is enabled, ensure that a time driver implementation
|
||||||
// is available:
|
// is available:
|
||||||
#[cfg(feature = "embassy")]
|
#[cfg(feature = "embassy")]
|
||||||
{
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(feature = "esp32")] {
|
if #[cfg(feature = "esp32")] {
|
||||||
assert_unique_used_features!("embassy-time-timg0");
|
assert_unique_used_features!("embassy-time-timg0");
|
||||||
@ -66,13 +29,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
assert_unique_used_features!("embassy-time-systick-16mhz", "embassy-time-timg0");
|
assert_unique_used_features!("embassy-time-systick-16mhz", "embassy-time-timg0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "flip-link")]
|
#[cfg(all(
|
||||||
{
|
feature = "flip-link",
|
||||||
#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
|
not(any(feature = "esp32c6", feature = "esp32h2"))
|
||||||
panic!("flip-link is only available on ESP32-C6/ESP32-H2");
|
))]
|
||||||
}
|
esp_build::error!("flip-link is only available on ESP32-C6/ESP32-H2");
|
||||||
|
|
||||||
// NOTE: update when adding new device support!
|
// NOTE: update when adding new device support!
|
||||||
// Determine the name of the configured device:
|
// Determine the name of the configured device:
|
||||||
@ -96,12 +58,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
unreachable!() // We've confirmed exactly one known device was selected
|
unreachable!() // We've confirmed exactly one known device was selected
|
||||||
};
|
};
|
||||||
|
|
||||||
if detect_atomic_extension("a") || detect_atomic_extension("s32c1i") {
|
|
||||||
panic!(
|
|
||||||
"Atomic emulation flags detected in `.cargo/config.toml`, this is no longer supported!"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the configuration file for the configured device:
|
// Load the configuration file for the configured device:
|
||||||
let chip = Chip::from_str(device_name)?;
|
let chip = Chip::from_str(device_name)?;
|
||||||
let config = Config::for_chip(&chip);
|
let config = Config::for_chip(&chip);
|
||||||
@ -126,8 +82,14 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
println!("cargo:rustc-link-search={}", out.display());
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
|
||||||
|
// RISC-V and Xtensa devices each require some special handling and processing
|
||||||
|
// of linker scripts:
|
||||||
|
|
||||||
if cfg!(feature = "esp32") || cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") {
|
if cfg!(feature = "esp32") || cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") {
|
||||||
fs::copy("ld/xtensa/hal-defaults.x", out.join("hal-defaults.x"))?;
|
// Xtensa devices:
|
||||||
|
|
||||||
|
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||||
|
File::create(out.join("memory_extras.x"))?.write_all(&generate_memory_extras())?;
|
||||||
|
|
||||||
let (irtc, drtc) = if cfg!(feature = "esp32s3") {
|
let (irtc, drtc) = if cfg!(feature = "esp32s3") {
|
||||||
("rtc_fast_seg", "rtc_fast_seg")
|
("rtc_fast_seg", "rtc_fast_seg")
|
||||||
@ -148,25 +110,30 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
fs::write(out.join("alias.x"), alias)?;
|
fs::write(out.join("alias.x"), alias)?;
|
||||||
|
fs::copy("ld/xtensa/hal-defaults.x", out.join("hal-defaults.x"))?;
|
||||||
} else {
|
} else {
|
||||||
|
// RISC-V devices:
|
||||||
|
|
||||||
|
preprocess_file(&config_symbols, "ld/riscv/asserts.x", out.join("asserts.x"))?;
|
||||||
|
preprocess_file(&config_symbols, "ld/riscv/debug.x", out.join("debug.x"))?;
|
||||||
preprocess_file(
|
preprocess_file(
|
||||||
&config_symbols,
|
&config_symbols,
|
||||||
"ld/riscv/hal-defaults.x",
|
"ld/riscv/hal-defaults.x",
|
||||||
out.join("hal-defaults.x"),
|
out.join("hal-defaults.x"),
|
||||||
)?;
|
)?;
|
||||||
preprocess_file(&config_symbols, "ld/riscv/asserts.x", out.join("asserts.x"))?;
|
|
||||||
preprocess_file(&config_symbols, "ld/riscv/debug.x", out.join("debug.x"))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With the architecture-specific linker scripts taken care of, we can copy all
|
||||||
|
// remaining linker scripts which are common to all devices:
|
||||||
copy_dir_all(&config_symbols, "ld/sections", &out)?;
|
copy_dir_all(&config_symbols, "ld/sections", &out)?;
|
||||||
copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?;
|
copy_dir_all(&config_symbols, format!("ld/{device_name}"), &out)?;
|
||||||
|
|
||||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
|
||||||
File::create(out.join("memory_extras.x"))?.write_all(&generate_memory_extras())?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helper Functions
|
||||||
|
|
||||||
fn copy_dir_all(
|
fn copy_dir_all(
|
||||||
config_symbols: &Vec<String>,
|
config_symbols: &Vec<String>,
|
||||||
src: impl AsRef<Path>,
|
src: impl AsRef<Path>,
|
||||||
@ -234,32 +201,6 @@ fn preprocess_file(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_atomic_extension(ext: &str) -> bool {
|
|
||||||
let rustflags = env::var_os("CARGO_ENCODED_RUSTFLAGS")
|
|
||||||
.unwrap()
|
|
||||||
.into_string()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Users can pass -Ctarget-feature to the compiler multiple times, so we have to
|
|
||||||
// handle that
|
|
||||||
let target_flags = rustflags
|
|
||||||
.split(0x1f as char)
|
|
||||||
.filter_map(|s| s.strip_prefix("target-feature="));
|
|
||||||
for tf in target_flags {
|
|
||||||
let tf = tf
|
|
||||||
.split(',')
|
|
||||||
.map(|s| s.trim())
|
|
||||||
.filter_map(|s| s.strip_prefix('+'));
|
|
||||||
for tf in tf {
|
|
||||||
if tf == ext {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "esp32")]
|
#[cfg(feature = "esp32")]
|
||||||
fn generate_memory_extras() -> Vec<u8> {
|
fn generate_memory_extras() -> Vec<u8> {
|
||||||
let reserve_dram = if cfg!(feature = "bluetooth") {
|
let reserve_dram = if cfg!(feature = "bluetooth") {
|
||||||
|
@ -35,6 +35,9 @@ riscv = { version = "0.11.0", features = ["critical-section-single-har
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
panic-halt = "0.2.0"
|
panic-halt = "0.2.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
esp-build = { version = "0.1.0", path = "../esp-build" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["embedded-hal-02"]
|
default = ["embedded-hal-02"]
|
||||||
|
|
||||||
|
@ -1,41 +1,6 @@
|
|||||||
use std::{env, error::Error, fs, path::PathBuf};
|
use std::{env, error::Error, fs, path::PathBuf};
|
||||||
|
|
||||||
// Macros taken from:
|
use esp_build::assert_unique_used_features;
|
||||||
// https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110
|
|
||||||
|
|
||||||
// Given some features, assert that AT MOST one of the features is enabled.
|
|
||||||
macro_rules! assert_unique_features {
|
|
||||||
() => {};
|
|
||||||
|
|
||||||
( $first:tt $(,$rest:tt)* ) => {
|
|
||||||
$(
|
|
||||||
#[cfg(all(feature = $first, feature = $rest))]
|
|
||||||
compile_error!(concat!("Features \"", $first, "\" and \"", $rest, "\" cannot be used together"));
|
|
||||||
)*
|
|
||||||
assert_unique_features!($($rest),*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given some features, assert that AT LEAST one of the features is enabled.
|
|
||||||
macro_rules! assert_used_features {
|
|
||||||
( $all:tt ) => {
|
|
||||||
#[cfg(not(feature = $all))]
|
|
||||||
compile_error!(concat!("The feature flag must be provided: ", $all));
|
|
||||||
};
|
|
||||||
|
|
||||||
( $($all:tt),+ ) => {
|
|
||||||
#[cfg(not(any($(feature = $all),*)))]
|
|
||||||
compile_error!(concat!("One of the feature flags must be provided: ", $($all, ", "),*));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given some features, assert that EXACTLY one of the features is enabled.
|
|
||||||
macro_rules! assert_unique_used_features {
|
|
||||||
( $($all:tt),* ) => {
|
|
||||||
assert_unique_features!($($all),*);
|
|
||||||
assert_used_features!($($all),*);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
// NOTE: update when adding new device support!
|
// NOTE: update when adding new device support!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user