Make et CMake/Ctest - LISIC
Transcription
Make et CMake/Ctest - LISIC
Make et CMake/Ctest E. RAMAT Université du Littoral - Côte d’Opale 21 septembre 2010 E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 1 / 54 Objectifs aboder les outils de gestion du processus de compilation ; intégrer la phase de tests unitaires ; documenter ses sources et générer la documentation ; Contexte Ces thèmes sont abordés dans le contexte des langages C et C++. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 2 / 54 Plan 1 Make 2 CMake 3 CTest et Boost E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 3 / 54 Introduction Les Makefiles sont des fichiers utilisés par le programme make pour exécuter un ensemble d’actions Plusieurs utilitaires GNU make mais aussi : gmake, nmake, tmake, . . . Make est un outil qui contrôle la génération d’exécutables et les autres fichiers non-source d’un programme à partir des fichiers sources. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 4 / 54 Introduction gérer les dépendances entre fichiers à : construire / compiler / “linker” / exécuter automatiser la construction / l’exécution en reconstruisant ce qui est nécessaire et uniquement suffisant rapidité de construction par rapport au processus “à la main” Exemples .o/.c/.h : bibliothèque, archive, installation .tex/.dvi/.ps : génération de documentation E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 5 / 54 Principe Un graphe de dépendances va être construit à partir : de cibles (fichier ou simple nom) de leurs dépendances des tâches à réaliser Qu’est qu’une dépendance ? Un élément qui nécessite l’exécution des tâches s’il n’est pas à jour par rapport à la cible Comment détermine-t-on qu’on est à jour ? Par les dates de dernière modification E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 6 / 54 Principe L’ensemble des informations est centralisé dans un fichier, interprété par la commande make : Nom par défaut : makefile ou Makefile Constitué de règles Une règle a la forme : cible : liste des dépendances <tab> tâches (en sh) Des raccourcis et des variables d’environnement permettent de décrire plus facilement les règles, les cibles, les dépendances et les tâches E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 7 / 54 Principe Un premier exemple helloworld : helloworld . o <tab > gcc -o helloworld helloworld . o helloworld . o : helloworld . c helloworld . h <tab > gcc -c helloworld . c E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 8 / 54 Principe Schéma général cible1 ... cibleN : prerequis1 ... prerequisP <tab > commande1 ; ... ; commandeC ou bien cible1 ... cibleN : prerequis1 ... prerequisP ; cde1 ; ... ; cdeC ou encore cible1 ... cibleN : prerequis1 ... prerequisP <tab > commande1 <tab > ... <tab > commandeC Tous les cas intermédiaires sont possibles ... Les cibles doivent être séparées par des espaces ou tabulations ainsi que les dépendances. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 9 / 54 Interprétation Pour décider d’exécuter les tâches d’une règle, il faut vérifier au préalable si une des dépendances nécessite une mise en cohérence par rapport à la cible. Les commandes qui composent la tâches sont alors exécutées séquentiellement Si une commande provoque à une erreur, alors la cible n’est pas rendue cohérente et TOUT le processus s’arrête. Une cible est incohérente lorsque : I I I un de ses dépendants est incohérent, la cible n’existe pas, sa date de dernière modification est antérieure à celles de ses dépendances E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 10 / 54 La commande Make make make nomDeCible : construit la cible indiquée make f monMakefile : utilise le fichier indiqué si ce dernier ne se nomme pas makefile ou Makefile make i : ignire globalement toutes les erreurs qui peuvent survenir make n : montre ce que l’on ferait make : recontruit la première cible trouvée dans le fichier Makefile ou makefile dans le répertoire courant E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 11 / 54 Autres éléments de syntaxe Commentaire : toute suite de caractères après un #. Le caractère TAB : I I I une ligne commence par TAB, ce qui suit est interprété comme une commande shell une série d’espaces n’a pas le même effet un TAB esthétique en début de ligne peut jouer des tours . . . Commande invisible : le caractère placé devant une commande empêche l’affichage de l’intitulé de la commande à la console. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 12 / 54 Les variables Il y a plusieurs types de variables pour make : les variables passées par commande les variables d’environnement les variables définies dans le makefile les variables automatiques Variable passée par commande make TOTO=objet.c dans le fichier makefile, toutes les occurrences de $(TOTO) ou de $TOTO seront remplacées par objet.c. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 13 / 54 Les variables d’environnement Toutes les variables du shell lançant make sont accessibles echo \ $ ( VARIABLE ) # renvoie la valeur de la variable d ’ envi ␣ ␣ ␣ ␣ ␣ ␣ VARIABLE . ␣␣␣␣ Si la commande make est lancée par un shell donné (bash, zsh, sh, ...), toutes les variables d’environnement de ce shell peuvent être utilisées dans le makefile. La seule exception est la variable SHELL qui, par défaut, vaut toujours /bin/sh, mais qui peut être modifiée dans le makefile. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 14 / 54 Les variables définies dans le Makefile Définition : var = valeur Mécanisme : la substitution de la variable var I toutes les occurrences de $(var) ou de $var seront remplacées par valeur Attention, la substitution est récursive ! E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 15 / 54 Les variables $variable correspond à une variable du makefile le $$ peut être utilisé pour passer une expression de variable commençant par $ au shell. affiche : <TAB > for fic in *. c ; do ls $$fic ; done $ make affiche for fic in *. c ; do ls $fic ; done convert2sens . c convertir . c outils . c E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 16 / 54 Les variables Pour pouvoir ajouter quelque chose à une variable (à substitution récursive ou simple), on utilise l’opérateur binaire + = : variable = valeur variable+ = davantage est équivalent à : temp = valeur variable = $(temp) + davantage sauf qu’aucune variable temp n’est définie CC = gcc CFLAGS = -c OBJS = convertir . o outils . o convert2sens . o convertir : $ ( OBJS ) $ ( CC ) $ ( OBJS ) -o convertir convert2sens . o : convert2sens . c convertir . h outils . h $ ( CC ) $ ( CFLAGS ) convert2sens . c E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 17 / 54 Les variables * et ?, [a-z] et autres peuvent être utilisés dans : I I I les commandes shell (comme d’habitude) les cibles les prérequis on peut ainsi créer des règles à motifs : *. o : *. c <TAB > gcc -c *. c E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 18 / 54 Les variables Les variables automatiques Ces variables sont définies et remises à jour par make. Elles ne peuvent être utilisées que dans une règle et désignent une des cibles, les prérequis, un sous-ensemble de prérequis, . . . $ : remplacé par le nom du fichier cible. I s’il y a plusieurs noms dans la cible, alors $ est remplacé par celui des noms dans la cible qui a déclenché l’application de la règle. convertir : $ ( OBJS ) <TAB > $ ( CC ) $ ( OBJS ) -o $@ E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 19 / 54 Les variables Les variables automatiques $* : préfixe de la cible $ˆ : remplacé par la liste des prérequis, chaque nom étant séparé par une espace : I I si un certain prérequis a été répété plusieurs fois, alors il n’apparaît qu’une seule fois dans $ˆ. si on veut que l’ordre des éléments et le nombre des répétitions soient préservés, il faudra utiliser $+ au lieu de $ˆ. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 20 / 54 Les variables Les variables automatiques $< désigne le premier prérequis. I nom du fichier qui a causé l’action associée à la cible (celui qui serait utilisé par la règle implicite) convert2sens . o : convert2sens . c <TAB > $ ( CC ) -c $ < E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 21 / 54 Les variables Les variables automatiques $? est remplacé par la liste des prérequis qui sont plus jeunes qu’au moins une des cibles. I en fait $? désigne la liste des prérequis qui sont responsables de l’application de la commande de la règle. print : *. c <TAB > @echo $ ? : fichiers C $ make print convert2sens . c convertir . c outils . c : fichiers C il existe d’autres variables automatiques ($ E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 22 / 54 Les règles explicites convert2sens . o : convert2sens . c <TAB > $ ( CC ) -c $ < La règle ci-dessus est intéressante mais on pourrait l’appliquer à tout fichier .c pour le lier au .o correspondant. Il existe en fait une telle règle, dite implicite : .c.o: <TAB > $ ( CC ) -c $ < ou %. o : %. c <TAB > $ ( CC ) -c $ < E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 23 / 54 Un exemple complet CC = gcc CFLAGS = - Wall - ansi LDFLAGS = - Wall - ansi EXEC = hello all : $ ( EXEC ) hello : hello . o main . o $ ( CC ) -o $@ $ ^ $ ( LDFLAGS ) main . o : hello . h %. o : %. c $ ( CC ) -o $@ -c $ < $ ( CFLAGS ) clean : rm - rf *. o E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 24 / 54 Plan 1 Make 2 CMake 3 CTest et Boost E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 25 / 54 CMake C’est quoi ? outil d’aide au processus de compilation (build), multi plates-formes et open source développé depuis 2001 par Kitware (VTK – Visualization ToolKit) adopté par les développeurs de KDE Pour faire quoi ? capable de générer des makefile/unix, des projets MS Visual Studio, Borland, . . . qui seront utilisés par les outils natifs lors de la compilation nombreuses commandes permettant de localiser les fichiers d’entêtes, les bibliothèques, les executables, . . . E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 26 / 54 CMake Pour faire quoi ? - suite propose de nombreuses extensions pour localiser X, Qt, OpenGL, Swig, . . . propose des interfaces de test (CTest) et de packaging (CPack) Liens et installation site Web : http://www.cmake.org paquet Debian - unstable : version 2.8.2 installation : apt-get install cmake E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 27 / 54 CMake avec Make main . o : main . c main . h <TAB > cc -c main . c MyProgram : main . o <TAB > cc -o MyProgram main . o - lm - lz avec CMake PROJECT ( MyProject C ) ADD_E XECUTABL E ( MyProgram main . c ) T A R G E T _ L I N K _ L I B R A R I E S ( MyProgram z m ) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 28 / 54 CMake Schéma de compilation capable de gérer le processus de compilation indépendamment du système d’exploitation et du compilateur connaissance de très nombreuses plates-formes et outils l’utilisateur configure son build avec CMake E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 29 / 54 CMake Structure et répertoires L’arborescence des sources contient : fichier d’entrée de CMake (CMakeLists.txt) fichiers sources du programme (*.cpp, par exemple) L’arborescence des produits de la compilation contient : fichiers natifs de compilation (Makefile, *.dsp pour Visual Studio) les bibliothèques et les exécutables (*.exe, par exemple) Les deux arborescences peuvent être : dans le même répertoire (in-source build) dans des répertoires différents (out-of-source build) : I I src : les sources (cpp, hpp, java, py, . . . ) et les CMakeLists.txt build : les produits de la compilation (.so, .a, .exe, . . . ) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 30 / 54 CMake Eléments de syntaxe CMake dispose d’un langage de type script : commentaire : # commentaire jusqu’à la fin de la ligne commande : COMMAND (arg1 arg2 ...) liste : A;B;C variable : ${VAR} structure de contrôle : IF (CONDITION) FOREACH(v A B C) détection de bibliothèques : FIND_LIBRARY(...) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 31 / 54 CMake Le cache de CMake résume l’ensemble de la configuration du build fichier CMakeCache.txt situé à la racine du projet créé et mis à jour lors des phases de configuration réalisées par CMake Les variables incontournables CMAKE_BUILD_TYPE=[Debug, Release] CMAKE_INSTALL_PREFIX=[/usr/local] CMAKE_VERBOSE_MAKEFILE=[OFF, ON] E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 32 / 54 CMake Un exemple - les fichiers Attention, les sources des sous-répertoires ne sont inclus dans le projet que si un CMakeLists.txt n’est présent dans le répertoire FOO-code : I I I ADD_SUBDIRECTORY(foo) ADD_SUBDIRECTORY(bar) ADD_SUBDIRECTORY(example) ou : SUBDIRS(foo bar example) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 33 / 54 CMake Un exemple - les CMakeLists.txt E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 34 / 54 CMake Installation par défaut, les éléments (.h, .so, les exécutables, ...) sont installés dans /usr/local/ dans le cas de la séparation du build des sources (construction dans le répertoire build) : cmake - D C M A K E _ I N S T A L L _ P R E F I X =/ home / eric / usr / .. la variable ${CMAKE_INSTALL_PREFIX} est modifiée E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 35 / 54 CMake Installation la commande d’installation des résultats de la compilation : INSTALL ( TARGETS example DESTINATION $ { C M A K E _ I N S T A L L _ P R E F I installation des headers : SET ( BAR_H bar1 . h bar2 . h ) INSTALL ( FILES $ { BAR_H } DESTINATION $ { C M A K E _ I N S T A L L _ P R E F I X }/ includ la même technique peut être utilisé pour n’importe quel fichier E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 36 / 54 CMake Librairies et pkgconfig toutes les librairies ne sont pas reconnus par CMake à l’installation de bibliothèques, on peut avoir à notre disposition des .pc : informations sur l’emplacement des fichiers (.h, .a, .so, ...) Exemple $ pkg - config -- libs glibmm -2.4 - lglibmm -2.4 - lgobject -2.0 - lsigc -2.0 - lglib -2.0 $ pkg - config -- cflags glibmm -2.4 -I / usr / include / glibmm -2.4 -I / usr / lib / glibmm -2.4/ include -I / usr / include / sigc ++ -2.0 -I / usr / lib / sigc ++ -2.0/ include -I / usr / include / glib -2.0 -I / usr / lib / glib -2.0/ include E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 37 / 54 CMake Recherche des paquets # chargement du paquet CMake prenant en charge PkgConfig FIND_PACKAGE ( PkgConfig ) # recheche de la librairie glibmm -2.4 PK G _ C H E C K _ M O D U L E S ( GLIBMM glibmm -2.4) Utilisation des informations # utilisation des informations de chemins I N C L U D E _ D I R E C T O R I E S ( $ { G L I B M M _ I N C L U D E _ D I R S }) LI N K _ D I R E C T O RI E S ( $ { G L I B M M _ L I B R A R Y _ D I R S }) ADD_E XECUTABL E ( example example1 . cpp example2 . cpp ) # utilisation des informations de nommage des librairies T A R G E T _ L I N K _ L I B R A R I E S ( example $ { G L I B M M _ L I B R A R I E S }) les sources example1.cpp et example2.cpp peuvent maintenant inclure des headers de la glibmm les variables créées par la commande PKG_CHECK_MODULES E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 38 / 54 Plan 1 Make 2 CMake 3 CTest et Boost E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 39 / 54 CTest Qu’est ce que c’est ? fait partie de la distribution CMake peut-être utilisé avec ou sans CMake permet de réaliser plusieurs types de test sur le code source : I I exécution de tests prédéfinis, exécution de tests avancés: F F couverture de code : uniquement avec g++ -fprofile-arcs -ftest-coverage état de la mémoire : utilisation de purify ou valgrind E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 40 / 54 CTest Comment faire ? les tests doivent être activés dans le CMakeLists.txt principal : ENABLE_TESTING() le programme de tests est un exécutable comme les autres ADD_E XECUTABL E ( test1 test1 . cpp ) T A R G E T _ L I N K _ L I B R A R I E S ( test1 $ { B o o s t _ U N I T T E S T F R A M E W O R K }) ADD_TEST ( apptest1 test1 ) ici, on linke l’exécutable avec une bibliothèque de tests unitaires : Boost::UnitTestFramework E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 41 / 54 CTest Les commandes liste des tests : ctest -N exécution des tests : make test ou ctest ; tous tests sont exécutés et un rapport est généré exécution d’un sous-ensemble des tests : ctest -I 2,3 ; les tests 2 et 3 sont exécutés un répertoire Testing/Temporary est crée dans le build avec les rapports : LastTest.log et LastTestsFailed.log E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 42 / 54 Les tests unitaires et Boost Le test unitaire est une technique qui permet de s’assurer du fonctionnement correct d’une partie déterminée d’un logiciel ou d’une portion d’un programme. le code du test est indépendant du reste du programme. → utilise uniquement les interfaces fonctionnelles. il couvre le maximum de code : couverture de code. → tout n’est cependant pas testable, il faut parfois émuler : bases de données, fichiers, web, etc. nécessite un framework : → JUnit (java), → CPPunit (C++), → Pyunit (Python), etc. → E. Ramat (ULCO) Boost::Test Make/CMake/CTest 21 septembre 2010 43 / 54 Suite de test Les tests sont, en général, de simples assertions inclues dans des suites de tests : test cases et test suites. test case : de simple tests, A == B, str == "toto" etc. BOOST_CHECK (0 == 1); B O O S T _ C H E C K _ T H R O W ( openfile ( " test . dat " ) , std :: exception ); test suite : dirige les tests, réaction fasse aux erreurs, où sortir les erreurs, etc. std :: ofstream out ( " output . log " ); unit_test_log :: instance (). set_l og_outpu t ( out ); E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 44 / 54 Test case : les types d’erreurs Les trois types de cas de tests : Type WARN CHECK REQUIRE Définition avertissement erreur erreur fatale Compteur non affecté affecté affecté Comportement continue continue annulé Note Le compteur décris le nombre d’erreurs dans une suite de test. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 45 / 54 Boost::test : API BOOST_[type](test) : s’assure que le test est vrai BOOST_[type]_MESSAGE(str) : affiche la chaîne de caractères str BOOST_[type]_EQUAL(x, y) : s’assure que x égal y BOOST_[type]_CLOSE(x, y, z) : test d’égalité entre des réels x et y avec une tolérance z BOOST_[type]_THROW(fct, expt) : s’assure que l’appel à la fonction fct lève une exception expt BOOST_[type]_NO_THROW(fct, expt) : s’assure que l’appel à la fonction fct ne lève pas une exception expt BOOST_CHECKPOINT(str) : capture la levée de signaux, division par zéro, boucle infinie, etc. Remarque À noter l’existence de la macro BOOST_MESSAGE(str) qui montre une chaîne de caractères. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 46 / 54 Description de l’exemple Dans la méthode Extrem Programming, il est recommandé d’écrire les tests avant le code afin de forcer à définir des interfaces de programmation propres. Dans l’exemple suivant nous considérons les tests unitaires de type fonctions : I I test.cc contient une suite de tests qui exécute un ensemble de fonction représentant les tests. moyenne.cc la fichier contenant la fonction à tester. Remarque Les gestionnaires de projets tel que les autotools, cmake ou encore scons gèrent les makefile de tests. Pour gérer l’exemple suivant, nous écrivons un makefile « maison ». E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 47 / 54 Écriture d’un makefile Makefile CFLAGS = - Wall -g - O2 LDFLAGS = LDFLAGSTEST = - l b o o s t _ u n i t _ t e s t _ f r a m e w o r k # construction de l ’ executable all : exe exe : moyenne . o g ++ -o exe moyenne . o $ ( LDFLAGS ) moyenne . o : moyenne . cc g ++ -c moyenne . cc $ ( CFLAGS ) c # construction et exà cution du test check : test1 ./ test1 test1 : test1 . o moyenne . o g ++ -o test1 test1 . o moyenne . o $ ( LDFLAGSTEST ) test1 . o : test1 . cc g ++ -c test1 . cc $ ( CFLAGS ) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 48 / 54 Exemple 1 Fichier de test : test.cc # include < boost / test / unit_test . hpp > using n a m e s p a c e boost :: u n i t _ t e s t _ f r a m e w o r k ; /* la fonction de test */ void test_moyenne () { std :: vector < float > tab ; BOOST_REQUIRE ( moyenne ( tab ) == 0.0); tab += 1.0 , 2.0 , 3.0; BOOST_REQUIRE ( moyenne ( tab ) == 2.0); } /* encapsulation du main par boost :: unit */ boost :: u n i t _ t e s t _ f r a m e w o r k :: test_suite * i n i t _ u n i t _ t e s t _ s u i t e ( int , char * []) { boost :: u n i t _ t e s t _ f r a m e w o r k :: test_suite * test ; test = B O O S T _ T E S T _ S UI T E ( " test " ); test - > add ( BO O ST _T EST_ C AS E (& test_moyenne )); return test ; } E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 49 / 54 Exemple 2 Fichier de calcul float moyenne ( const std :: vector < float >& tab ) { float sum = 0.0; for ( std :: vector < float >:: con st_itera tor it = tab . begin (); it != tab . end (); ++ it ) { sum += * it ; } return sum / tab . size (); } E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 50 / 54 Exemple 2 Fichier de calcul float moyenne ( const std :: vector < float >& tab ) { float sum = 0.0; for ( std :: vector < float >:: con st_itera tor it = tab . begin (); it != tab . end (); ++ it ) { sum += * it ; } return sum / tab . size (); } Problème À l’exécution des tests, le premier test plante sur une division par zéro ! E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 50 / 54 Exemple 3 Modification du fichier de calcul float moyenne ( const std :: vector < float >& tab ) { if ( not tab . empty ()) { float sum = 0.0; for ( std :: vector < float >:: con st_itera tor it = tab . begin (); it != tab . end (); ++ it ) { sum += * it ; } return sum / tab . size (); } else { return 0.0; } } E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 51 / 54 Une autre façon de faire les tests Utilisation des auto-tests # define B O OS T_ TE ST _ MA IN # define B O O S T _ A U T O _ T E S T _ M A I N # define B O O S T _ T E S T_ M O D U L E moyenne_test # include < boost / test / unit_test . hpp > # include < boost / test / auto_un it_test . hpp > B O O S T _ A U T O _ T E S T _ C A S E ( moyenne ) { std :: vector < float > tab ; B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 0.0); tab . push_back (1.0); tab . push_back (2.0); tab . push_back (3.0); B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 2.0); } E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 52 / 54 Une autre façon de faire les tests Utilisation des auto-tests # define B O OS T_ TE ST _ MA IN # define B O O S T _ A U T O _ T E S T _ M A I N # define B O O S T _ T E S T_ M O D U L E moyenne_test # include < boost / test / unit_test . hpp > # include < boost / test / auto_un it_test . hpp > B O O S T _ A U T O _ T E S T _ C A S E ( moyenne ) { std :: vector < float > tab ; B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 0.0); tab . push_back (1.0); tab . push_back (2.0); tab . push_back (3.0); B O O S T _ R E Q U I R E _ E Q U A L ( moyenne ( tab ) , 2.0); } Auto-tests Cette technique permet de réduire le code des tests. La création de la suite de tests est automatique. E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 52 / 54 Boost::Test et CMake Le CMakeLists.txt - racine PROJECT ( MOYENNE CXX C ) ENABL E_TESTIN G () FIND_PACKAGE ( Boost ) IF ( Boost_FOUND ) FIND_LIBRARY ( B o o s t _ U N I T T E S T F R A M E W O R K boost_unit_test_framework - mt PATHS IF ( B o o s t _ U N I T T E S T F R A M E W O R K ) SET ( H A V E _ U N I T T E S T F R A M E W O R K 1 CACHE ELSE ( B o o s t _ U N I T T E S T F R A M E W O R K ) SET ( H A V E _ U N I T T E S T F R A M E W O R K 0 CACHE ENDIF ( B o o s t _ U N I T T E S T F R A M E W O R K ) ENDIF ( Boost_FOUND ) NAMES b o o s t _ u n i t _ t e s t _ f r a m e w o r k Boost_LIBRARY_DIRS ) INTERNAL " " FORCE ) INTERNAL " " FORCE ) A D D _ S U B D I R E C TO R Y ( src ) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 53 / 54 Boost::Test et CMake Le CMakeLists.txt - du répertoire src I N C L U D E _ D I R E C T O R I E S ( $ { B o o s t _ I N C L U D E _ D I R S }) L I N K _ D I R E C T O RI E S ( $ { B o o s t _ L I B R A R Y _ D I R S }) ADD_E XECUTABL E ( test1 test . cpp moyenne . cpp ) ADD_TEST ( moyenne_test test1 ) T A R G E T _ L I N K _ L I B R A R I E S ( test1 $ { B o o s t _ U N I T T E S T F R A M E W O R K }) E. Ramat (ULCO) Make/CMake/CTest 21 septembre 2010 54 / 54