【发布时间】:2021-01-08 15:18:36
【问题描述】:
我正在尝试从我制作的库中创建一个测试可执行文件。让我们将它们命名为 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 的输出。
lib1 的 CMakelist.txt:
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)
这是lib1_test 的 CMakeList.txt:
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)
这是lib2 的 CMakeList.txt:
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)
最后是 lib2_test 的 CMakeList:
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
关于 cmets,如您所见,lib2_test.cpp 上的调用正常,并且使用相同的签名。
更新 2
我还需要补充一点,该项目是在 Windows 中使用 Visual Studio 和 cmake 构建的!然而在 Linux(ubuntu 20.04),我正面临这些问题。所以这不仅仅是调用不同/错误的方法或使用错误的签名。这段代码应该可以很好地编译和链接,但是我在这里做错了,我不确定它是什么。
注2
lib1 和 lib2 只是为实际文件名组成的名称(我只是选择 lib1 和 lib2 以使事情更简单,并在这里替换了名称,所以如果您发现大小写不同,请不要介意,实际文件是一样的。
【问题讨论】:
-
错误表明您在 lib2_test 中进行的调用与库中任何调用的签名都不匹配。
-
使用
nm -C查看liblib2_dynamic.so中定义了哪些符号 - 特别是 Lib2::Evaluate 和 Lib2::Lib2。 -
如果其他 cmets 不清楚,似乎 Lib2_Test 不正确,因为它试图使用功能
Lib2::Evaluate和构造函数Lib2::Lib2,这可能应该作为 @ 的一部分实现987654349@。你确定这是lib1的问题吗? -
谢谢你们。非常感谢您的帮助。 @JohnZwinck 我做了,结果如下:paste.ee/p/b2Kk4 符号在那里。
-
@squareskittles 不介意名称,我替换了实际名称以遵循我在问题中给出的示例。他们指的是同一个文件。我还需要补充一点,整个项目是在 Visual Studio 和 windows 中创建的,一切正常。然后有人告诉我,我们也必须为 linux 提供二进制文件,我的故事从这里开始。这就是 cmake 进来的地方,我在这里
标签: c++ linux cmake torch libtorch