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?
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 parfind_package()
etfind_library()
sont des chemins absolus. Transmettez ces chemins de fichiers de bibliothèque absolus directement à la commandetarget_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.
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.
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} )