我正在尝试从我创建的库中创建一个测试可执行文件。让我们给它们取名为lib1和lib2。lib1和它的测试一起构建得很好。lib2的构建也没有任何问题。但是,每当我试图将lib2与其测试可执行文件(即使用lib2的示例程序)链接时,我就会得到以下错误:
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我试着使用readelf -d和ldd命令查看头部,这两个库似乎都具有所有必要的引用。但是,lib1没有任何问题,而lib2在链接到使用它的可执行文件时会生成未引用的相关错误。
下面是我为他们两人制作的cmakeLists,稍后我还包括了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)这是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)这是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)最后,这里是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)运行readelf -d lib1 --这是我得到的输出:
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这是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然而,lib1的构建和链接非常好,而依赖于lib1的lib2在链接到其测试或任何其他库时会出现问题。我对此一无所知,也不知道是什么导致了这一切。我遗漏了什么?
更新1
这是lib2_test.cpp:https://paste.ee/p/pOgFk,头文件是这样的:
#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关于注释,正如您可以看到的那样,对lib2_test.cpp的调用是OK的,并且它使用相同的签名。
更新2
我还需要加上这一点,该项目是在Windows环境下使用Visual和cmake构建的。但是,在Linux (Ubuntu20.04)下,我面临着这些问题。因此,这不仅仅是调用不同的/错误的方法,或者使用错误的签名。这段代码应该能够很好地编译和链接,但是我在这里做了一些错误的事情,我不知道它是什么。
注2
lib1和lib2只是实际文件名的名称(我只是选择了lib1和lib2来保持简单,并在这里替换了名称,所以如果您看到不同的情况,请不要介意,实际的文件是相同的。
发布于 2020-09-23 02:48:59
摘要
第三方库(torch)是使用Pre-cxx11 ABI构建的,用它构建的lib显然不能链接到使用cxx11 ABI的对象!
长篇解释
经过几个小时的调试,一段代码在和CMake中运行良好,而在Linux中却很痛苦,我找到了罪魁祸首!
libtorch附带了两种类型的build Pre-cxx11和cxx11 ABI!它使用的是它的package (torch1.6cpu)附带的Pre-cxx11构建的lib,而且由于Anaconda3在路上,我也使用它来构建库,我面临了这个问题。
在这些小时之后,给它带来的是那些未定义的方法的奇怪论点,这些方法是:std::__cxx11::basic_string,它本来应该是std::string。我没想到这两者会有所不同,并认为,这是一个奇怪的命名方案,直到不久前,g++正在使用,这让我说,让我们搜索,也许我可以得到一些东西!瞧,瞧!情况就是这样:
如果您收到关于涉及std::__cxx11命名空间中类型或标记abi:cxx11 11的符号的未定义引用的链接器错误,那么它可能表明您试图将使用_GLIBCXX_USE_CXX11_ABI宏不同值编译的对象文件链接到一起。这种情况通常发生在链接到第三方库时,后者是用较旧版本的GCC编译的。如果第三方库不能用新的ABI重新构建,那么您就需要用旧的ABI重新编译代码。
为了解决这个问题,我只是在所有的libs创建中直接使用libtorch cxx11,这就做到了。意思是,不像在毕火炬的官方文档中所显示的那样。不要做:
cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" ..通过这样做,所有的地狱将打破如果你,就像我期望的libs已经建立了与cxx11!因为他们没有!
因此,如果您在Linux上,只需抓取并使用预置CXX11 ABI的库!避开那些带着火炬的飞船!
备注
如果您正在使用Pybind11和libtorch构建Python扩展,请确保您的Python也是使用GLIBCXX_USE_CXX11_ABI=1构建的,否则您将看到基于您现在知道的原因而产生的未定义的引用!只需在终端/cmd中运行以下代码段即可检查此代码:
python -c "import torch; 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。所以要注意这一点。
如果您碰巧需要从源代码构建,您可以遵循本指南。
至于为什么毕圣威的飞船是这样的:
我们有那面旗帜,因为我们用gcc 4.9.x建造的,它只有旧的ABI。在GCC 5.1中,ABI for std::string被更改了,并且使用gcc >= 5.1编译的二进制文件与用小于5.1的二进制构建的二进制文件不兼容(就像py手电筒一样),除非您设置了该标志。参考
https://stackoverflow.com/questions/64010727
复制相似问题