web-dev-qa-db-fra.com

Créer un lien vers une bibliothèque externe

Comment obliger CMake à lier un exécutable à une bibliothèque externe partagée qui n'est pas construite dans le même projet CMake?

Il suffit de faire target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so) donne l'erreur

make[2]: *** No rule to make target `res/mylib.so', needed by `GLBall'.  Stop.
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2
make: *** [all] Error 2
(GLBall is the executable)

après avoir copié la bibliothèque dans le répertoire binaire bin/res.

J'ai essayé d'utiliser find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

Ce qui échoue avec RESULT-NOTFOUND.

105
Prime

Définir le chemin de recherche des bibliothèques en premier:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

Et puis juste faire

TARGET_LINK_LIBRARIES(GLBall mylib)
92
arrowd

la réponse de arrowdodger est correcte et préférée à plusieurs occasions. Je voudrais simplement ajouter une alternative à sa réponse:

Vous pouvez ajouter une cible de bibliothèque "importée" au lieu d'un répertoire de liens. Quelque chose comme:

# Your-external "mylib", add GLOBAL if the imported library is located in directories above the current.
add_library( mylib SHARED IMPORTED )
# You can define two import-locations: one for debug and one for release.
set_target_properties( mylib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/res/mylib.so )

Et liez ensuite comme si cette bibliothèque avait été construite par votre projet:

TARGET_LINK_LIBRARIES(GLBall mylib)

Une telle approche vous donnerait un peu plus de flexibilité: jetez un coup d'œil à la commande add_library () et à la commande de nombreuses propriétés de cible liées aux bibliothèques importées .

Je ne sais pas si cela résoudra votre problème avec "versions mises à jour de libs".

111
André

Je suppose que vous voulez créer un lien vers une bibliothèque appelée foo , son nom de fichier est généralement quelque chose de lien foo.dll ou libfoo.so.

1. Trouver la bibliothèque
Vous devez trouver la bibliothèque. C'est une bonne idée, même si vous connaissez le chemin d'accès à votre bibliothèque. CMake affichera une erreur si la bibliothèque a disparu ou a reçu un nouveau nom. Cela permet de détecter les erreurs à un stade précoce et d'indiquer clairement à l'utilisateur (éventuellement vous-même) la cause du problème.
Pour trouver une bibliothèque foo et stocker le chemin dans FOO_LIB utilisez

    find_library(FOO_LIB foo)

CMake déterminera lui-même le nom du fichier. Il vérifie les endroits habituels comme /usr/lib, /usr/lib64 et les chemins dans PATH.

Vous connaissez déjà l'emplacement de votre bibliothèque. Ajoutez-le au CMAKE_PREFIX_PATH lorsque vous appelez CMake. CMake recherchera également votre bibliothèque dans les chemins d'accès passés.

Parfois, vous devez ajouter des astuces ou des suffixes de chemins, consultez la documentation pour plus de détails: https://cmake.org/cmake/help/latest/command/find_library.html

2. Lier la bibliothèque Depuis 1. vous avez le nom complet de la bibliothèque dans FOO_LIB. Vous l’utilisez pour lier la bibliothèque à votre cible mylib comme dans

  target_link_libraries(mylib "${FOO_LIB}")

Vous voudrez peut-être ajouter PRIVATE, PUBLIC ou INTERFACE devant la bibliothèque, cf. la documentation: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

3. Add includes (Cette étape n'est peut-être pas obligatoire.)
Si vous souhaitez également inclure des fichiers d’en-tête, utilisez find_path de la même façon que find_library et recherchez un fichier d’en-tête. Ajoutez ensuite le répertoire include avec target_include_directories, similaire à target_link_libraries.

Documentation: https://cmake.org/cmake/help/latest/command/find_path.html et https://cmake.org/cmake/help/latest/command/target_include_directories .html

Si disponible pour le logiciel externe, vous pouvez remplacer find_library et find_path par find_package.

45
usr1234567

Une autre alternative, dans le cas où vous travaillez avec l'Appstore, nécessite "Droits" et doit donc être liée à un Apple-Framework.

Pour que les droits fonctionnent (par exemple, GameCenter), vous devez posséder un "Link Binary with Libraries" -buildstep puis un lien avec "GameKit.framework". CMake "injecte" les bibliothèques à un "bas niveau" dans la ligne de commande, donc Xcode ne le sait pas , et en tant que tel, vous ( pas l'activation de GameKit dans l'écran Capabilities.

Une façon d'utiliser CMake et d'avoir un "lien avec les binaires" -buildstep est de générer le xcodeproj avec CMake, puis d'utiliser 'sed' pour 'rechercher & remplacer' et d'ajouter le GameKit à la façon dont XCode l'aime ...

Le script ressemble à ceci (pour Xcode 6.3.1).

s#\/\* Begin PBXBuildFile section \*\/#\/\* Begin PBXBuildFile section \*\/\
    26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks \*\/ = {isa = PBXBuildFile; fileRef = 26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/; };#g

s#\/\* Begin PBXFileReference section \*\/#\/\* Begin PBXFileReference section \*\/\
    26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System\/Library\/Frameworks\/GameKit.framework; sourceTree = SDKROOT; };#g

s#\/\* End PBXFileReference section \*\/#\/\* End PBXFileReference section \*\/\
\
\/\* Begin PBXFrameworksBuildPhase section \*\/\
    26B12A9F1C10543B00A9A2BA \/\* Frameworks \*\/ = {\
        isa = PBXFrameworksBuildPhase;\
        buildActionMask = 2147483647;\
        files = (\
            26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks xxx\*\/,\
        );\
        runOnlyForDeploymentPostprocessing = 0;\
    };\
\/\* End PBXFrameworksBuildPhase section \*\/\
#g

s#\/\* CMake PostBuild Rules \*\/,#\/\* CMake PostBuild Rules \*\/,\
            26B12A9F1C10543B00A9A2BA \/\* Frameworks xxx\*\/,#g
s#\/\* Products \*\/,#\/\* Products \*\/,\
            26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/,#g

sauvegardez ceci dans "gamecenter.sed" puis "appliquez-le" comme ça (ça change votre xcodeproj!)

sed -i.pbxprojbak -f gamecenter.sed myproject.xcodeproj/project.pbxproj

Vous devrez peut-être modifier les commandes de script pour répondre à vos besoins.

Avertissement: il est probable que la version du Xcode diffère d'une version à l'autre car le format du projet peut changer, le numéro unique (codé en dur) peut ne pas être vraiment unique - et généralement les solutions proposées par d'autres personnes sont meilleures - donc à moins que vous n'ayez besoin de Supporter l'Appstore + Les droits (et les constructions automatisées), ne le faites pas.

Ceci est un bogue de CMake, voir http://cmake.org/Bug/view.php?id=14185 et http://gitlab.kitware.com/cmake/cmake/ issues/14185

3
kalmiya