STM32F4项目CMake添加.a库遇arm_math.h未定义引用及链接错误求助
STM32F4项目集成ARM DSP库的CMake配置问题修复
基于STM32F4芯片开发项目,使用VSCode+CMake编译,无额外库时编译正常,添加arm_math.h后出现**"arm_math.h未定义引用"**错误,同时CMake在执行target_link_libraries(${CMAKE_PROJECT_NAME} ${link_LIBS})时报错:
[cmake] CMake Error at CMakeLists.txt:127 (target_link_libraries):
[cmake] Cannot specify link libraries for target "test" which is not built
[cmake] by this project.
核心错误点分析
- 目标创建顺序错误:
target_link_libraries必须在目标(可执行文件/库)创建后调用,原配置中在add_executable之前就执行该指令,此时${CMAKE_PROJECT_NAME}对应的目标还未生成。 - 预编译库引入方式错误:手动执行
add_library(test STATIC libarm_cortexM4lf_math.a)重复使用项目名test,且未指定库的正确路径,CMake无法定位该库文件。 - 路径语法错误:
link_LIBS中${PROJ_PATH}后缺少斜杠,导致路径拼接失效,无法找到libarm_cortexM4lf_math.a。 - 宏定义重复:既在
symbols_SYMB中定义了ARM_MATH_CM4,又通过add_definitions重复定义,属于冗余配置。
修正后的CMakeLists.txt
cmake_minimum_required(VERSION 3.22) # Setup compiler settings set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) set(PROJ_PATH ${CMAKE_CURRENT_SOURCE_DIR}) message("Build type: " ${CMAKE_BUILD_TYPE}) # # Core project settings # project(test) enable_language(C CXX ASM) # # Core MCU flags, CPU, instruction set and FPU setup # set(CPU_PARAMETERS -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ) # Set linker script set(linker_script_SRC ${PROJ_PATH}/STM32F407VGTX_FLASH.ld) # Link directories set(link_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Middlewares/ST/ARM/DSP/Lib/ ) set(EXECUTABLE ${CMAKE_PROJECT_NAME}) # Link Libraries - 修正路径斜杠 set(link_LIBS libarm_cortexM4lf_math.a ) # # List of source files to compile # set(sources_SRCS ${PROJ_PATH}/Core/Src/main.c ${PROJ_PATH}/Core/Src/adc.c ${PROJ_PATH}/Core/Src/can.c ${PROJ_PATH}/Core/Src/dac.c ${PROJ_PATH}/Core/Src/gpio.c ${PROJ_PATH}/Core/Src/i2c.c ${PROJ_PATH}/Core/Src/log.c ${PROJ_PATH}/Core/Src/tim.c ${PROJ_PATH}/Core/Src/usart.c ${PROJ_PATH}/Core/Src/retarget.c ${PROJ_PATH}/Core/Src/rpm.c ${PROJ_PATH}/Core/Src/stm32f4xx_hal_msp.c ${PROJ_PATH}/Core/Src/stm32f4xx_it.c # ${PROJ_PATH}/Core/Src/syscalls.c ${PROJ_PATH}/Core/Src/sysmem.c ${PROJ_PATH}/Core/Src/system_stm32f4xx.c ${PROJ_PATH}/Core/Startup/startup_stm32f407vgtx.s ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c ) # # Include directories # set(include_path_DIRS ${PROJ_PATH}/Core/Inc ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Inc ${PROJ_PATH}/Drivers/CMSIS/Device/ST/STM32F4xx/Include ${PROJ_PATH}/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy ${PROJ_PATH}/Drivers/CMSIS/Include ${PROJ_PATH}/Middlewares/ST/ARM/DSP/Inc ) # # Symbols definition # set(symbols_SYMB "DEBUG" "STM32F407xx" "USE_HAL_DRIVER" "ARM_MATH_CM4" ) # Link directories setup link_directories(${link_DIRS}) # Executable files - 先创建目标 add_executable(${EXECUTABLE} ${sources_SRCS}) # Link libraries - 目标创建后再链接 target_link_libraries(${EXECUTABLE} PRIVATE ${link_LIBS}) # Include paths target_include_directories(${EXECUTABLE} PRIVATE ${include_path_DIRS}) # Project symbols target_compile_definitions(${EXECUTABLE} PRIVATE ${symbols_SYMB}) # Compiler options target_compile_options(${EXECUTABLE} PRIVATE ${CPU_PARAMETERS} -Wall -Wextra -Wpedantic -Wno-unused-parameter -Og -g3 -ggdb ) # Linker options target_link_options(${EXECUTABLE} PRIVATE -T${linker_script_SRC} ${CPU_PARAMETERS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map --specs=nosys.specs -u _printf_float -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group -Wl,--print-memory-usage ) # Execute post-build to print size add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${EXECUTABLE}> ) # Convert output to hex and binary add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.hex ) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.bin )
关键修改说明
- 调整指令顺序:将
add_executable移到target_link_libraries之前,确保链接操作时目标已存在。 - 修正路径配置:
link_LIBS中直接使用库文件名,配合link_directories指定的路径,CMake会自动查找库文件;同时补全include_path_DIRS中DSP头文件路径的斜杠。 - 移除错误指令:删除
add_library(test STATIC libarm_cortexM4lf_math.a),避免与项目名冲突,直接通过target_link_libraries链接预编译库。 - 清理冗余配置:删除
add_definitions(-DARM_MATH_CM4),保留symbols_SYMB中的宏定义即可。
target_link_libraries与add_library配合的标准用法
如果需要将预编译库作为CMake目标管理(便于复用),可以用以下方式引入:
# 引入预编译静态库作为CMake目标 add_library(arm_math STATIC IMPORTED) set_target_properties(arm_math PROPERTIES IMPORTED_LOCATION ${PROJ_PATH}/Middlewares/ST/ARM/DSP/Lib/libarm_cortexM4lf_math.a INTERFACE_INCLUDE_DIRECTORIES ${PROJ_PATH}/Middlewares/ST/ARM/DSP/Inc ) # 将库目标链接到可执行文件 target_link_libraries(${EXECUTABLE} PRIVATE arm_math)
这种方式更符合CMake的目标管理逻辑,后续其他目标需要使用该库时,直接引用arm_math即可。
内容的提问来源于stack exchange,提问作者ro88
相关产品推荐
相关产品推荐

