C++链接错误:libtorch与OpenNMTTokenizer.so联编出现undefined reference
问题根因分析
- C++ ABI不兼容(90%以上概率)
libtorch官方预编译包为了兼容旧版系统,默认编译时开启了-D_GLIBCXX_USE_CXX11_ABI=0选项,禁用了C11及以后版本的新ABI规则。而你编译安装的OpenNMTTokenizer.so如果没有手动指定这个编译选项,默认会用_GLIBCXX_USE_CXX11_ABI=1的新ABI,两类ABI下相同C类/函数的符号名(name mangling结果)完全不同,链接时自然无法匹配到onmt::Tokenizer的对应符号。
单独链接其中任意一个库时,整个项目的ABI是统一的,所以不会报错,只有同时依赖两个不同ABI的库时才会触发问题。 - 链接顺序错误
CMake的target_link_libraries遵循依赖前置的规则,如果你的写法是把OpenNMTTokenizer.so放在libtorch前面,部分ld版本会因为符号检索顺序问题漏扫依赖,也会导致找不到符号。
解决方案
方案1:统一ABI规则(优先推荐)
两种选择二选一即可:
- 重新编译OpenNMTTokenizer,编译时指定和libtorch一致的ABI选项,编译OpenNMTTokenizer的CMake命令加上参数:
cmake .. -DCMAKE_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=0"
重新编译安装后再构建你的项目即可。
2. 如果你用的是支持C++11 ABI版本的libtorch(PyTorch 1.6+都提供对应预编译包),可以在你自己的项目CMakeLists.txt里显式指定和OpenNMTTokenizer一致的ABI,在find_package(Torch)之前加入:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=1")
如果是自行编译libtorch,编译时加上-D_GLIBCXX_USE_CXX11_ABI=1参数即可。
方案2:调整链接顺序
如果确认ABI一致还是报错,调整CMakeLists.txt里的链接顺序,把被依赖的库放在后面:
# 正确顺序:你的目标文件在前,上层依赖放前,底层依赖放最后 target_link_libraries(your_target_name OpenNMTTokenizer ${TORCH_LIBRARIES} )
排查验证方法
可以用nm命令验证两个库的ABI是否一致:
# 查看OpenNMTTokenizer里的Tokenizer符号 nm -D /path/to/libOpenNMTTokenizer.so | grep "onmt.*Tokenizer" # 查看你的项目编译出来的中间目标文件里的符号需求 nm your_test.cpp.o | grep "onmt.*Tokenizer"
如果两者输出的符号名有明显区别(比如一个带[abi:cxx11]标记一个不带),就可以确认是ABI不兼容问题。
内容的提问来源于stack exchange,提问作者Inez A
相关产品推荐
相关产品推荐

