c++ - 带有交叉编译、模块和库的 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 项目划分为模块、库和子目录的经验,我很乐意接受任何帮助。
解决方案
推荐阅读
- ios - 是否可以在 Instagram 故事中将链接集成回我的应用程序,例如 Spotify、Pandora 如何使用他们的播放按钮?
- java - 谷歌云语音 SpeechClient 未找到
- mysql - MySQL上的查询缓存是否会在一段时间后自动重置?一些结果缓存了一段时间,但第二天会重置
- php - 当涉及到数千行时,如何优化这个 mysql 查询以更快?
- c - 无法使用通过 brew 安装 GLFW 的 OpenGL 3.3 上下文 macOS 创建窗口
- javascript - 测试来自 POST 请求的多个响应
- microsoft-teams - Microsoft Teams 是否有用于查看用户是否已登录的 API?
- python - Manim 的问题。'转换为 dvi 时出错。'
- python - 这个CNN怎么会有奇数个参数?
- r - How to extract "distance" of the unmatched cases in matchit package?