From f39befcbad57052240d9f55385a4b99d63c8ce5e Mon Sep 17 00:00:00 2001 From: ttwards Date: Mon, 13 Oct 2025 21:19:59 +0800 Subject: [PATCH] fix(zephyr-sys): bindgen stddef.h not found error Fix bindgen build failure caused by missing system headers by: - Pass CC environment variable from CMake to cargo build/doc commands - Dynamically detect GCC toolchain path and version from CC variable - Add GCC include directory to clang arguments for bindgen - Create dummy arm_acle.h header to avoid ARM ACLE parsing errors The root cause was that bindgen couldn't find stddef.h and other GCC builtin headers because: 1. CC variable was not passed to cargo, preventing toolchain detection 2. GCC include path was not provided to clang 3. ARM ACLE headers caused constant expression errors in bindgen Tested on: qemu_cortex_m3, Zephyr SDK 0.17.2 Signed-off-by: ttwards --- CMakeLists.txt | 2 ++ zephyr-sys/build.rs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75ece41..6bf427f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,6 +173,7 @@ ${config_paths} WRAPPER_FILE="${WRAPPER_FILE}" DT_AUGMENTS="${DT_AUGMENTS}" BINARY_DIR_INCLUDE_GENERATED="${BINARY_DIR_INCLUDE_GENERATED}" + CC=${CMAKE_C_COMPILER} cargo build ${rust_build_type_arg} @@ -217,6 +218,7 @@ ${config_paths} WRAPPER_FILE="${WRAPPER_FILE}" DT_AUGMENTS="${DT_AUGMENTS}" BINARY_DIR_INCLUDE_GENERATED="${BINARY_DIR_INCLUDE_GENERATED}" + CC=${CMAKE_C_COMPILER} cargo doc ${rust_build_type_arg} diff --git a/zephyr-sys/build.rs b/zephyr-sys/build.rs index 5d6a93f..880a6ed 100644 --- a/zephyr-sys/build.rs +++ b/zephyr-sys/build.rs @@ -53,8 +53,31 @@ fn main() -> Result<()> { let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let wrapper_path = PathBuf::from(env::var("WRAPPER_FILE").unwrap()); + // Get GCC toolchain info to find stddef.h + let cc = env::var("CC").unwrap_or_default(); + let gcc_include = if !cc.is_empty() { + let cc_path = Path::new(&cc); + let toolchain_path = cc_path.parent().and_then(|p| p.parent()).unwrap(); + let target_triple = cc_path.file_name().unwrap().to_str().unwrap() + .strip_suffix("-gcc").unwrap_or("arm-zephyr-eabi"); + let gcc_version = std::process::Command::new(&cc) + .arg("-dumpversion") + .output().ok() + .and_then(|o| String::from_utf8(o.stdout).ok()) + .map(|v| v.trim().to_string()) + .unwrap_or("12.2.0".to_string()); + format!("{}/lib/gcc/{}/{}/include", toolchain_path.display(), target_triple, gcc_version) + } else { + String::new() + }; + + // Create dummy ARM headers to avoid ACLE errors + let dummy_headers = out_path.join("dummy_headers"); + std::fs::create_dir_all(&dummy_headers).ok(); + std::fs::write(dummy_headers.join("arm_acle.h"), "").ok(); + // Bindgen everything. - let bindings = Builder::default() + let mut bindings = Builder::default() .header( Path::new("wrapper.h") .canonicalize() @@ -63,7 +86,13 @@ fn main() -> Result<()> { .unwrap(), ) .use_core() - .clang_arg(&target_arg); + .clang_arg(&target_arg) + .clang_arg(format!("-I{}", dummy_headers.display())); + + if !gcc_include.is_empty() { + bindings = bindings.clang_arg(format!("-I{}", gcc_include)); + } + let bindings = define_args(bindings, "-I", "INCLUDE_DIRS"); let bindings = define_args(bindings, "-D", "INCLUDE_DEFINES"); let bindings = bindings