Skip to content

Instantly share code, notes, and snippets.

@MathyV
Last active February 21, 2023 21:15
Show Gist options
  • Save MathyV/29e65b8d4714f1b19bc846fb7893107d to your computer and use it in GitHub Desktop.
Save MathyV/29e65b8d4714f1b19bc846fb7893107d to your computer and use it in GitHub Desktop.
A snippet of (what I believe) it currently takes to build a cmake project from Rust using esp-idf-sys
use std::env;
use anyhow::{anyhow, Result};
use embuild::{cargo, path_buf};
use embuild::cmake;
// This function is derived from the build system used in esp-idf-sys. Because esp-idf-sys is a
// dependency certain configuration is already propagated in ENV variables which is then reloaded by
// embuild using the try_from_env functions.
pub fn build(module: &str) -> Result<()> {
for (key, value) in env::vars() {
eprintln!("{key}: {value}");
}
let out_dir = cargo::out_dir();
let src_dir = "src/".to_owned() + module;
let links = "ESP_IDF";
eprintln!("Building {} with CMake in directory {}",
module,
src_dir);
eprintln!("Output dir: {}", out_dir.display());
let cfg_args = embuild::build::CfgArgs::try_from_env(links)?;
// TODO: it would be better if we can grab this from esp-idf-sys or if embuild would discover it
let path = env::var("DEP_ESP_IDF_EMBUILD_ENV_PATH")?;
let idf_path = env::var("DEP_ESP_IDF_EMBUILD_ESP_IDF_PATH")?;
env::set_var("PATH", path);
env::set_var("IDF_PATH", idf_path.clone());
// Try to locate IDF
let idf = embuild::espidf::EspIdf::try_from_env()?;
eprintln!("Found ESP IDF in: {}", idf_path);
let chip_name = cfg_args.get("esp_idf_idf_target").ok_or_else(|| {
anyhow!("Could not find target chip")
})?;
// Borrowed from esp-idf-sys
let cmake_toolchain_file = path_buf![
&idf.repository.worktree(),
"tools",
"cmake",
format!("toolchain-{}.cmake", chip_name)
];
// Get the asm, C and C++ flags from the toolchain file, these would otherwise get
// overwritten because `cmake::Config` also sets these (see
// https://github.com/espressif/esp-idf/issues/7507).
let (asm_flags, c_flags, cxx_flags) = {
let extractor_script = cmake::script_variables_extractor(&cmake_toolchain_file)?;
let output = embuild::cmd!(
cmake::cmake(),
"-P",
extractor_script.as_ref().as_os_str();
env=("IDF_PATH", &idf.repository.worktree().as_os_str()))
.stdout()?;
let mut vars = cmake::process_script_variables_extractor_output(output)?;
(
vars.remove("CMAKE_ASM_FLAGS").unwrap_or_default(),
vars.remove("CMAKE_C_FLAGS").unwrap_or_default(),
vars.remove("CMAKE_CXX_FLAGS").unwrap_or_default(),
)
};
let mut cmake_config = cmake::Config::new(src_dir);
cmake_config
// We hardcode to Ninja for now
// TODO: check if we can reuse esp_idf::config.native.esp_idf_cmake_generator()
.generator(cmake::Generator::Ninja.name())
.out_dir(&out_dir)
.no_build_target(true)
.define("CMAKE_TOOLCHAIN_FILE", &cmake_toolchain_file)
.define("CMAKE_BUILD_TYPE", "")
.always_configure(true)
.pic(false)
.asmflag(asm_flags)
.cflag(c_flags)
.cxxflag(cxx_flags);
let dst = cmake_config.build();
println!("cargo:rustc-link-search=native={}/build", dst.display());
println!("cargo:rustc-link-lib=static=sample_c");
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment