ESP32 快速入门(四): CMake 以及分解 esp-idf 中的 hello_world 工程结构

一. CMake 简介

CMake 是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的 makefile 或者 project 文件,能测试编译器所支持的 C++ 特性,类似 UNIX 下的 automake。


二. CMake 示例及语法

以下是我选取的 CMake 代码示例:

[cpp] view plain copy
#project name  
PROJECT(test_math)  
#head file path  
INCLUDE_DIRECTORIES(  include  )  
#source directory  
AUX_SOURCE_DIRECTORY(src DIR_SRCS)  
#set environment variable  
SET(TEST_MATH  ${DIR_SRCS}  )  
#set extern libraries  
SET(LIBRARIES  libm.so  )  
#add executable file  
ADD_EXECUTABLE(../bin/bin ${TEST_MATH})  
#add link library  
TARGET_LINK_LIBRARIES(../bin/bin ${LIBRARIES}  

由此我们可以总结出对应的 CMake 语法:

  1. PROJECT( project name ) 工程名称
  2. INCLUDE_DIRECTORIES( include ) 头文件所在路径
  3. SET( TEST_DIR ${DIR_SRCS}) 设置环境变量
  4. SET(LIBRARIES libm.so) 设置外部库
  5. ADD_EXECUTABLE( ../bin/bin ${TEST_DIR}) 设置可执行文件路径
  6. TARGET_LINK_LIBRARIES(../bin/bin ${LIBRARIES}) 设置链接库
  7. ADD_SUBDIRECTORY 设置代码子目录

三. esp-idf 中 hello_world 项目结构简析

我们打开 esp-idf 中的 hello_world 工程,打开终端,使用 cd 命令进入 esp-idf/examples/get-started/hello_world,然后在终端使用 tree 查看此项目当前的结构:

├── CMakeLists.txt
├── main
│   ├── CMakeLists.txt
│   ├── component.mk
│   └── hello_world_main.c
├── Makefile
├── README.md
├── sdkconfig
└── sdkconfig.old

我们可以看到:

  • CMakeLists.txt (CMake 配置文件)
  • main (工程主代码目录)
    • CMakeLists.txt (main 文件夹下的的 CMake 配置文件)
    • component.mk (main 组件的配置文件)
    • hello_world_main.c (hello_world 的主要代码)
  • Makefile(make 配置文件)
  • README.md
  • sdkconfig (通过 make menuconfig 生成的配置文件)
  • sdkconfig.old(通过 make menuconfig 生成的备份配置文件)

然后我们可以将工程结构相关的文件一一拿出来讨论。

1. CMakeLists.txt

文件里的内容如下:

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

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

这是 CMake 加载的配置文件,首先通过 cmake_minimum_required(VERSION 3.5) 定义了 CMake 所支持的最小版本。然后使用 include($ENV{IDF_PATH}/tools/cmake/project.cmake) 来包含 esp-idf 下的 project.cmake 文件,这个文件包含许多需要加载的组件,如果想深入了解,可以自行去查看。最后采取 project(hello-world) 来说明工程名为 hello-world

2. Makefile

文件里的内容如下:

#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := hello-world

include $(IDF_PATH)/make/project.mk

Makefile 文件是 make 命令加载的配置文件, 内容同 CMakeLists.txt 基本一致,PROJECT_NAME := hello-world 说明工程名为 hello-worldinclude $(IDF_PATH)/make/project.mk 用来包含 esp-idf 下的 project.cmake 文件。

3. main

main 文件夹用来放置工程主要源文件。在这个工程里有三个文件,分别是:

  1. CMakeLists.txt
    文件里的内容如下:
    set(COMPONENT_SRCS "hello_world_main.c")
    set(COMPONENT_ADD_INCLUDEDIRS "")
    
    register_component()
    
    CMakeLists.txt 用来编译 main 组件的配置,可以发现 set(COMPONENT_SRCS "hello_world_main.c")set(COMPONENT_ADD_INCLUDEDIRS "") 用来设置相关源码的位置,最后通过 register_component() 注册组件。
  2. component.mk
    文件里的内容如下:
    #
    # "main" pseudo-component makefile.
    #
    # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
    
    component.mk 用来编译 main 组件,我们可以发现这是个空文件,在这种情况下会默认编译该目录下的所有代码。
  3. hello_world_main.c
    此文件里的内容由于与构建工程无关,省略至如下:
    #include 
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_spi_flash.h"
    
    void app_main()
    {
    	printf("Hello world!\n");
    }
    
    hello_world_main.c 是项目比较核心的文件,我们可以在里面修改代码满足我们的相关需求。

四. 项目结构的要点总结及展望

通过本文的探索,我们可以总结出以下要点:

  • Makefile 文件应该放在项目根目录,一般情况下该文件所在目录会被编译系统自动保存为 PROJECT_NAME
  • sdkconfig 文件由 make menuconfig 自动生成,同级目录还会自动生成 sdkconfig.oldsdkconfig.defaults,这两个文件可以用于恢复上一次设置或默认设置
  • main 目录放置工程主要源文件,该目录被官方定义为“伪组件”,和组件目录遵循相同的编译规则。

最后,在更大型的工程中,我们可以发现工程中会存在 components 目录。以下是我搜索到的部分要点:

  • 在 components 目录下可以不设置,构建系统会自动从 IDF_PATH 目录调用 component 源代码,如果将要使用到的 component 复制到工程目录。构建系统会使用当前目录下的 component,不影响 IDF_PATH 中的源代码。

  • 可以使用 Kconfig 来声明 menuconfig 的选项,通过界面交互修改组件的宏定义。component.mk 用于配置组件的各种行为。

你可能感兴趣的:(ESP32)