CMake C++项目依赖的C语言共享库未自动构建导致链接失败如何解决
问题修复方案
核心问题排查
1. 构建目标依赖关系缺失
你在项目P的target_link_libraries中直接硬编码了库文件路径${S_LIB_DIR}/libS.so、${T_LIB_DIR}/libT.so,没有直接链接CMake构建目标,导致CMake无法感知P和S、T的构建依赖关系,不会自动在构建P之前触发S、T的构建流程。
另外库S的构建脚本中,定义的目标名为sbin,编译后输出的库文件名为libsbin.so,和你P中链接的libS.so文件名不匹配,也是触发链接报错的直接原因之一。
2. 交叉编译配置顺序错误
你在P的CMakeLists.txt中,先include了S、T的构建脚本,后才配置交叉编译工具链参数。虽然T、S的构建脚本中单独重写了工具链配置暂时没出问题,但这个顺序不符合CMake规范,很容易导致编译链不匹配的隐藏问题。另外你原配置中CMAKE_FIND_ROOT_PTH变量名拼写错误,正确应为CMAKE_FIND_ROOT_PATH。
具体修改步骤
第一步:调整P的CMakeLists.txt配置顺序
把交叉编译相关配置挪到include子库构建脚本之前:
cmake_minimum_required(VERSION 2.8) set(P pexec) project(${P}) set(P_DIR ${CMAKE_CURRENT_LIST_DIR}/..) set(P_SRC_DIR ${P_DIR}/src) set(P_INCLUDE_DIR ${P_DIR}/include) set(T_PROGRAM_NAME T) set(T_DIR ${P_DIR}/../Dependencies/T) set(T_LIB_DIR ${P_DIR}/../Dependencies/T/lib) set(S_PROGRAM_NAME S) set(S_DIR ${P_DIR}/../Dependencies/S) set(S_LIB_DIR ${S_DIR}/lib) set(BSP_LIB_DIR ${S_DIR}/bsp/architecture/lib) include(GNUInstallDirs) # 先配置全局编译链参数 set(CMAKE_SYSTEM_NAME linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(COMPILER_TOOLS_DIR ${P_DIR}/../Tools/gnu/aarch64/lin/aarch64-linux/bin) set(CMAKE_C_COMPILER ${COMPILER_TOOLS_DIR}/aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER ${COMPILER_TOOLS_DIR}/aarch64-linux-gnu-g++) set(CMAKE_FIND_ROOT_PATH ${COMPILER_TOOLS_DIR}) # 后include子库构建脚本 include(${S_DIR}/build/build.cmake) include(${T_DIR}/build/build.cmake) # 后续其他配置保持不变
第二步:统一库目标名与链接名
修改S的build.cmake中的目标名,和P中引用的名称对齐:
# S的build.cmake中,把set(S_PROGRAM_NAME sbin)替换为 set(S_PROGRAM_NAME S)
如果T的目标名和引用不一致也需要同步修改。
第三步:修改P的链接配置,直接链接构建目标
把硬编码的库路径换成CMake目标名,这样CMake会自动建立依赖关系,先构建S、T再构建P:
target_link_libraries( ${P} LINK_PUBLIC ${BSP_LIB_DIR}/libbsp.a S # 替换原来的${S_LIB_DIR}/libS.so dl pthread T # 替换原来的${T_LIB_DIR}/libT.so )
同时可以删除P中冗余的T、S头文件路径配置,因为你在S、T的构建脚本中已经通过target_include_directories声明了PUBLIC头文件路径,链接对应目标时会自动继承。
额外优化建议
- 可以删除T、S构建脚本中重复的交叉编译链配置,继承P中定义的全局配置,避免多套配置不一致的问题
- 如果需要保留库文件输出到子库自己的lib目录,保留子库中
CMAKE_LIBRARY_OUTPUT_DIRECTORY的配置即可
内容的提问来源于stack exchange,提问作者Matt Nash
相关产品推荐
相关产品推荐

