web-dev-qa-db-fra.com

Erreur de liaison CMake (référence non définie à)

Je travaille avec le logiciel SSL-Vision. Il a un exemple de client que j'ai essayé de séparer de l'ensemble du projet. J'ai trouvé les sources nécessaires pour éditer un client moi-même, alors je les ai juste copiées à partir du logiciel et utilisé CMake pour construire mon client.

La structure du projet ci-dessous est simplifiée, se limitant au problème (je crois!).

.
├── 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 )

Il pourrait s'agir d'un #include dans le messages_ssl_... fichiers, mais ils sont tous générés automatiquement et semblent corrects.

Dans messages_robocup_ssl_detection.pb.h et messages_robocup_ssl_detection.pb.h il n'y a que des inclusions protobuf.

Dans messages_robocup_ssl_refbox_log.pb.h:

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

Dans messages_robocup_ssl_wrapper.h:

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

Dans chaque fichier .cc est inclus uniquement son en-tête et d'autres bibliothèques protobuf.

Enfin, quand je fais, l'erreur suivante est générée:

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

J'essaie de résoudre ce problème depuis un certain temps. Pourquoi est-ce que libmessages_robocup_ssl_wrapper.pb.so montrant des erreurs s'il a déjà été construit avant la liaison?

16
Lucas

Il pourrait bien s'agir de l'ordre de liaison.

Il semble que messages_robocup_ssl_wrapper.pb Dépend de messages_robocup_ssl_geometry.pb. Si c'est le cas, le wrapper devrait venir avant géométrie dans la ligne de lien.

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 )

Encore mieux, laissez CMake s'occuper des dépendances comme celle-ci.

Si vous ajoutez ...

target_link_libraries( messages_robocup_ssl_wrapper.pb
                       messages_robocup_ssl_geometry.pb )

alors CMake conservera automatiquement cette dépendance lorsque messages_robocup_ssl_wrapper.pb est spécifié comme dépendance d'une autre cible. Si vous procédez ainsi, vous pouvez choisir d'omettre messages_robocup_ssl_geometry.pb De l'appel target_link_libraries( clientTest ... ).

26
Fraser

Encore une autre raison pour observer cette erreur, peut-être moins courante cependant, est que les ABI ne sont pas compatibles.

Par exemple, l'un des fichiers de bibliothèque peut être créé avec l'indicateur -D_GLIBCXX_USE_CXX11_ABI=0 alors que le projet ne l'est pas. Cela peut être désagréable à déboguer, surtout lorsque vous n'êtes pas conscient que cela peut être le problème.

Je me rends compte que ce n'est pas le problème dans votre scénario spécifique, mais cette réponse pourrait aider d'autres à y trébucher.

7
Martin R.

Une autre raison pour undefined reference to ... peut être une fonction marquée comme inline dans un fichier source qui n'est pas un en-tête. Lorsque l'optimisation est activée, le compilateur peut réellement incorporer la fonction et ignorer la génération du symbole conduisant à l'erreur.

Dans ce cas, la solution consiste à déplacer les fonctions en ligne vers les en-têtes ou à supprimer la marque en ligne.

7
Helmut