本地正常但GitHub Actions编译C++动态库遇pthread/dl未定义引用问题
问题描述
我正在开发一个基于SQLite的C++17动态库,采用CMake构建,因为计划通过JNI调用,所以必须编译为动态库。
项目中SQLite被编译为静态库:
add_library(sqlite3 STATIC "${sqlite3_SOURCE_DIR}/sqlite3.c") # STATIC to efficiently link to SHARED main library set_target_properties(sqlite3 PROPERTIES POSITION_INDEPENDENT_CODE ON) # Required to link STATIC to SHARED target_include_directories(sqlite3 PUBLIC "${sqlite3_SOURCE_DIR}")
主库编译为共享库:
add_library(${PROJECT_NAME} SHARED <library sources>) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # To include headers without using relative paths target_link_libraries(${PROJECT_NAME} PRIVATE sqlite3)
本地链接可执行文件时构建运行正常:
add_executable(app <app's sources>) target_compile_features(app PUBLIC cxx_std_17) target_include_directories(app PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} <main library src dir>) # Including the main library like this is a temporary solution, because there is no separate include dir yet target_link_libraries(app PUBLIC ${PROJECT_NAME})
但在GitHub Actions构建时出现链接错误:
[100%] Linking CXX executable app /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_mutexattr_destroy' /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_create' /usr/bin/ld: ../src/mylib.so: undefined reference to `dlopen' /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_mutex_trylock' /usr/bin/ld: ../src/mylib.so: undefined reference to `dlclose' /usr/bin/ld: ../src/mylib.so: undefined reference to `dlerror' /usr/bin/ld: ../src/mylib.so: undefined reference to `dlsym' /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_mutexattr_settype' /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_join' /usr/bin/ld: ../src/mylib.so: undefined reference to `pthread_mutexattr_init' collect2: error: ld returned 1 exit status
我尝试将主库链接到${CMAKE_DL_LIBS}和Threads::Threads后问题解决,但不确定这是否是正确做法,还是只是掩盖了其他问题。我的库代码中并未直接使用上述错误中的函数。
我的问题:
- 为什么本地构建正常,但GitHub Actions中失败?
- 我所做的修复是否正确?
本地环境:Ubuntu 22.04(WSL),GCC 11.3.0;GitHub Actions环境:Ubuntu 20.04,GCC 9.4.0。
问题解答
1. 本地与GitHub Actions构建差异的原因
核心是GCC版本差异导致的链接行为变化:
- 较新版本的GCC(如本地的11.3.0)在链接共享库时,会自动处理部分依赖的传递性,或者系统默认链接选项会隐式包含
pthread和dl相关库,间接满足了静态链接的SQLite的依赖需求。 - 旧版本GCC(如GitHub Actions中的9.4.0)对链接依赖的处理更严格,不会自动添加这些系统库。SQLite默认启用线程安全和动态加载扩展功能,这两个特性分别依赖
pthread和dl库;由于你将SQLite编译为静态库,这些依赖不会自动传递到主共享库,在旧版GCC环境下就会出现未定义引用错误。
2. 修复方式的正确性
你的修复是正确且规范的做法:
- SQLite的线程安全模式确实需要依赖
pthread库,使用Threads::Threads是CMake跨平台链接线程库的标准方式,能自动适配不同系统的线程库配置。 CMAKE_DL_LIBS是CMake提供的变量,会自动指向系统中的动态加载库(如Linux下的libdl),正好对应SQLite动态扩展功能的依赖需求。- 虽然你的代码没有直接调用这些函数,但静态链接的SQLite内部使用了它们,因此必须显式将这些依赖添加到主共享库的链接项中,确保所有符号都能被正确解析。这不是掩盖问题,而是补全了静态库依赖的系统级链接项,完全符合CMake的依赖管理规范。
内容的提问来源于stack exchange,提问作者Eyjafl
相关产品推荐
相关产品推荐

