Conan构建C++项目升级Thrift至v0.15时出现链接报错
问题根因
这个报错和libevent、手动补充的系统依赖无关,核心是Thrift 0.14版本做了模块拆分:原0.13版本中编译进libthrift核心静态库的异步模块实现(包含apache::thrift::async::TConcurrentClientSyncInfo类的全部成员方法),从0.14开始被独立拆分到libthriftnb静态库中,属于版本升级未在文档明确标注的破坏性变更,旧配置只链核心库自然会出现符号缺失。
静态库链接顺序错误、Conan包编译选项缺失是这类升级后链接错误的次要诱因。
解决步骤
按顺序操作,每步做完可以先试编译,不用全做完:
- 清理CMakeLists中冗余的手动链接项
删掉你之前临时加的裸库名形式的thriftnb、event、手动指定的openssl/zlib/librt链接项。Conan生成的CONAN_PKG::*目标已经自带所有传递依赖的链接属性、头文件路径,手动硬编码系统库名很容易打乱静态库的链接顺序,反而触发符号解析失败。 - 重新编译本地Conan缓存的Thrift 0.15包,确保异步模块开启
很多人安装Thrift 0.15时用了默认配置,Conan包默认关闭libevent(异步模块)编译开关,就算你写了链接CONAN_PKG::thriftnb,实际库文件里也没有异步相关的符号。在项目根目录执行以下命令强制重编译Thrift,带上必要的编译选项:conan install . --build=thrift -s build_type=Release \ --options thrift:with_libevent=True \ --options thrift:with_openssl=True \ --options thrift:fPIC=True - 修正CMake目标的链接顺序
GCC/Clang对静态库的符号解析严格按输入顺序从左到右执行,依赖其他库的模块必须放在被依赖模块的前面。将jokers_server目标的链接配置改成如下形式即可:
不需要手动加libevent、openssl、zlib、rt这些依赖,target_link_libraries(jokers_server PRIVATE CONAN_PKG::ibsapi CONAN_PKG::thriftnb CONAN_PKG::thrift pthread )CONAN_PKG::thriftnb和CONAN_PKG::thrift已经通过接口属性透传了这些依赖,CMake会自动按正确顺序追加到链接命令中。
校验&排障
如果做完以上步骤还是报错,按以下方法定位:
- 校验静态库内是否存在缺失符号
从Conan日志里找到libthriftnb.a的本地缓存路径,执行以下命令查符号:
如果输出中没有对应类的成员方法(标记为nm -gC /你的/conan缓存路径/libthriftnb.a | grep TConcurrentClientSyncInfoT的全局文本段符号),说明Thrift包编译时没正确开启异步模块,回到上一步重新带选项编译即可。 - 排查头文件/库版本混链
检查编译日志的头文件搜索路径,确保没有引用系统预装的0.13版本Thrift头文件:如果编译时用0.13的头文件生成符号引用,链接时用0.15的库,会因为符号修饰、类结构变更出现不匹配的undefined reference错误。可以在编译选项中加-H参数,输出所有引用的头文件路径,确认所有thrift/开头的头文件都来自Conan缓存目录。 - 排查静态库fPIC选项
如果你的项目依赖的其他静态库开启了fPIC编译,Thrift库没开的话也会触发链接阶段异常,重编译Thrift时带上之前提的thrift:fPIC=True选项即可解决。
内容的提问来源于stack exchange,提问作者Erik
相关产品推荐
相关产品推荐

