Skip to content

Commit

Permalink
Merge pull request #114 from esp-rs/feature/extra-components
Browse files Browse the repository at this point in the history
Refactor the configuration to use `serde` and the `envy` crate, and allow all build configurations to be specified in the `Cargo.toml`. This is possible by setting the specific option (lowercased) in the `package.metadata.esp-idf-sys` object of the root crate's `Cargo.toml`. The build script gets the metadata by running `cargo metadata` in the workspace directory.
If `cargo metadata` does not give a root crate, it can be specified with the `ESP_IDF_SYS_ROOT_CRATE` environment variable.

Add support for specifying extra esp-idf components in the `package.metadata.esp-idf-sys.extra_components` array of the root crate's *and* all **direct** dependencies' `Cargo.toml`.

Document the new features in the README.
  • Loading branch information
N3xed authored Aug 1, 2022
2 parents 7406c09 + 27eb477 commit ae22edb
Show file tree
Hide file tree
Showing 12 changed files with 1,774 additions and 899 deletions.
11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "esp-idf-sys"
version = "0.31.6"
authors = ["Alexey Arbuzov <aarbuzov@termt.com>", "sapir <yasapir@gmail.com>", "Ivan Markov <ivan.markov@gmail.com>"]
authors = ["Alexey Arbuzov <aarbuzov@termt.com>", "sapir <yasapir@gmail.com>", "Ivan Markov <ivan.markov@gmail.com>", "Dominik Gschwind <dominik.gschwind99@gmail.com>"]
edition = "2021"
resolver = "2"
categories = ["embedded", "hardware-support"]
Expand All @@ -24,16 +24,19 @@ binstart = []
libstart = []

# Use native `esp-idf` tooling to build the `esp-idf`
native = ["embuild/cmake", "embuild/espidf", "strum"]
native = ["embuild/cmake", "embuild/espidf"]
# Backup: use `platformio` to build the `esp-idf`
pio = ["embuild/pio"]

[dependencies]
paste = "1"

[build-dependencies]
embuild = { version = "0.30", features = ["glob", "kconfig"] }
embuild = { version = "0.30.2", features = ["glob", "kconfig"] }
anyhow = "1"
strum = { version = "0.24", features = ["derive"], optional = true }
regex = "1.5"
bindgen = "0.60"
cargo_metadata = "0.15"
serde = { version = "1.0", features = ["derive"] }
strum = { version = "0.24", features = ["derive"] }
envy = "0.4.2"
305 changes: 210 additions & 95 deletions README.md

Large diffs are not rendered by default.

116 changes: 89 additions & 27 deletions build/build.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
#[cfg(not(any(feature = "pio", feature = "native")))]
compile_error!("One of the features `pio` or `native` must be selected.");

use std::env;
use std::fs;
use std::io::{BufWriter, Write};
use std::iter::once;
use std::path::PathBuf;

use ::bindgen::callbacks::{IntKind, ParseCallbacks};
use anyhow::*;
use bindgen::callbacks::{IntKind, ParseCallbacks};
use common::*;
use embuild::bindgen::BindgenExt;
use embuild::utils::OsStrExt;
use embuild::{bindgen, build, cargo, kconfig, path_buf};
use embuild::{bindgen as bindgen_utils, build, cargo, kconfig, path_buf};

mod common;

// Note that the feature `pio` must come before `native`. These features are really
// mutually exclusive but that would require that all dependencies specify the same
// feature so instead we prefer the `pio` feature over `native` so that if one package
// specifies it, this overrides the `native` feature for all other dependencies too.
mod config;

#[cfg(feature = "native")]
mod native;
#[cfg(feature = "pio")]
mod pio;

// Note that the first alias must exclude the `pio` feature, so that in the event both
// features are specified the `pio` build driver is preferred.
// The `native` and `pio` features are really mutually exclusive but that would require
// that all dependencies specify the same feature so instead we prefer the `pio` feature
// over `native` so that if one package specifies it, this overrides the `native` feature
// for all other dependencies too.
// See https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features.
#[cfg(any(feature = "pio", feature = "native"))]
#[cfg_attr(feature = "pio", path = "pio.rs")]
#[cfg_attr(all(feature = "native", not(feature = "pio")), path = "native.rs")]
mod build_driver;
#[cfg(all(feature = "native", not(feature = "pio")))]
use native as build_driver;
#[cfg(feature = "pio")]
use pio as build_driver;

#[derive(Debug)]
struct BindgenCallbacks;
Expand Down Expand Up @@ -72,10 +81,10 @@ fn main() -> anyhow::Result<()> {
)
})?;

let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
let manifest_dir = manifest_dir()?;

let header_file = path_buf![
manifest_dir,
&manifest_dir,
"src",
"include",
if mcu == "esp8266" {
Expand All @@ -88,13 +97,12 @@ fn main() -> anyhow::Result<()> {

cargo::track_file(&header_file);

let bindings_file = bindgen::run(
build_output
.bindgen
.builder()?
// Because we have multiple bindgen invocations and we can't clone a bindgen::Builder,
// we have to set the options every time.
let configure_bindgen = |bindgen: bindgen::Builder| {
Ok(bindgen
.parse_callbacks(Box::new(BindgenCallbacks))
.ctypes_prefix("c_types")
.header(header_file.try_to_str()?)
.blocklist_function("strtold")
.blocklist_function("_strtold_r")
.blocklist_function("v.*printf")
Expand All @@ -112,8 +120,62 @@ fn main() -> anyhow::Result<()> {
// We don't really have a similar issue with Xtensa, but we pass it explicitly as well just in case
"xtensa"
},
]),
)?;
]))
};

let bindings_file = bindgen_utils::default_bindings_file()?;
let bindgen_err = || {
anyhow!(
"failed to generate bindings in file '{}'",
bindings_file.display()
)
};
let mut headers = vec![header_file];

#[cfg(feature = "native")]
// Add additional headers from extra components.
headers.extend(
build_output
.config
.native
.combined_bindings_headers()?
.into_iter()
.inspect(|h| cargo::track_file(h)),
);

configure_bindgen(build_output.bindgen.clone().builder()?)?
.headers(headers)?
.generate()
.with_context(bindgen_err)?
.write_to_file(&bindings_file)
.with_context(bindgen_err)?;

// Generate bindings separately for each unique module name.
#[cfg(feature = "native")]
(|| {
let mut output_file =
BufWriter::new(fs::File::options().append(true).open(&bindings_file)?);

for (module_name, headers) in build_output.config.native.module_bindings_headers()? {
let bindings = configure_bindgen(build_output.bindgen.clone().builder()?)?
.headers(headers.into_iter().inspect(|h| cargo::track_file(h)))?
.generate()?;

writeln!(
&mut output_file,
"pub mod {} {{\
use crate::c_types;\
{}\
}}",
module_name, bindings
)?;
}
Ok(())
})()
.with_context(bindgen_err)?;

// Cargo fmt generated bindings.
bindgen_utils::cargo_fmt_file(&bindings_file);

let cfg_args = build::CfgArgs {
args: cfg_args
Expand All @@ -124,7 +186,6 @@ fn main() -> anyhow::Result<()> {
.chain(once(mcu))
.collect(),
};

cfg_args.propagate();
cfg_args.output();

Expand All @@ -133,13 +194,14 @@ fn main() -> anyhow::Result<()> {

// In case other crates need to have access to the ESP-IDF toolchains
if let Some(env_path) = build_output.env_path {
// TODO: Replace with embuild::build::VAR_ENV_PATH once we have a new embuild release
cargo::set_metadata("EMBUILD_ENV_PATH", env_path);
cargo::set_metadata(embuild::build::ENV_PATH_VAR, env_path);
}

// In case other crates need to the ESP-IDF SDK
// TODO: Replace with embuild::espidf::XXX paths once we have a new embuild release
cargo::set_metadata("EMBUILD_ESP_IDF_PATH", build_output.esp_idf.try_to_str()?);
cargo::set_metadata(
embuild::build::ESP_IDF_PATH_VAR,
build_output.esp_idf.try_to_str()?,
);

build_output.cincl_args.propagate();

Expand Down
Loading

0 comments on commit ae22edb

Please sign in to comment.