尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

第四篇:交叉编译与工具链文件——一套代码,多个平台

第四篇:交叉编译与工具链文件——一套代码,多个平台 前言前几篇文章我们写了CMakeLists.txt但里面有一些硬编码的内容arm-none-eabi-gcc编译器名称-mcpucortex-m3CPU 型号stm32f103.ld链接脚本如果换一个芯片比如从 STM32F103 换到 STM32F407这些内容都要改。有没有办法让 CMakeLists.txt 完全不用动只改一个文件就能切换芯片呢答案是工具链文件Toolchain File。 一、什么是交叉编译在继续之前先理解一个概念交叉编译。本地编译在 PC 上编译在 PC 上运行比如你用 VS Code 写了一个 Hello World在电脑上运行交叉编译在 PC 上编译在另一个平台上运行比如在 PC 上编译出单片机可以运行的机器码单片机开发就是典型的交叉编译。我们需要告诉 CMake编译器不是系统的gcc而是arm-none-eabi-gcc目标系统不是 Windows/Linux而是裸机编译选项要根据芯片型号来定这些信息都可以放在工具链文件里。 二、工具链文件长什么样工具链文件本质上就是一个 CMake 脚本里面set()了一系列变量。cmake/arm-none-eabi-gcc.cmake# # 工具链文件ARM GCC 交叉编译配置 # # 1. 目标系统 set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) # 2. 编译器 set(CMAKE_C_COMPILER arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER arm-none-eabi-g) set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) # 3. 编译选项可由用户覆盖 set(MCU_FLAGS -mcpucortex-m3 -mthumb) set(CMAKE_C_FLAGS ${MCU_FLAGS} -Wall -Wextra -stdc11 CACHE STRING FORCE) set(CMAKE_CXX_FLAGS ${MCU_FLAGS} -Wall -Wextra -stdc14 CACHE STRING FORCE) set(CMAKE_ASM_FLAGS ${MCU_FLAGS} CACHE STRING FORCE) set(CMAKE_EXE_LINKER_FLAGS ${MCU_FLAGS} -T ${CMAKE_SOURCE_DIR}/stm32f103.ld CACHE STRING FORCE) # 4. 调试信息 set(CMAKE_C_FLAGS_DEBUG -O0 -g3 CACHE STRING FORCE) set(CMAKE_C_FLAGS_RELEASE -Os CACHE STRING FORCE)注意CACHE STRING FORCE的写法它让这些变量可以被用户在命令行覆盖。 三、如何使用工具链文件使用工具链文件非常简单在cmake配置时通过-DCMAKE_TOOLCHAIN_FILE参数指定cmake -B build -DCMAKE_TOOLCHAIN_FILEcmake/arm-none-eabi-gcc.cmake cmake --build build如果你的工程支持多个芯片平台可以准备多个工具链文件cmake/ ├── arm-none-eabi-gcc-stm32f1.cmake # STM32F1 ├── arm-none-eabi-gcc-stm32f4.cmake # STM32F4 ├── arm-none-eabi-gcc-stm32l4.cmake # STM32L4 └── esp32.cmake # ESP32切换芯片只需要换一个工具链文件。CMakeLists.txt 完全不用动。 四、实战同一份代码编译到不同芯片4.1 项目结构my_firmware/ ├── CMakeLists.txt # 一份完全不用动 ├── cmake/ │ ├── stm32f103.cmake # STM32F103 工具链 │ └── stm32f407.cmake # STM32F407 工具链 ├── src/ │ └── main.c # 一份完全不用动 └── ld/ ├── stm32f103.ld # F103 链接脚本 └── stm32f407.ld # F407 链接脚本4.2 CMakeLists.txt不再包含硬件相关的硬编码cmake_minimum_required(VERSION 3.20) project(MyFirmware C ASM) # 编译选项和链接脚本都在工具链文件中定义 # CMakeLists.txt 只关注“有哪些源文件” add_executable(my_firmware src/main.c src/system.c ) target_include_directories(my_firmware PRIVATE inc/ drivers/inc/ )4.3 编译到 STM32F103cmake -B build_f103 -DCMAKE_TOOLCHAIN_FILEcmake/stm32f103.cmake cmake --build build_f1034.4 编译到 STM32F407cmake -B build_f407 -DCMAKE_TOOLCHAIN_FILEcmake/stm32f407.cmake cmake --build build_f407同一份代码同一个 CMakeLists.txt两个不同的芯片两套独立的编译产物。⚙️ 五、CMake Presets更优雅的切换方式如果你的项目支持多个平台每次都要输入长长的命令有点麻烦。CMake 3.19 支持CMake Presets可以把配置写在CMakePresets.json里。CMakePresets.json{ version: 3, configurePresets: [ { name: stm32f103, displayName: STM32F103, generator: Ninja, binaryDir: ${sourceDir}/build_f103, cacheVariables: { CMAKE_TOOLCHAIN_FILE: ${sourceDir}/cmake/stm32f103.cmake } }, { name: stm32f407, displayName: STM32F407, generator: Ninja, binaryDir: ${sourceDir}/build_f407, cacheVariables: { CMAKE_TOOLCHAIN_FILE: ${sourceDir}/cmake/stm32f407.cmake } } ] }之后只需要cmake --preset stm32f103 cmake --build build_f103 六、总结工具链文件的核心价值把“硬件相关”的配置从 CMakeLists.txt 中抽离出来。放在 CMakeLists.txt 中放在工具链文件中项目名称编译器路径源文件列表CPU 型号头文件路径编译选项模块依赖链接脚本这样做的好处CMakeLists.txt 只关注“代码组织”不关注“硬件差异”换芯片 换工具链文件业务代码完全不动同一份代码可以在 CI 中并行编译到多个平台
返回列表