how to make CMake structure for ESP-IDF components with separate include/src directories?

souler
Posts: 5
Joined: Sun May 26, 2024 12:01 am

how to make CMake structure for ESP-IDF components with separate include/src directories?

Postby souler » Wed Mar 26, 2025 10:33 pm

I have an ESP-IDF v5.4 project with this structure:

Code: Untitled.c Select all

 
root/
├── main/
│ ├── CMakeLists.txt
│ └── main.c
└── components/
└── mis_comp/
├── CMakeLists.txt
├── include/ # .h files
└── src/ # .c files
How should I configure the CMakeLists.txt files to handle multiple components?
Do I need a CMakeLists.txt file in each folder (components, mis_comp, include, and src)?

I tried to do this in cmake from the main folder:

Code: Untitled.cmake Select all


idf_component_register(
SRCS
"main.c"

INCLUDE_DIRS "."

REQUIRES mis_comp
)

and mis_comp folder:

Code: Untitled.cmake Select all


idf_component_register(
SRCS
"src/initGPIO.c"
"src/adc_esp32.c"
"src/initWifi.c"
"src/fun_i2c_master.c"
"src/fun_i2c_slave.c"
"src/mqtt_esp32.c"
INCLUDE_DIRS
"include"

)


but it didn't work for me, it doesn't compile the program.
What’s the right way to do it?

limpens
Posts: 21
Joined: Tue Jan 25, 2022 9:14 am

Re: how to make CMake structure for ESP-IDF components with separate include/src directories?

Postby limpens » Thu Mar 27, 2025 7:11 am

This is working for me, a standard esp-idf C project, and few components.
Originally, the include files where located in the component directory (the headers for common_utils next to the sources in common_utils, the headers for snmp in the snmp directory), but to mimick your setup, I created an include directory and moved the .h files.

Code: Select all

experiments/waveshare/$ tree  -d -L 3
.
├── build
├── components
│   ├── common_utils
│   │   ├── example
│   │   └── include
│   ├── snmp
│   │   ├── example
│   │   └── include
│   └── wifi_utils
│       ├── example
│       └── include
├── data
└── main
So, this is a test project called waveshare, with 3 components. Every component has it's own CMakeLists.txt, for example:

Code: Select all

include($ENV{IDF_PATH}/tools/cmake/version.cmake)

execute_process(
    COMMAND git describe --tags --always
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    OUTPUT_VARIABLE GIT_VERSION
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Generate a header file with version information
configure_file( "${COMPONENT_DIR}/version.h.in" "${COMPONENT_DIR}/version.h" @ONLY )

idf_component_register(
    SRCS snmp.c snmp-utils.c hwinfo.c
    INCLUDE_DIRS . include
)
I didn't alter my code, it is still using includes like: #include <snmp.h> I only added the include directory name to the INCLUDE_DIRS statement in idf_component_register.

For clarity; my top level CMakeLists.txt:

Code: Select all

cmake_minimum_required(VERSION 3.16)

set(PROJECT_VER 0.0.0.7)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)

project(WaveShare)

idf_build_set_property(COMPILE_OPTIONS "-D_PROJECT_NAME_=\"${CMAKE_PROJECT_NAME}\"" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-D_PROJECT_VER_=\"${PROJECT_VER}\"" APPEND)

target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "data/index.html" TEXT)

and the CMakeLists.txt in the top source directory (main):

Code: Select all

idf_component_register(
    SRCS main.c app_wifi.c app_web.c task_ota.c task_rgb.c lcd.c esp_lcd_panel_st7789t.c
    REQUIRES app_update esp_https_ota esp_http_server mqtt driver json esp-tls wifi_utils snmp common_utils lvgl led_strip
)

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: how to make CMake structure for ESP-IDF components with separate include/src directories?

Postby MicroController » Thu Mar 27, 2025 7:18 am

it doesn't compile the program.
Any details on that?
What errors do you get?

User avatar
egionet
Posts: 39
Joined: Thu Sep 26, 2024 4:34 am
Location: Atlantic Canada

Re: how to make CMake structure for ESP-IDF components with separate include/src directories?

Postby egionet » Fri Mar 28, 2025 2:46 am

Thanks so much for the example @limpens

I managed to get versioning implemented with Git-Version and CMake.

version.h.in template:

Code: Select all

/**
 * Copyright (c) 2024 Eric Gionet (gionet.c.eric@gmail.com)
 *
 * MIT Licensed as described in the file LICENSE
 */

#ifndef __FW_VERSION_H__
#define __FW_VERSION_H__

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif


/**
 * public constant definitions
 */

/** Version release date  */
#define FW_VERSION_DATE        "@GIT_VERSION_DATE@"
/** Major version number (X.x.x) */
#define FW_VERSION_MAJOR       "@GIT_VERSION_MAJOR@"
/** Minor version number (x.X.x) */
#define FW_VERSION_MINOR       "@GIT_VERSION_MINOR@"
/** Patch version number (x.x.X) */
#define FW_VERSION_PATCH       "@GIT_VERSION_PATCH@"
/** Semantic version number (X.X.X-X) */
#define FW_SEMANTIC_VERSION    "@GIT_FULL_SEM_VER@"
/** Git version hash */
#define FW_GIT_SHORT_SHA       "@GIT_SHORT_SHA@"


/**
 * public macro definitions
 */

/** 
 * Macro to print x parameter as a string i.e. enclose x in double quotes. 
 */
#define STR_QUOTES( x ) #x

/** 
 * Macro to create a string of x parameter with all macros fully expanded. 
 */                 
#define STR( x ) STR_QUOTES( x )

/** 
 * Macro to generate current firmware version numbers (major, minor, patch) into a string that is formatted as X.X.X (e.g. 4.0.0). 
 */
#define FW_VERSION_STR                        \
        STR( FW_VERSION_MAJOR ) "." \
        STR( FW_VERSION_MINOR ) "." \
        STR( FW_VERSION_PATCH )

/** 
 * Macro to convert firmware version parameters (major, minor, patch numbers) into an integer (`int32_t`) 
 * value that can be used for comparison purposes.
 * 
 * As an example, FW_VERSION_INT32 >= FW_VERSION_PARAMS_INT32(4, 0, 0).
 */
#define FW_VERSION_PARAMS_INT32( major, minor, patch )        \
        ((major << 16) | (minor << 8) | (patch))

/**
 * Macro to generate current firmware version numbers (major, minor, patch) as an integer (`int32_t`) value that can 
 * be used for comparison purposes.
 * 
 * As an example, FW_VERSION_INT32 >= FW_VERSION_PARAMS_INT32(4, 0, 0).
 */
#define FW_VERSION_INT32                            \
        FW_VERSION_PARAMS_INT32(FW_VERSION_MAJOR,   \
                                FW_VERSION_MINOR,   \
                                FW_VERSION_PATCH)

#ifdef __cplusplus
}
#endif

/**@}*/

#endif //__FW_VERSION_H__
Component CMakeList.txt:

Code: Select all

#
# Install Git-Version via command prompt: dotnet tool install --global GitVersion.Tool
# Create a GitVersion.yml file in the root of your project with the following content:
#
#   major-version-bump-message: '\+semver:\s?(breaking|major)'
#   minor-version-bump-message: '\+semver:\s?(feature|minor)'
#   patch-version-bump-message: '\+semver:\s?(fix|patch)'
#   commit-message-incrementing: Enabled
#
# CMake JSON-Parser: https://github.com/sbellus/json-cmake/blob/master/JSONParser.cmake
# Copy the JSONParser.cmake file to the tools/cmake directory of your ESP-IDF installation.
# i.e. C:\Users\user\.platformio\packages\framework-espidf\tools\cmake
#
include($ENV{IDF_PATH}/tools/cmake/version.cmake)
include($ENV{IDF_PATH}/tools/cmake/JSONParser.cmake)

# get latest versioning information from git repository
execute_process(
    COMMAND dotnet-gitversion
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    OUTPUT_VARIABLE GIT_VERSION_OUTPUT
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

# instantiate json variable
sbeParseJson(GIT_VERSION_JSON GIT_VERSION_OUTPUT)

# parse versioning variables from json output
set(GIT_VERSION_DATE ${GIT_VERSION_JSON.CommitDate})
set(GIT_VERSION_MAJOR ${GIT_VERSION_JSON.Major})
set(GIT_VERSION_MINOR ${GIT_VERSION_JSON.Minor})
set(GIT_VERSION_PATCH ${GIT_VERSION_JSON.Patch})
set(GIT_FULL_SEM_VER ${GIT_VERSION_JSON.FullSemVer})
set(GIT_SHORT_SHA ${GIT_VERSION_JSON.ShortSha})

# release json variable
sbeClearJson(GIT_VERSION_JSON)

# Generate a header file with version information
configure_file( "${COMPONENT_DIR}/include/version.h.in" "${COMPONENT_DIR}/include/version.h" @ONLY )

idf_component_register(
    SRCS type_utils.c
    INCLUDE_DIRS include
    REQUIRES esp_common
)
Version header file results:

Code: Select all

/** Version release date  */
#define FW_VERSION_DATE        "2025-03-28"
/** Major version number (X.x.x) */
#define FW_VERSION_MAJOR       "0"
/** Minor version number (x.X.x) */
#define FW_VERSION_MINOR       "0"
/** Patch version number (x.x.X) */
#define FW_VERSION_PATCH       "1"
/** Semantic version number (X.X.X-X) */
#define FW_SEMANTIC_VERSION    "0.0.1-3"
/** Git version hash */
#define FW_GIT_SHORT_SHA       "da4614f"
Regards,

Eric Gionet P.Tech.(Eng.), CIOTP, SMIEEE

Who is online

Users browsing this forum: PerplexityBot, Qwantbot, YisouSpider and 6 guests