You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地正常但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后问题解决,但不确定这是否是正确做法,还是只是掩盖了其他问题。我的库代码中并未直接使用上述错误中的函数。

我的问题:

  1. 为什么本地构建正常,但GitHub Actions中失败?
  2. 我所做的修复是否正确?

本地环境: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:25:53