cmake

Introduction

cmake, développé par Kitware est un outil d’aide à la génération de Makefile (cmake sait aussi générer des projets Microsoft Visual Studio, Borland …). Il permet de gérer pour nous beaucoup de problèmes, liés à la cross-compilation, compilation multi-plateforme.

Il remplace avantageusement les autotools (Set de 3 outils : libtool, automake et autoconf), qui ont de gros avantages mais aussi de gros inconvénients. En effet, ils automatisent beaucoup de choses comme cmake, mais à chaque évolution d’un des outils, il n’est pas étonnant d’avoir à modifier les fichiers de configuration dont la syntaxe à changée. De plus l’apprentissage de plusieurs langages de description (un pour automake, un pour autoconf, m4 …) est aussi un frein à leur utilisation.

cmake utilise un fichier CMakeLists.txt pour décrire la compilation d’un projet.

Sa syntaxe :

Nom du projet

Pour définir un projet on utilise la commande PROJECT :

PROJECT (nom_du_projet CXX) (Pour du C++)
PROJECT (nom_du_projet Language) (Générique)
PROJECT (nom_du_projet)

Inclusion

Il est possible d’inclure un fichier cmake dans un CMakeLists.txt en utilisant la commande INCLUDE.

INPUT(plugins.cmake)

Répertoires

On include des sous répertoires avec ADD_SUBDIRECTORY :

INCLUDE_DIRECTORIES(AFTER SYSTEM . ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR} ) #/usr/include/gtk-2.0 /usr/lib/gtk-2.0/include /usr/include/atk-1.0 /usr/include/cairo /usr/include/pango-1.0 /usr/include/glib-2.0 /usr/lib/glib-2.0/include /usr/include/freetype2 /usr/include/libpng12 /usr/include/pixman-1 /usr/include/glib-2.0 /usr/lib/glib-2.0/include)

Les cibles

Trois types de commandes, permettent de définir des cibles :

ADD_EXECUTABLE

Le premier argument est le nom de binaire à construire. Le reste sont des fichiers sources nécessaires à la compilation du binaire.

Exemple:

ADD_EXECUTABLE(gbemu ${gbemu_src})

ADD_CUSTOM_TARGET

Exemple :

ADD_CUSTOM_TARGET(cscope COMMAND find ${CMAKE_SOURCE_DIR} -name “.h” -o -name “.cpp” > ${CMAKE_SOURCE_DIR}/cscope.files && cscope -b -q -f${CMAKE_SOURCE_DIR}/cscope.out)

et

ADD_LIBRARY

Il est possible de positionner ou récupérer leurs propriétés en utilisant les commandes :

SET_TARGET_PROPERTIERS
GET_TARGET_PROPERTIERS

Librairies

Si rien n’est spécifié, cmake utilisera la valeur de la variable BUILD_SHARED_LIBS (Si BUILD_SHARED_LIBS n’est pas renseignée, cmake compilera en statique.) pour construire les librairies. Il suffit d’ajouter #cmakedefine BUILD_SHARED_LIBS dans le fichier config.h.cmake pour l’activer.

Librairie statique :

ADD_LIBRARY(nom STATIC file1.cpp file2.cpp)

Librairie dynamique :

ADD_LIBRARY(nom SHARED file1.cpp file2.cpp)

Il est possible d’utiliser la commande FIND_LIBRARY pour rechercher des librairies sur le système :

FIND_LIBRARY(LIBC_LIBRARY NAMES libc libc5 libc6 PATHS /usr/lib /usr/local/lib)

Les fichiers sources

Il est possible de spécifié les propriétés des fichiers sources gràce à :

SET_SOURCE_FILE_PROPERTIES
GET_SOURCE_FILE_PROPERTIES

Propriétés

LINK_FLAGS : Options de link des librairies.
COMPILE_FLAGS : Flags des fichiers source (notamment -D, -I …).
GENERATED : Le fichier à été généré ?
OBJECT_DEPENDS : Ajouter des fichiers dont dépend le fichier source.

Il est possible de spécifié avec quelle(s) librairie(s) compilera une cible gràce à : LINK_LIBRARIES ou TARGET_LINK_LIBRARIES.

Les listes

Il est possible de définir des listes, de fichiers sources par exemple :

SET(SCLEANER_SRC scleaner_wx.cpp engine.cpp)

On utilisera ${SCLEANER_SRC} par la suite.

Les variables

Les variables peuvent être définies n’importe où dans le fichier cmakeList.txt.

Définir la variable VAR et lui affecter la valeur 10 : SET (VAR 10).

IF

La commande IF s’utilise ainsi :

IF (${VAR} LESS 3)
SET (VAR 3)
ELSE (${VAR} LESS 3}
SET (VAR 4)
ENDIF (${VAR} LESS 3}

PLusieurs commandes sont définies permettant de faire différents tests :

NOT var : Non binaire.
var1 AND var2 : Et binaire.
var1 OR var2 : Ou binaire.
COMMAND nom : Vérifie que la commande est bien définie.
DEFINED var : Vérifie que la variable est bien définie.
EXISTS nom_fichier : Vérifie sur le fichier existe.
EXISTS nom_répertoire : Vérifie que le répertoire existe.
var MATCHES exp_reg : Correspond à une expression régulière.
chaine MATCHES exp_reg : Correspond à une expression régulière.
var [STR]EQUAL nombre
chaine [STR]EQUAL nombre
var [STR]LESS nombre
chaine [STR]LESS nombre
var [STR]GREATER nombre
chaine [STR]GREATER nombre

FOREACH

SET(VAR 1 2 3}

FOREACH(I ${VAR}) MESSAGE(“Ca y est je compte sur mes doigts ${I}”) ENDFOREACH(I ${VAR})

WHILE

WHILE(var LESS 3600)
MESSAGE(“Ca y est je compte sur mes doigts ${I}”)
ENDWHILE(var LESS 3600)

Crosscompilation avec cmake

Avant de commencer on est obligé de définir quelques variables d’environnement que cmake n’est pas encore capable de deviner tout seul (A partir de la version 2.6.0 semble t’il) :

CMAKE_SYSTEM_NAME : Le nom du système donc Linux, Windows ou Generic. Une fois cette variable positionée, cmake positionne CMAKE_CROSSCOMPILING à vrai, ce qui permet de savoir que l’on souhaite crosscompiler l’application. (Après test cela ne fonctionne pas dans la 2.4, CMAKE_CROSSCOMPILING reste indéfini)
CMAKE_C_COMPILER : Localisation du compilateur C.
CMAKE_CXX_COMPILER : Localisation du compilateur CXX.