首页 > 解决方案 > 带有交叉编译、模块和库的 CMake 设置

问题描述

我正在尝试编写一个适当的 CMake 脚本来构建嵌入式项目(STM32)。我们的项目结构如下所示:

App/
....Module1/
....Module2/
Core/
....OwnFramework/
........CoreModule1/
........CoreModule2/
....CubeMXGeneratedCode/
........Core/ (there are more files and dirs, but they are not relevant)
...........Src/main.c (only important info is that main is here)
........Drivers/
....Libs/
........Lib1/ (for example ETL)

现在根项目目录中有一个 CMakeLists.txt 文件,但这似乎是一个糟糕的解决方案。我尝试将 CMakeLists 添加到 App/ 和 App/Module 中,但随后会出现链接错误(在查看 compile_commands 时,我发现它们是在几乎没有标志的情况下编译的)。

./CMakeLists.txt (删除了一些不重要的部分,比如设置变量很明显,所以它有点短)

set(APP_INCLUDE_DIRECTORIES
    ${APP_DIR}/Module1
    ${APP_DIR}/Module2
)

set(CORE_INCLUDE_DIRECTORIES
    ${Core_DIR}/CoreModule1
    ${Core_DIR}/CoreModule2
)

set(FLAGS
    "-Wl,--gc-sections")
set(CPP_FLAGS
    "-fno-rtti -fno-exceptions -fno-threadsafe-statics")

set(CPU_PARAMETERS
    -mcpu=cortex-m4
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard)

set(STARTUP_SCRIPT ${CUBEMX_DIR}/startup_stm32fxxxxx.s)
set(MCU_LINKER_SCRIPT ${CUBEMX_DIR}/STM32Fxxxxxxx_FLASH.ld)

set(CUBEMX_INCLUDE_DIRECTORIES
    ${CUBEMX_DIR}/Core/Inc
    ... and some more Inc dirs
set(PROJECT_INCLUDE_DIRECTORIES
    ${CMAKE_SOURCE_DIR}
    ${APP_INCLUDE_DIRECTORIES}
    ${CORE_INCLUDE_DIRECTORIES})

file(GLOB_RECURSE STM32CUBEMX_SOURCES
    ${CUBEMX_DIR}/Core/*.c
    ${CUBEMX_DIR}/Drivers/*.c
    ${CUBEMX_DIR}/Middlewares/Third_Party/FreeRTOS/Source/*.c)

file(GLOB_RECURSE PROJECT_SOURCES FOLLOW_SYMLINKS
    ${APP_DIR}/*.cpp
    ${APP_DIR}/*.c
    ${CORE_DIR}/*.cpp
    ${CORE_DIR}/*.c)

add_executable(${EXECUTABLE}
    ${STM32CUBEMX_SOURCES} 
    ${PROJECT_SOURCES}
    ${STARTUP_SCRIPT})

target_compile_definitions(${EXECUTABLE} PRIVATE
    ${MCU_MODEL}
    USE_HAL_DRIVER)

target_include_directories(${EXECUTABLE} PRIVATE
    ${CUBEMX_INCLUDE_DIRECTORIES}
    ${PROJECT_INCLUDE_DIRECTORIES})

target_compile_options(${EXECUTABLE} PRIVATE
    ${CPU_PARAMETERS}
    ${FLAGS}
    -Wall
    -Wextra
    -Wpedantic
    -Wno-unused-parameter
    $<$<COMPILE_LANGUAGE:CXX>:
    ${CPP_FLAGS}
    -Wno-volatile
    -Wold-style-cast
    -Wuseless-cast
    -Wsuggest-override>
    $<$<CONFIG:Debug>:-Og -g3 -ggdb>
    $<$<CONFIG:Release>:-Og -g0>)

target_link_options(${EXECUTABLE} PRIVATE
    -T${MCU_LINKER_SCRIPT}
    ${CPU_PARAMETERS}
    -Wl,-Map=${CMAKE_PROJECT_NAME}.map
    --specs=nosys.specs
    -Wl,--start-group
    -lc
    -lm
    -lstdc++
    -lsupc++
    -Wl,--end-group
    -Wl,--print-memory-usage)

add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
    COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${EXECUTABLE}>)

add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}>
    ${EXECUTABLE}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}>
    ${EXECUTABLE}.bin)

还有工具链文件:

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(FLAGS
    "-fdata-sections -ffunction-sections \
    --specs=nano.specs -Wl,--gc-sections")

set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc ${FLAGS})
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ ${FLAGS})
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)

我正在使用此命令构建所有内容:

cmake -B${workspaceFolder}/build -DCMAKE_TOOLCHAIN_FILE=gcc-arm-none-eabi.cmake -DCMAKE_BUILD_TYPE=Debug

这个设置很有效,但我觉得这是一种很糟糕的做法。当我尝试在 App 和每个模块中添加子目录时,由于编译标志的问题(arm none eabi elf 使用 VFP 寄存器参数链接错误),我遇到了链接错误。我也不确定当我开始添加像嵌入式模板库这样的库时它的效果如何。所以我的问题是,如何添加子目录,以便它们以与我的根 CMakeLists 相同的方式编译?我已经尝试按照以下多个指南和示例进行此操作:https ://github.com/rgujju/STM32_Base_Project/blob/master/modules/simple_module/CMakeLists.txt 。但是当我把它放在我的 App/Module/CMakeLists.txt

set(MODULE_NAME simple_module)

file(GLOB SOURCES ./*.c)

add_library(${MODULE_NAME} STATIC
    ${SOURCES}
    )

target_include_directories(${MODULE_NAME}
    PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}
    ${PROJECT_SOURCE_DIR}/include
    )

并将 add_subdirectory(App) 添加到 main,我为没有我的大部分标志且没有链接的模块生成的命令。如果有人有将 CMake 项目划分为模块、库和子目录的经验,我很乐意接受任何帮助。

标签: c++ccmakeembeddedstm32

解决方案


推荐阅读