24

我正在使用 SSL-Vision 软件。它有一个示例客户端,我一直试图将其与整个项目分开。我找到了自己编辑客户端所需的资源,所以我只是从软件中复制它们并使用 CMake 来构建我的客户端。

下面的项目结构被简化,缩小到问题(我相信!)。

.
├── CMakeLists.txt 
├── main.cc
├── build
│   ├── CMakeLists.txt
│   └── messages_ssl_... (.cc/.h, 4 each)
└── src
    ├── CMakeLists.txt
    └── (Other subdirs and sources/headers) 

./CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project( TestClient )

find_package( PkgConfig REQUIRED )
pkg_check_modules( QTCORE_PKG QtCore )
include_directories( ${QTCORE_PKG_INCLUDE_DIRS} )

include(FindProtobuf)
find_package( Protobuf REQUIRED )
include_directories( ${PROTOBUF_INCLUDE_DIRS} )

find_package( PkgConfig REQUIRED )
pkg_check_modules( GLIB_PKG glib-2.0 ) 
include_directories( ${GLIB_PKG_INCLUDE_DIRS} )

include_directories( "src" ) 
add_subdirectory( src )

include_directories( "build" ) 
add_subdirectory( build )


add_executable( clientTest clientTest.cc )

target_link_libraries( clientTest robocup_ssl_client messages_robocup_ssl_detection.pb messages_robocup_ssl_geometry.pb messages_robocup_ssl_wrapper.pb messages_robocup_ssl_refbox_log.pb netraw robocup_ssl_client protobuf QtCore )

./build/CMakeLists.txt

add_library( messages_robocup_ssl_detection.pb SHARED messages_robocup_ssl_detection.pb.cc )

add_library( messages_robocup_ssl_refbox_log.pb SHARED messages_robocup_ssl_refbox_log.pb.cc )

add_library( messages_robocup_ssl_geometry.pb SHARED messages_robocup_ssl_geometry.pb.cc )

add_library( messages_robocup_ssl_wrapper.pb SHARED messages_robocup_ssl_wrapper.pb.cc )

#include文件中可能缺少它messages_ssl_...,但它们都是自动生成的,并且似乎是正确的。

并且messages_robocup_ssl_detection.pb.h只有messages_robocup_ssl_detection.pb.hprotobuf 包含。

messages_robocup_ssl_refbox_log.pb.h

#include "messages_robocup_ssl_detection.pb.h"
// Other protobuf includes

messages_robocup_ssl_wrapper.h

#include "messages_robocup_ssl_detection.pb.h"
#include "messages_robocup_ssl_geometry.pb.h"
// Other protobuf includes

在每个 .cc 文件中仅包含其头文件和其他 protobuf 库。

最后,当我做时,会产生以下错误:

Linking CXX executable clientTest
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::ByteSize() const'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::MergeFrom(SSL_GeometryData const&)'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `protobuf_AddDesc_messages_5frobocup_5fssl_5fgeometry_2eproto()'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::Clear()'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::SSL_GeometryData()'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::default_instance()'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::SerializeWithCachedSizesToArray(unsigned char*) const'
build/libmessages_robocup_ssl_wrapper.pb.so: undefined reference to `SSL_GeometryData::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*)'
collect2: ld returned 1 exit status
make[2]: ** [clientTest] Erro 1
make[1]: ** [CMakeFiles/clientTest.dir/all] Erro 2
make: ** [all] Erro 2

一段时间以来,我一直在尝试解决此问题。libmessages_robocup_ssl_wrapper.pb.so如果在链接之前已经构建,为什么会显示错误?

4

3 回答 3

32

这很可能是链接顺序。

看起来messages_robocup_ssl_wrapper.pb取决于messages_robocup_ssl_geometry.pb. 如果是这样,则包装器应位于链接行中的几何图形之前。

target_link_libraries( clientTest robocup_ssl_client
                       messages_robocup_ssl_detection.pb
                       messages_robocup_ssl_wrapper.pb
                       messages_robocup_ssl_geometry.pb
                       messages_robocup_ssl_refbox_log.pb
                       netraw
                       robocup_ssl_client
                       protobuf
                       QtCore )

更好的是,让 CMake 处理这样的依赖关系。

如果添加...

target_link_libraries( messages_robocup_ssl_wrapper.pb
                       messages_robocup_ssl_geometry.pb )

messages_robocup_ssl_wrapper.pb那么当被指定为另一个目标的依赖项时,CMake 将自动保留该依赖项。如果您这样做,那么您可以选择messages_robocup_ssl_geometry.pbtarget_link_libraries( clientTest ... )呼叫中省略。

于 2013-05-15T20:26:12.400 回答
14

另一个原因undefined reference to ...可能是inline在源文件中标记为不是标头的函数。启用优化后,编译器实际上可以内联函数并跳过生成导致错误的符号。

对于这种情况,解决方案是将内联函数移动到标题或删除内联标记。

于 2016-03-09T15:33:04.637 回答
14

观察到此错误的另一个原因(虽然可能不太常见)是 ABI 不兼容。

例如,可以使用标志构建库文件之一,-D_GLIBCXX_USE_CXX11_ABI=0而项目不是。这可能很难调试,尤其是在没有意识到这可能是问题的情况下。

我意识到这不是您的特定场景中的问题,但这个答案可能有助于其他绊脚石。

于 2019-03-08T17:17:03.577 回答