1.stm32 cubemx的cmaek工程分析
stm32 CubeMX可以生成cmake工程,没有这个选项升级stm32 cubemx至最新版本
我的工程下载链接:
https://hedejiang.tpddns.cn:5001/sharing/Sv1syijlJ
以下是STM32的工程目录,只关心工程管理的部分
hdj@hdj-virtual-machine:~/st-cmake-project$ tree -L 2
.
├── cmake
│ ├── gcc-arm-none-eabi.cmake
│ └── stm32cubemx
├── CMakeLists.txt
├── CMakePresets.json
├── Core
│ ├── Inc
│ └── Src
├── Drivers
│ ├── CMSIS
│ └── STM32H7xx_HAL_Driver
├── startup_stm32h750xx.s
├── STM32H750XBHx_FLASH.ld
└── stm32h7-cmake.ioc
cmake目录下
hdj@hdj-virtual-machine:~/st-cmake-project/cmake$ tree -L 2
.
├── gcc-arm-none-eabi.cmake
└── stm32cubemx
└── CMakeLists.txt
这是生成的cmake工程结构,可以看到在文件中有关cmaek管理工程的几个文件有如下几个,分析这几个文件的作用是什么,如下
工程目录下st-cmake-project的文件有 CMakeLists.txt CMakePresets.json
cmake文件夹下有 gcc-arm-none-eabi.cmake
cmaek->stm32cubemx CMakeLists.txt
上述需要了解的有四个文件,来看看这些文件分别是什么,我将在原来的文件下将英文更改为中文注释,最后做小结
文件1:st-cmake-project -> CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
#
# This file is generated only once,
# and is not re-generated if converter is called multiple times.
#
# User is free to modify the file as much as necessary
#
# Setup compiler settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
# Define the build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# Set the project name
set(CMAKE_PROJECT_NAME stm32h7-cmake)
# Include toolchain file
include("cmake/gcc-arm-none-eabi.cmake")
# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
# Enable CMake support for ASM and C languages
enable_language(C ASM)
# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})
# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME})
# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)
# Link directories setup
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined library search paths
)
# Add sources to executable
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# Add user sources here
)
# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined include paths
)
# Add project symbols (macros)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined symbols
)
# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
# Add user defined libraries
)
文件1解释
cmake_minimum_required(VERSION 3.22)
#
# 此文件仅生成一次,
# 即使多次调用转换器也不会重新生成。
#
# 用户可以根据需要自由修改此文件
#
# 设置编译器配置
set(CMAKE_C_STANDARD 11) # 设置C标准为C11
set(CMAKE_C_STANDARD_REQUIRED ON) # 强制要求C11标准
set(CMAKE_C_EXTENSIONS ON) # 允许使用C的扩展
# 定义构建类型
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug") # 如果未指定,默认设置为“Debug”构建类型
endif()
# 设置项目名称
set(CMAKE_PROJECT_NAME stm32h7-cmake) # 定义项目名称
# 包含工具链文件
include("cmake/gcc-arm-none-eabi.cmake") # 引入交叉编译工具链文件,配置用于编译ARM代码的编译器和编译选项
# 启用编译命令生成,方便如clangd等工具的索引
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) # 生成编译命令数据库文件compile_commands.json,便于代码索引
# 启用CMake对ASM和C语言的支持
enable_language(C ASM) # 启用汇编(ASM)和C语言支持
# 核心项目设置
project(${CMAKE_PROJECT_NAME})
message("构建类型: " ${CMAKE_BUILD_TYPE}) # 输出构建类型的信息,便于用户确认当前构建模式
# 创建一个可执行对象
add_executable(${CMAKE_PROJECT_NAME}) # 定义生成的可执行文件对象,以项目名称命名
# 添加STM32CubeMX生成的源文件目录
add_subdirectory(cmake/stm32cubemx) # 添加子目录 cmake/stm32cubemx ,用于包含STM32CubeMX生成的源文件和库
# 设置链接目录
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户定义的库搜索路径
)
# 添加源文件到可执行文件
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户自定义的源文件路径
)
# 添加包含路径
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户定义的包含(头文件)路径
)
# 添加项目符号(宏定义)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# 添加用户自定义的符号(宏定义)
)
# 添加链接库
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx # 链接由STM32CubeMX生成的库stm32cubemx
# 添加用户定义的库
)
文件1总结
. CMakeLists.txt (项目根目录)
该文件是项目的主要CMake配置文件,负责定义项目的总体设置和构建逻辑。
项目设置:定义项目名称和编译标准(C11),指定默认的构建类型为Debug。
工具链:通过include("cmake/gcc-arm-none-eabi.cmake")引入ARM的交叉编译工具链文件。
支持语言:启用了C和汇编(ASM)支持。
添加目标和库:定义了一个可执行文件${CMAKE_PROJECT_NAME},并通过add_subdirectory将cmake/stm32cubemx子目录(包含STM32CubeMX生成的文件)添加为构建的一部分。
链接配置:设置链接目录、源文件、头文件路径等,还提供了一个接口库stm32cubemx。
文件2:st-cmake-project -> CMakePresets.json
{
"version": 3,
"configurePresets": [
{
"name": "default",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake",
"cacheVariables": {
}
},
{
"name": "Debug",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "RelWithDebInfo",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "Release",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "MinSizeRel",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "MinSizeRel"
}
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "Debug"
},
{
"name": "RelWithDebInfo",
"configurePreset": "RelWithDebInfo"
},
{
"name": "Release",
"configurePreset": "Release"
},
{
"name": "MinSizeRel",
"configurePreset": "MinSizeRel"
}
]
}
文件2解释
{
"version": 3, // CMake预设文件的版本号
"configurePresets": [
{
"name": "default", // 默认配置预设
"hidden": true, // 隐藏此配置,用户不可见
"generator": "Ninja", // 指定使用Ninja作为生成器
"binaryDir": "${sourceDir}/build/${presetName}", // 构建输出目录,基于源代码目录和预设名称
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake", // 工具链文件路径,用于交叉编译配置
"cacheVariables": {
// 可在此添加缓存变量
}
},
{
"name": "Debug", // 调试配置
"inherits": "default", // 继承默认配置
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug" // 设置构建类型为Debug,启用调试信息
}
},
{
"name": "RelWithDebInfo", // 发布带调试信息的配置
"inherits": "default", // 继承默认配置
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo" // 设置构建类型为RelWithDebInfo,启用优化并保留调试信息
}
},
{
"name": "Release", // 发布配置
"inherits": "default", // 继承默认配置
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release" // 设置构建类型为Release,优化构建并移除调试信息
}
},
{
"name": "MinSizeRel", // 最小化尺寸发布配置
"inherits": "default", // 继承默认配置
"cacheVariables": {
"CMAKE_BUILD_TYPE": "MinSizeRel" // 设置构建类型为MinSizeRel,优化代码大小
}
}
],
"buildPresets": [
{
"name": "Debug", // 调试构建预设
"configurePreset": "Debug" // 使用Debug配置预设
},
{
"name": "RelWithDebInfo", // 发布带调试信息的构建预设
"configurePreset": "RelWithDebInfo" // 使用RelWithDebInfo配置预设
},
{
"name": "Release", // 发布构建预设
"configurePreset": "Release" // 使用Release配置预设
},
{
"name": "MinSizeRel", // 最小化尺寸发布构建预设
"configurePreset": "MinSizeRel" // 使用MinSizeRel配置预设
}
]
}
在 CMake 中,CMakePresets.json
文件的主要作用是定义和管理配置和构建的预设。它为不同的开发环境、构建类型、工具链等设置了固定的参数,这使得在不同机器或项目之间更容易统一配置,而不需要每次手动设置。
让我们以你当前的 STM32 项目为例来解释这个文件的实际作用。
- 配置预设(
configurePresets
):
配置预设定义了如何配置 CMake 的生成过程。它告诉 CMake 使用哪个工具链文件、构建目录等。这个部分是让你能够跨不同环境、不同平台之间复用工具链配置。
实际应用:
假设正在开发一个 STM32 嵌入式项目,使用 gcc-arm-none-eabi
工具链进行交叉编译。可以通过在 CMakePresets.json
中设置一个配置预设来指定工具链文件、构建生成器等,避免每次编译时手动设置。
{
"name": "default",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake",
"cacheVariables": {}
}
toolchainFile
指定了交叉编译所需的工具链文件,确保编译时使用正确的编译器和工具。generator
设置为Ninja
,指定构建工具为 Ninja(可以改成其他工具如Make
)。
这样做的好处:每次运行 CMake 配置时,它会自动读取这个文件并按照预设的设置来进行配置,确保一致性。
- 构建预设(
buildPresets
):
构建预设指定了要使用的配置预设以及其他构建相关的选项,比如构建类型(Debug/Release)等。它使得不同的构建类型(调试、发布等)使用不同的选项。
实际应用:
可能在开发过程中需要根据不同的需求切换不同的构建配置,比如 Debug
和 Release
。可以在 CMakePresets.json
中定义这些构建预设,然后在实际构建时通过简单的命令来选择。
例如:
{
"name": "Debug",
"configurePreset": "Debug"
}
configurePreset
设置为Debug
,意味着每次选择Debug
构建预设时,CMake 会使用预设中的配置选项(例如:启用调试信息,禁用优化等)。
这样做的好处:不需要每次手动指定编译选项,只需要通过选择合适的预设来自动应用一组配置。
- 在实际开发中如何使用:
假设已经设置了 CMakePresets.json
文件并定义了以下预设:
Debug
(调试模式)Release
(发布模式)RelWithDebInfo
(带有调试信息的优化版本)
当需要切换到不同的构建模式时,可以通过命令行轻松选择:
配置并构建 Debug 模式:
cmake --preset Debug
cmake --build --preset Debug
配置并构建 Release 模式:
cmake --preset Release
cmake --build --preset Release
CMake 会自动根据你选择的预设来应用相应的工具链、编译选项等,简化了手动设置的步骤。
4. 好处总结:
- 一致性:通过定义预设,保证了团队成员或不同环境中使用相同的构建配置。
- 简化流程:减少了手动设置的复杂性。例如,不需要每次编译时手动指定工具链文件、编译类型等。
- 可维护性:只需要修改
CMakePresets.json
文件中的配置,当环境或需求变化时,修改一次预设即可生效。
小结:
在当前的 STM32 项目中,CMakePresets.json
能够集中管理并简化编译过程。它避免了每次修改构建参数时的繁琐操作,通过预设的方式,确保了编译的一致性、灵活性和可维护性。
文件3:cmaek -> gcc-arm-none-eabi.cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
set(CMAKE_C_COMPILER_ID GNU)
set(CMAKE_CXX_COMPILER_ID GNU)
# Some default GCC settings
# arm-none-eabi- must be part of path environment
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size)
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# MCU specific flags
set(TARGET_FLAGS "-mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections")
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3")
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -g0")
endif()
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics")
set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32H750XBHx_FLASH.ld\"")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --specs=nano.specs")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group")
文件3解释
# 设置系统名称为通用类型(Generic)
set(CMAKE_SYSTEM_NAME Generic)
# 设置处理器架构为ARM
set(CMAKE_SYSTEM_PROCESSOR arm)
# 强制指定C和C++编译器
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
# 设置编译器ID为GNU
set(CMAKE_C_COMPILER_ID GNU)
set(CMAKE_CXX_COMPILER_ID GNU)
# 一些默认的GCC设置
# arm-none-eabi- 必须在环境路径中
set(TOOLCHAIN_PREFIX arm-none-eabi-)
# 指定工具链中的各个工具
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) # C编译器
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) # 汇编编译器
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++) # C++编译器
set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}g++) # 链接器
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) # 二进制文件转换工具
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) # 二进制文件大小检查工具
# 为生成的可执行文件设置后缀
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")
# 尝试编译的目标类型设为静态库
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# MCU 特定的编译标志
set(TARGET_FLAGS "-mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard ") # 指定处理器、浮点单元和浮点ABI
# C编译器的通用标志
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections")
# 针对不同构建类型的C编译器优化
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3") # 调试构建,禁用优化并启用最高调试信息
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -g0") # 发布构建,优化代码大小并移除调试信息
endif()
# 汇编编译器的标志
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") # 设置汇编语言预处理支持和依赖文件生成
# C++编译器的标志
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") # 禁用运行时类型信息、异常和线程安全的静态变量
# 链接器标志
set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}")
# 使用链接脚本指定存储器布局
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32H750XBHx_FLASH.ld\"")
# 使用nano.specs库,减少二进制文件大小
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --specs=nano.specs")
# 生成内存映射文件并删除未使用的段
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections")
# 设置库组链接,确保标准C库和数学库的链接
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")
# 打印内存使用情况
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage")
# C++链接器标志,添加标准C++库
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group")
文件4:cmaek -> stm32cubemx -> CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(stm32cubemx)
add_library(stm32cubemx INTERFACE)
# Enable CMake support for ASM and C languages
enable_language(C ASM)
target_compile_definitions(stm32cubemx INTERFACE
USE_HAL_DRIVER
STM32H750xx
$<$<CONFIG:Debug>:DEBUG>
)
target_include_directories(stm32cubemx INTERFACE
../../Core/Inc
../../Drivers/STM32H7xx_HAL_Driver/Inc
../../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy
../../Drivers/CMSIS/Device/ST/STM32H7xx/Include
../../Drivers/CMSIS/Include
)
target_sources(stm32cubemx INTERFACE
../../Core/Src/main.c
../../Core/Src/gpio.c
../../Core/Src/memorymap.c
../../Core/Src/stm32h7xx_it.c
../../Core/Src/stm32h7xx_hal_msp.c
../../Core/Src/stm32h7xx_hal_timebase_tim.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
../../Core/Src/system_stm32h7xx.c
../../Core/Src/sysmem.c
../../Core/Src/syscalls.c
../../startup_stm32h750xx.s
)
target_link_directories(stm32cubemx INTERFACE
)
target_link_libraries(stm32cubemx INTERFACE
)
# Validate that STM32CubeMX code is compatible with C standard
if(CMAKE_C_STANDARD LESS 11)
message(ERROR "Generated code requires C11 or higher")
endif()
文件4解释
# 设置CMake的最低版本要求为3.22
cmake_minimum_required(VERSION 3.22)
# 设置项目名称为 stm32cubemx
project(stm32cubemx)
# 创建一个INTERFACE类型的库
# INTERFACE库只是提供头文件和其他设置,而不生成二进制文件
add_library(stm32cubemx INTERFACE)
# 启用C和汇编语言的CMake支持
enable_language(C ASM)
# 为库定义编译时的宏定义
target_compile_definitions(stm32cubemx INTERFACE
USE_HAL_DRIVER # 启用HAL驱动支持
STM32H750xx # 指定目标芯片型号 STM32H750xx
$<$<CONFIG:Debug>:DEBUG> # 在Debug模式下定义DEBUG宏
)
# 为库添加头文件路径
# INTERFACE库的头文件路径会影响所有链接此库的目标
target_include_directories(stm32cubemx INTERFACE
../../Core/Inc # STM32核心文件夹中的头文件
../../Drivers/STM32H7xx_HAL_Driver/Inc # STM32 H7 HAL驱动头文件
../../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy # 旧版HAL驱动头文件
../../Drivers/CMSIS/Device/ST/STM32H7xx/Include # STM32H7系列CMSIS设备头文件
../../Drivers/CMSIS/Include # CMSIS库公共头文件
)
# 为库添加源文件
# INTERFACE库的源文件将包含在所有链接此库的目标中
target_sources(stm32cubemx INTERFACE
../../Core/Src/main.c # 主程序文件
../../Core/Src/gpio.c # GPIO驱动文件
../../Core/Src/memorymap.c # 内存映射文件
../../Core/Src/stm32h7xx_it.c # STM32中断处理文件
../../Core/Src/stm32h7xx_hal_msp.c # STM32硬件抽象层的初始化文件
../../Core/Src/stm32h7xx_hal_timebase_tim.c # STM32时间基准定时器设置
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c # Cortex相关初始化
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c # 系统时钟配置文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c # RCC扩展功能
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c # 闪存驱动文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c # 闪存扩展功能
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c # GPIO驱动
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c # 半主机模式控制
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c # DMA驱动文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c # DMA扩展
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c # MDMA驱动
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c # 电源管理驱动
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c # 电源管理扩展功能
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c # HAL驱动库
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c # I2C驱动文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c # I2C扩展功能
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c # 外部中断驱动文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c # 定时器驱动文件
../../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c # 定时器扩展
../../Core/Src/system_stm32h7xx.c # 系统初始化文件
../../Core/Src/sysmem.c # 系统内存管理文件
../../Core/Src/syscalls.c # 系统调用文件
../../startup_stm32h750xx.s # 启动汇编文件
)
# 设置库的链接目录
target_link_directories(stm32cubemx INTERFACE
# 如果有需要的链接库路径可以添加在此
)
# 为库指定链接的外部库
target_link_libraries(stm32cubemx INTERFACE
# 如果有需要的外部链接库可以添加在此
)
# 验证STM32CubeMX生成的代码是否符合C标准要求
if(CMAKE_C_STANDARD LESS 11)
message(ERROR "Generated code requires C11 or higher") # 如果C标准低于C11,输出错误信息
endif()
四个文件关联(重要)
主 CMakeLists.txt
文件的结构和关联
-
包含工具链文件(
gcc-arm-none-eabi.cmake
) 在主CMakeLists.txt
文件的顶部,使用include()
语句包含了工具链文件gcc-arm-none-eabi.cmake
。这个文件定义了交叉编译的设置,包括 GCC 编译器、链接器等。工具链文件的目的是指定 ARM 编译工具链以及相关的编译和链接选项。include("cmake/gcc-arm-none-eabi.cmake")
-
设置 CMake 项目的核心设置 主 CMake 文件中还设置了一些基本的 CMake 配置,例如 C 标准为 C11,并且指定了编译器的类型。
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON)
这些设置确保了编译过程中使用的 C 标准为 C11。
-
创建可执行目标(
add_executable
) 主CMakeLists.txt
使用add_executable()
创建了一个可执行目标。这个目标的名字是stm32h7-cmake
,并且会链接所有相关的源文件和库。add_executable(${CMAKE_PROJECT_NAME})
-
引入 STM32CubeMX 生成的文件(
add_subdirectory(cmake/stm32cubemx)
) 通过add_subdirectory()
引入了cmake/stm32cubemx
子目录,这个子目录包含了从 STM32CubeMX 工具生成的代码。这些代码包括初始化代码、驱动程序等,这些文件是 STM32 特定的启动和硬件抽象代码。add_subdirectory(cmake/stm32cubemx)
这意味着在主 CMake 项目中,
stm32cubemx
子目录中的CMakeLists.txt
文件会被引入并执行。cmake/stm32cubemx
目录中的文件会作为stm32cubemx
库的源文件链接到主项目中。 -
设置链接目录和库(
target_link_directories
和target_link_libraries
) 主 CMake 文件还设置了可执行目标的链接目录和库。这里通过target_link_libraries()
将stm32cubemx
库链接到可执行文件中。target_link_libraries(${CMAKE_PROJECT_NAME} stm32cubemx)
这会把
stm32cubemx
作为一个 INTERFACE 库链接到项目中,意味着stm32cubemx
库只提供头文件和链接信息,而不包含实际的目标文件或代码。 -
添加源文件和头文件(
target_sources
和target_include_directories
) 在stm32cubemx
子目录的CMakeLists.txt
文件中,使用target_sources()
和target_include_directories()
来添加 STM32CubeMX 生成的源文件和头文件路径:target_sources(stm32cubemx INTERFACE ../../Core/Src/main.c ../../Core/Src/gpio.c ../../Core/Src/memorymap.c ... ) target_include_directories(stm32cubemx INTERFACE ../../Core/Inc ../../Drivers/STM32H7xx_HAL_Driver/Inc ... )
这些源文件和头文件会被添加到
stm32cubemx
INTERFACE 库中,并且通过target_link_libraries()
被链接到主项目。 -
设置编译选项和符号(
target_compile_definitions
)target_compile_definitions()
允许你为编译过程添加一些宏定义,通常用于条件编译。比如:target_compile_definitions(stm32cubemx INTERFACE USE_HAL_DRIVER STM32H750xx $<$<CONFIG:Debug>:DEBUG> )
这会在 STM32CubeMX 生成的代码中定义
USE_HAL_DRIVER
、STM32H750xx
等宏,确保适当的驱动和硬件配置被启用。
文件间的关联总结
CMakeLists.txt
(主项目):- 引入了工具链文件
gcc-arm-none-eabi.cmake
来设置交叉编译环境。 - 创建了可执行目标并链接了 STM32CubeMX 生成的源代码。
- 使用
add_subdirectory()
包含了stm32cubemx
目录,在其中查找 STM32CubeMX 生成的代码。 - 通过
target_sources()
和target_include_directories()
将 STM32CubeMX 的源文件和头文件引入到主项目中。
- 引入了工具链文件
CMakePresets.json
:- 定义了不同的构建配置(Debug、Release 等),并且指定了使用的工具链文件。
- 构建时,
CMakePresets.json
文件提供了针对不同构建类型(例如 Debug 或 Release)配置的 CMake 构建选项。
gcc-arm-none-eabi.cmake
(工具链文件):- 定义了交叉编译工具链,指定了 GCC 编译器、链接器以及相关的选项。
- 定义了目标 CPU(如
-mcpu=cortex-m7
)、优化选项、以及调试和发布模式下的编译标志。
stm32cubemx/CMakeLists.txt
:- 通过
target_sources()
和target_include_directories()
向stm32cubemx
INTERFACE 库添加 STM32CubeMX 生成的源文件和头文件。 - 定义了与 STM32H7 系列 MCU 相关的编译宏,确保适当的硬件和驱动配置。
- 通过
总结起来,主 CMakeLists.txt
文件通过包含工具链文件、添加 STM32CubeMX 子目录、以及配置目标和链接库,成功地将各个模块和文件整合起来,确保了整个 STM32 项目的构建和编译过程。
实际上可以用一个文件解决,这里将 编译工具链 与 **包含源文件以及头文件路径 **拆分开了,目的是保持主文件非必要无需更改,让层次更清晰