Zephyr构建系统-配置过程详解
在Zephyr构建过程简述一文中说明过Zephyr的构建过程。Zephyr使用CMake进行构建,构建可以分为两个阶段
- 配置生成阶段
- 编译阶段
配置生成阶段执行 CMakeLists.txt 和.cmake构建脚本,配置完成后CMake 就有了 Zephyr 构建的内部模型,并且可以生成目标的构建脚本。这些构建脚本决定了编译阶段要执行那些动作,以及这些编译动作之间的顺序和关系。因此只要理解了配置生成阶段的过程,就理解Zephyr的构建编译过程。
Zephyr下CMake只支持生成 Ninja 和 Make配置。配置完成后,可以通过执行生成的构建脚本来开始构建编译阶段。在构建编译阶段,这些构建脚本可以重编译应用程序,在代码修改后不用再进行CMake的配置e。
CMake配置入口 链接到标题
当编译一个Zephyr的应用时,将首先使用应用的CMakeList.txt,例如当执行west build -b mm_feather zephyr/samples/hello_world
时, 从CMake系统就会从zephyr/samples/hello_world/CMakeLists.txt
开始处理
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(hello_world)
target_sources(app PRIVATE src/main.c)
进入该CMakeLists.txt,最开始就算查找Zephyr CMake-package并处理
Zephyr CMake-package 链接到标题
Zephyr的CMake package放在zephyr/share/zephyr-package
下,在建立Zephyr构建环境的时候会执行west zephyr-export
,这条指令将Zephyr的包信息写到~/.cmake/packages/Zephyr
下,CMake系统在find_package(Zephyr)
时就可以通过包信息就能找到zephyr/share/zephyr-package
, 找到zephyr-package后将会按照下面顺序进行cmake处理
zephyr/share/zephyr-package/cmake/ZephyrConfigVersion.cmake
zephyr/share/zephyr-package/cmake/zephyr_package_search.cmake
zephyr/cmake/modules/version.cmake
zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake
Zephyr的CMake配置入口就是zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake
,它完成了真正的对Zephyr构建的配置
Zephyr构建配置 链接到标题
ZephyrConfig.cmake
将调用zephyr/cmake/modules
下的各种.cmake文件和生成的.cmake文件,各级目录的CMakeLists.txt来生成构建配置脚本。这些.cmake和CMakeLists.txt可以分为三大类:
- 工具和环境配置
- Zephyr配置文件的生成
- Zephyr构建源文件添加,编译/链接/目标控制
这三大类生成的配置脚本执行顺序也是按照从上到下执行。
工具和环境配置 链接到标题
ZephyrConfig.cmake
会includezephyr/cmake/modules
内的.cmake文件,按照下面列表从上到下顺序执行:
python.cmake
查找pythonuser_cache.cmake
配置user cache文件夹version.cmake
获取Zephyr版本basic_settings.cmake
对基本设置进行处理(sysbuild)west.cmake
通过west构建时,会进行west的一些处理root.cmake
将Zephyr的一些root路径转换为绝对路径(MODULE_EXT_ROOT,BOARD_ROOT,SOC_ROOT,ARCH_ROOT,SCA_ROOT
)
环境准备好后就进行下一阶段Zephyr陪葬文件的生成
Zephyr配置文件的生成 链接到标题
ZephyrConfig.cmake
会继续includezephyr/cmake/modules
内的.cmake文件,按照下面列表从上到下顺序执行:
board.cmake
验证构建命令传入的主板是否合法,并设置主板参数shields.cmake
验证构建命令传入的shields是否合法,并设置shields参数snippets.cmake
通过zephyr/scripts/snippets.py读取片段文件,并进行片段变量的设置arch_v1.cmake
对hwmv1的arch进行处理, hwmv1以后将会被废弃hwm_v2.cmake
调用 list_hardware.py 生成构建用 Kconfig 文件,包含了所有hwmv2的Arch和Soc的Kconfigconfiguration_files.cmake
找到要使用的 Kconfig,DT文件和应用配置所在目录generated_file_directories.cmake
在构建目录中创建生成文件的目录dts.cmake
生成设备树宏和完整的设备树文件kconfig.cmake
处理Kconfig,扫描所有Kconfig项并生成配置项arch_v2.cmake
根据 Kconfig 设置和 arch root 配置 ARCH 设置soc_v1.cmake
根据 Kconfig 设置和 SoC 根目录配置 hwmv1的SoC 设置, 将来hwmv1将会被废弃soc_v2.cmake
根据 Kconfig 设置和 SoC 根目录配置 hwmv2的SoC 设置
Zephyr构建内核源文件添加,编译/链接/目标控制 链接到标题
最后ZephyrConfig.cmake
会includezephyr/cmake/modules/kernel.cmake
, 该文件会负责添加要加入编译的源代码,建立编译/链接的选项和生成目标文件的控制. 下面列表按照按照从上到下顺序执行:
- 首先通过下面cmake文件设置工具链和编译选项
- zephyr/cmake/modules/FindTargetTools.cmake
- zephyr/cmake/modules/FindScaTools.cmake
- build/CMakeFiles/3.28.3/CMakeSystem.cmake
- build/CMakeFiles/3.28.3/CMakeCCompiler.cmake
- build/CMakeFiles/3.28.3/CMakeCXXCompiler.cmake
- build/CMakeFiles/3.28.3/CMakeASMCompiler.cmake
- zephyr/cmake/target_toolchain_flags.cmake
- 再处理指定主板的cmake,使用的主板不同导入的cmake不同,例如mm_feather的如下:
- zephyr/boards/madmachine/mm_feather/board.cmake
- 最后以顶级目录zephyr/CMakeLists.txt开始逐项展开
- 处理链接选项cmake
- 依次处理arch/soc/board/subsys/driver下的CMakeLists.txt
- 处理外部module的CMakeLists.txt
- 处理外部kernel的CMakeLists.txt
- 处理产生目标的cmake
- 处理flash/usage/report的cmake
添加应用代码 链接到标题
在内核的cmake处理完后,回到应用的CMakeLists.txt中添加应用的代码
target_sources(app PRIVATE src/main.c)
关于extensions.cmake 链接到标题
Zephyr在zephyr/cmake/modules/extensions.cmake
内封装了大量的CMake函数,在前面提到的所有.cmake和CMakeLists中都使用了这些函数,要更细节的理解这些文件,需要参考extensions.cmake.
小节 链接到标题
一图胜前言,下面这张图总结了Zephyr CMake生成构建配置各文件的依赖关系,需要注意的是这张图只表示的层级关系,图中的叶子节点都还可能有下一级