CMake链接git子模块spdlog静态库到.so共享库报重定位错误
问题根因
报错的核心原因是:你链接到Engine共享库(.so)的spdlog静态库,编译时没有开启位置无关代码(-fPIC)选项。
x86_64 Linux平台下,所有要被链接进共享对象的目标文件/静态库,必须使用-fPIC参数编译生成位置无关代码,否则链接阶段就会抛出你看到的R_X86_64_TPOFF32重定位错误。你直接通过add_subdirectory引入spdlog时,spdlog默认编译的静态库是为可执行文件链接准备的,默认未开启PIC选项,不满足共享库的链接要求。
解决方案
二选一即可,优先选第一种,符合spdlog官方推荐的静态使用方式。
方案1:编译spdlog静态库时开启PIC(推荐)
修改Engine目录下的CMakeLists.txt,在引入spdlog子目录前,开启spdlog的PIC编译配置:
message(STATUS "BUILD Engine shared library File") # 强制spdlog静态库开启PIC编译,适配共享库链接要求 set(SPDLOG_ENABLE_PIC ON CACHE BOOL "Build spdlog with position independent code" FORCE) add_subdirectory(spdlog) add_library(Engine SHARED Log.cpp Log.h) target_include_directories(Engine INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries(Engine PUBLIC spdlog)
注意:把spdlog的链接权限改成PUBLIC,这样依赖Engine的可执行目标会自动继承spdlog的头文件路径,不需要你手动配置spdlog的include目录。
方案2:将spdlog编译为共享库
如果你不需要静态链接spdlog,可以直接把spdlog编译为动态库,天然满足PIC要求:
在add_subdirectory(spdlog)前添加配置:
set(SPDLOG_BUILD_SHARED ON CACHE BOOL "Build spdlog as shared library" FORCE)
这种方式的缺点是部署时需要额外携带spdlog的.so文件,不符合官方静态使用的推荐。
额外配置优化建议
你现有CMake配置存在几处冗余/不规范点,可以顺手调整:
- 已经通过
set(CMAKE_CXX_STANDARD 17)配置了C++标准,不需要在CMAKE_CXX_FLAGS里重复加-std=c++17,重复配置可能跨编译器时出现兼容问题 CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS是Windows平台专属配置,在Linux下编译.so完全无效,可以加平台判断包裹,避免无效配置- 不需要手动为Engine添加spdlog的include路径,通过
target_link_libraries链接spdlog时,CMake会自动传递spdlog配置的头文件搜索路径,手动硬编码路径在spdlog版本更新后容易出现路径不匹配问题。
修改完配置后,建议先删除整个build目录重新编译,避免旧的无PIC的spdlog静态库缓存导致报错复现。
内容的提问来源于stack exchange,提问作者miyoku
相关产品推荐
相关产品推荐

