# [Mini HOWTO] Construisez vos projets avec CMake

## SanKuKai

1- Préambule

Ayant pour habitude de confier la gestion de la compilation des petits projets que je créé parfois aux célèbres autotools, je ne m'étais jamais penché sur une alternative possible. Cependant, il faut le reconnaître, l'utilisation du triplet libtool/automake/autoconf n'est pas chose aisée et demande un investissement non négligeable à tel point que certains préfèrent se jeter sur des IDE afin de s'affranchir de la gestion des Makefiles.

C'est ainsi qu'en parcourant un excellent article du non moins excellent Gnu Linux Magazine/France du mois de Mars que j'ai découvert une alternative plus que séduisante aux autotools : CMake.

2- Introduction 

L'un des principaux atouts de CMake est le fait qu'il n'utilise qu'un seul type de fichier et par conséquent une syntaxe unique pour décrire les différentes étapes de construction de son projet. Ainsi, une commande unique :

```

$ cmake .

```

remplace les trois appels à : automake, autoconf et configure.

Enfin, CMake est plus souple puisque, en plus de permettre la génération de Makefiles, il peut produire des fichiers de projets exploitables par KDevelop et Visual Studio.

3- Exemple d'utilisation 

Puisqu'un bout de code vaut mieux qu'un long discours, je vous propose de découvrir une utilisation (très sommaire !) de CMake à  travers un petit exemple.

Nous allons construire un programme testant la parité d'un nombre entré en argument. Pour cela, on s'appuiera sur les fichiers suivants :

[*] lib/libparite.c, qui est une petite bibliothèque testant la parité d'un nombre :

```

#include <math.h>

int libparite(int i) {

        return i%2;

}

```

[*] lib/libparite.h, qui constitue la définition de l'interface de la bibliothèque :

```

#ifndef __LIBPARITE_H_

#define __LIBPARITE_H_

extern int libparite(int i);

#endif

```

[*] main.c qui contient le code du programme principal :

```

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include "lib/libparite.h"

int main(int argc, char *argv[]) {

        int i = atoi(argv[1]);

        if (libparite(i) == 0) {

                printf("Nombre pair");

        } else {

                printf("Nombre impair");

        }

        return EXIT_SUCCESS;

}

```

Afin de compiler la bibliothèque libparite puis le programme parite et le lier avec la bibliothèque, il faut définir deux fichiers CMakeLists.txt, un placé à la racine du projet et un placé dans le sous répertoire lib/.

Commençons par décrire le CMakeLists.txt situé dans le répertoire lib/ et chargé de compiler la bibliothèque.

Pour cela, il faut tout d'abord définir une variable contenant les sources de la bibliothèque par le biais de la commande SET, puis définir la bibliothèque à l'aide de la commande ADD_LIBRARY. Voilà le résultat :

```

$ cat lib/CMakeLists.txt

SET(parite_lib_src libparite.c)

ADD_LIBRARY(libparite SHARED ${parite_lib_src})

```

Et c'est tout ! Les règles de construction tiennent sur deux lignes.

(Vous remarquerez la présence du mot clef SHARED, si nous avions voulu créer une bibliothèque statique, nous aurions logiquement utilisé le mot clef STATIC à la place).

Créons maintenant le CMakeLists.txt racine qui construira le projet. Pour cela, commençons par donner un nom au projet à l'aide de la variable PROJECT, ensuite il faut appeler la compilation de la bibliothèque à l'aide de la variable ADD_SUBDIRECTORY et en fin créer l'exécutable avec ADD_EXECUTABLE puis le lier à la bibliothèque avec TARGET_LINK_LIBRARIES. Voici le résultat sur notre mini projet :

```

$ cat CMakeLists.txt

PROJECT(parite)

ADD_SUBDIRECTORY(lib)

SET(parite_src main.c)

ADD_EXECUTABLE(parite ${parite_src})

TARGET_LINK_LIBRARIES(parite libparite)

```

Il ne nous reste plus qu'à générer le Makefile en lançant CMake :

```

$ cmake .

cmake .

-- Check for working C compiler: gcc

-- Check for working C compiler: gcc -- works

-- Check size of void*

-- Check size of void* - done

-- Check for working CXX compiler: c++

-- Check for working CXX compiler: c++ -- works

-- Configuring done

-- Generating done

-- Build files have been written to: /home/cetcheve/tmp/parite

```

Nous pouvons maintenant compiler notre projet par un appel classique à make :

```

$ make      

[ 50%] Built target libparite

Scanning dependencies of target parite

[100%] Building C object CMakeFiles/parite.dir/main.o

Linking C executable parite

[100%] Built target parite

```

Et voilà le travail ! Il ne reste plus qu'à tester le programme :

```

$ ./parite 13

Nombre impair

```

Vous êtes peut-être surpris par la concision du rapport de compilation renvoyé par make, sachez qu'il est possible d'avoir une sortie plus « verbeuse » en lançant :

```

$ VERBOSE=1 make

```

4- Conclusion

Ce mini howto est évidemment très loin d'être exhaustif, de très nombreuses options sont disponibles -- comme l'utilisation de structure conditionnelles pour tester la présence de bibliothèques sur le système, l'installation du projet construit grâce à la variable INSTALL, etc. -- et je vous renvoie au site du projet pour de plus amples informations.

J'espère juste vous avoir fait découvrir une alternative très sérieuse aux autotools et peut-être un moyen de vous réconcilier avec la compilation de projets de moyenne et grande envergure.

----------

## anigel

Il est déjà tard, et je confesse ne pas avoir tout lu. Mais c'est propre, la présentation est soignée, et tu cite ta source (je ne t'aurai pas pardonné le contraire  :Wink: ) : merci beaucoup !

----------

## truc

ahaha, il est tôt, j'ai tout lu, c'est propre, soigné, et j'ai cliqué sur ce topic pour voir si justement tu citais la source! C'est du bon boulot, merci; ça va me servir en tout cas!  :Smile: 

----------

