Hey all,
I think this might have gotten lost in another thread. So reposting in the hope of some visibility…sorry if this is not allowed. I have returned to the matter and am now a bit stuck still:
Brief Overview:
I am using espidf and platformIO. My set up is really gross with a load of stuff under src with a load of #include ../../crapI would like to break this into proper components. With this in mind, I created a component that runs a .cmake script at BUILD time (not configure time) to give me some compile time information. When I run it with idf.py build, it works but when I run it with pio, I can see in the compile_commands.json the path to where my generated file is there but it isn’t generated by platformIO. But I can’t understand why….
Reading:
I have read the platformIO docs for espidf framework and the espidf ones as well as the dev talk on the build system on YouTube. I wonder if I have missed something crucial or perhaps I just don’t get this.
Currently, my situation is this:
-
I have a pio project with src_dir pointing to main. I renamed it so that I could build the project in espidf too (since espidf seems to insist on its own pre-defined layout)
[platformio] src_dir = main -
In
PROJECT_DIR/mainI have a load of subfolders, each pertaining to different peripherals and FreeRTOS task set up. They are very ugly and do a lot of#include ../blah/blah.h. I also havePROJECT_DIR/main/main.cpp. I want to get away from this ugly layout and modularise things properly into espidf components. -
My
CMakeLists.txtat the root of the project looks like this:cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(<PROJECT_NAME>) set(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Root of the project") # This is currently being used as the working dir of one of my build time generating .cmake scripts -
The
CMakeLists.txtinmain/looks like this:FILE(GLOB_RECURSE app_sources ${COMPONENT_DIR}/*.*) message(STATUS "All application sources: ${app_sources}") idf_component_register( SRCS ${app_sources} INCLUDE_DIRS "." REQUIRES build_info ) -
in
PROJECT_DIR/componentsI have a component calledbuild_info. It contains aCMakeLists.txt. It looks like this:set(GENERATED_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(BUILD_INFO_HEADER ${GENERATED_BUILD_DIR}/build_info.h) idf_component_register( SRCS dummy.cpp INCLUDE_DIRS ${GENERATED_BUILD_DIR} ) # Always-run generator add_custom_target(generate_build_info ALL COMMAND ${CMAKE_COMMAND} -DOUTPUT_FILE=${BUILD_INFO_HEADER} -DPROJECT_ROOT=${PROJECT_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate_build_info.cmake BYPRODUCTS ${BUILD_INFO_HEADER} # optional, helps CMake know the file exists VERBATIM ) # Ensure component builds after header is generated add_dependencies(${COMPONENT_LIB} generate_build_info) # Expose include directory for consumers target_include_directories(${COMPONENT_LIB} PUBLIC ${GENERATED_BUILD_DIR}) # Mark the file as GENERATED so CMake doesn’t warn set_source_files_properties(${BUILD_INFO_HEADER} PROPERTIES GENERATED TRUE) # Export path for other components set(BUILD_INFO_HEADER_PATH ${BUILD_INFO_HEADER} CACHE INTERNAL "Path to build_info.h") -
The key bit is that I am trying to do a basic example to get to grips with this build system. The idea is that this will run the platform independent .cmake file every time at BUILD time not CONFIGURATION time. This is because the
build_info.hheader is supposed to include details like git commit and the datetime of compilation and make it available to anything that depends on it.For reference the .cmake file looks like this: -
execute_process( COMMAND git rev-parse --short HEAD WORKING_DIRECTORY ${PROJECT_ROOT} OUTPUT_VARIABLE GIT_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Get build-time timestamp (THIS is now build-time, not configure-time) # this does appear to get generated at build time and not configure time AS LONG AS THE target file is not there string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S") message(STATUS "Running build_info generation in script mode. Targetting git command in ${PROJECT_ROOT}") message(STATUS "Output file: ${OUTPUT_FILE}") message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") if(NOT GIT_COMMIT) set(GIT_COMMIT "UNKNOWN") endif() file(WRITE ${OUTPUT_FILE} "#pragma once\n" "#define BUILD_GIT_COMMIT \"${GIT_COMMIT}\"\n" "#define BUILD_TIME \"${BUILD_TIME}\"\n" ) -
If we build in a devcontainer using idf.py and look at the build/ dir and at the compile commands.json we can see that associated to main.cpp is an -I/workspace/build/esp-idf/build_info:
-I/workspace/build/esp-idf/build_info -mlongcalls -Wno-frame-address -fno-builtin-memcpy -fno-builtin-memset -fno-builtin-bzero -fno-builtin-stpcpy -fno-builtin-strncpy -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=unused-but-set-variable -Wno-error=deprecated-declarations -Wextra -Wno-error=extra -Wno-unused-parameter -Wno-sign-compare -Wno-enum-conversion -gdwarf-4 -ggdb -Og -fno-shrink-wrap -fmacro-prefix-map=/workspace=. -fmacro-prefix-map=/home/vscode/esp/esp-idf=/IDF -fstrict-volatile-bitfields -fno-jump-tables -fno-tree-switch-conversion -std=gnu++2b -fno-exceptions -fno-rtti -fuse-cxa-atexit -o esp-idf/main/CMakeFiles/__idf_main.dir/main.cpp.obj -c /workspace/main/main.cpp", "file": "/workspace/main/main.cpp" -
If we look in /workspace/build/esp-idf/build_info we can find build_info.h with full read and write permission for everyone. When we view it, it is correct:
vscode@ef9b1cc41195:/workspace$ cat build/esp-idf/build_info/build_info.h
#pragma once
#define BUILD_GIT_COMMIT “c7a5c10”
#define BUILD_TIME “2026-03-25 10:34:55”
vscode@ef9b1cc41195:/workspace$
and yet when we try and compile:
main/main.cpp:19:10: fatal error: build_info.h: No such file or directory
Looking for build_info.h dependency? Check our library registry!
CLI > platformio lib search “header:build_info.h”
Web > https://registry.platformio.org/search?q=header:e[me[Kbuild_info.h
19 | #include “build_info.h”
| ^~~~~~~~~~~~~~
compilation terminated.
If we investigate in platformIO we can see that the file is not there:
.pio\build\esp32_debug\esp-idf\build_info
# Mode LastWriteTime Length Name
# ---- ------------- ------ ----
# d---- 25/03/2026 14:40 CMakeFiles
# -a--- 25/03/2026 16:48 1629 cmake_install.cmake
But if this works in espidf shouldn’t I be able to build my project in platformIO. Afterall, isn’t the espidf pio platform supposed to abstract over this?