Added the zig_main project to software for zig based implementation of code for robot

This commit is contained in:
2026-05-05 20:14:04 +12:00
parent 7d752f2534
commit f21f909a71
83 changed files with 13631 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
# ──────────────────────────────────────────────────────────────────────────────
# Download translate_c-standalone
# ──────────────────────────────────────────────────────────────────────────────
# Determine platform triple for translate_c-standalone naming
if(ZIG_PLATFORM STREQUAL "linux-musl")
if(ZIG_ARCH STREQUAL "aarch64")
set(TRANSLATE_C_TRIPLE "aarch64-linux-musl")
set(HASH_SUM "7d5968a41a02064d90035db95ef102fc2ab5e71a2eb48ba6cf028eb79b4ae43d")
elseif(ZIG_ARCH STREQUAL "x86_64")
set(TRANSLATE_C_TRIPLE "x86_64-linux-musl")
set(HASH_SUM "d098e2675fc6706914b6e53dd72f6536895420460f287e73e19772c979fabb84")
else()
message(FATAL_ERROR "Unsupported architecture for translate_c-standalone: ${ZIG_ARCH}")
endif()
set(ARCHIVE_EXT "tar.xz")
elseif(ZIG_PLATFORM STREQUAL "windows")
if(ZIG_ARCH STREQUAL "x86_64")
set(TRANSLATE_C_TRIPLE "x86_64-windows-gnu")
set(HASH_SUM "8e53a03ee44983eea2786c2ba028e83a816b9a993a768b3f4ca8c6e3525923e2")
else()
message(FATAL_ERROR "Unsupported architecture for translate_c-standalone: ${ZIG_ARCH}")
endif()
set(ARCHIVE_EXT "zip")
elseif(ZIG_PLATFORM STREQUAL "macos")
if(ZIG_ARCH STREQUAL "aarch64")
set(TRANSLATE_C_TRIPLE "aarch64-macos")
set(HASH_SUM "8b3d2360d09add35f764ac138e0ec497503dc3de788a01e93fd7b9923a44369c")
else()
message(FATAL_ERROR "Unsupported architecture for translate_c-standalone: ${ZIG_ARCH}")
endif()
set(ARCHIVE_EXT "tar.xz")
else()
message(FATAL_ERROR "Unsupported platform for translate_c-standalone: ${ZIG_PLATFORM}")
endif()
set(TRANSLATE_C_DIR "${CMAKE_BINARY_DIR}/translate_c-standalone")
set(TRANSLATE_C_ARCHIVE "${CMAKE_BINARY_DIR}/translate_c-standalone-${TRANSLATE_C_TRIPLE}-baseline.${ARCHIVE_EXT}")
set(TRANSLATE_C_BIN "${TRANSLATE_C_DIR}/bin")
# Download if not already extracted
if(NOT EXISTS "${TRANSLATE_C_BIN}")
set(TRANSLATE_C_URL "https://github.com/kassane/zig-espressif-bootstrap/releases/download/0.16.0-xtensa-dev/translate_c-standalone-${TRANSLATE_C_TRIPLE}-baseline.${ARCHIVE_EXT}")
message(STATUS "Downloading translate_c-standalone (${TRANSLATE_C_TRIPLE}):")
message(STATUS " => ${TRANSLATE_C_ARCHIVE}")
file(DOWNLOAD "${TRANSLATE_C_URL}" "${TRANSLATE_C_ARCHIVE}"
TLS_VERIFY ON
EXPECTED_HASH SHA256=${HASH_SUM}
STATUS download_status
LOG download_log
)
list(GET download_status 0 dl_code)
if(NOT dl_code EQUAL 0)
message(FATAL_ERROR "Download failed:\n${download_log}")
endif()
message(STATUS "Extracting ${ARCHIVE_EXT} ...")
file(MAKE_DIRECTORY "${TRANSLATE_C_DIR}")
if(HOST_OS_LOWER MATCHES "windows|win")
execute_process(
COMMAND powershell -NoProfile -ExecutionPolicy Bypass
-Command "Expand-Archive -Path '${TRANSLATE_C_ARCHIVE}' -DestinationPath '${TRANSLATE_C_DIR}' -Force"
RESULT_VARIABLE extract_result
)
else()
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xf "${TRANSLATE_C_ARCHIVE}"
WORKING_DIRECTORY "${TRANSLATE_C_DIR}"
RESULT_VARIABLE extract_result
)
endif()
if(NOT extract_result EQUAL 0)
message(FATAL_ERROR "Extraction failed (code ${extract_result})")
endif()
file(REMOVE "${TRANSLATE_C_ARCHIVE}")
# Make executable on Unix
if(NOT HOST_OS_LOWER MATCHES "windows|win")
execute_process(
COMMAND chmod +x "${TRANSLATE_C_BIN}"
RESULT_VARIABLE chmod_result
)
if(NOT chmod_result EQUAL 0)
message(WARNING "Failed to set executable bit on translate_c-standalone")
endif()
endif()
message(STATUS "translate_c-standalone ready at: ${TRANSLATE_C_BIN}")
else()
message(STATUS "Using cached translate_c-standalone: ${TRANSLATE_C_BIN}")
endif()
set(BINDGEN "${TRANSLATE_C_BIN}/translate-c")
# ──────────────────────────────────────────────────────────────────────────────
# Helper to invoke translate-c (mirrors zig_run from zig-runner.cmake)
# ──────────────────────────────────────────────────────────────────────────────
function(bindgen_run)
cmake_parse_arguments(PARSE_ARGV 0 ARG
"VERBATIM;ALLOW_FAIL"
"WORKING_DIRECTORY;RESULT_VARIABLE;OUTPUT_VARIABLE;ERROR_VARIABLE;OUTPUT_FILE;TIMEOUT"
"COMMAND"
)
if(NOT ARG_COMMAND)
message(FATAL_ERROR "bindgen_run: COMMAND list is required")
endif()
if(NOT DEFINED ARG_WORKING_DIRECTORY)
set(ARG_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
if(NOT DEFINED ARG_TIMEOUT)
set(ARG_TIMEOUT 300)
endif()
set(extra_args)
if(ARG_VERBATIM)
list(APPEND extra_args VERBATIM)
endif()
if(ARG_OUTPUT_FILE)
list(APPEND extra_args OUTPUT_FILE "${ARG_OUTPUT_FILE}")
endif()
execute_process(
COMMAND "${BINDGEN}" ${ARG_COMMAND}
WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE error
TIMEOUT ${ARG_TIMEOUT}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
${extra_args}
)
if(DEFINED ARG_RESULT_VARIABLE)
set(${ARG_RESULT_VARIABLE} "${result}" PARENT_SCOPE)
endif()
if(DEFINED ARG_OUTPUT_VARIABLE)
set(${ARG_OUTPUT_VARIABLE} "${output}" PARENT_SCOPE)
endif()
if(DEFINED ARG_ERROR_VARIABLE)
set(${ARG_ERROR_VARIABLE} "${error}" PARENT_SCOPE)
endif()
if(NOT ARG_ALLOW_FAIL)
if(result MATCHES "timeout")
message(FATAL_ERROR
"translate-c timed out after ${ARG_TIMEOUT}s — Aro deadlock on stub headers (issue #61)\n"
" Command: ${BINDGEN} ${ARG_COMMAND}\n"
"--- stderr ---\n${error}")
elseif(NOT result EQUAL 0)
message(FATAL_ERROR
"translate-c failed (code ${result}):\n"
" ${BINDGEN} ${ARG_COMMAND}\n"
"--- stderr ---\n${error}")
endif()
endif()
endfunction()

View File

@@ -0,0 +1,32 @@
# ────────────────────────────────────────────────────────────────────────────────
# Helper for downloading / referencing esp-rs/esp-idf-sys bindings.h
#
# This file is part of a Zig + ESP-IDF project using translate-c.
# It downloads the official bindings.h mega-header from esp-rs/esp-idf-sys
# as a reference (helps when improving stubs.h or comparing generated bindings).
#
# Huge thanks to the esp-rs community for maintaining esp-idf-sys
# Repository: https://github.com/esp-rs/esp-idf-sys
# bindings.h: https://github.com/esp-rs/esp-idf-sys/blob/master/src/include/esp-idf/bindings.h
# ────────────────────────────────────────────────────────────────────────────────
set(BINDINGS_URL
"https://raw.githubusercontent.com/esp-rs/esp-idf-sys/refs/heads/master/src/include/esp-idf/bindings.h"
)
set(BINDINGS_ESP_RS "${CMAKE_SOURCE_DIR}/include/bindings.h")
if(NOT EXISTS "${BINDINGS_ESP_RS}")
file(DOWNLOAD ${BINDINGS_URL} ${BINDINGS_ESP_RS}
TLS_VERIFY ON
STATUS download_status
LOG download_log
TIMEOUT 15
)
list(GET download_status 0 status_code)
list(GET download_status 1 error_msg)
if(NOT status_code EQUAL 0)
message(FATAL_ERROR "Failed to download esp-idf/bindings.h\nStatus: ${status_code}\nError: ${error_msg}\nLog:\n${download_log}")
endif()
message(STATUS "Downloaded esp-idf/bindings.h => ${BINDINGS_ESP_RS}")
else()
message(STATUS "esp-idf/bindings.h already exists => ${BINDINGS_ESP_RS}")
endif()

View File

@@ -0,0 +1,124 @@
# ─── Optional/Managed Components Detection ───────────────────────────────────
idf_build_get_property(BUILD_COMPS BUILD_COMPONENTS)
# Get IDF_PATH from environment
set(IDF_PATH $ENV{IDF_PATH})
# Include version.cmake to get IDF_VERSION_MAJOR, IDF_VERSION_MINOR, etc.
if(EXISTS "${IDF_PATH}/tools/cmake/version.cmake")
include("${IDF_PATH}/tools/cmake/version.cmake")
else()
message(FATAL_ERROR "Failed to find version.cmake in ${IDF_PATH}/tools/cmake")
endif()
# Helper function to check and add component
macro(check_managed_component COMPONENT_NAME VENDOR PACKAGE DEFINE_NAME)
set(COMP_PATHS "")
set(COMP_BASE "${CMAKE_SOURCE_DIR}/managed_components/${VENDOR}__${PACKAGE}")
if("${PACKAGE}" STREQUAL "esp-dsp")
list(APPEND COMP_PATHS
"${COMP_BASE}/modules/common/include"
"${COMP_BASE}/modules/dotprod/include"
"${COMP_BASE}/modules/support/include"
"${COMP_BASE}/modules/support/mem/include"
"${COMP_BASE}/modules/windows/include"
"${COMP_BASE}/modules/windows/hann/include"
"${COMP_BASE}/modules/windows/blackman/include"
"${COMP_BASE}/modules/windows/blackman_harris/include"
"${COMP_BASE}/modules/windows/blackman_nuttall/include"
"${COMP_BASE}/modules/windows/nuttall/include"
"${COMP_BASE}/modules/windows/flat_top/include"
"${COMP_BASE}/modules/iir/include"
"${COMP_BASE}/modules/fir/include"
"${COMP_BASE}/modules/math/include"
"${COMP_BASE}/modules/math/add/include"
"${COMP_BASE}/modules/math/sub/include"
"${COMP_BASE}/modules/math/mul/include"
"${COMP_BASE}/modules/math/addc/include"
"${COMP_BASE}/modules/math/mulc/include"
"${COMP_BASE}/modules/math/sqrt/include"
"${COMP_BASE}/modules/matrix/include"
"${COMP_BASE}/modules/matrix/mul/include"
"${COMP_BASE}/modules/matrix/add/include"
"${COMP_BASE}/modules/matrix/addc/include"
"${COMP_BASE}/modules/matrix/mulc/include"
"${COMP_BASE}/modules/matrix/sub/include"
"${COMP_BASE}/modules/fft/include"
"${COMP_BASE}/modules/dct/include"
"${COMP_BASE}/modules/conv/include"
"${COMP_BASE}/modules/kalman/ekf/include"
"${COMP_BASE}/modules/kalman/ekf_imu13states/include"
)
elseif("${PACKAGE}" STREQUAL "esp_wifi_remote")
# Add base include if exists
set(BASE_INCLUDE "${COMP_BASE}/include")
if(EXISTS "${BASE_INCLUDE}")
list(APPEND COMP_PATHS "${BASE_INCLUDE}")
endif()
# Add version-specific include using MAJOR.MINOR
set(VERSION_SUBDIR "idf_v${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")
set(VERSION_PATH "${COMP_BASE}/${VERSION_SUBDIR}/include")
if(EXISTS "${VERSION_PATH}")
list(APPEND COMP_PATHS "${VERSION_PATH}")
endif()
elseif("${PACKAGE}" STREQUAL "esp_hosted")
# Add host and api include paths for esp_hosted
set(HOST_PATH "${COMP_BASE}/host")
if(EXISTS "${HOST_PATH}")
list(APPEND COMP_PATHS "${HOST_PATH}")
endif()
set(API_PATH "${HOST_PATH}/api/include")
if(EXISTS "${API_PATH}")
list(APPEND COMP_PATHS "${API_PATH}")
endif()
elseif("${PACKAGE}" STREQUAL "esp_matter")
# esp_matter is a C++ (CHIP SDK) library.
# matter_stubs.h provides the C interface for translate-c instead.
list(APPEND COMP_PATHS "${COMP_BASE}/components/esp_matter")
else()
list(APPEND COMP_PATHS "${COMP_BASE}/include")
endif()
# Check if component is in build
if("${VENDOR}__${PACKAGE}" IN_LIST BUILD_COMPS OR "${PACKAGE}" IN_LIST BUILD_COMPS)
# Verify at least one path exists (check the base directory)
if(EXISTS "${COMP_BASE}")
message(STATUS "${COMPONENT_NAME} component found")
set(${DEFINE_NAME} 1)
# Add all include paths that actually exist
set(VALID_PATHS 0)
foreach(COMP_PATH IN LISTS COMP_PATHS)
if(EXISTS "${COMP_PATH}")
list(APPEND INCLUDE_DIRS "${COMP_PATH}")
math(EXPR VALID_PATHS "${VALID_PATHS} + 1")
endif()
endforeach()
if(VALID_PATHS GREATER 0)
message(STATUS " Added ${VALID_PATHS} include paths for ${COMPONENT_NAME}")
else()
message(WARNING "${COMPONENT_NAME} base exists but no include paths found")
set(${DEFINE_NAME} 0)
endif()
else()
message(WARNING "${COMPONENT_NAME} in components but not found: ${COMP_BASE}")
set(${DEFINE_NAME} 0)
endif()
else()
message(STATUS "${COMPONENT_NAME} not in build. To add: idf.py add-dependency ${VENDOR}/${PACKAGE}")
set(${DEFINE_NAME} 0)
endif()
list(APPEND EXTRA_DEFINE_FLAGS "-D${DEFINE_NAME}=${${DEFINE_NAME}}")
endmacro()
# Add your components here
check_managed_component("LED Strip" "espressif" "led_strip" "HAS_LED_STRIP")
check_managed_component("ESP-DSP" "espressif" "esp-dsp" "HAS_ESP_DSP")
check_managed_component("ESP Wifi Remote" "espressif" "esp_wifi_remote" "HAS_ESP_WIFI_REMOTE")
check_managed_component("ESP Hosted" "espressif" "esp_hosted" "HAS_ESP_HOSTED")
check_managed_component("ESP Matter" "espressif" "esp_matter" "HAS_ESP_MATTER")

View File

@@ -0,0 +1,162 @@
# ============================================================================
# Zig Bindings Patcher
# Removes and replaces problematic structs/functions from ESP-IDF bindings
# ============================================================================
message(STATUS "Patching Zig bindings: ${TARGET_FILE}")
# ============================================================================
# Read file content
# ============================================================================
file(READ "${TARGET_FILE}" FILE_CONTENT)
# ============================================================================
# Determine WiFi support based on target
# ============================================================================
if(CONFIG_IDF_TARGET_ESP32P4 OR CONFIG_IDF_TARGET_ESP32H2 OR CONFIG_IDF_TARGET_ESP32H21 OR CONFIG_IDF_TARGET_ESP32H4)
set(WIFI_SUPPORTED FALSE)
else()
set(WIFI_SUPPORTED TRUE)
endif()
# ============================================================================
# Component status (passed from zig-config.cmake)
# ============================================================================
if(NOT DEFINED HAS_LED_STRIP)
set(HAS_LED_STRIP 0)
endif()
if(NOT DEFINED HAS_ESP_DSP)
set(HAS_ESP_DSP 0)
endif()
# message(STATUS "Component detection:")
# message(STATUS " HAS_LED_STRIP: ${HAS_LED_STRIP}")
# message(STATUS " HAS_ESP_DSP: ${HAS_ESP_DSP}")
# ============================================================================
# Remove problematic definitions
# ============================================================================
# WiFi patches (only for WiFi-enabled targets)
if(WIFI_SUPPORTED)
string(REGEX REPLACE "pub const wifi_sta_config_t[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const wifi_ap_config_t[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
endif()
# Remove portTICK_PERIOD_MS (will be replaced with custom version)
string(REGEX REPLACE "pub const portTICK_PERIOD_MS[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
# ============================================================================
# Handle bitfield-related opaque types and unions
# ============================================================================
string(REGEX REPLACE "(//[^\n]*\n?)*const struct_unnamed_[0-9]+ = opaque {};( //[^\n]*\n?)*" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "(//[^\n]*\n?)*const union_unnamed_[0-9]+ = extern union \\{\n unnamed_0: struct_unnamed_[0-9]+,\n val: u32,\n\\};( //[^\n]*\n?)*" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "unnamed_0: struct_unnamed_[0-9]+,\n?" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "([a-zA-Z0-9_]+): ((\[[0-9]+\])?)(struct|union)_unnamed_[0-9]+" "\\1: \\2u32" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "zeroes\\((struct|union)_unnamed_[0-9]+\\)" "zeroes(u32)" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "zeroes\\((\\[[0-9]+\\])(struct|union)_unnamed_[0-9]+\\)" "zeroes(\\1u32)" FILE_CONTENT "${FILE_CONTENT}")
# ============================================================================
# Fix peripheral register structs (lp_*, gpio_dev_t, i2c_dev_t, etc.)
# ============================================================================
# 1. Aggressively remove ALL gpio_dev_t and lp_* declarations (including opaque and aliases)
string(REGEX REPLACE "pub const (struct_)?gpio_dev_t = [^;]+;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const (struct_)?lp_[a-z0-9_]*_dev_t = [^;]+;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const (struct_)?i2c_dev_t = [^;]+;" "" FILE_CONTENT "${FILE_CONTENT}")
# 2. Also remove any remaining aliases that point to struct_ versions
string(REGEX REPLACE "pub const (lp_[a-z0-9_]+_dev_t|gpio_dev_t|i2c_dev_t) = struct_[^;]+;" "" FILE_CONTENT "${FILE_CONTENT}")
# 3. Append clean definitions with correct sizes
string(APPEND FILE_CONTENT "
pub const lp_io_dev_t = extern struct { reserved: [1024]u8 };
pub const lp_clkrst_dev_t = extern struct { reserved: [1024]u8 };
pub const lp_i2c_dev_t = extern struct { reserved: [0x184]u8 };
pub const lp_timer_dev_t = extern struct { reserved: [1024]u8 };
pub const lp_uart_dev_t = extern struct { reserved: [0xa0]u8 };
pub const lp_wdt_dev_t = extern struct { reserved: [1024]u8 };
pub const lp_io_mux_dev_t = extern struct { reserved: [512]u8 };
pub const lp_iomux_dev_t = extern struct { reserved: [84]u8 };
pub const lp_aonclkrst_dev_t = extern struct { reserved: [1024]u8 };
pub const i2c_dev_t = extern struct { reserved: [388]u8 };
")
# 4. Add gpio_dev_t with target-specific size (this must come AFTER the general remove)
if(CONFIG_IDF_TARGET_ESP32C61 OR CONFIG_IDF_TARGET_ESP32C5 OR CONFIG_IDF_TARGET_ESP32H4)
string(APPEND FILE_CONTENT "\npub const gpio_dev_t = extern struct { reserved: [3584]u8 };")
elseif(CONFIG_IDF_TARGET_ESP32P4)
string(APPEND FILE_CONTENT "\npub const gpio_dev_t = extern struct { reserved: [2048]u8 };")
elseif(CONFIG_IDF_TARGET_ESP32C2 OR CONFIG_IDF_TARGET_ESP32C6 OR CONFIG_IDF_TARGET_ESP32H2)
string(APPEND FILE_CONTENT "\npub const gpio_dev_t = extern struct { reserved: [1792]u8 };")
else()
# Fallback
endif()
if(CONFIG_IDF_TARGET_ESP32P4)
string(APPEND FILE_CONTENT "\npub const lp_gpio_dev_t = extern struct { reserved: [308]u8 };")
else()
string(APPEND FILE_CONTENT "\npub const lp_gpio_dev_t = extern struct { reserved: [1024]u8 };")
endif()
# ESP32-P4 specific: Remove xPortCanYield function
if(CONFIG_IDF_TARGET_ESP32P4)
string(REGEX REPLACE "pub fn xPortCanYield\\([^)]*\\) callconv\\(\\.c\\) bool \\{([^{}]|\\{[^{}]*\\})*\\}" "" FILE_CONTENT "${FILE_CONTENT}")
endif()
# LED Strip component patches (if enabled)
if(HAS_LED_STRIP EQUAL 1)
message(STATUS " Applying LED Strip patches")
string(REGEX REPLACE "pub const struct_led_strip_rmt_extra_config_20[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const struct_format_layout_15[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const led_strip_rmt_config_t[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const led_color_component_format_t[^;]*;" "" FILE_CONTENT "${FILE_CONTENT}")
string(REGEX REPLACE "pub const led_strip_config_t = extern struct \\{[^}]*\\};" "" FILE_CONTENT "${FILE_CONTENT}")
endif()
# ============================================================================
# Append custom patch files
# ============================================================================
set(PATCH_DIR "${CMAKE_SOURCE_DIR}/../../../patches")
# Define patches to apply
set(PATCH_FILES
"porttick_period_ms.zig"
)
# Add target-specific patches
if(CONFIG_IDF_TARGET_ESP32P4)
list(APPEND PATCH_FILES "xport_can_yield.zig")
endif()
# Add WiFi patches
if(WIFI_SUPPORTED)
list(APPEND PATCH_FILES
"wifi/wifi_sta_config_t.zig"
"wifi/wifi_ap_config_t.zig"
)
endif()
# Add LED Strip patches
if(HAS_LED_STRIP EQUAL 1)
list(APPEND PATCH_FILES
"led_strip/led_strip_rmt_extra_config_20.zig"
"led_strip/led_strip_struct_format_layout_15.zig"
"led_strip/led_color_component_format_t.zig"
"led_strip/led_strip_rmt_config_t.zig"
"led_strip/led_strip_config_t.zig"
)
endif()
# Apply each patch file
foreach(PATCH_FILE IN LISTS PATCH_FILES)
set(PATCH_PATH "${PATCH_DIR}/${PATCH_FILE}")
if(EXISTS "${PATCH_PATH}")
message(STATUS " Applying patch: ${PATCH_FILE}")
file(READ "${PATCH_PATH}" PATCH_CONTENT)
string(APPEND FILE_CONTENT "\n${PATCH_CONTENT}")
else()
message(WARNING " Patch file not found: ${PATCH_FILE}")
endif()
endforeach()
# ============================================================================
# Write patched content
# ============================================================================
file(WRITE "${TARGET_FILE}" "${FILE_CONTENT}")
message(STATUS "Patching completed: ${TARGET_FILE}")

View File

@@ -0,0 +1,488 @@
# ──────────────────────────────────────────────────────────────────────────────
# Zig configuration for ESP-IDF (esp32 xtensa/riscv targets)
# ──────────────────────────────────────────────────────────────────────────────
set(ZIG_MIN_VERSION "0.16.0")
# ─── Host platform & architecture detection ──────────────────────────────────
cmake_host_system_information(RESULT HOST_OS QUERY OS_NAME)
string(TOLOWER "${HOST_OS}" HOST_OS_LOWER)
set(HOST_ARCH "${CMAKE_HOST_SYSTEM_PROCESSOR}")
# Normalize to Zig-style triple names
if(HOST_ARCH MATCHES "^(AMD64|amd64|x86_64|X64)$")
set(ZIG_ARCH "x86_64")
elseif(HOST_ARCH MATCHES "^(aarch64|arm64|ARM64)$")
set(ZIG_ARCH "aarch64")
elseif(HOST_ARCH MATCHES "^(x86|i686|i386|i[345]86)$")
set(ZIG_ARCH "x86")
else()
message(FATAL_ERROR "Unsupported host architecture '${HOST_ARCH}'.\n"
"Please report:\n"
" CMAKE_HOST_SYSTEM_PROCESSOR = ${CMAKE_HOST_SYSTEM_PROCESSOR}\n"
" cmake --system-information | findstr PROCESSOR")
endif()
# Platform + extension
if(HOST_OS_LOWER MATCHES "(linux|unix)")
set(ZIG_PLATFORM "linux-musl")
set(ARCHIVE_EXT "tar.xz")
elseif(HOST_OS_LOWER MATCHES "windows|win")
set(ZIG_PLATFORM "windows")
set(ARCHIVE_EXT "zip")
elseif(HOST_OS_LOWER MATCHES "darwin|mac|osx")
set(ZIG_PLATFORM "macos")
set(ARCHIVE_EXT "tar.xz")
else()
message(FATAL_ERROR "Unsupported host OS: ${HOST_OS}")
endif()
set(ZIG_TRIPLET "${ZIG_ARCH}-${ZIG_PLATFORM}-baseline")
set(ZIG_DIR "${CMAKE_BINARY_DIR}/zig-relsafe-${ZIG_TRIPLET}")
set(ZIG_ARCHIVE "${ZIG_DIR}.${ARCHIVE_EXT}")
# ─── Decide which zig to use ─────────────────────────────────────────────────
find_program(ZIG_FOUND zig)
set(USE_ZIG_ESPRESSIF_BOOTSTRAP TRUE)
if(ZIG_FOUND AND CONFIG_IDF_TARGET_ARCH_RISCV)
# For most RISC-V prefer system zig (except P4 & H4)
if(NOT (CONFIG_IDF_TARGET_ESP32P4 OR CONFIG_IDF_TARGET_ESP32H4))
set(USE_ZIG_ESPRESSIF_BOOTSTRAP FALSE)
endif()
endif()
# ─── Download & extract espressif zig if needed ──────────────────────────────
if(USE_ZIG_ESPRESSIF_BOOTSTRAP)
include(${CMAKE_SOURCE_DIR}/cmake/zig-download.cmake)
else()
if(NOT ZIG_FOUND)
message(FATAL_ERROR "System 'zig' not found and espressif bootstrap is disabled.")
endif()
set(ZIG_BIN "${ZIG_FOUND}")
endif()
message(STATUS "Using Zig executable: ${ZIG_BIN}")
# ────────────────────────────────────────────────────────────────────────────────────
include(${CMAKE_SOURCE_DIR}/cmake/zig-runner.cmake)
# ─────── get Zig version ────────────────────────────────────────────────────────────
zig_run(COMMAND version OUTPUT_VARIABLE ZIG_VERSION)
if("${ZIG_VERSION}" VERSION_LESS "${ZIG_MIN_VERSION}")
message(FATAL_ERROR "Zig version too old: ${ZIG_VERSION} < ${ZIG_MIN_VERSION}")
endif()
message(STATUS "Zig version: ${ZIG_VERSION}")
# Detect whether this Zig build is the Espressif fork (has named ESP32 RISC-V CPU models).
# Upstream Zig only ships generic RISC-V models; the fork adds esp32c3, esp32c6, etc.
zig_run(
COMMAND build-obj --show-builtin -target riscv32-freestanding -mcpu=esp32c3
RESULT_VARIABLE _zig_esp_riscv_probe
OUTPUT_VARIABLE _zig_esp_riscv_probe_out
ERROR_VARIABLE _zig_esp_riscv_probe_err
ALLOW_FAIL
)
if(_zig_esp_riscv_probe EQUAL 0)
set(ZIG_HAS_ESP_RISCV_MODELS ON)
message(STATUS "Zig RISC-V: Espressif fork detected — using named ESP CPU models")
else()
set(ZIG_HAS_ESP_RISCV_MODELS OFF)
message(STATUS "Zig RISC-V: upstream Zig detected — falling back to generic_rv32 models")
endif()
# ====================================================================================
# Determine target model from CONFIG_IDF_TARGET
string(TOLOWER "${CONFIG_IDF_TARGET}" TARGET_IDF_MODEL)
# Target architecture configuration lookup table
set(RISCV_TARGETS
"esp32c2" "esp32c3" "esp32c5" "esp32c6" "esp32c61" "esp32c61eco0"
"esp32h2" "esp32h21" "esp32h4" "esp32p4" "esp32p4eco4" "esp32s31")
set(XTENSA_TARGETS
"esp32" "esp32s2" "esp32s3")
if(TARGET_IDF_MODEL IN_LIST RISCV_TARGETS)
set(TARGET_IDF_ARCH "riscv")
# MACF group (FPU): use eabihf ABI. All others use none.
set(_rv_macf_targets "esp32h4" "esp32s31" "esp32p4" "esp32p4eco4")
if(TARGET_IDF_MODEL IN_LIST _rv_macf_targets)
set(ZIG_TARGET "riscv32-freestanding-eabihf")
else()
set(ZIG_TARGET "riscv32-freestanding-none")
endif()
if(ZIG_HAS_ESP_RISCV_MODELS)
# Espressif Zig fork: use named CPU model (feature set is already encoded in model).
set(TARGET_CPU_MODEL "${TARGET_IDF_MODEL}")
else()
# Upstream Zig: fall back to generic_rv32 with explicit feature sets.
# MC (c2, c3): m+c+zicsr+zifencei abi=none
# MAC (c5, c6, c61, h2, h21): m+a+c+zicsr+zifencei abi=none
# MACF (h4, s31, p4, p4eco4): m+a+c+f+zicsr+zifencei abi=eabihf
set(_rv_mc_targets "esp32c2" "esp32c3")
set(_rv_mac_targets "esp32c5" "esp32c6" "esp32c61" "esp32c61eco0" "esp32h2" "esp32h21")
if(TARGET_IDF_MODEL IN_LIST _rv_mc_targets)
set(TARGET_CPU_MODEL "generic_rv32+m+c+zicsr+zifencei")
elseif(TARGET_IDF_MODEL IN_LIST _rv_mac_targets)
set(TARGET_CPU_MODEL "generic_rv32+m+a+c+zicsr+zifencei")
elseif(TARGET_IDF_MODEL IN_LIST _rv_macf_targets)
set(TARGET_CPU_MODEL "generic_rv32+m+a+c+f+zicsr+zifencei")
else()
set(TARGET_CPU_MODEL "generic_rv32+m+c+zicsr+zifencei")
endif()
endif()
elseif(TARGET_IDF_MODEL IN_LIST XTENSA_TARGETS)
set(TARGET_IDF_ARCH "xtensa")
set(ZIG_TARGET "xtensa-freestanding-none")
set(TARGET_CPU_MODEL "${TARGET_IDF_MODEL}")
else()
message(FATAL_ERROR "Unsupported IDF target: ${CONFIG_IDF_TARGET}")
endif()
message(STATUS "ESP-IDF Target: ${TARGET_IDF_MODEL}")
message(STATUS "Architecture: ${TARGET_IDF_ARCH}")
message(STATUS "Zig Target: ${ZIG_TARGET}")
message(STATUS "CPU Model: ${TARGET_CPU_MODEL}")
# Check Toolchain version
get_filename_component(TOOLCHAIN_BIN_DIR "${CMAKE_C_COMPILER}" DIRECTORY)
get_filename_component(TOOLCHAIN_VERSION_DIR "${TOOLCHAIN_BIN_DIR}" DIRECTORY)
if("${TOOLCHAIN_VERSION_DIR}" MATCHES "esp-([0-9]+\\.[0-9]+\\.[0-9]+_[0-9]+)")
set(TOOLCHAIN_VERSION "${CMAKE_MATCH_1}")
message(STATUS "Detected ESP toolchain version: ${TOOLCHAIN_VERSION}")
else()
message(WARNING "Standard ESP version pattern not found in: ${TOOLCHAIN_VERSION_DIR}")
endif()
if(CONFIG_IDF_TARGET_ARCH_RISCV)
set(ARCH "riscv")
set(TRIPLE "riscv32-esp-elf")
set(ARCH_DEFINE "__riscv")
elseif(CONFIG_IDF_TARGET_ARCH_XTENSA)
set(ARCH "xtensa")
set(TRIPLE "xtensa-esp-elf")
set(ARCH_DEFINE "__XTENSA__")
endif()
# Get toolchain includes with fallback paths
set(POSSIBLE_INCLUDE_PATHS
"${TOOLCHAIN_VERSION_DIR}/${TRIPLE}/include"
"${TOOLCHAIN_BIN_DIR}/../${TRIPLE}/include"
"${TOOLCHAIN_VERSION_DIR}/${TRIPLE}/${TRIPLE}/include"
)
# Find the toolchain include directory
set(TOOLCHAIN_ELF_INCLUDE "")
foreach(PATH ${POSSIBLE_INCLUDE_PATHS})
if(IS_DIRECTORY "${PATH}")
set(TOOLCHAIN_ELF_INCLUDE "${PATH}")
message(STATUS "Found toolchain include at: ${TOOLCHAIN_ELF_INCLUDE}")
break()
endif()
endforeach()
# sys-include should be sys-include directory OR the same as regular include
# (since sys headers are typically under include/sys/)
set(POSSIBLE_SYS_INCLUDE_PATHS
"${TOOLCHAIN_VERSION_DIR}/${TRIPLE}/sys-include"
"${TOOLCHAIN_BIN_DIR}/../${TRIPLE}/sys-include"
"${TOOLCHAIN_VERSION_DIR}/${TRIPLE}/${TRIPLE}/sys-include"
"${TOOLCHAIN_VERSION_DIR}/${TRIPLE}/${TRIPLE}/include"
"${TOOLCHAIN_ELF_INCLUDE}"
)
# Find the first existing sys-include directory
set(TOOLCHAIN_SYS_INCLUDE "")
foreach(PATH ${POSSIBLE_SYS_INCLUDE_PATHS})
if(IS_DIRECTORY "${PATH}")
set(TOOLCHAIN_SYS_INCLUDE "${PATH}")
message(STATUS "Found sys-include at: ${TOOLCHAIN_SYS_INCLUDE}")
break()
endif()
endforeach()
if(NOT IS_DIRECTORY "${TOOLCHAIN_ELF_INCLUDE}")
message(WARNING "Toolchain include directory not found: ${TOOLCHAIN_ELF_INCLUDE}")
endif()
if(NOT IS_DIRECTORY "${TOOLCHAIN_SYS_INCLUDE}")
message(WARNING "Toolchain sys-include directory not found: ${TOOLCHAIN_SYS_INCLUDE}")
endif()
# components list
set(INCLUDE_DIRS
# Wrapper dir MUST come first — redirects "freertos/portmacro.h" through a
# single canonical path to fix Windows mixed-separator #pragma once failure.
# See include/freertos-compat/freertos/portmacro.h for details (issue #50).
"${CMAKE_SOURCE_DIR}/include/freertos-compat"
"${IDF_PATH}/components/freertos/FreeRTOS-Kernel-SMP/portable/${ARCH}/include/freertos"
"${IDF_PATH}/components/freertos/FreeRTOS-Kernel/include"
"${IDF_PATH}/components/freertos/config/include"
"${IDF_PATH}/components/freertos/config/include/freertos"
"${IDF_PATH}/components/freertos/esp_additions/include"
"${IDF_PATH}/components/freertos/config/${ARCH}/include"
"${IDF_PATH}/components/esp_hw_support/include"
"${IDF_PATH}/components/soc/include"
"${IDF_PATH}/components/soc/${TARGET_IDF_MODEL}/include"
"${IDF_PATH}/components/esp_common/include"
"${IDF_PATH}/components/hal/include"
"${IDF_PATH}/components/bootloader_support/include"
"${IDF_PATH}/components/${ARCH}/include"
"${IDF_PATH}/components/bt/include/${TARGET_IDF_MODEL}/include"
"${IDF_PATH}/components/bt/host/nimble/nimble/nimble/include"
"${IDF_PATH}/components/bt/host/bluedroid/api/include"
"${IDF_PATH}/components/bt/host/bluedroid/api/include/api"
"${IDF_PATH}/components/${ARCH}/${TARGET_IDF_MODEL}/include"
"${IDF_PATH}/components/${ARCH}/${TARGET_IDF_MODEL}/include/${ARCH}"
"${IDF_PATH}/components/${ARCH}/${TARGET_IDF_MODEL}/include/${ARCH}/config"
"${IDF_PATH}/components/${ARCH}/${TARGET_IDF_MODEL}/include/${ARCH}/core"
"${IDF_PATH}/components/soc/${TARGET_IDF_MODEL}/register"
"${IDF_PATH}/components/esp_system/include"
"${IDF_PATH}/components/esp_hw_support/etm/include"
"${IDF_PATH}/components/esp_hw_support/ldo/include"
"${IDF_PATH}/components/esp_hal_ana_cmpr/include"
"${IDF_PATH}/components/esp_hal_ana_conv/include"
"${IDF_PATH}/components/esp_hal_cam/include"
"${IDF_PATH}/components/esp_hal_dma/include"
"${IDF_PATH}/components/esp_hal_gpio/include"
"${IDF_PATH}/components/esp_hal_gpio/${TARGET_IDF_MODEL}/include"
"${IDF_PATH}/components/esp_hal_gpspi/include"
"${IDF_PATH}/components/esp_hal_i2c/include"
"${IDF_PATH}/components/esp_hal_i2s/include"
"${IDF_PATH}/components/esp_hal_lcd/include"
"${IDF_PATH}/components/esp_hal_ledc/include"
"${IDF_PATH}/components/esp_hal_mcpwm/include"
"${IDF_PATH}/components/esp_hal_mspi/include"
"${IDF_PATH}/components/esp_hal_parlio/include"
"${IDF_PATH}/components/esp_hal_pcnt/include"
"${IDF_PATH}/components/esp_hal_ppa/include"
"${IDF_PATH}/components/esp_hal_rmt/include"
"${IDF_PATH}/components/esp_hal_timg/include"
"${IDF_PATH}/components/esp_hal_touch_sens/include"
"${IDF_PATH}/components/esp_hal_twai/include"
"${IDF_PATH}/components/esp_hal_uart/include"
"${IDF_PATH}/components/esp_hal_usb/include"
"${IDF_PATH}/components/esp_hal_wdt/include"
"${IDF_PATH}/components/esp_driver_ana_cmpr/include"
"${IDF_PATH}/components/esp_driver_bitscrambler/include"
"${IDF_PATH}/components/esp_driver_cam/include"
"${IDF_PATH}/components/esp_driver_dac/include"
"${IDF_PATH}/components/esp_driver_gpio/include"
"${IDF_PATH}/components/esp_driver_gptimer/include"
"${IDF_PATH}/components/esp_driver_i2c/include"
"${IDF_PATH}/components/esp_driver_i2s/include"
"${IDF_PATH}/components/esp_driver_i3c/include"
"${IDF_PATH}/components/esp_driver_isp/include"
"${IDF_PATH}/components/esp_driver_jpeg/include"
"${IDF_PATH}/components/esp_driver_ledc/include"
"${IDF_PATH}/components/esp_driver_mcpwm/include"
"${IDF_PATH}/components/esp_driver_parlio/include"
"${IDF_PATH}/components/esp_driver_pcnt/include"
"${IDF_PATH}/components/esp_driver_ppa/include"
"${IDF_PATH}/components/esp_driver_rmt/include"
"${IDF_PATH}/components/esp_driver_sd_intf/include"
"${IDF_PATH}/components/esp_driver_sdio/include"
"${IDF_PATH}/components/esp_driver_sdm/include"
"${IDF_PATH}/components/esp_driver_sdmmc/include"
"${IDF_PATH}/components/esp_driver_sdspi/include"
"${IDF_PATH}/components/esp_driver_spi/include"
"${IDF_PATH}/components/esp_driver_touch_sens/include"
"${IDF_PATH}/components/esp_driver_tsens/include"
"${IDF_PATH}/components/esp_driver_twai/include"
"${IDF_PATH}/components/esp_driver_uart/include"
"${IDF_PATH}/components/esp_driver_usb_serial_jtag/include"
"${IDF_PATH}/components/esp_phy/include"
"${IDF_PATH}/components/esp_tee/include"
"${IDF_PATH}/components/esp_timer/include"
"${IDF_PATH}/components/esp_coex/include"
"${IDF_PATH}/components/esp_psram/include"
"${IDF_PATH}/components/esp_security/include"
"${IDF_PATH}/components/esp_trace/include"
"${IDF_PATH}/components/esp_blockdev/include"
"${IDF_PATH}/components/pthread/include"
"${IDF_PATH}/components/hal/platform_port/include"
"${IDF_PATH}/components/heap/include"
"${IDF_PATH}/components/ieee802154/include"
"${IDF_PATH}/components/openthread/include"
"${IDF_PATH}/components/openthread/openthread/third_party/mbedtls/repo/include"
"${IDF_PATH}/components/esp_rom/${TARGET_IDF_MODEL}/include/${TARGET_IDF_MODEL}"
"${IDF_PATH}/components/esp_rom/include"
"${IDF_PATH}/components/esp_wifi/include"
"${IDF_PATH}/components/esp_bootloader_format/include"
"${IDF_PATH}/components/esp_app_format/include"
"${IDF_PATH}/components/esp_pm/include"
"${IDF_PATH}/components/esp_lcd/include"
"${IDF_PATH}/components/esp_lcd/interface"
"${IDF_PATH}/components/esp_lcd/dsi/include"
"${IDF_PATH}/components/esp_lcd/rgb/include"
"${IDF_PATH}/components/mbedtls/mbedtls/tf-psa-crypto/drivers/builtin/include"
"${IDF_PATH}/components/mbedtls/mbedtls/tf-psa-crypto/include"
"${IDF_PATH}/components/mbedtls/esp_crt_bundle/include"
"${IDF_PATH}/components/mbedtls/port/include"
"${IDF_PATH}/components/mbedtls/mbedtls/include"
"${IDF_PATH}/components/http_parser"
"${IDF_PATH}/components/esp-tls"
"${IDF_PATH}/components/esp_https_ota/include"
"${IDF_PATH}/components/esp_http_server/include"
"${IDF_PATH}/components/esp_https_server/include"
"${IDF_PATH}/components/esp_http_client/include"
"${IDF_PATH}/components/log/include"
"${IDF_PATH}/components/vfs/include"
"${IDF_PATH}/components/wpa_supplicant/esp_supplicant/include"
"${IDF_PATH}/components/nvs_flash/include"
"${IDF_PATH}/components/esp_partition/include"
"${IDF_PATH}/components/esp_netif/include"
"${IDF_PATH}/components/esp_event/include"
"${IDF_PATH}/components/driver/i2c/include"
"${IDF_PATH}/components/driver/deprecated"
"${IDF_PATH}/components/driver/touch_sensor/${TARGET_IDF_MODEL}/include"
"${IDF_PATH}/components/driver/touch_sensor/include"
"${IDF_PATH}/components/driver/twai/include"
"${IDF_PATH}/components/spi_flash/include"
"${IDF_PATH}/components/esp_vfs_console/include"
"${IDF_PATH}/components/esp_ringbuf/include"
"${IDF_PATH}/components/esp_usb_cdc_rom_console/include"
"${CMAKE_SOURCE_DIR}/build/config"
)
# Toolchain system includes (separate from regular includes)
set(SYSTEM_INCLUDE_DIRS
"${TOOLCHAIN_SYS_INCLUDE}"
"${TOOLCHAIN_ELF_INCLUDE}"
"${IDF_PATH}/components/newlib"
"${IDF_PATH}/components/newlib/platform_include"
"${IDF_PATH}/components/esp_libc/platform_include"
"${IDF_PATH}/components/lwip/lwip/src/include"
"${IDF_PATH}/components/lwip/port/esp32xx/include"
"${IDF_PATH}/components/lwip/port/freertos/include"
"${IDF_PATH}/components/lwip/port/include"
"${IDF_PATH}/components/lwip/include"
"${IDF_PATH}/components/lwip/include/apps"
)
if(CONFIG_IDF_TARGET_ESP32P4)
list(APPEND INCLUDE_DIRS "${IDF_PATH}/components/soc/${TARGET_IDF_MODEL}/register/hw_ver3")
elseif(CONFIG_IDF_TARGET_ESP32H4)
list(APPEND INCLUDE_DIRS "${IDF_PATH}/components/soc/${TARGET_IDF_MODEL}/register/hw_ver_mp")
endif()
# get esp-idf C Macros
idf_build_get_property(all_defines COMPILE_DEFINITIONS)
set(EXTRA_DEFINE_FLAGS "")
foreach(def ${all_defines})
string(STRIP "${def}" def_clean)
if(NOT def_clean STREQUAL "")
if(NOT def_clean MATCHES "^-D")
list(APPEND EXTRA_DEFINE_FLAGS "-D${def_clean}")
else()
list(APPEND EXTRA_DEFINE_FLAGS "${def_clean}")
endif()
endif()
endforeach()
string(TOUPPER "${TARGET_IDF_ARCH}" TARGET_IDF_ARCH_UPPER)
string(TOUPPER "${TARGET_IDF_MODEL}" TARGET_IDF_MODEL_UPPER)
set(DEFINE_FLAGS
"-D__${TARGET_IDF_ARCH}"
"-Dcpu_${TARGET_CPU_MODEL}"
"-D${ARCH_DEFINE}"
"-D__${TARGET_IDF_ARCH_UPPER}_EL__"
"-DCONFIG_IDF_TARGET_${TARGET_IDF_MODEL_UPPER}"
"-D__COUNTER__=0"
"-DIRAM_ATTR="
"-D_SECTION_ATTR_IMPL\\(x,y\\)="
"-DSOC_MMU_PAGE_SIZE=0x8000"
"-DLWIP_NO_UNISTD_H="
)
string(JOIN " " DEFINE_FLAGS_STR ${DEFINE_FLAGS})
if(ARCH_DEFINE)
set(DEFINE_FLAGS "${DEFINE_FLAGS} -D${ARCH_DEFINE}")
endif()
set(IDF_SYS_ZIG "${CMAKE_SOURCE_DIR}/imports/idf-sys.zig")
set(IDF_SYS_C "${CMAKE_SOURCE_DIR}/include/stubs.h")
# get esp-rs bindings.h
include(${CMAKE_SOURCE_DIR}/cmake/bindings.cmake)
# add extra-components
include(${CMAKE_SOURCE_DIR}/cmake/extra-components.cmake)
set(INCLUDE_FLAGS "")
foreach(dir ${INCLUDE_DIRS})
# Normalize to forward slashes (prevents Windows mixed-separator double-include in translate-c)
file(TO_CMAKE_PATH "${dir}" dir)
set(INCLUDE_FLAGS "${INCLUDE_FLAGS} -I\"${dir}\"")
endforeach()
# Build system include flags (for toolchain)
foreach(dir ${SYSTEM_INCLUDE_DIRS})
file(TO_CMAKE_PATH "${dir}" dir)
set(INCLUDE_FLAGS "${INCLUDE_FLAGS} -isystem \"${dir}\"")
endforeach()
if(NOT WIN32)
separate_arguments(INCLUDE_FLAGS UNIX_COMMAND "${INCLUDE_FLAGS}")
else()
separate_arguments(INCLUDE_FLAGS WINDOWS_COMMAND "${INCLUDE_FLAGS}")
endif()
# Run `translate-c` to generate `idf-sys.zig`
include(${CMAKE_SOURCE_DIR}/cmake/bindgen-standalone.cmake)
bindgen_run(
COMMAND
${IDF_SYS_C} -target ${ZIG_TARGET} -mcpu ${TARGET_CPU_MODEL}
${DEFINE_FLAGS} ${EXTRA_DEFINE_FLAGS} ${INCLUDE_FLAGS}
OUTPUT_FILE ${IDF_SYS_ZIG}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/imports
DEPENDS ${IDF_SYS_C}
)
set(PATCHES_DONE "${CMAKE_BINARY_DIR}/patches_applied.done")
add_custom_command(
OUTPUT "${PATCHES_DONE}"
COMMAND ${CMAKE_COMMAND}
-D TARGET_FILE=${IDF_SYS_ZIG}
-D CONFIG_IDF_TARGET_ESP32H2=${CONFIG_IDF_TARGET_ESP32H2}
-D CONFIG_IDF_TARGET_ESP32H21=${CONFIG_IDF_TARGET_ESP32H21}
-D CONFIG_IDF_TARGET_ESP32H4=${CONFIG_IDF_TARGET_ESP32H4}
-D CONFIG_IDF_TARGET_ESP32P4=${CONFIG_IDF_TARGET_ESP32P4}
-D CONFIG_IDF_TARGET_ESP32C2=${CONFIG_IDF_TARGET_ESP32C2}
-D CONFIG_IDF_TARGET_ESP32C5=${CONFIG_IDF_TARGET_ESP32C5}
-D CONFIG_IDF_TARGET_ESP32C6=${CONFIG_IDF_TARGET_ESP32C6}
-D CONFIG_IDF_TARGET_ESP32C61=${CONFIG_IDF_TARGET_ESP32C61}
-D HAS_LED_STRIP=${HAS_LED_STRIP}
-D HAS_ESP_DSP=${HAS_ESP_DSP}
-P ${CMAKE_SOURCE_DIR}/cmake/patch.cmake
COMMAND ${CMAKE_COMMAND} -E touch "${PATCHES_DONE}"
DEPENDS "${IDF_SYS_ZIG}"
COMMENT "Patching idf-sys.zig"
VERBATIM
)
add_custom_target(translate_c ALL DEPENDS "${PATCHES_DONE}")
message(STATUS "IDF_SYS_ZIG is set to: ${IDF_SYS_ZIG}")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(ZIG_BUILD_TYPE "Debug")
else()
set(ZIG_BUILD_TYPE "ReleaseSafe")
endif()
add_custom_target(zig_build
${ZIG_BIN} build
--build-file ${CMAKE_SOURCE_DIR}/build.zig
-Doptimize=${ZIG_BUILD_TYPE}
-Dtarget=${ZIG_TARGET}
-Dcpu=${TARGET_CPU_MODEL}
${ZIG_EXAMPLE_ARG}
-freference-trace
--cache-dir ${CMAKE_BINARY_DIR}/../.zig-cache
--prefix ${CMAKE_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
BYPRODUCTS ${CMAKE_BINARY_DIR}/obj/app_zig.o
VERBATIM)
add_dependencies(zig_build translate_c)
add_dependencies(${COMPONENT_LIB} zig_build)
target_sources(${COMPONENT_LIB}
PRIVATE
${CMAKE_BINARY_DIR}/obj/app_zig.o
)

View File

@@ -0,0 +1,58 @@
if(NOT EXISTS "${ZIG_DIR}/zig")
if(ZIG_PLATFORM STREQUAL "linux-musl")
if(ZIG_ARCH STREQUAL "aarch64")
set(HASH_SUM "d3e4930bbac053b40860290cdec2ad1e052418172aa452e590b242c081a01f94")
elseif(ZIG_ARCH STREQUAL "x86_64")
set(HASH_SUM "411f1858a9610803af28cd271acf4548873545ccc866f4b9060903ff0d4b6e8e")
else()
message(FATAL_ERROR "Unsupported architecture: ${ZIG_ARCH}")
endif()
elseif(ZIG_PLATFORM STREQUAL "windows")
if(ZIG_ARCH STREQUAL "x86_64")
set(HASH_SUM "4d5b66d857e790d068e408e6bdd0054f9e78ca2d0ab96b5ce25f63a125f1701e")
else()
message(FATAL_ERROR "Unsupported architecture: ${ZIG_ARCH}")
endif()
elseif(ZIG_PLATFORM STREQUAL "macos")
if(ZIG_ARCH STREQUAL "aarch64")
set(HASH_SUM "f47ac7927ae44f3b8290aa818d3158b0f9adc12742e03b7496ad440b6d89d38e")
else()
message(FATAL_ERROR "Unsupported architecture: ${ZIG_ARCH}")
endif()
endif()
set(ZIG_URL "https://github.com/kassane/zig-espressif-bootstrap/releases/download/0.16.0-xtensa/zig-relsafe-${ZIG_TRIPLET}.${ARCHIVE_EXT}")
message(STATUS "Downloading Zig (espressif variant):")
message(STATUS " => ${ZIG_ARCHIVE}")
file(DOWNLOAD "${ZIG_URL}" "${ZIG_ARCHIVE}"
TLS_VERIFY ON
EXPECTED_HASH SHA256=${HASH_SUM}
STATUS download_status
LOG download_log
# SHOW_PROGRESS
)
list(GET download_status 0 dl_code)
if(NOT dl_code EQUAL 0)
message(FATAL_ERROR "Download failed:\n${download_log}")
endif()
message(STATUS "Extracting ${ARCHIVE_EXT} ...")
if(HOST_OS_LOWER MATCHES "windows|win")
execute_process(
COMMAND powershell -NoProfile -ExecutionPolicy Bypass
-Command "Expand-Archive -Path '${ZIG_ARCHIVE}' -DestinationPath '${CMAKE_BINARY_DIR}' -Force"
RESULT_VARIABLE extract_result
)
else()
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xf "${ZIG_ARCHIVE}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
RESULT_VARIABLE extract_result
)
endif()
if(NOT extract_result EQUAL 0)
message(FATAL_ERROR "Extraction failed (code ${extract_result})")
endif()
file(REMOVE "${ZIG_ARCHIVE}")
else()
message(STATUS "Using cached espressif zig: ${ZIG_DIR}/zig")
endif()
set(ZIG_BIN "${ZIG_DIR}/zig")

View File

@@ -0,0 +1,63 @@
# ──────────────────────────────────────────────────────────────────────────────
# HELPER to run zig cli (build - translate-c - fmt - ...)
# ──────────────────────────────────────────────────────────────────────────────
function(zig_run)
cmake_parse_arguments(PARSE_ARGV 0 ARG
"VERBATIM;ALLOW_FAIL"
"WORKING_DIRECTORY;RESULT_VARIABLE;OUTPUT_VARIABLE;ERROR_VARIABLE;OUTPUT_FILE;TIMEOUT"
"COMMAND"
)
if(NOT ARG_COMMAND)
message(FATAL_ERROR "zig_run: COMMAND list is required")
endif()
if(NOT DEFINED ARG_WORKING_DIRECTORY)
set(ARG_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endif()
# Default timeout: 300 s. translate-c normally finishes in seconds;
if(NOT DEFINED ARG_TIMEOUT)
set(ARG_TIMEOUT 300)
endif()
set(extra_args)
if(ARG_VERBATIM)
list(APPEND extra_args VERBATIM)
endif()
if(ARG_OUTPUT_FILE)
list(APPEND extra_args OUTPUT_FILE "${ARG_OUTPUT_FILE}")
endif()
execute_process(
COMMAND "${ZIG_BIN}" ${ARG_COMMAND}
WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE error
TIMEOUT ${ARG_TIMEOUT}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
${extra_args}
)
# Propagate results to parent scope if requested
if(DEFINED ARG_RESULT_VARIABLE)
set(${ARG_RESULT_VARIABLE} ${result} PARENT_SCOPE)
endif()
if(DEFINED ARG_OUTPUT_VARIABLE)
set(${ARG_OUTPUT_VARIABLE} "${output}" PARENT_SCOPE)
endif()
if(DEFINED ARG_ERROR_VARIABLE)
set(${ARG_ERROR_VARIABLE} "${error}" PARENT_SCOPE)
endif()
if(NOT ARG_ALLOW_FAIL)
if(result MATCHES "timeout")
message(FATAL_ERROR
"Zig command timed out after ${ARG_TIMEOUT}s\n"
" Command: ${ZIG_BIN} ${ARG_COMMAND}\n"
"--- stdout ---\n${output}\n"
"--- stderr ---\n${error}")
elseif(NOT result EQUAL 0)
message(FATAL_ERROR
"Zig command failed (code ${result}):\n"
" ${ZIG_BIN} ${ARG_COMMAND}\n"
"--- stdout ---\n${output}\n"
"--- stderr ---\n${error}")
endif()
endif()
endfunction()