Skip to content

Commit

Permalink
Make build script apply esp-idf patches
Browse files Browse the repository at this point in the history
Improved recompile speed (now it doesn't regenerate the bindings every time).
Corrected handling of `ESPIDF_SDKCONFIG_DEFAULTS`, not can contain a `;` seperated list.
  • Loading branch information
N3xed committed Aug 12, 2021
1 parent 16e185b commit ea1aaff
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 38 deletions.
3 changes: 0 additions & 3 deletions sdk_build_support/cmake_project/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ set(SDKCONFIG $ENV{ESPIDF_SDKCONFIG})
set(SDKCONFIG_DEFAULTS $ENV{ESPIDF_SDKCONFIG_DEFAULTS})

include($ENV{IDF_PATH}/tools/cmake/idf.cmake)
__target_init()
__target_set_toolchain()

project(libespidf C)

idf_build_process($ENV{IDF_TARGET})
Expand Down
121 changes: 86 additions & 35 deletions sdk_build_support/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use utils::*;

use std::array;
use std::fs;
use std::io::Write;
use std::path::Path;
use std::{env, path::PathBuf};

Expand Down Expand Up @@ -75,37 +74,42 @@ pub fn build(build_env: &BuildEnv) -> Result<()> {
..
} = build_env;
let mcu = chip.to_string();
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);

println!("cargo:rerun-if-env-changed=ESPIDF_VERSION");
println!("cargo:rerun-if-env-changed=ESPIDF_URL");
println!("cargo:rerun-if-env-changed=ESPIDF_SDKCONFIG_DEFAULTS");
println!("cargo:rerun-if-env-changed=ESPIDF_SDKCONFIG");

// Clone esp-idf.
fs::create_dir_all(&sdk_dir)?;
let esp_idf_dir = path_buf![&sdk_dir, "esp-idf"];
let esp_idf_version =
env::var("ESPIDF_VERSION").unwrap_or(consts::DEFAULT_ESPIDF_VERSION.into());

env::set_current_dir(&sdk_dir)?;
let should_clone = !esp_idf_dir.exists() || {
let (should_clone, esp_idf_changed) = if esp_idf_dir.exists() {
let g = push_current_dir(&esp_idf_dir)?;

let git_describe =
cmd_output!("git", "describe", "--all", "--exact-match").unwrap_or("".into());
if git_describe == format!("tags/{}", esp_idf_version) {
false
(false, false)
} else if git_describe == format!("heads/{}", esp_idf_version) {
cmd!("git", "reset", "--hard")?;
cmd!("git", "pull", "--rebase")?;

false
(false, true)
} else {
drop(g);

cmd!("cmake", "-E", "rm", "-rf", &esp_idf_dir)?;
true
(true, true)
}
} else {
(true, true)
};

if should_clone {
let espidf_url = env::var("ESPIDF_URL").unwrap_or(consts::DEFAULT_ESPIDF_URL.into());
cmd!(
Expand All @@ -121,6 +125,30 @@ pub fn build(build_env: &BuildEnv) -> Result<()> {
)?;
}

// apply patches
if esp_idf_changed {
let patch_set = if esp_idf_version == consts::DEFAULT_ESPIDF_VERSION {
&[
"esp32c3_atomics_emul.diff",
"pthread_destructor_fix.diff",
"ping_setsockopt_fix.diff",
"missing_xtensa_atomics_fix.diff",
][..]
} else if esp_idf_version == "master" {
&[
"master_missing_xtensa_atomics_fix.diff",
"ping_setsockopt_fix.diff",
][..]
} else {
&[]
};

if !patch_set.is_empty() {
let _g = push_current_dir(&esp_idf_dir);
cmd!("git", "apply"; args=(patch_set.iter().map(|p| path_buf![&manifest_dir, "patches", p])))?;
}
}

// This is a workaround for msys or even git bash.
// When using them `idf_tools.py` prints unix paths (ex. `/c/user/` instead of
// `C:\user\`), so we correct this with an invocation of `cygpath` which converts the
Expand Down Expand Up @@ -210,12 +238,24 @@ pub fn build(build_env: &BuildEnv) -> Result<()> {
// Create dummy cmake project (copies from `cmake_project`).
let libespidf_dir = path_buf![out_dir, "libespidf"];
let libespidf_build_dir = path_buf![&libespidf_dir, "build"];
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);

fs::create_dir_all(&libespidf_dir)?;
cmd!(
"cmake",
"-E",
"copy_directory",
path_buf![&manifest_dir, "sdk_build_support", "cmake_project"],
"copy_if_different",
path_buf![
&manifest_dir,
"sdk_build_support",
"cmake_project",
"CMakeLists.txt"
],
path_buf![
&manifest_dir,
"sdk_build_support",
"cmake_project",
"main.c"
],
&libespidf_dir
)?;

Expand Down Expand Up @@ -247,16 +287,16 @@ pub fn build(build_env: &BuildEnv) -> Result<()> {
.unwrap_or(String::new());
let espidf_sdkconfig_defaults = env::var("ESPIDF_SDKCONFIG_DEFAULTS")
.ok()
.and_then(|v| {
if !v.is_empty() {
Some(
utils::abspath_relative_to(v, &workspace_dir)
.map(|v| {
v.split(';')
.filter(|s| !s.is_empty())
.map(|s| {
abspath_relative_to(s, &workspace_dir)
.to_string_lossy()
.into_owned(),
)
} else {
None
}
.to_string()
})
.collect::<Vec<_>>()
.join(";")
})
.unwrap_or(String::new());

Expand Down Expand Up @@ -329,28 +369,39 @@ pub fn build(build_env: &BuildEnv) -> Result<()> {

// Generate bindings.
let header_file = path_buf![&manifest_dir, "src", "include", "esp-idf", "bindings.h"];
bindgen::builder()
.header(format!("{}", header_file.display()))
.ctypes_prefix("c_types")
.blocklist_function("(_)?strtold(_r)?")
.clang_args(clang_args)
.use_core()
.detect_include_paths(false)
.derive_default(true)
.generate()
.or_else(|_| bail!("Failed to generate bindings."))?
.write_to_file(out_dir.join("bindings.rs"))?;
if esp_idf_changed || !out_dir.join("bindings.rs").exists() {
bindgen::builder()
.header(format!("{}", header_file.display()))
.ctypes_prefix("c_types")
.blocklist_function("(_)?strtold(_r)?")
.clang_args(clang_args)
.use_core()
.detect_include_paths(false)
.derive_default(true)
.generate()
.or_else(|_| bail!("Failed to generate bindings."))?
.write_to_file(out_dir.join("bindings.rs"))
.context("Could not write the generated bindings to file.")?;
}

// Create archive of all libraries and write linker args to file.
env::set_current_dir(&libespidf_build_dir)?;

let linker_args = target
.link
.command_fragments
.into_iter()
.map(|f| {
if cfg!(windows) {
f.fragment.replace('\\', "/")
} else {
f.fragment
}
})
.collect::<Vec<_>>()
.join(" ");
let linker_args_file = out_dir.join("linker_args.rsp");
let mut linker_args_rsp = fs::File::create(&linker_args_file)?;

for f in target.link.command_fragments {
write!(&mut linker_args_rsp, "{} ", f.fragment.replace('\\', "/"))?;
if !linker_args_file.exists() || &std::fs::read_to_string(&linker_args_file)? != &linker_args {
std::fs::write(&linker_args_file, &linker_args)?;
}
drop(linker_args_rsp);

cmd!("cmake", "-E", "rm", "-rf", workspace_dir.join("esp-idf")).ok();
cmd!(
Expand Down

0 comments on commit ea1aaff

Please sign in to comment.