303 votes

Comment ajouter un drapeau d'édition de liens ou de compilation dans un fichier CMake ?

J'utilise le arm-linux-androideabi-g++ compilateur. Lorsque j'essaie de compiler un simple programme "Hello, World !", il se compile correctement. Lorsque je le teste en ajoutant une simple gestion d'exception dans ce code, il fonctionne également (après avoir ajouté -fexceptions .. Je suppose qu'il est désactivé par défaut).

C'est pour un appareil Android, et je ne veux utiliser que CMake, pas ndk-build .

Par exemple - first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}

./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions

Il fonctionne sans problème...

Le problème ... J'essaie de compiler le fichier avec un fichier CMake.

Je souhaite ajouter le -fexceptions comme un drapeau. J'ai essayé avec

set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )

et

set ( CMAKE_C_FLAGS "fexceptions")

Il affiche toujours une erreur.

304voto

Offirmo Points 3374

Note : Etant donné l'évolution de CMake depuis que cette réponse a été écrite en 2012, la plupart des suggestions ici sont maintenant dépassées et ont de meilleures alternatives.


Supposons que vous souhaitiez ajouter ces drapeaux (mieux vaut les déclarer dans une constante) :

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

Il y a plusieurs façons de les ajouter :

  1. Le plus simple (pas propre, mais facile et pratique, et ne fonctionne que pour les drapeaux de compilation, C et C++ à la fois) :

     add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Ajout aux variables CMake correspondantes :

     SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
     SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
  3. Utilisation des propriétés de la cible, cf. doc Propriété de la cible du drapeau de compilation CMake et doivent connaître le nom de la cible.

     get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
     if(TEMP STREQUAL "TEMP-NOTFOUND")
       SET(TEMP "") # Set to empty string
     else()
       SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
     endif()
     # Append our values
     SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
     set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )

Pour l'instant, j'utilise la méthode 2.

254voto

vitaut Points 10255

Dans les versions plus récentes de CMake, vous pouvez définir les drapeaux du compilateur et de l'éditeur de liens pour une cible unique à l'aide de la commande target_compile_options y target_link_libraries respectivement (oui, la dernière définit également les options de l'éditeur de liens) :

target_compile_options(first-test PRIVATE -fexceptions)

L'avantage de cette méthode est que vous pouvez contrôler la propagation des options vers d'autres cibles qui dépendent de celle-ci par l'intermédiaire de PUBLIC y PRIVATE .

Depuis CMake 3.13, vous pouvez également utiliser target_link_options pour ajouter des options de liaison qui rendent l'intention plus claire.

59voto

sakra Points 13373

Essayez de définir la variable CMAKE_CXX_FLAGS au lieu de CMAKE_C_FLAGS :

set (CMAKE_CXX_FLAGS "-fexceptions")

La variable CMAKE_C_FLAGS n'affecte que le compilateur C, mais vous compilez du code C++.

Ajouter le drapeau à CMAKE_EXE_LINKER_FLAGS est redondant.

9voto

JMcF Points 631

La meilleure façon de spécifier des options spécifiques à une chaîne d'outils est d'utiliser la fonction facilité d'utilisation de la chaîne d'outils . Cela permet d'assurer une séparation nette entre les deux :

  • des instructions sur la manière d'organiser les fichiers sources en cibles -- exprimées en CMakeLists.txt entièrement indépendant de la chaîne d'outils ; et
  • les détails de la configuration de certaines chaînes d'outils - séparées dans des fichiers CMake script, extensibles par les futurs utilisateurs de votre projet, évolutifs.

Idéalement, il ne devrait pas y avoir de drapeaux de compilateur ou d'éditeur de liens dans votre fichier CMakeLists.txt même à l'intérieur d'un if / endif blocs. Votre programme doit être construit pour la plateforme native avec la chaîne d'outils par défaut (par exemple GCC sur GNU/Linux ou MSVC sur Windows) sans drapeaux supplémentaires.

Etapes pour ajouter une chaîne d'outils :

  1. Créer un fichier, par exemple arm-linux-androideadi-gcc.cmake avec les paramètres globaux de la chaîne d'outils :

    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
    set(CMAKE_CXX_FLAGS_INIT "-fexceptions")

    (Vous pouvez trouver un exemple de fichier de chaîne d'outils de compilation croisée Linux aquí .)

  2. Lorsque vous souhaitez générer un système de construction avec cette chaîne d'outils, spécifiez l'option CMAKE_TOOLCHAIN_FILE sur la ligne de commande :

    mkdir android-arm-build && cd android-arm-build
    cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..

    (Note : vous ne pouvez pas utiliser un chemin relatif).

  3. Construire normalement :

    cmake --build .

Les fichiers de la chaîne d'outils facilitent la compilation croisée, mais ils ont d'autres utilisations :

  • Des diagnostics renforcés pour vos tests unitaires.

    set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
  • Outils de développement difficiles à configurer.

    # toolchain file for use with gcov
    set(CMAKE_CXX_FLAGS_INIT "--coverage -fno-exceptions -g")
  • Contrôles de sécurité renforcés.

    # toolchain file for use with gdb
    set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error")
    set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")

4voto

kaveish Points 826

Vous pouvez également ajouter des drapeaux de liaison à une cible spécifique à l'aide de la commande LINK_FLAGS propriété :

set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")

Si vous souhaitez propager cette modification à d'autres cibles, vous pouvez créer une cible fictive vers laquelle établir un lien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X