尽管已在CMake中指定了库,但仍存在未定义的参考错误(与libtorch链接的问题(C ++ 11 ABI?) [英] Undefined reference error despite of having the library specified in CMake (Issues linking with libtorch (C++11 ABI?)

查看:231
本文介绍了尽管已在CMake中指定了库,但仍存在未定义的参考错误(与libtorch链接的问题(C ++ 11 ABI?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从我制作的库中创建一个测试可执行文件.让我们将它们命名为lib1和lib2.lib1和它的测试一起构建就好了.lib2的构建也没有任何问题.但是,每当我尝试将lib2与其测试可执行文件(即使用lib2的示例程序)链接时,都会出现以下错误:

  usr/bin/ld:CMakeFiles/Lib2_Test.dir/Lib2_Test.cpp.o:在函数main中:Lib2_Test.cpp :(.text + 0xf3):未定义引用`Lib2 :: Lib2(std :: __ cxx11 :: basic_string< char,std :: char_traits< char> ;, std :: allocator< char> ;, std::__ cxx11 :: basic_string< char,std :: char_traits< char> ;, std :: allocator< char>> ;, int,int)'/usr/bin/ld:Lib2_Test.cpp :(.text + 0x3f5):对`Lib2 :: Evaluate(bool& ;, std :: __ cxx11 :: basic_string< char,std :: char_traits< char> ;, std:的未定义引用:allocator< char>& ;, float& ;, cv :: Mat& ;, cv :: Mat& ;, bool)'collect2:错误:ld返回1退出状态make [2]:*** [CMakeFiles/Lib2_Test.dir/build.make:130:Lib2_Test]错误1make [1]:*** [CMakeFiles/Makefile2:76:CMakeFiles/Lib2_Test.dir/all]错误2make:*** [Makefile:130:全部]错误2 

我尝试使用 readelf -d ldd 命令查看标头,两个库似乎都具有所有必需的引用.但是lib1没有任何问题,而lib2链接到使用它的可执行文件时会生成未引用的相关错误.

下面是我为它们创建的cmakeList,后来我还包含了 readelf 的输出.

lib1 的

CMakelist.txt:

  cmake_minimum_required(版本3.11)项目(库1)设置(CMAKE_CXX_STANDARD 17)find_package(需要火炬)find_package(需要OpenCV)add_definitions(-D_LIB1_BUILD_DLL)set(CMAKE_CXX_FLAGS"$ {CMAKE_CXX_FLAGS} -fPIC")设置(CMAKE_INSTALL_PREFIX/home/me/Desktop/LibtorchPort/built_stuff)include_directories(/home/me/Desktop/LibtorchPort/Dependencies/include $ {TORCH_INCLUDE_DIRS} $ {OpenCV_INCLUDE_DIRS})LINK_DIRECTORIES(/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib)#http://dlib.net/examples/CMakeLists.txt.htmladd_subdirectory(/home/me/dlib-19.21/home/me/dlib-19.21/build)设置(Lib1_SRC ./lib1.cpp)add_library(lib1 SHARED $ {Lib1_SRC})# 关联target_link_libraries(lib1 $ {TORCH_LIBRARIES})target_link_libraries(lib1 $ {OpenCV_LIBS})target_link_libraries(lib1 dlib :: dlib)安装(TARGETS lib1 LIBRARY DESTINATION lib) 

这是 lib1_test 的CMakeList.txt:

  cmake_minimum_required(版本3.11)项目(Lib1_Test)设置(CMAKE_CXX_STANDARD 17)find_package(需要火炬)find_package(需要OpenCV)设置(CMAKE_INSTALL_PREFIX/home/me/Desktop/LibtorchPort/built_stuff)include_directories(/home/me/Desktop/LibtorchPort/Dependencies/include $ {TORCH_INCLUDE_DIRS} $ {OpenCV_INCLUDE_DIRS})# 关联add_executable(lib1_dynamic_test ./Lib1_Test.cpp)target_link_directories(lib1_dynamic_test PRIVATE/home/me/Desktop/LibtorchPort/Lib1/build)target_link_libraries(lib1_dynamic_test lib1)target_link_libraries(lib1_dynamic_test $ {TORCH_LIBRARIES})target_link_libraries(lib1_dynamic_test $ {OpenCV_LIBS})安装(TARGETS lib1_dynamic_test DESTINATION bin) 

这是 lib2 的CMakeList.txt:

  cmake_minimum_required(版本3.11)项目(库2)设置(CMAKE_CXX_STANDARD 17)find_package(需要火炬)find_package(需要OpenCV)add_definitions(-D_LIB2_BUILD_DLL)设置(CMAKE_INSTALL_PREFIX/home/me/Desktop/LibtorchPort/built_stuff)include_directories(/home/me/Desktop/LibtorchPort/Dependencies/include $ {TORCH_INCLUDE_DIRS} $ {OpenCV_INCLUDE_DIRS})LINK_DIRECTORIES(/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib)LINK_DIRECTORIES(/home/me/Desktop/LibtorchPort/Lib1/build)设置(LIB2_SRC ./lib2.cpp)add_library(lib2_dynamic SHARED $ {LIB2_SRC})target_link_directories(lib2_dynamic PRIVATE/home/me/Desktop/LibtorchPort/Lib1/build)target_link_libraries(lib2_dynamic lib1)target_link_libraries(lib2_dynamic $ {TORCH_LIBRARIES})target_link_libraries(lib2_dynamic $ {OpenCV_LIBS})安装(TARGETS lib2_dynamic库目标库lib) 

最后是 lib2_test 的CMakeList:

  cmake_minimum_required(版本3.11)项目(Lib2_Test)设置(CMAKE_CXX_STANDARD 17)设置(CMAKE_INSTALL_PREFIX/home/me/Desktop/LibtorchPort/built_stuff)#find_package(需要使用火炬)find_package(需要OpenCV)include_directories(/home/me/Desktop/LibtorchPort/Dependencies/include $ {OpenCV_INCLUDE_DIRS})LINK_DIRECTORIES(/home/me/Desktop/LibtorchPort/Lib1/build)add_executable(Lib2_Test ./lib2_test.cpp)target_link_directories(Lib2_Test PRIVATE/home/me/Desktop/LibtorchPort/Lib2/build)#target_link_directories(Lib2_Test PUBLIC/home/me/Desktop/LibtorchPort/Lib1/build)#关联target_link_libraries(Lib2_Test $ {OpenCV_LIBS})target_link_libraries(Lib2_Test lib2_dynamic)安装(TARGETS Lib2_Test DESTINATION bin) 

运行 readelf -d lib1 ,这是我得到的输出:

 偏移量为0x908f8的动态部分包含38个条目:标签类型名称/值0x0000000000000001(需要)共享库:[libtorch.so]0x0000000000000001(需要)共享库:[libc10.so]0x0000000000000001(需要)共享库:[libtorch_cpu.so]0x0000000000000001(需要)共享库:[libopencv_highgui.so.3.4]0x0000000000000001(需要)共享库:[libopencv_imgproc.so.3.4]0x0000000000000001(需要)共享库:[libopencv_core.so.3.4]0x0000000000000001(需要)共享库:[libcblas.so.3]0x0000000000000001(需要)共享库:[liblapack.so.3]0x0000000000000001(需要)共享库:[libstdc ++.so.6]0x0000000000000001(需要)共享库:[libm.so.6]0x0000000000000001(需要)共享库:[libgcc_s.so.1]0x0000000000000001(需要)共享库:[libc.so.6]0x0000000000000001(需要)共享库:[ld-linux-x86-64.so.2]0x000000000000000e(SONAME)库soname:[libLib1.so]0x000000000000001d(RUNPATH)库运行路径:[/home/me/anaconda3/lib/python3.8/site-packages/torch/lib:/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib:/usr/local/lib:]0x000000000000000c(初始值)0x1a0000x000000000000000d(FINI)0x57e000x0000000000000019(INIT_ARRAY)0x90b280x000000000000001b(INIT_ARRAYSZ)32(字节)0x000000000000001a(FINI_ARRAY)0x90b480x000000000000001c(FINI_ARRAYSZ)8(字节)0x000000006ffffef5(GNU_HASH)0x3280x0000000000000005(STRTAB)0x68400x0000000000000006(SYMTAB)0x17580x000000000000000a(STRSZ)56053(字节)0x000000000000000b(SYMENT)24(字节)0x0000000000000003(PLTGOT)0x920000x0000000000000002(PLTRELSZ)8112(字节)0x0000000000000014(PLTREL)RELA0x0000000000000017(JMPREL)0x17ff00x0000000000000007(RELA)0x14b580x0000000000000008(RELASZ)13464(字节)0x0000000000000009(相关)24(字节)0x000000006ffffffe(VERNEED)0x149f80x000000006fffffff(VERNEEDNUM)50x000000006ffffff0(VERSYM)0x143360x000000006ffffff9(RELACOUNT)60x0000000000000000(NULL)0x0 

这是 lib2 的输出:

 偏移量为0x37ba0的动态部分包含32个条目:标签类型名称/值0x0000000000000001(需要)共享库:[libLib1.so]0x0000000000000001(需要)共享库:[libtorch.so]0x0000000000000001(需要)共享库:[libtorch_cpu.so]0x0000000000000001(需要)共享库:[libopencv_core.so.3.4]0x0000000000000001(需要)共享库:[libstdc ++.so.6]0x0000000000000001(需要)共享库:[libgcc_s.so.1]0x0000000000000001(需要)共享库:[libc.so.6]0x000000000000000e(SONAME)库soname:[libLib2_dynamic.so]0x000000000000001d(RUNPATH)库运行路径:[/home/me/anaconda3/lib/python3.8/site-packages/torch/lib:/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib:/home/me/Desktop/LibtorchPort/Lib1/build:/usr/local/lib:]0x000000000000000c(INIT)0x1e0000x000000000000000d(FINI)0x2ec100x0000000000000019(INIT_ARRAY)0x381080x000000000000001b(INIT_ARRAYSZ)16(字节)0x000000000000001a(FINI_ARRAY)0x381180x000000000000001c(FINI_ARRAYSZ)8(字节)0x000000006ffffef5(GNU_HASH)0x2f00x0000000000000005(STRTAB)0x7d880x0000000000000006(SYMTAB)0x1dd00x000000000000000a(STRSZ)62708(字节)0x000000000000000b(SYMENT)24(字节)0x0000000000000003(PLTGOT)0x390000x0000000000000002(PLTRELSZ)14784(字节)0x0000000000000014(PLTREL)RELA0x0000000000000017(JMPREL)0x19e900x0000000000000007(RELA)0x17b380x0000000000000008(RELASZ)9048(字节)0x0000000000000009(相关)24(字节)0x000000006ffffffe(VERNEED)0x17a780x000000006fffffff(VERNEEDNUM)30x000000006ffffff0(VERSYM)0x1727c0x000000006ffffff9(RELACOUNT)40x0000000000000000(NULL)0x0 

然而, lib1 的构建和链接很好,而依赖于 lib1 lib2 链接到其测试时存在问题或任何其他库.我在这一点上一无所知,不知道是什么原因造成的.我想念什么?

更新1

这是 lib2_test.cpp : https://paste.ee/p/pOgFk 头文件就是这样的:

 <代码> #ifndef Lib2_H#定义Lib2_H/*如果我们在Windows上,则需要一个单独的定义.*/#if!defined(_WIN32)&&(已定义(__WIN32__)||已定义(WIN32)||已定义(__MINGW32__))#定义_WIN32#endif/* _WIN32 */#if defined(_WIN32)&&定义的(_Lib2_BUILD_DLL)/*我们正在将Lib2构建为Win32 DLL */#定义LIB2_API __declspec(dllexport)#elif define(_WIN32)&&已定义(Lib2_DLL)/*我们将Lib2称为Win32 DLL */#定义LIB2_API __declspec(dllimport)#elif define(__ GNUC__)&&定义的(_Lib2_BUILD_DLL)/*我们正在将Lib2构建为共享/动态库*/#定义LIB2_API __attribute __((visibility(默认"))))#别的/*我们正在将Lib2构建或调用为静态库*/#定义LIB2_API#万一#include< string>#include< vector>#include< map>#include< memory>#include< opencv2/core.hpp>枚举类ValidationStatus{无= -1,UnderValidation = 0,已验证= 1,无效= 2异常检测= 3,ToomuchAnonalyDetected = 4};typedef std :: tuple< ValidationStatus,std :: string,bool>Lib2Result;类Lib2Impl;类LIB2_API Lib2{私人的:std :: shared_ptr< Lib2Impl>Lib2;上市:Lib2(std :: string shape_predictor_path =,std :: string eyeNet_path =",int valid_presence_delay = 5,int fpasPassed = 0);std :: vector< Lib2Result>运行(std :: map< std :: string,bool>&validity_result,std :: vector< std :: tuple< std :: string,float>&ID,std :: vector< cv :: Mat>&面孔,cv :: Mat&originalImage,bool show_debug_info = false);Lib2Result Evaluate(bool& status,std :: string& name,float& theta,cv :: Mat& face_image,cv :: Mat& originalImage,bool debug_info = true);〜Lib2();};#endif//!Lib2_H 

关于注释,您可以看到 lib2_test.cpp 上的调用是正常的,并且使用相同的签名.

更新2

我还需要添加此内容,该项目在Windows中使用Visual Studio构建得很好,也可以使用cmake!但是在Linux(ubuntu 20.04),我正在面对这些问题.因此,这不仅是调用不同/错误的方法或使用错误的签名.该代码应该可以编译和链接,但是我在这里做错了什么,我不确定它是什么.

注释2

lib1和lib2只是由实际文件名组成的名称(我只是选择lib1和lib2来简化内容,并在此处替换了名称,因此,如果您发现大小写有所不同,请不要介意实际文件名一样.

解决方案

摘要

第三方库(火炬)是使用 Pre-cxx11 ABI构建的,并且使用该库构建的库显然无法链接到使用 cxx11 ABI!

详细说明

经过数小时的调试,在Visual Studio和CMake中,它们在Windows中都可以正常工作,而在Linux中却令人头痛,我找到了罪魁祸首!

libtorch附带两种类型的构建 Pre-cxx11 cxx11 ABI!它使用它的Python软件包(torch1.6cpu)附带的 Pre-cxx11 构建的库,并且由于Anaconda3在Path中,并且我也使用它来构建库,所以我遇到了这个问题.

所有这些时间后,遗忘了未定义方法的怪异参数: std :: __ cxx11 :: basic_string 应该只是 std :: string .我没想到这两者会有所不同并且以为,那是g ++直到现在才使用的奇怪的命名方案,这让我说,让我们进行搜索,也许我可以从中找到一些东西!瞧!就是这种情况:

如果收到有关未定义符号引用的链接器错误,涉及std :: __ cxx11命名空间或标记[abi:cxx11]中的类型那么它可能表明您正在尝试将对象链接在一起使用不同值编译的文件_GLIBCXX_USE_CXX11_ABI宏.当链接到使用旧版GCC编译的第三方库时,通常会发生这种情况.如果第三方库无法使用新的ABI重建,那么您将需要使用旧的ABI重新编译代码.

ref

要解决此问题,我仅在所有libs创建中直接使用了libtorch cxx11 ,就做到了.含义,与Pytorch官方文档中显示的内容不同.不要做:

  cmake -DCMAKE_PREFIX_PATH =''$(python -c'导入torch.utils; print(torch.utils.cmake_prefix_path)')'.. 

这样做,如果您像我一样期望库是使用 cxx11 构建的,那么地狱将彻底崩溃!因为他们还没有!

因此,如果您使用的是Linux,则只需抓取并使用带有 CXX11 ABI的预构建库即可!并避免Pytorch附带的东西!

注意

如果您要使用Pybind11和libtorch构建Python扩展,请确保您的Pytorch也使用 GLIBCXX_USE_CXX11_ABI = 1 构建,否则由于您现在知道的原因,您将看到未定义的引用!您可以通过在terminal/cmd中运行以下代码片段来简单地进行检查:

  python -c导入炬管;print(f'GLIBCXX_USE_CXX11_ABI = {int(torch._C._GLIBCXX_USE_CXX11_ABI)}')'; 

基于此处提供的信息 conda软件包(仅限cuda构建)随 GLIBCXX_USE_CXX11_ABI = 1 一起提供.我使用pip和conda测试了1.6cpu,但它们均报告 GLIBCXX_USE_CXX11_ABI = 0 .因此请注意.

如果您碰巧需要从源代码构建,则可以遵循本指南./p>

关于Pytorch为什么这样运送:

我们设置了该标志,因为我们使用的是gcc 4.9.x,旧的ABI.在GCC 5.1中,更改了std :: string的ABI,并且使用gcc> = 5.1编译的二进制文件与ABI不兼容使用gcc<构建二进制文件5.1(例如pytorch),除非您设置该标志.参考

I'm trying to create a test executable out of a library I made. Lets name them lib1 and lib2. lib1 gets built along with its test just fine. the lib2 is also built without any issues. However, whenever I try to link lib2 with its test executable (i.e. a sample program that uses lib2) I get the following error:

usr/bin/ld: CMakeFiles/Lib2_Test.dir/Lib2_Test.cpp.o: in function `main':
Lib2_Test.cpp:(.text+0xf3): undefined reference to `Lib2::Lib2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, int)'
/usr/bin/ld: Lib2_Test.cpp:(.text+0x3f5): undefined reference to `Lib2::Evaluate(bool&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, float&, cv::Mat&, cv::Mat&, bool)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Lib2_Test.dir/build.make:130: Lib2_Test] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/Lib2_Test.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

I tried viewing the headers using readelf -d and using the ldd command, both of the libs seems to be having all the necessary references. However lib1 doesn't have any issues, while lib2 generates unreferenced related errors when being linked to an executable that uses it.

Below are the cmakeLists I made for both of them and later on I also included the output of readelf.

CMakelist.txt for lib1:

cmake_minimum_required(VERSION 3.11)
project(Lib1)

set(CMAKE_CXX_STANDARD 17)

find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)

add_definitions(-D_LIB1_BUILD_DLL) 

set( CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -fPIC" )

set(CMAKE_INSTALL_PREFIX /home/me/Desktop/LibtorchPort/built_stuff)

include_directories( /home/me/Desktop/LibtorchPort/Dependencies/include ${TORCH_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
LINK_DIRECTORIES(/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib)

# http://dlib.net/examples/CMakeLists.txt.html
add_subdirectory(/home/me/dlib-19.21 /home/me/dlib-19.21/build)     

set(Lib1_SRC ./lib1.cpp)

add_library(lib1 SHARED  ${Lib1_SRC})

# Link
target_link_libraries(lib1 ${TORCH_LIBRARIES})
target_link_libraries(lib1 ${OpenCV_LIBS})
target_link_libraries(lib1 dlib::dlib)

install(TARGETS lib1 LIBRARY DESTINATION lib)

This is the CMakeList.txt for lib1_test:

cmake_minimum_required(VERSION 3.11)
project(Lib1_Test)
set(CMAKE_CXX_STANDARD 17)

find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)

set(CMAKE_INSTALL_PREFIX /home/me/Desktop/LibtorchPort/built_stuff)
include_directories( /home/me/Desktop/LibtorchPort/Dependencies/include ${TORCH_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
 
# Link
add_executable(lib1_dynamic_test ./Lib1_Test.cpp)
target_link_directories(lib1_dynamic_test PRIVATE /home/me/Desktop/LibtorchPort/Lib1/build)

target_link_libraries(lib1_dynamic_test lib1 )
target_link_libraries(lib1_dynamic_test ${TORCH_LIBRARIES} )
target_link_libraries(lib1_dynamic_test ${OpenCV_LIBS})
install(TARGETS lib1_dynamic_test DESTINATION bin)

This is the CMakeList.txt for lib2:

cmake_minimum_required(VERSION 3.11)
project(Lib2)

set(CMAKE_CXX_STANDARD 17)

find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)

add_definitions(-D_LIB2_BUILD_DLL) 

set(CMAKE_INSTALL_PREFIX /home/me/Desktop/LibtorchPort/built_stuff)

include_directories( /home/me/Desktop/LibtorchPort/Dependencies/include ${TORCH_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})

LINK_DIRECTORIES(/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib)
LINK_DIRECTORIES(/home/me/Desktop/LibtorchPort/Lib1/build)

set(LIB2_SRC  ./lib2.cpp )

add_library(lib2_dynamic SHARED ${LIB2_SRC} )

target_link_directories(lib2_dynamic PRIVATE /home/me/Desktop/LibtorchPort/Lib1/build)

target_link_libraries(lib2_dynamic  lib1)
target_link_libraries(lib2_dynamic  ${TORCH_LIBRARIES})
target_link_libraries(lib2_dynamic  ${OpenCV_LIBS})

install(TARGETS lib2_dynamic LIBRARY DESTINATION lib)

And finally here is the CMakeList for lib2_test:

cmake_minimum_required(VERSION 3.11)
project(Lib2_Test)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_INSTALL_PREFIX /home/me/Desktop/LibtorchPort/built_stuff)

#find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)

include_directories( /home/me/Desktop/LibtorchPort/Dependencies/include ${OpenCV_INCLUDE_DIRS})
LINK_DIRECTORIES(/home/me/Desktop/LibtorchPort/Lib1/build)

add_executable(Lib2_Test ./lib2_test.cpp)

target_link_directories(Lib2_Test PRIVATE /home/me/Desktop/LibtorchPort/Lib2/build)
#target_link_directories(Lib2_Test PUBLIC /home/me/Desktop/LibtorchPort/Lib1/build)

#Link
target_link_libraries(Lib2_Test ${OpenCV_LIBS})
target_link_libraries(Lib2_Test lib2_dynamic)
install(TARGETS Lib2_Test DESTINATION bin)

running the readelf -d lib1 this is the output I get:

Dynamic section at offset 0x908f8 contains 38 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libtorch.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc10.so]
 0x0000000000000001 (NEEDED)             Shared library: [libtorch_cpu.so]
 0x0000000000000001 (NEEDED)             Shared library: [libopencv_highgui.so.3.4]
 0x0000000000000001 (NEEDED)             Shared library: [libopencv_imgproc.so.3.4]
 0x0000000000000001 (NEEDED)             Shared library: [libopencv_core.so.3.4]
 0x0000000000000001 (NEEDED)             Shared library: [libcblas.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [liblapack.so.3]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x000000000000000e (SONAME)             Library soname: [libLib1.so]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/me/anaconda3/lib/python3.8/site-packages/torch/lib:/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib:/usr/local/lib:]
 0x000000000000000c (INIT)               0x1a000
 0x000000000000000d (FINI)               0x57e00
 0x0000000000000019 (INIT_ARRAY)         0x90b28
 0x000000000000001b (INIT_ARRAYSZ)       32 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x90b48
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x328
 0x0000000000000005 (STRTAB)             0x6840
 0x0000000000000006 (SYMTAB)             0x1758
 0x000000000000000a (STRSZ)              56053 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x92000
 0x0000000000000002 (PLTRELSZ)           8112 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x17ff0
 0x0000000000000007 (RELA)               0x14b58
 0x0000000000000008 (RELASZ)             13464 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x149f8
 0x000000006fffffff (VERNEEDNUM)         5
 0x000000006ffffff0 (VERSYM)             0x14336
 0x000000006ffffff9 (RELACOUNT)          6
 0x0000000000000000 (NULL)               0x0

and this is the output for lib2:

Dynamic section at offset 0x37ba0 contains 32 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libLib1.so]
 0x0000000000000001 (NEEDED)             Shared library: [libtorch.so]
 0x0000000000000001 (NEEDED)             Shared library: [libtorch_cpu.so]
 0x0000000000000001 (NEEDED)             Shared library: [libopencv_core.so.3.4]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libLib2_dynamic.so]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/me/anaconda3/lib/python3.8/site-packages/torch/lib:/home/me/libtorch-cxx11-abi-shared-with-deps-1.6.0+cpu/libtorch/lib:/home/me/Desktop/LibtorchPort/Lib1/build:/usr/local/lib:]
 0x000000000000000c (INIT)               0x1e000
 0x000000000000000d (FINI)               0x2ec10
 0x0000000000000019 (INIT_ARRAY)         0x38108
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x38118
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x7d88
 0x0000000000000006 (SYMTAB)             0x1dd0
 0x000000000000000a (STRSZ)              62708 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x39000
 0x0000000000000002 (PLTRELSZ)           14784 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x19e90
 0x0000000000000007 (RELA)               0x17b38
 0x0000000000000008 (RELASZ)             9048 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x17a78
 0x000000006fffffff (VERNEEDNUM)         3
 0x000000006ffffff0 (VERSYM)             0x1727c
 0x000000006ffffff9 (RELACOUNT)          4
 0x0000000000000000 (NULL)               0x0

And yet the lib1 builds and links just fine, while lib2 that is dependant on lib1, has issues when being linked to its test or any other libs. I'm clueless at this point and have no idea what could have caused this. What am I missing?

Update 1

This is the lib2_test.cpp : https://paste.ee/p/pOgFk and this is how the header file looks like :

#ifndef Lib2_H
#define Lib2_H

/* If we are we on Windows, we want a single define for it.*/
#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
#define _WIN32
#endif /* _WIN32 */

#if defined(_WIN32) && defined(_Lib2_BUILD_DLL)
/* We are building Lib2 as a Win32 DLL */
#define LIB2_API __declspec(dllexport)
#elif defined(_WIN32) && defined(Lib2_DLL)
/* We are calling Lib2 as a Win32 DLL */
#define LIB2_API __declspec(dllimport)
#elif defined(__GNUC__) && defined(_Lib2_BUILD_DLL)
/* We are building Lib2 as a shared / dynamic library */
#define LIB2_API __attribute__((visibility("default")))
#else
/* We are building or calling Lib2 as a static library */
#define LIB2_API
#endif

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <opencv2/core.hpp>


enum class ValidationStatus
{
    None = -1,
    UnderValidation = 0,
    Validated = 1,
    Invalidated = 2,
    AnomalyDetected = 3,
    ToomuchAnonalyDetected = 4
};

typedef std::tuple<ValidationStatus, std::string, bool> Lib2Result;

class Lib2Impl;

class LIB2_API Lib2
{
private:
    std::shared_ptr<Lib2Impl> Lib2;

public:
    Lib2(std::string shape_predictor_path = "", std::string eyeNet_path = "", int valid_presence_delay = 5, int fpasPassed = 0);

    std::vector<Lib2Result> Run(std::map<std::string, bool>& validity_result, 
                                       std::vector<std::tuple<std::string, float>>& ids,
                                       std::vector<cv::Mat>& faces, 
                                       cv::Mat& originalImage,
                                       bool show_debug_info=false);

    Lib2Result Evaluate(bool& status, std::string& name, float& theta, cv::Mat& face_image, cv::Mat& originalImage, bool debug_info = true);
    ~Lib2();

};

#endif // !Lib2_H

Concerning the comments, as you can see the calls on the lib2_test.cpp is OK and it uses the same signature.

Update 2

I need to add this as well that , the project was built just fine in Windows using visual studio and also cmake! however under Linux(ubuntu 20.04), I'm facing these issues. So this is not just calling different/wrong methods or with wrong signatures. this code should compile and link just fine but I'm doing something wrong here which I'm not sure what it is.

Note 2

The lib1 and lib2 are just made up name for the actual filenames (I just chose lib1 and lib2 to keep things simpler and replaced the names here, so if you see difference in cases, don't mind it, the actual files are the same.

解决方案

Summary

The third party lib (torch) was built using a Pre-cxx11 ABI, and libs built with that couldn't obviously be linked to the object that was using cxx11 ABI!

Long explanation

After hours of debugging of a code that worked just fine in Windows both in Visual Studio and CMake while being a pain in the neck in Linux I found the culprit!

The libtorch is shipped with two types of build Pre-cxx11 and cxx11 ABIs! It was using the Pre-cxx11 built libs that was shipped with its Python package (torch1.6cpu) and since Anaconda3 was in the Path and I was also using it to build the libs I faced this issue.

What gave it away after all these hours was the weird arguments to the undefined methods which were : std::__cxx11::basic_string where it should have been simply std::string. I didn't expect this two to be different and thought, that's a weird naming scheme the g++ is using until moments ago, that made me say, let's give that a search maybe I can get something out it! Lo and behold! this was the case :

If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.

ref

To fix this I simply directly used the libtorch cxx11 in all libs creation and that just did it. meaning, unlike what is being shown in the Pytorch's official documentation. Do not do:

cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" ..

By doing this all hell will break loose if you, like me expected the libs to have been built with cxx11! Because they have not!

So if you are on Linux, just grab and use the prebuilt libs with CXX11 ABI! and avoid what ships with Pytorch!

Note

If you are building a Python extension using Pybind11 and libtorch, make sure your Pytorch is also built using the GLIBCXX_USE_CXX11_ABI=1 or else you'll see the undefined references for the reason you now know! You can check this simply by running the following snippet in terminal/cmd:

python -c "import torch; print(f'GLIBCXX_USE_CXX11_ABI = {int(torch._C._GLIBCXX_USE_CXX11_ABI)}')"

Based on the information provided here conda packages (cuda builds only) should be shipped with GLIBCXX_USE_CXX11_ABI=1. I tested the 1.6cpu using pip and conda but they both reported GLIBCXX_USE_CXX11_ABI = 0. So be aware of that.

If you happened to need to build from source, you can follow this guide.

As to why Pytorch ships like this :

we have that flag set because we build with gcc 4.9.x, which only has the old ABI. In GCC 5.1, the ABI for std::string was changed, and binaries compiling with gcc >= 5.1 are not ABI-compatible with binaries build with gcc < 5.1 (like pytorch) unless you set that flag. ref

这篇关于尽管已在CMake中指定了库,但仍存在未定义的参考错误(与libtorch链接的问题(C ++ 11 ABI?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆