[001] [ESP32 Development Notes] IDF project creation and CMake configuration

Chip model:ESP32-S2-MINI-1
Development environment: VS Code + ESP-IDF plug-in

1 Project creation

  • In VS Code click View – Command Panel (orCtrl+Shift+P

  • entershow examples projects

  • then clickUse current ESP-ID

  • Choose a routine (e.g.blink), clickCreate project using example blink

  • Select a folder to store the project (There cannot be Chinese paths and spaces

  • In the SDKblinkAs a template, a new project is automatically created

  • Modify the project name, such asmy_project, and then modifyblink_example_main.cModify, such asapp_main

  • Modify projectCMakeLists.txt, the project name is changed tomy_project

  • RevisemaincomponentsCMakeLists.txt, the name of the file containing C is modified toapp_main(This will now be modified automatically)

  • MakefileCan be compiled for the old version of GNU Make without modification, Cmake isCMakeLists.txtcontrol

  • deleteexample_test.pysdkconfig.cisdkconfig.defaultsunnecessary files

  • Select the development chip model, mine isESP32-S2

2 Engineering Analysis

Analysis with the official example project:

- myProject/
             - CMakeLists.txt
             - sdkconfig
             - components/ - component1/ - CMakeLists.txt
                                         - Kconfig
                                         - src1.c
                           - component2/ - CMakeLists.txt
                                         - Kconfig
                                         - src1.c
                                         - include/ - component2.h
             - main/       - CMakeLists.txt
                           - src1.c
                           - src2.c

             - build/
  • CMakeLists.txt
    top level projectCMakeLists.txtIt is the main file used by CMake to learn how to build a project. You can set global CMake variables for the project in this file. top level projectCMakeLists.txtThe file will be imported/tools/cmake/project.cmakefile, which implements the rest of the build system. The file ends by setting the name of the project and defining the project.
  • sdkconfig
    Can usemecuconfigConfigure this file. This file saves the configuration information of all components of the project (including ESP-IDF itself). You can use the idf plug-in to visualize the configuration. Click the settings button to open:
  • components
    Optional components include some custom components of the project. If the project has many source files, do not put them all inmain, can be placed in the custom component. The componentThe name cannot be changed at will(folder name), the alias needs to be at the top levelCMakeLists.txtMedium settingsEXTRA_COMPONENT_DIRSVariable to find components at other specified locations.
  • main
    mainis a special component that contains the source code of the project itself.mainis the default name of the CMake variableCOMPONENT_DIRSThis component is included by default, but this variable can be modified. (generally not changed)
  • build
    This directory will be compiled byidfCreated automatically, CMake will configure the project and generate temporary build files in this directory. While the main build process is running, this directory also holds temporary object files, library files, and the final output binary. This directory is usually not added to the project’s source code management system, nor is it distributed with the project source code. (That is, you can delete the directory release project after debugging)

Notice

  • Each component directory contains aCMakeLists.txtfile, which will define some variables to control the building process of the component and its integration with the entire project.
  • Each component can also contain aKconfigfile, which is used to definemenuconfigdisplayed whenComponent configurationoptions. Some components may also containKconfig.projbuildandproject_include.cmakespecial files, they are used forOverride some project settings

3 itemsCMakeLists document

Every project has a top levelCMakeLists.txtFile containing build settings for the entire project. By default, project CMakeLists files will be very small.

3.1 Necessary parts


minimal projectCMakeLists The file must contain the following three lines of code:

cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(myProject)
  • cmake_minimum_required(VERSION 3.5): Must be placed on the first line of the CMakeLists.txt file, it will tell CMake the minimum version number required to build the project. ESP-IDF supports CMake 3.5 or higher.
  • include($ENV{IDF_PATH}/tools/cmake/project.cmake): Will import other functions of CMake to complete tasks such as configuring projects and retrieving components.
  • project(myProject)myProjectis the project name (such as hello_world), this command will create the project itself and specify the project name. This name will be used as the name of the final output binary file, that ismyProject.elfandmyProject.bin. Only one project can be defined per CMakeLists file.

3.2 Optional project variables

  • COMPONENT_DIRS:Search directory for components, default isIDF_PATH/componentsPROJECT_DIR/components,andEXTRA_COMPONENT_DIRS. If you don’t want components to be searched in these locations, override this variable.
  • EXTRA_COMPONENT_DIRS: A list of additional optional directories to search for components.
  • COMPONENTS: A list of component names to be built into the project, the default isCOMPONENT_DIRSAll components retrieved in the directory. Use this variable to “lean” your project to improve build times. Please note that if a component passesCOMPONENT_REQUIRESspecifies another component that it depends on, it will automatically be added toCOMPONENTSin, soCOMPONENTSThe list can be very short.

Notice:

  • The path in the above variable can be an absolute path, or a relative path relative to the project directory.
  • useset command in cmaketo set these variables, such asset(VARIABLE "VALUE"). Please note,set()The command needs to be placed ininclude(...)Before,cmake_minimum(...)after. like:
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

3.3 Overriding the default build specification

The build system sets some global build specifications (compile flags, definitions, etc.) that can be used to compile all source files from all components.

For example, one of the default build specifications is the compile optionWextra. Suppose a user wants to useWno-extraTo override this option, should be inproject()Then proceed:

cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(myProject)

idf_build_set_property(COMPILE_OPTIONS "-Wno-error" APPEND)

4 componentsCMakeLists document

ComponentsyesCOMPONENT_DIRSThe list containsCMakeLists.txtAny directory of files. is modular and independent code that is compiled into a static library (.a file) and linked to the application. Each project contains one or more components, which can be part of ESP-IDF, part of the project’s own component catalog, or added from a custom component catalog

minimal componentCMakeListsdocument

minimal componentCMakeLists.txtfile by usingidf_component_registerAdd components to the build system.

idf_component_register( SRCS "app_main.c"
                    	INCLUDE_DIRS "include"
                        REQUIRES mbedtls)
  • SRCSis a list of source files (*.c*.cpp*.cc*.S), all source files inside will be compiled into the component library.
  • INCLUDE_DIRSIs a directory list, the path inside will be added to the global include search path of all components that require this component (including the main component). (If there is only one level directory, you canINCLUDE_DIRS "."or leave it blank)
  • REQUIRESNot actually required, but usually needed to declare what other components this component needs to use

You can also use CMakesetgrammar:

set(srcs 
"app_main.c" "src/oled.c")
idf_component_register(SRCS ${srcs}
                    INCLUDE_DIRS "inc")

4.1 Components with the same name

When ESP-IDF searches for all components to be built, it followsCOMPONENT_DIRSThe specified order is followed, i.e. ESP-IDF internal components (IDF_PATH/components)–> EXTRA_COMPONENT_DIRSComponents in –> Project Components (PROJECT_DIR/components). If two or more of these directories contain components with the same name, the searchedlast positions component. This allows components to be copied into the project directory and modified to overwrite the ESP-IDF components. If used this way, the ESP-IDF directory itself can remain unchanged.

If you overwrite a component in an existing project by moving it to a new location, the project will not automatically see the path to the new component. Please runidf.py reconfigurecommand (or delete the project build folder) and then build again.

4.2 Double namingmaincomponents

The build system willmainComponents receive special treatment. ifmainThe component is in the expected location (i.e.${PROJECT_PATH}/main), it will be automatically added to the build system. Other components are also added to the build system as their dependencies, which relieves the user from dealing with dependencies and provides out-of-the-box build functionality. RenamemainComponents alleviate this behind-the-scenes work but require the user to specify the location of the renamed component and manually add dependencies for it. RenamemainThe steps for the component are as follows:

  1. double namingmainTable of contents.
  2. existprojectCMakeLists.txtSet in fileEXTRA_COMPONENT_DIRS, and add the renamedmainTable of contents.
  3. existcomponentsofCMakeLists.txtSet in fileCOMPONENT_REQUIRESorCOMPONENT_PRIV_REQUIRESto specify dependencies.

4.3 Default component variables

The following component-specific variables can be used in component CMakeLists, butNot recommendedRevise:

  • COMPONENT_DIRComponent Catalog, that is, includingCMakeLists.txtThe absolute path to the file, which is the same asCMAKE_CURRENT_SOURCE_DIRLike variables, the path cannot contain spaces.
  • COMPONENT_NAMEComponent name, the same as the component directory name.
  • COMPONENT_ALIASlibrary alias, created internally by the build system for the component.
  • COMPONENT_LIBLibrary name, created internally by the build system for the component.

The following variables are set at the project level but are available in component CMakeLists:

  • CONFIG_*: Each value in the project configuration corresponds to a value beginning withCONFIG_variable at the beginning. (refer toKconfig
  • ESP_PLATFORM:The value is set to 1 when the ESP-IDF build system processes CMake files.

4.4 Build/Project Variables

The following are the build/project variables available as build properties via the component CMakeLists.txtidf_build_get_propertyQuery its variable value.

  • PROJECT_NAMEItem name, set in the project CMakeLists.txt file.
  • PROJECT_DIR: The absolute path to the project directory (containing the project CMakeLists file), withCMAKE_SOURCE_DIRThe variables are the same.
  • COMPONENTSThe names of all components included in this build, the specific format is a CMake list separated by semicolons.
  • IDF_VER:ESP-IDFgit version number,Depend ongit describeCommand generation.
  • IDF_VERSION_MAJORIDF_VERSION_MINORIDF_VERSION_PATCH: ESP-IDFComponent version, can be used in conditional expressions. Please note that this information is not as precise asIDF_VERvariable, version numberv4.0-dev-*v4.0-beta1v4.0-rc1andv4.0correspondingIDF_VERSION_*The variable values ​​are the same, butIDF_VERThe values ​​are different.
  • IDF_TARGET: The hardware target name of the project.
  • PROJECT_VER: Project version number.

4.5 Component configuration

Each component can contain aKconfigfiles, andCMakeLists.txtPut it in the same directory.KconfigThe file contains some configuration setting information to be added to the component’s configuration menu.

5 Component dependencies

Each component needs to declare the components it depends on, i.e.requires

idf_component_register(...
                       REQUIRES mbedtls
                       PRIV_REQUIRES console spiffs)
  • REQUIRESNeed to include all components in the current componentpublicThe component containing the #include header file in the header file. (such as a componentREQUIRES bb component, if c component contains the public interface ah of a component, it can recursively contain b component)
  • PRIV_REQUIRESNeed to include the component where the header file #included by the source file of the current component is located (unless it has been set inREQUIRESmiddle). And the components that must be linked for the current component to work properly.
  • REQUIRESandPRIV_REQUIRESThe value cannot depend on any configuration option (CONFIG_xxxmacro). This is because dependencies are expanded before the configuration is loaded. Other component variables (such as include paths or source files) can depend on configuration choices.
  • If the current component is in addition toCommon component dependenciesExcept for the common components (such as RTOS, libc, etc.) set in it, it does not depend on other components, so for the above twoREQUIRESVariables, you can choose to set one or neither.

If the component only supports certain hardware targets (IDF_TARGETvalue), you canidf_component_registerspecified inREQUIRED_IDF_TARGETSto declare this requirement. In this case, the build system will report an error if it imports a component that is not supported by the current hardware target.

In CMake,REQUIRESandPRIV_REQUIRESis a CMake functiontarget_link_libraries(... PUBLIC ...)andtarget_link_libraries(... PRIVATE ...)Approximate packaging.

5.1 Component dependency example

Suppose there is now acarcomponent, it needs to useenginecomponent, whileengineComponents need to usespark_plugComponents:

- autoProject/
             - CMakeLists.txt
             - components/ - car/ - CMakeLists.txt
                                     - car.c
                                     - car.h
                           - engine/ - CMakeLists.txt
                                     - engine.c
                                     - include/ - engine.h
                           - spark_plug/  - CMakeLists.txt
                                          - plug.c
                                          - plug.h

5.1.1 Car component

car.hhead File

car.hThe header file iscarThe component’s public interface. This header file directly containsengine.h, this is because it requires usingengine.hSome statements in:

/* car.h */
#include "engine.h"

#ifdef ENGINE_IS_HYBRID
#define CAR_MODEL "Hybrid"
#endif

At the same time, car.c also containscar.h:

/* car.c */
#include "car.h"

This represents the filecar/CMakeLists.txtNeed to declarecarneedengine

idf_component_register(SRCS "car.c"
                  INCLUDE_DIRS "."
                  REQUIRES engine)
  • SRCSsupplycarList of source files in the component.
  • INCLUDE_DIRSProvides a directory listing of the component’s public header files, sincecar.hIt is a public interface, so here is a list of all includedcar.hDirectory.
  • REQUIRESGives a list of components required for this component’s public interface. becausecar.his a public header file and contains files fromengineheader file, so we include hereengine. This ensures that anycar.hOther components ofrecursioncontains the requiredengine.h

5.1.2 Engine component

engineComponents also have a public header fileinclude/engine.h, but this header file is simpler:

/* engine.h */
#define ENGINE_IS_HYBRID

void engine_start(void);

existengine.cIn execution:

/* engine.c */
#include "engine.h"
#include "spark_plug.h"
...

In this component,enginedepends onspark_plug, but this is a private dependency. compileengine.cneedspark_plug.hbut does not need to includeengine.h

This represents the fileengine/CMakeLists.txtcan usePRIV_REQUIRES

idf_component_register(SRCS "engine.c"
                  INCLUDE_DIRS "include"
                  PRIV_REQUIRES spark_plug)

therefore,carSource files in components do not need to be added to the compiler search pathspark_pluginclude directory. This can speed up compilation and avoid verbose compiler command lines.

5.1.3 Spark Plug Component

spark_plugThe component has no dependencies, it has a public header filespark_plug.h, but does not include the header files of other components.

This meansspark_plug/CMakeLists.txtThe file does not require anyREQUIRESorPRIV_REQUIRES

idf_component_register(SRCS "spark_plug.c"
                  INCLUDE_DIRS ".")

5.2 Source file Include directory

Each component’s source files are compiled using these Include paths, which are passed toidf_component_registerSpecified in the parameters:

idf_component_register(..
                       INCLUDE_DIRS "include" # include all .h files in the folder
                       PRIV_INCLUDE_DIRS "other")
  • current componentINCLUDE_DIRSdesignationincludeAll .h files in the folder
  • currentcomponentsPRIV_INCLUDE_DIRS.h files containing other components
  • REQUIRESandPRIV_REQUIRESAll parameters specifiedotherSet by the component (that is, all public and private dependencies of the current component)INCLUDE_DIRS
  • List all components recursivelyREQUIRESListINCLUDE_DIRSDirectory (such as recursively expanding all public dependencies of this component).

5.3 mainComponent dependencies

mainA component is special because it automatically depends on all other components during the build process. So there is no need to pass it to this componentREQUIRESorPRIV_REQUIRES

5.4 Common component dependencies

To avoid duplication of work, each component automatically depends on some “common” IDF components, even if they are not explicitly mentioned. The header files of these components willalways includedin the build system.

Common components include: cxx, newlib, freertos, esp_hw_support, heap, log, lwip, soc, hal, esp_rom, esp_common, esp_system.

Notice: to avoidcircular dependency, for its definition and solution reference:circular dependency


reference:

  1. ESP-IDF Programming Guide-Building System
  2. ESP32 development 2. Add .ch and modify CMakeLists to customize your own project
  3. ESPIDF adds custom components (creates C and H files)
  4. ESP32 study notes (21) – Build your own projects and component libraries

END

Related Posts

My NBIOT learning – BC35-G uses AT commands to connect to Huawei Cloud through CoAP protocol

The simplest Anaconda+Python3.7 installation tutorial on the Internet for Win10 (100% successful)

STM32+ESP8266+MQTT connects to Alibaba Cloud server (3. AT command connects to Alibaba Cloud platform)

[Graphic tutorial to solve the problem of Chinese garbled output in vscode terminal]

LeetCode Greedy Algorithm 1005. Maximized array sum after K times inversion

Robomaster wheel motion calculation

vscode card Setting up SSH Host XX:Copying VS Code Server to host with scp

Embedded linux/Hongmeng development board (IMX6ULL) development (19) I2C application programming

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*