Skip to content

Commit

Permalink
Implement native esp-idf cmake build
Browse files Browse the repository at this point in the history
Move `build.rs` contents to `build_pio.rs`
Add feature `native`
Add optional dependency `strum`
  • Loading branch information
N3xed committed Sep 6, 2021
1 parent 6d08b4f commit 50853c2
Show file tree
Hide file tree
Showing 6 changed files with 569 additions and 135 deletions.
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@ links = "esp_idf"
default-target = "x86_64-unknown-linux-gnu"

[features]
default = ["std", "embedded-svc/std"]
default = ["std", "embedded-svc/std", "native"]

std = []

# Use `platformio` to build the `esp-idf`
platformio = []
# Use native `esp-idf` tooling to build it
native = ["strum"]

[dependencies]
mutex-trait = "0.2"
embedded-svc = "0.8.3"
paste = "1"

[build-dependencies]
embuild = "0.23"
anyhow = "1"
anyhow = {version = "1", features = ["backtrace"]}
strum = { version = "0.21", optional = true, features = ["derive"] }
144 changes: 11 additions & 133 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,136 +1,14 @@
use std::convert::TryFrom;
use std::{env, path::PathBuf};
#[cfg(not(any(feature = "pio", feature = "native")))]
compile_error!("One of the features `platformio` or `native` must be selected.");

use anyhow::*;
#[cfg(all(feature = "pio", feature = "native"))]
compile_error!("The features `platformio` and `native` are mutually exclusive. Only one of them can be selected at a time.");

use embuild::bindgen;
use embuild::build;
use embuild::cargo;
use embuild::kconfig;
use embuild::pio;
use embuild::pio::project;
#[cfg(any(feature = "platformio", feature = "native"))]
#[cfg_attr(feature = "platformio", path = "build_pio.rs")]
#[cfg_attr(feature = "native", path = "build_native.rs")]
mod build_impl;

fn main() -> Result<()> {
let pio_scons_vars = if let Some(pio_scons_vars) = project::SconsVariables::from_piofirst() {
println!("cargo:info=PIO->Cargo build detected: generating bindings only");

pio_scons_vars
} else {
let pio = pio::Pio::install_default()?;

let resolution = pio::Resolver::new(pio.clone())
.params(pio::ResolutionParams {
platform: Some("espressif32".into()),
frameworks: vec!["espidf".into()],
target: Some(env::var("TARGET")?),
..Default::default()
})
.resolve(true)?;

let mut builder =
project::Builder::new(PathBuf::from(env::var("OUT_DIR")?).join("esp-idf"));

builder
.enable_scons_dump()
.enable_c_entry_points()
.options(build::env_options_iter("ESP_IDF_SYS_PIO_CONF")?)
.files(build::tracked_globs_iter(
PathBuf::from("."),
&["patches/**"],
)?)
.files(build::tracked_env_globs_iter("ESP_IDF_SYS_GLOB")?);

#[cfg(feature = "espidf_master")]
builder
.platform_package(
"framework-espidf",
"https://github.com/ivmarkov/esp-idf.git#master",
)
.platform_package_patch(
PathBuf::from("patches").join("master_missing_xtensa_atomics_fix.diff"),
PathBuf::from("framework-espidf"),
)
.platform_package_patch(
PathBuf::from("patches").join("ping_setsockopt_fix.diff"),
PathBuf::from("framework-espidf"),
);

#[cfg(feature = "espidf_master")]
env::set_var("IDF_MAINTAINER", "1");

#[cfg(not(feature = "espidf_master"))]
builder
.platform_package_patch(
PathBuf::from("patches").join("pthread_destructor_fix.diff"),
PathBuf::from("framework-espidf"),
)
.platform_package_patch(
PathBuf::from("patches").join("ping_setsockopt_fix.diff"),
PathBuf::from("framework-espidf"),
)
.platform_package_patch(
PathBuf::from("patches").join("missing_xtensa_atomics_fix.diff"),
PathBuf::from("framework-espidf"),
);

let project_path = builder.generate(&resolution)?;

pio.build(&project_path, env::var("PROFILE")? == "release")?;

let pio_scons_vars = project::SconsVariables::from_dump(&project_path)?;

build::LinkArgsBuilder::try_from(&pio_scons_vars)?
.build()
.propagate();

pio_scons_vars
};

// In case other SYS crates need to have access to the ESP-IDF C headers
build::CInclArgs::try_from(&pio_scons_vars)?.propagate();

let cfg_args = kconfig::CfgArgs::try_from(
pio_scons_vars
.project_dir
.join(if pio_scons_vars.release_build {
"sdkconfig.release"
} else {
"sdkconfig.debug"
})
.as_path(),
)?;

cfg_args.propagate("ESP_IDF");
cfg_args.output("ESP_IDF");

let mcu = pio_scons_vars.mcu.as_str();

// Output the exact ESP32 MCU, so that we and crates depending directly on us can branch using e.g. #[cfg(esp32xxx)]
println!("cargo:rustc-cfg={}", mcu);
println!("cargo:MCU={}", mcu);

let header = PathBuf::from("src")
.join("include")
.join(if mcu == "esp8266" {
"esp-8266-rtos-sdk"
} else {
"esp-idf"
})
.join("bindings.h");

cargo::track_file(&header);

bindgen::run(
bindgen::Factory::from_scons_vars(&pio_scons_vars)?
.builder()?
.ctypes_prefix("c_types")
.header(header.to_string_lossy())
.blacklist_function("strtold")
.blacklist_function("_strtold_r")
.clang_args(if mcu == "esp32c3" {
vec!["-target", "riscv32"]
} else {
vec![]
}),
)
}
fn main() -> anyhow::Result<()> {
build_impl::main()
}
Loading

0 comments on commit 50853c2

Please sign in to comment.