web-dev-qa-db-fra.com

Cmake ne peut pas trouver la bibliothèque en utilisant "link_directories"

Ubuntu, j’apprends à faire et à fabriquer, et j’essaie juste de donner un exemple simple. J'ai deux répertoires: src et build. Dans src, j'ai deux fichiers: main.cpp Et CMakeLists.txt, Qui contient (uniquement) le texte suivant:

add_executable(test main.cpp)
link_directories(/usr/lib/x86_64-linux-gnu)
target_link_libraries(test protobuf)

Dans /usr/lib/x86_64-linux-gnu, Il existe une bibliothèque partagée appelée libprotobuf.so, Vers laquelle je veux faire un lien. Mon main.cpp Utilise les fonctions de cette bibliothèque en incluant le fichier d'en-tête correspondant, #include <google/protobuf/message.h>.

Maintenant, dans mon répertoire build, je lance cmake ../src, Puis make. Cependant, des erreurs de l'éditeur de liens m'indiquent qu'il existe des références indéfinies à certaines fonctions de la bibliothèque protobuf. Si je fais une recherche dans tous les fichiers et sous-répertoires de build, il n’est fait mention d’aucun élément lié à protobuf.

Cependant, si je supprime la ligne link_directories Dans mon fichier CMakeLists.txt Et écris à la place le chemin complet de la bibliothèque lors de la spécification de l'exécutable, c'est-à-dire target_link_libraries(test /usr/lib/x86_64-linux-gnu/libprotobuf.so), il compile et lie bien.

Pourquoi link_directories N'autorise-t-il pas cmake à trouver cette bibliothèque?

40
Karnivaurus

N'utilisez pas link_directories Comme ceci dans CMake.

C'est une erreur courante pour les débutants, car de nombreux autres environnements de compilation fonctionnent de la sorte, mais dans CMake, cela ne fait que poser problème. Même la page de manuel le déconseille expressément:

Notez que cette commande [link_directories] Est rarement nécessaire. Les emplacements de bibliothèque renvoyés par find_package() et find_library() sont des chemins absolus. Transmettez ces chemins de fichiers de bibliothèque absolus directement à la commande target_link_libraries(). CMake s'assurera que l'éditeur de liens les trouve.

Donc, au lieu de cela, passez toujours les chemins absolus à target_link_libraries Et utilisez find_library pour résoudre le problème. répertoire de liens:

find_library(PROTOBUF_LIBRARY protobuf HINTS /usr/lib/x86_64-linux-gnu)
target_link_libraries(test PUBLIC ${PROTOBUF_LIBRARY})

Cela présente l’énorme avantage que vous obtiendrez probablement un diagnostic lors de la configuration de CMake si la bibliothèque attendue ne peut pas être trouvée, au lieu d’une erreur de liaison aléatoire au moment de la compilation. En outre, cela permet à l'utilisateur de spécifier un emplacement de bibliothèque via l'interface graphique si la machine cible a une structure de répertoire non standard.

Donc, si cela ne fonctionne pas tout de suite, vérifiez le résultat de l'appel find_library Et consultez la page de manuel pour savoir pourquoi votre bibliothèque n'a pas été trouvée comme prévu.

56
ComicSansMS

Assurez-vous que votre appel à link_directories _ a lieu avant votre appel au correspondant add_executable.

J'avais cru, à tort, qu'il ne fallait que cela avant l'appel à target_link_libraries, mais ce n'est pas le cas. Après avoir déplacé l'appel, la bibliothèque est liée correctement.

42
aardvarkk

Assurez-vous que la commande sera link_directories, définissez PROJECT_LINK_LIBS, add_executable, puis target_link_libraries.

Vous trouverez ci-dessous un exemple de démonstration:

cmake_minimum_required(VERSION 2.8.9)
project (Logging)
include_directories(include)
file(GLOB LOGGINGSOURCES "libsrc/*.cpp")
file(GLOB SOURCES "src/*.cpp")
add_library(convertString SHARED ${LOGGINGSOURCES})
install(TARGETS convertString DESTINATION /root/Deepak/)
link_directories( /root/Deepak/ )
set(PROJECT_LINK_LIBS libconvertString.so)
add_executable(hello ${SOURCES})
target_link_libraries(hello ${PROJECT_LINK_LIBS} )
1
user6882413