J'essaie de faire fonctionner un système de construction multi-plateforme en utilisant CMake. Maintenant, le logiciel a quelques dépendances. Je les ai compilés moi-même et les ai installés sur mon système.
Quelques exemples de fichiers installés:
-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake
Maintenant, CMake a un find_package()
qui ouvre un Find*.cmake
fichier et recherche après la bibliothèque sur le système et définit certaines variables comme SomeLib_FOUND
etc.
My CMakeLists.txt contient quelque chose comme ceci:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
La première commande définit où CMake recherche après le Find*.cmake
et j'ai ajouté le répertoire SomeLib
où le FindSomeLib.cmake
peut être trouvé, donc find_package()
fonctionne comme prévu.
Mais c'est un peu étrange car l'une des raisons pour lesquelles il find_package()
existe est de s'éloigner des chemins codés en dur non inter-plates-formes.
Comment cela se fait-il habituellement? Dois-je copier le cmake/
répertoire de SomeLib
dans mon projet et définir le CMAKE_MODULE_PATH
relatif?
Réponses:
La commande
find_package
a deux modes:Module
mode etConfig
mode. Vous essayez d'utiliser leModule
mode alors que vous en avez réellement besoinConfig
.Mode module
Find<package>.cmake
fichier situé dans votre projet. Quelque chose comme ça:CMakeLists.txt
contenu:Notez que cela
CMAKE_MODULE_PATH
a une priorité élevée et peut être utile lorsque vous devez réécrire unFind<package>.cmake
fichier standard .Mode de configuration (installer)
<package>Config.cmake
fichier situé à l' extérieur et produit parinstall
commande d'un autre projet (Foo
par exemple).foo
bibliothèque:Version simplifiée du fichier de configuration:
Par défaut, projet installé dans le
CMAKE_INSTALL_PREFIX
répertoire:Mode de configuration (utilisation)
Utilisez
find_package(... CONFIG)
pour inclureFooConfig.cmake
avec la cible importéefoo
:Notez que la cible importée est hautement configurable. Voyez ma réponse .
Mettre à jour
la source
configure_package_config_file
. Au fait, si vous avez d'autres suggestions, vous pouvez m'envoyer une pull request.bin/lib
(essayez d'installer l'exécutable et de l'exécuter sous Windows). Et les espaces de noms sont très jolis, donc je les garderai aussi :) J'ai également ajoutémonolithic
build.Si vous exécutez
cmake
pourSomeLib
vous générer (par exemple dans le cadre d'un superbuild), envisagez d'utiliser le registre de packages utilisateur . Cela ne nécessite aucun chemin codé en dur et est multiplateforme. Sous Windows (y compris mingw64), cela fonctionne via le registre. Si vous examinez comment la liste des préfixes d'installation est construite par leCONFIG
mode de la commande find_packages () , vous verrez que le registre de packages utilisateur est l'un des éléments.Bref comment faire
Associez les cibles
SomeLib
dont vous avez besoin en dehors de ce projet externe en les ajoutant à un jeu d'export dans lesCMakeLists.txt
fichiers où elles sont créées:Créez un
XXXConfig.cmake
fichier pourSomeLib
dans son${CMAKE_CURRENT_BUILD_DIR}
et stockez cet emplacement dans le registre de packages utilisateur en ajoutant deux appels à export () auCMakeLists.txt
associé àSomeLib
:find_package(SomeLib REQUIRED)
Émettez votre commande dans leCMakeLists.txt
fichier du projet qui dépend deSomeLib
sans que les "chemins codés en dur non multiplateformes" bricolent avec leCMAKE_MODULE_PATH
.Quand cela pourrait être la bonne approche
Cette approche est probablement la mieux adaptée aux situations où vous n'utiliserez jamais votre logiciel en aval du répertoire de construction (par exemple, vous faites une compilation croisée et n'installez jamais rien sur votre machine, ou vous construisez le logiciel juste pour exécuter des tests dans le répertoire build), car il crée un lien vers un fichier .cmake dans votre sortie "build", qui peut être temporaire.
Mais si vous n'installez jamais réellement
SomeLib
dans votre flux de travail, l'appelEXPORT(PACKAGE <name>)
vous permet d'éviter le chemin codé en dur. Et, bien sûr, si vous installezSomeLib
, vous connaissez probablement votre plate-formeCMAKE_MODULE_PATH
, etc., donc l'excellente réponse de @ user2288008 vous couvrira.la source
Vous n'avez pas besoin de spécifier le chemin du module en soi. CMake est livré avec son propre ensemble de scripts find_package intégrés, et leur emplacement est dans le CMAKE_MODULE_PATH par défaut.
Le cas d'utilisation plus normal pour les projets dépendants qui ont été CMakeified serait d'utiliser la commande external_project de CMake et d'inclure ensuite le fichier Use [Project] .cmake du sous-projet. Si vous avez juste besoin du script Find [Project] .cmake, copiez-le hors du sous-projet et dans le code source de votre propre projet, et vous n'aurez pas besoin d'augmenter le CMAKE_MODULE_PATH pour trouver le sous-projet au niveau du système.
la source
their location is in the default CMAKE_MODULE_PATH
par défautCMAKE_MODULE_PATH
est videCMAKE_MODULE_PATH
est vide sous Windows.Si vous ne faites pas confiance à CMake pour avoir ce module, alors - oui, faites cela - en quelque sorte: Copiez le
find_SomeLib.cmake
et ses dépendances dans votrecmake/
répertoire. C'est ce que je fais comme solution de secours. C'est une solution moche cependant.Notez que les
FindFoo.cmake
modules sont chacun une sorte de pont entre la dépendance de la plate-forme et l'indépendance de la plate-forme - ils recherchent à divers endroits spécifiques à la plate-forme pour obtenir des chemins dans des variables dont les noms sont indépendants de la plate-forme.la source