Linux链接到.so,但仍然得到未定义的引用

linux linking to a .so , but still getting undefined reference

本文关键字:未定义 引用 链接 so Linux      更新时间:2023-10-16

我正在尝试创建一个使用静态库和共享库代码的可执行文件:

静态库是几个boost .a, pthreadlibbus.a。共享库类型为libwrap.so

注意libwrap使用libbus的代码,而libbus使用pthread的代码。最后,可执行文件使用libwrapboost中的代码。

由于链接器中包含的库的顺序很重要,所以我试图找到"获胜"的序列。

链接阶段如下(为方便起见,粘贴成多行):

$ /usr/bin/c++   
    -Wall -Wextra 
    -fPIC 
    -fvisibility=hidden -fno-strict-aliasing -Wno-long-long 
    -m64 
    -rdynamic 
    -D_UNICODE -DUNICODE 
    CMakeFiles/Wrapper_Test.dir/test.cpp.o
    /usr/local/lib/libboost_log.a 
     /usr/local/lib/libboost_system.a 
    /usr/local/lib/libboost_filesystem.a 
    /usr/local/lib/libboost_date_time.a 
    /usr/local/lib/libboost_thread.a 
    /usr/local/lib/libboost_log_setup.a 
    /usr/local/lib/libboost_chrono.a 
    -pthread  
    /home/nass/dev/Data_Parser/trunk/external/lib/linux64_gcc_release/libbus.a  
    -L/home/nass/dev/Data_Parser_build/lib                    #this is where the libwrap.so is located
    -Wl,-rpath,/home/nass/dev/Data_Parser_build/lib 
    -lwrap                                                    #the shared lib 
    -o ../../../bin/Wrapper_Test

链接错误

CMakeFiles/Wrapper_Test.dir/test.cpp.o: In function `main':
test.cpp:(.text+0x2e): undefined reference to `wrapperNamespace::GetWrapper()'
collect2: error: ld returned 1 exit status

GetWrapper()当然位于libwrap.so中,我可以验证它是一个可以在那里找到的符号:

$ nm -Ca ../../../lib/libwrap.so | grep GetWrapper  
00000000000423d6 t wrapperNamespace::GetWrapper()

但是,链接器找不到它。我哪里做错了?

编辑:

上面的链接命令由以下CMakeLists.txt文件生成:

set(TARGET_NAME Wrapper_Test)
#set(CMAKE_BINARY_DIR       ${CMAKE_SOURCE_DIR}/bin)
#set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
#set(LIBRARY_OUTPUT_PATH    ${CMAKE_BINARY_DIR})
# INCLUDE INTERNAL FOLDER
include_directories(${CMAKE_SOURCE_DIR}/include/Wrapper) 
add_executable(${TARGET_NAME} test.cpp)
add_boost_lib(${TARGET_NAME} log system filesystem date_time thread log_setup chrono)
setup_libbus(${TARGET_NAME})    #the libbus.a
target_link_libraries(${TARGET_NAME} -L../../../lib -lwrap)
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER test)

我将从生成这些行的cmake文件开始。

在路径中添加共享库应该很简单,例如:
find_library(
        LIBWrapper
        NAMES wrap
        PATHS /home/nass/dev/Data_Parser_build/lib
)

然后链接到您的测试文件,例如

add_executable(test src/test.cpp)
target_link_libraries(test ${LIBWrapper})

也适用于静态库。这样做的好处是,你不必处理CMake应该为你处理的所有编译器/平台特定细节,这些细节可能相当复杂。模糊。

如果你的库是动态生成的,即在cmake配置时间之前,你可以把适当的链接标志传递给target_link_libraries:

target_link_libraries(test -L/home/nass/dev/Data_Parser_build/lib -lwrap)

我在几个项目(例如https://github.com/caskorg/cask/blob/master/CMakeLists.txt)中使用了这个建议,它动态生成库,然后链接到它。

您应该在静态库前面使用-Wl,-Bstatic,在动态库前面使用-Wl,-Bdynamic。您还需要为库使用-l,为库路径使用-L

类似:

$ /usr/bin/c++ test.cpp.o  
  -L/usr/local/lib 
  -Wl,-Bstatic 
  -lboost_log 
  -lsystem 
  -L/home/nass/dev/Data_Parser_build/lib 
  -Wl-Bdynamic 
  -Wl,-rpath,/home/nass/dev/Data_Parser_build/lib 
  -lwrap 
  -o ../../../bin/Wrapper_Test

看起来更好。很多事情取决于你的编译器/链接器/操作系统的版本。