linux 链接到 .so ,但仍然得到未定义的引用
linux linking to a .so , but still getting undefined reference
我正在尝试创建一个使用静态库和共享库代码的可执行文件:
静态库有几个 boost.a,pthread
和 libbus.a
。共享库是 libwrap.so
。
请注意,libwrap 使用来自 libbus
的代码,而 libbus
使用来自 pthread
的代码。最后,可执行文件使用来自 libwrap
和 boost
.
的代码
由于 linker 中包含的库的顺序很重要,所以我试图找到 "winning" 序列。
linking阶段如下(为方便粘贴多行):
$ /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
link 错误是
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()
但是,linker 找不到它。我在这里做错了什么?
编辑:
上面的 linking 命令由以下 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)
您应该在静态库前使用 -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
看起来好多了。许多事情取决于您的 compiler/linker/OS.
的版本
我将从查看生成这些行的 cmake
文件开始。
将共享库添加到您的路径应该很简单,例如:
find_library(
LIBWrapper
NAMES wrap
PATHS /home/nass/dev/Data_Parser_build/lib
)
然后link将它们添加到您的测试文件中,例如
add_executable(test src/test.cpp)
target_link_libraries(test ${LIBWrapper})
类似的应该适用于静态库。这样做的好处是您不必处理 CMake 理应为您处理的所有 compiler/platform 具体细节,这些细节可能相当复杂和晦涩。
如果您的库是动态生成的,即在 cmake 配置时间之前,您可以将适当的 linking 标志传递给 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)中使用了这个建议,然后 link 反对它。如果这不起作用,我怀疑是其他地方出了问题。
我正在尝试创建一个使用静态库和共享库代码的可执行文件:
静态库有几个 boost.a,pthread
和 libbus.a
。共享库是 libwrap.so
。
请注意,libwrap 使用来自 libbus
的代码,而 libbus
使用来自 pthread
的代码。最后,可执行文件使用来自 libwrap
和 boost
.
由于 linker 中包含的库的顺序很重要,所以我试图找到 "winning" 序列。
linking阶段如下(为方便粘贴多行):
$ /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
link 错误是
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()
但是,linker 找不到它。我在这里做错了什么?
编辑:
上面的 linking 命令由以下 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)
您应该在静态库前使用 -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
看起来好多了。许多事情取决于您的 compiler/linker/OS.
的版本我将从查看生成这些行的 cmake
文件开始。
将共享库添加到您的路径应该很简单,例如:
find_library(
LIBWrapper
NAMES wrap
PATHS /home/nass/dev/Data_Parser_build/lib
)
然后link将它们添加到您的测试文件中,例如
add_executable(test src/test.cpp)
target_link_libraries(test ${LIBWrapper})
类似的应该适用于静态库。这样做的好处是您不必处理 CMake 理应为您处理的所有 compiler/platform 具体细节,这些细节可能相当复杂和晦涩。
如果您的库是动态生成的,即在 cmake 配置时间之前,您可以将适当的 linking 标志传递给 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)中使用了这个建议,然后 link 反对它。如果这不起作用,我怀疑是其他地方出了问题。