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

Build extra components specified in manifest metadata #114

Merged
merged 13 commits into from
Aug 1, 2022
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 <[email protected]>", "sapir <[email protected]>", "Ivan Markov <[email protected]>"]
authors = ["Alexey Arbuzov <[email protected]>", "sapir <[email protected]>", "Ivan Markov <[email protected]>", "Dominik Gschwind <[email protected]>"]
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