web-dev-qa-db-fra.com

Basculer entre GCC et Clang / LLVM en utilisant CMake

J'ai un certain nombre de projets construits en utilisant CMake et j'aimerais pouvoir facilement basculer entre GCC ou Clang/LLVM pour les compiler. Je crois (corrigez-moi si je me trompe!) Que pour utiliser Clang, je dois définir les paramètres suivants:

    SET (CMAKE_C_COMPILER             "/usr/bin/clang")
    SET (CMAKE_C_FLAGS                "-Wall -std=c99")
    SET (CMAKE_C_FLAGS_DEBUG          "-g")
    SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_CXX_COMPILER             "/usr/bin/clang++")
    SET (CMAKE_CXX_FLAGS                "-Wall")
    SET (CMAKE_CXX_FLAGS_DEBUG          "-g")
    SET (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_AR      "/usr/bin/llvm-ar")
    SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
    SET (CMAKE_NM      "/usr/bin/llvm-nm")
    SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
    SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

Existe-t-il un moyen simple de basculer entre ces variables et les variables GCC par défaut, de préférence sous la forme d’un changement à l’échelle du système plutôt que selon le projet (c.-à-d. Ne pas simplement les ajouter au fichier CMakeLists.txt)?

Aussi, est-il nécessaire d'utiliser les programmes llvm-* plutôt que les valeurs par défaut du système lors de la compilation avec clang au lieu de gcc? Quelle est la différence?

244
Rezzie

CMake respecte les variables d'environnement CC et CXX lors de la détection des compilateurs C et C++ à utiliser:

$ export CC=/usr/bin/clang
$ export CXX=/usr/bin/clang++
$ cmake ..
-- The C compiler identification is Clang
-- The CXX compiler identification is Clang

Les indicateurs spécifiques au compilateur peuvent être remplacés en les plaçant dans un fichier CMake système et en pointant la variable CMAKE_USER_MAKE_RULES_OVERRIDE . Créez un fichier ~/ClangOverrides.txt avec le contenu suivant:

SET (CMAKE_C_FLAGS_INIT                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE_INIT        "-O3 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

SET (CMAKE_CXX_FLAGS_INIT                "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE_INIT        "-O3 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

Le suffixe _INIT fera en sorte que CMake initialise la variable *_FLAGS correspondante avec la valeur donnée. Ensuite, appelez cmake de la manière suivante:

$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..

Enfin, pour forcer l'utilisation de LLVM binutils, définissez la variable interne _CMAKE_TOOLCHAIN_PREFIX. Cette variable est honorée par le module CMakeFindBinUtils:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

En regroupant tous ces éléments, vous pouvez écrire un wrapper Shell qui configure les variables d'environnement CC et CXX, puis appelle cmake avec les substitutions de variables mentionnées.

313
sakra

Changement C++ à l'échelle du système sur Ubuntu:

Sudo apt-get install clang
Sudo update-alternatives --config c++

Imprimera quelque chose comme ceci:

  Selection    Path              Priority   Status
------------------------------------------------------------
* 0            /usr/bin/g++       20        auto mode
  1            /usr/bin/clang++   10        manual mode
  2            /usr/bin/g++       20        manual mode

Ensuite, il suffit de sélectionner Clang ++.

116
Coder

Vous pouvez utiliser la commande option:

option(USE_CLANG "build application with clang" OFF) # OFF is the default

et ensuite envelopper les paramètres du compilateur clang dans if () s:

if(USE_CLANG)
    SET (...)
    ....
endif(USE_CLANG)

De cette façon, il est affiché comme une option cmake dans les outils de configuration graphique.

Pour l’étendre à l’ensemble du système, vous pouvez bien sûr utiliser une variable d’environnement comme valeur par défaut ou conserver la réponse de Ferruccio.

23
Tobias Schlegel

Changement de système global sur Ubuntu:

Sudo update-alternatives --config cc

Changement C++ à l'échelle du système sur Ubuntu:

Sudo update-alternatives --config c++

Pour chacun des éléments ci-dessus, appuyez sur Numéro de sélection (1), puis sur Entrée pour sélectionner Clang:

  Selection    Path            Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcc     20        auto mode
  1            /usr/bin/clang   10        manual mode
  2            /usr/bin/gcc     20        manual mode
Press enter to keep the current choice[*], or type selection number:
16

Vous n'avez certainement pas besoin d'utiliser les différents programmes llvm-ar etc:

SET (CMAKE_AR      "/usr/bin/llvm-ar")
SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
SET (CMAKE_NM      "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

Celles-ci sont conçues pour fonctionner sur le format interne llvm et ne sont donc pas utiles pour la construction de votre application.

En tant que note, -O4 invoquera LTO sur votre programme, ce que vous ne voudrez peut-être pas (cela augmentera considérablement le temps de compilation) et clanguera par défaut le mode c99 afin que cet indicateur ne soit pas nécessairement nécessaire.

9
echristo

Vous pouvez utiliser le mécanisme de fichiers de la chaîne d’outils de cmake à cette fin (voir par exemple). ici . Vous écrivez un fichier de chaîne d’outils pour chaque compilateur contenant les définitions correspondantes. Au moment de la configuration, vous lancez par exemple

 cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..

et toutes les informations du compilateur seront définies lors de l'appel de project () à partir du fichier toolchain. Bien que la documentation ne soit mentionnée que dans le contexte de la compilation croisée, elle fonctionne également pour différents compilateurs sur le même système.

8
j_fu

Selon l’aide de cmake:

-C <initial-cache>
     Pre-load a script to populate the cache.

     When cmake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project.  This option may be used to specify a  file  from
     which to load cache entries before the first pass through the project's cmake listfiles.  The loaded entries take priority over the project's default values.  The given file should be a CMake
     script containing SET commands that use the CACHE option, not a cache-format file.

Vous pouvez créer des fichiers tels que gcc_compiler.txt et clang_compiler.txt pour inclure toutes les configurations relatives dans la syntaxe CMake.

Exemple de clang (clang_compiler.txt):

 set(CMAKE_C_COMPILER "/usr/bin/clang" CACHE string "clang compiler" FORCE)

Puis lancez le en tant que

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

Bruit:

cmake -C clang_compiler.txt XXXXXXXX
4
Enze Chi

Si le compilateur par défaut choisi par cmake est gcc et que vous avez installé clang, vous pouvez utiliser le moyen le plus simple pour compiler votre projet avec clang:

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
3
xl4times

Vous pouvez utiliser la syntaxe: $ENV{environment-variable} dans votre CMakeLists.txt pour accéder aux variables d'environnement. Vous pouvez créer des scripts qui initialisent correctement un ensemble de variables d’environnement et qui n’ont que des références à ces variables dans vos fichiers CMakeLists.txt.

3
Ferruccio