Cmake

Ce document fournit un aperçu rapide de CMake – une alternative multiplateforme à linux Makefiles et make. Pour de l’aide sur l’utilisation de make et Makefiles sans CMake, veuillez consulter la documentation du professeur Newhall. Ce document a été écrit pour cmake version 2.6, qui est installé sur les machines du laboratoire via stow (à partir de Jan 2009).

Pourquoi CMake

J’aime personnellement CMake car est il semble plus intuitif que d’écrire un Makefile standard. Les choses basiques et communes sont assez faciles et des choses plus difficiles sont possibles, bien que la plupart des choses que je construise soient assez basiques. Pour démontrer CMake, j’ai inclus quelques exemples de code dans le fichier cmake.tgz (4 KB). Enregistrez le fichier et décompressez le contenu n’importe où dans votre répertoire. Par exemple:

$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMakeLists.txt

CMake est contrôlé en écrivant des instructions dans les fichiers CMakeLists.txt. Chaque répertoire de votre projet devrait avoir un fichier CMakeLists.txt. Ce qui est bien avec CMake, c’est que les fichiers CMakeLists.txt dans un sous-répertoire héritent des propriétés définies dans le répertoire parent, ce qui réduit la quantité de code dupliqué. Pour notre projet d’exemple, nous avons seulement un sous-répertoire : w01-cpp. Le fichier CMakeLists.txt pour le répertoire cmake de niveau supérieur est assez simple mais démontre quelques fonctionnalités clés.

cmake_minimum_required(VERSION 2.6)project(CMAKEDEMO)#There are lots of scripts with cmake#for finding external libraries. #see /usr/local/share/cmake-2.6/Modules/Find*.cmake for more examplesfind_package(GLUT)find_package(OpenGL)set(CMAKE_CXX_FLAGS "-g -Wall")add_subdirectory(w01-cpp)

Ce code de démonstration inclut du code qui nécessite des bibliothèques OpenGL externes pour les graphiques. Dans une configuration typique de Makefile, nous aurions probablement besoin de spécifier où se trouvent les fichiers d’en-tête OpenGL, par exemple, -I/usr/local/include, quelles bibliothèques utiliser, par exemple, -lGL -lGLU -lglut, et l’emplacement des bibliothèques. L’emplacement des fichiers d’en-tête et des bibliothèques varie probablement d’une installation à l’autre et d’une plate-forme à l’autre. Cependant, il y a généralement quelques endroits standards à regarder, et CMake automatise cette recherche en utilisant les macros find_package. Ainsi find_package(GLUT) et find_package(OpenGL) trouvent l’emplacement des fichiers d’en-tête et des bibliothèques et configurent les bibliothèques les plus communes qui sont liées dans un projet OpenGL typique. CMake a un support pour trouver beaucoup de paquets. Voir /usr/local/share/cmake-2.6/Modules/Find*.cmake pour plus d’exemples. Pour utiliser l’un de ces scripts, utilisez find_package(PKGname) si le script CMake est nommé FindPKGname.cmake.

Pour en savoir plus sur la recherche de bibliothèques externes ou la création de vos propres macros find package, consultez le wiki KitWare sur le sujet.

Vous pouvez définir des drapeaux communs que vous définiriez dans un Makefile typique en utilisantingset(VARNAME VALUE). Dans cet exemple, j’ai activé les symboles de débogage (-g) et tous les avertissements (-Wall). J’ai aussi donné un nom à ce projet CMake en utilisant project(CMAKEDEMO). Vous pouvez nommer votre projet comme vous le souhaitez. Nous utiliserons ces informations dans le fichier CMakeLists.txt dans le répertoire w01-cpp. Enfin, nous indiquons que la plupart du code se trouve réellement dans le répertoire w01-cpp en disant à notre fichier CMakeLists.txt de niveau supérieur d’ajouter_subdirectory(w01-cpp)

Regardons le fichier CMakeLists.txt dans le sous-répertoire w01-cpp:

include_directories(${CMAKEDEMO_SOURCE_DIR}/w01-cpp)link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp)#the one C fileadd_executable(cdemo cdemo.c)target_link_libraries(cdemo m) #link the math library#these are all compiled the same wayset(PROGRAMS oglfirst pointers)set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m)foreach(program ${PROGRAMS}) add_executable(${program} ${program}.cpp) target_link_libraries(${program} ${CORELIBS})endforeach(program)#building just a library. add_library(geometry geometry.cpp)add_executable(test_geometry test_geometry.cpp)#linking against a custom librarytarget_link_libraries(test_geometry ${CORELIBS} geometry)

La macro include_directories indique à CMake où chercher les fichiers sources. En déclarant le nom du projet CMAKEDEMO dans le fichier CMakeLists.txt de niveau supérieur, les variables CMAKEDEMO_SOURCE_DIR et CMAKEDEMO_BINARY_DIR sont définies en fonction de l’emplacement actuel de votre code et de l’emplacement actuel de votre répertoire de construction (nous reviendrons plus tard sur ce dernier emplacement). L’ajout d’une cible pour un nouvel exécutable binaire est facile. Ajoutez juste une ligne add_executable(cdemo cdemo.c). CMake déterminera automatiquement le compilateur en se basant sur l’extension du type de fichier. Si des bibliothèques supplémentaires sont nécessaires, vous pouvez dire à CMake de les lier en utilisant target_link_libraries(cdemo m). Ceci indique à CMake que le programme cdemo doit être lié à la bibliothèque mathématique. Vous pouvez lier plus d’une bibliothèque en spécifiant les bibliothèques dans une liste. Voir par exemple set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m). Les variables GLUT_LIBRARY et OPENGL_LIBRARY sont définies par CMake lorsque nous avons utilisé les fonctions find_package(GLUT) et find_package(OpenGL). Pour savoir quelles variables sont définies lors de l’utilisation de find_package, vous devrez probablement ouvrir le fichier Find*.cmake approprié et lire la documentation généralement utile mais laconique.

Puisque plusieurs programmes dans ce dossier w01-cpp sont compilés de la même manière et liés contre les mêmes bibliothèques, nous pouvons les traiter tous avec une simple boucle montrée ci-dessus en utilisant la macro foreach de CMake. Enfin, nous montrons comment créer notre propre bibliothèque en utilisant add_library(geometry geometry.cpp) et en établissant un lien contre cette bibliothèque dans target_link_libraries(test_geometry ${CORELIBS} geometry).

Construire avec CMake

Mettre en place un tas de fichiers CMakeLists.txt ne vous permettra pas immédiatement de construire votre projet. CMake est juste une enveloppe multiplateforme autour de systèmes de construction plus traditionnels. Dans le cas de Linux, cela signifie make. Une étape rapide de prétraitement convertira votre description CMakeLists.txt en un système de construction traditionnel make automatiquement. Une fonctionnalité intéressante et hautement recommandée de CMake est la possibilité de faire des constructions hors source. De cette façon, vous pouvez faire tous vos fichiers .o, divers fichiers dépendants temporaires, et même les exécutables binaires sans encombrer votre arbre source. Pour utiliser les builds out of source, créez un répertoire de build dans votre dossier de premier niveau (techniquement, cela peut être n’importe où, mais le dossier de premier niveau du projet semble être un choix logique). Ensuite, changez dans votre répertoire de construction et exécutez cmake en le faisant pointer vers le répertoire du CMakeLists.txt de premier niveau. Par exemple:

cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..

N’oubliez pas d’être dans votre répertoire de construction et de faire pointer cmake uniquement sur le répertoire contenant le fichier CMakeLists.txt de premier niveau, et non sur le fichier lui-même. Si tout se passe bien, cmake traitera vos fichiers CMakeLists.txt, trouvera l’emplacement de toutes les bibliothèques et les chemins d’inclusion et produira un tas d’informations de configuration incluant un Makefile traditionnel dans votre répertoire de construction. (Si vous êtes familier avec autotools/autohell, ce processus cmake est similaire à ./configure). Vous êtes maintenant prêt à construire en utilisant le système traditionnel make. Exécutez make dans votre répertoire de construction pour tout compiler et lier. CMake ajoute même de jolies couleurs, des barres de progression, et supprime un tas de sorties de gcc. Si vous voulez une sortie verbeuse, vous pouvez taper VERBOSE=1 make (utile si quelque chose se passe mal).

En raison de la façon dont nous avons configuré le build out of source et les link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp), nos binaires fraîchement compilés se trouvent dans le dossier w01-cpp du répertoire de build où nous venons d’exécuter make.

cumin$ cd w01-cpp/cumin$ lsCMakeFiles/ cdemo* libgeometry.a pointers*Makefile cmake_install.cmake oglfirst* test_geometry*cumin$ ./cdemo Sqrt(2) = 1.4142 This concludes a short C democumin$ ./oglfirst cumin$ ./test_geometry 

Appuyez sur ESC pour quitter les démos OpenGL.

Wrapping up

Si vous modifiez le code dans votre répertoire source, y compris même un fichier CMakeLists.txt et que vous relancez make dans le répertoire de construction, make et cmake recompileront et reconstruiront les changements nécessaires. Si vous n’apportez des modifications que dans un sous-répertoire, vous pouvez simplement exécuter make dans le sous-répertoire correspondant dans l’arbre de construction pour traiter les mises à jour.

Une source initiale de confusion avec les builds out of source est que vous avez fondamentalement deux copies de votre arbre source, une avec le code source réel, et une avec les Makefiles et les exécutables binaires (dans l’arbre de construction). Il est probablement préférable de garder deux fenêtres ouvertes avec une dans l’arbre de construction pour faire et exécuter vos programmes, et une fenêtre dans l’arbre des sources pour modifier les fichiers sources.

Une bonne chose à propos des builds out of source est que le nettoyage des fichiers objets, des fichiers makedepend, des binaires, et d’autres cruft de construction divers peut être fait en supprimant simplement le répertoire de construction entier car il n’y a pas de source. Vous pouvez également utiliser make clean pour nettoyer les fichiers objets et binaires réels, mais lorsque vous envisagez de tar up votre source ou de distribuer votre code aux masses, vous pouvez simplement faire

cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/

pour nettoyer et empaqueter votre code.

Plus à explorer

Ceci ne fait qu’effleurer la surface de ce que CMake peut faire. Consultez le Wiki CMake pour plus d’informations. J’espère mettre à jour cette page si nous rencontrons des exemples plus complexes, et je suis heureux de prendre des commentaires ou des conseils d’autres cours qui pourraient utiliser CMake. Pour les utilisateurs très avancés, CMake a un programme compagnon CPack pour empaqueter automatiquement les binaires et les sources pour les systèmes Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin, et Nullsoft.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.