2.3 CMake 构建系统
2026/7/19大约 4 分钟项目结构构建系统CMake编译
2.3 CMake 构建系统
📚 本节导读
学习时长:约 20 分钟
难度级别:⭐⭐⭐☆☆
前置知识:第 2.2 节 Kconfig 配置系统
🎯 学习目标
- 理解 OneOS-Lite 的 CMake 构建流程
- 掌握 CMakeLists.txt 的层级结构
- 了解工具链配置和编译选项
- 能够独立编译和调试项目
一、构建系统概述
OneOS-Lite 使用 CMake 作为构建系统,支持多种编译工具链:
| 工具链 | 编译器 | 适用平台 |
|---|---|---|
| ARM GCC | arm-none-eabi-gcc | ARM Cortex-M/A |
| RISC-V GCC | riscv-none-elf-gcc | RISC-V |
| ARM CC | armcc / armclang | Keil MDK |
| MSVC / GCC / Clang | 主机编译器 | SIM 模拟器 |
二、CMake 构建流程
项目配置
│
├── Kconfig 配置
│ └── 生成 os_cfg.h
│
├── CMakeLists.txt (顶层)
│ ├── 设置工具链
│ ├── 设置编译选项
│ ├── 添加子目录
│ │ ├── arch/
│ │ ├── kernel/
│ │ ├── drivers/
│ │ ├── components/
│ │ └── ...
│ └── 添加可执行目标
│
└── 编译
├── 预处理 → 编译 → 汇编
├── 链接 (根据链接脚本)
└── 生成 .elf / .bin / .hex三、CMakeLists.txt 层级结构
3.1 顶层 CMakeLists.txt
# CMakeLists.txt (项目根目录)
cmake_minimum_required(VERSION 3.13)
# 项目信息
project(oneos_lite C ASM)
# 设置工具链
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/tools/toolchain.cmake)
# 全局编译选项
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
# 添加子目录
add_subdirectory(arch)
add_subdirectory(kernel)
add_subdirectory(drivers)
add_subdirectory(components)
add_subdirectory(osal)
add_subdirectory(libc)
add_subdirectory(common)
add_subdirectory(demos)
# 添加可执行文件目标
add_executable(${PROJECT_NAME}
${SOURCES}
)
# 链接脚本
set_target_properties(${PROJECT_NAME} PROPERTIES
LINK_FLAGS "-T${LINKER_SCRIPT}"
)
# 生成二进制文件
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${PROJECT_NAME}> ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${PROJECT_NAME}> ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex
)3.2 内核 CMakeLists.txt
# kernel/CMakeLists.txt
file(GLOB_RECURSE KERNEL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/source/*.c
)
# 添加头文件路径
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# 添加源文件
target_sources(${PROJECT_NAME} PRIVATE
${KERNEL_SOURCES}
)3.3 组件 CMakeLists.txt
# components/CMakeLists.txt
if(OS_USING_FS)
add_subdirectory(fs)
endif()
if(OS_USING_NET)
add_subdirectory(net)
endif()
if(OS_USING_SECURITY)
add_subdirectory(security)
endif()
if(OS_USING_SHELL)
add_subdirectory(shell)
endif()四、工具链配置
4.1 ARM GCC 工具链
# toolchain/arm-gcc.cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 编译器设置
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_SIZE arm-none-eabi-size)
# 编译选项
set(CMAKE_C_FLAGS_INIT
"-mcpu=cortex-m3 -mthumb -mfloat-abi=soft"
" -ffunction-sections -fdata-sections"
" -Wall -Wextra"
)
# 链接选项
set(CMAKE_EXE_LINKER_FLAGS_INIT
"-mcpu=cortex-m3 -mthumb -mfloat-abi=soft"
" -Wl,--gc-sections"
" -specs=nosys.specs -specs=nano.specs"
)4.2 RISC-V GCC 工具链
# toolchain/riscv-gcc.cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR riscv)
set(CMAKE_C_COMPILER riscv-none-elf-gcc)
set(CMAKE_CXX_COMPILER riscv-none-elf-g++)
set(CMAKE_ASM_COMPILER riscv-none-elf-gcc)
set(CMAKE_C_FLAGS_INIT
"-march=rv32imac -mabi=ilp32"
" -ffunction-sections -fdata-sections"
)五、编译选项说明
5.1 常用编译选项
| 选项 | 含义 | 使用场景 |
|---|---|---|
-mcpu=cortex-m3 | 指定目标 CPU | ARM Cortex-M 编译必需 |
-mthumb | 使用 Thumb 指令集 | 减小代码体积 |
-ffunction-sections | 每个函数独立段 | 配合 --gc-sections 去除未用函数 |
-fdata-sections | 每个数据独立段 | 配合 --gc-sections 去除未用数据 |
-Wall -Wextra | 开启所有警告 | 开发阶段 |
-Os | 优化代码体积 | 资源受限设备 |
-O2 | 平衡优化 | 一般场景 |
-Og | 调试优化 | 调试阶段 |
-g | 包含调试信息 | 调试阶段 |
-specs=nano.specs | 使用 newlib-nano | 减小 C 库体积 |
5.2 链接选项
| 选项 | 含义 |
|---|---|
-Wl,--gc-sections | 去除未引用的段 |
-T link.lds | 指定链接脚本 |
-nostartfiles | 不使用标准启动文件 |
-Wl,-Map=output.map | 生成内存映射文件 |
六、构建命令
6.1 基本编译流程
# 1. 创建构建目录
mkdir build && cd build
# 2. 配置项目(指定工具链和项目)
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=toolchain/arm-gcc.cmake \
-DPROJECT=stm32f103zet6-atk-elite
# 3. 编译
make -j$(nproc)
# 4. 查看输出文件
ls -la *.elf *.bin *.hex6.2 使用 Makefile 封装
# 编译项目
make
# 编译特定目标
make stm32f103zet6-atk-elite
# 清理编译产物
make clean
# 烧录到开发板
make flash
# 启动调试
make debug6.3 编译产物
| 文件 | 说明 |
|---|---|
*.elf | ELF 可执行文件(包含调试信息) |
*.bin | 原始二进制文件(用于烧录) |
*.hex | Intel HEX 格式文件(用于烧录) |
*.map | 内存映射文件(分析内存使用) |
*.lst | 反汇编列表文件 |
七、脚本辅助工具
scripts/ 目录提供了构建辅助脚本:
| 脚本 | 功能 |
|---|---|
generate.py | 代码生成工具 |
target.py | 目标平台管理 |
print_helper.py | 输出辅助 |
📝 本节小结
本节介绍了 OneOS-Lite 的 CMake 构建系统:
- 多工具链支持:ARM GCC、RISC-V GCC、Keil ARMCC 等
- 层级构建:顶层 CMakeLists.txt 逐层添加子目录
- 条件编译:根据 Kconfig 配置选择需要编译的组件
- 编译优化:支持体积优化(-Os)和调试优化(-Og)
- 构建产物:生成 elf/bin/hex/map 等多种格式