Comment ajouter un éditeur de liens ou un indicateur de compilation dans un fichier CMake?

220

J'utilise le arm-linux-androideabi-g++compilateur. Quand j'essaye de compiler un simple "Bonjour, monde!" programme il compile très bien. Lorsque je le teste en ajoutant une gestion d'exception simple dans ce code, cela fonctionne aussi (après l'ajout -fexceptions.. je suppose qu'il est désactivé par défaut).

C'est pour un appareil Android, et je veux seulement utiliser 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

Ça marche sans problème ...

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

Je veux ajouter le en -fexceptionstant que 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.

solti
la source
en ce moment, j'ai le même problème et j'essaie des choses différentes. Accrochez-vous un peu et je poste une réponse. Pour compiler des drapeaux, il existe un moyen impur mais facile: add_definitions ("- truc")
Offirmo
Pour une discussion plus à jour sur cette question (surtout si vous utilisez CMake 3.x ou une version plus récente): Quelle est la méthode moderne pour définir des drapeaux de compilation généraux dans CMake? .
ComicSansMS
Si les indicateurs de lien que vous voulez visent à configurer rpath , jetez un œil aux commandes spécifiques de CMake rpath gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Gabriel Devillers

Réponses:

243

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

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

Il existe plusieurs façons de les ajouter:

  1. Le plus simple (pas propre, mais facile et pratique, et ne fonctionne que pour compiler des drapeaux, C & 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 cibles, cf. doc CMake compile la propriété cible de l'indicateur et doit 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} )

En ce moment, j'utilise la méthode 2.

Offirmo
la source
4
pourquoi add_definitions () est-il impur?
leinaD_natipaC
14
@leinaD_natipaC: La documentation officielle dit: Cette commande peut être utilisée pour ajouter des indicateurs, mais elle est destinée à ajouter des définitions de préprocesseur . Je pense que c'est pourquoi.
Benoit Blanchon
Bien que ce soit la réponse acceptée, cela montre vraiment un style CMAKE très ancien, reportez-vous à la réponse de @vitaut pour savoir comment tout nouveau code CMAKE devrait être structuré en ce qui concerne les paramètres de temps de compilation
Harald Scheirich
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")est plus court et plus propre queset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
sanglant
165

Dans les versions plus récentes de CMake, vous pouvez définir des indicateurs de compilateur et de l'éditeur de liens pour une cible unique avec target_compile_optionset target_link_librariesrespectivement (oui, ce dernier 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 via PUBLICet PRIVATE.

Depuis CMake 3.13, vous pouvez également utiliser target_link_optionspour ajouter des options de l'éditeur de liens, ce qui rend l'intention plus claire.

vitaut
la source
2
J'ai essayé de l'utiliser: target_compile_options(main_static PRIVATE --static)mais ça ne semble pas fonctionner, une idée pourquoi?
Paweł Szczur
2
-staticest probablement un éditeur de liens, pas une option de compilation. Essayez de le transmettre à target_link_libraries.
vitaut
9
Oh, target_link_librariesj'ai raté cette partie du document: "Spécifiez les bibliothèques ou les drapeaux à utiliser lors de la liaison d'une cible donnée.". Merci.
Paweł Szczur
3
Un ajout récent: CMake 3.13 introduit target_link_optionscomme un moyen plus propre de spécifier les indicateurs de l'éditeur de liens. Vous devriez éviter d'utiliser target_link_librariesdes indicateurs pour l'éditeur de liens à l'avenir et utiliser à la target_link_optionsplace.
ComicSansMS
1
Il y a aussi add_compile_options - voir stackoverflow.com/questions/39501481/… et plus récemment add_link_options
Bruce Adams
46

Essayez de définir la variable CMAKE_CXX_FLAGSau lieu de CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

La variable CMAKE_C_FLAGSaffecte uniquement le compilateur C, mais vous compilez du code C ++.

L'ajout de l'indicateur à CMAKE_EXE_LINKER_FLAGSest redondant.

sakra
la source
j'ai essayé mais cela donne toujours une erreur. Est défini (CMAKE_CXX_FLAGS "-fexceptions") la seule façon de spécifier l'indicateur du compilateur.
solti
3
j'ai résolu le problème mais pas dans le bon sens c'est une mauvaise solution de contournement .. j'ai fait -DCMAKE_CXX_FLAGS = "-fexceptions" dans la ligne de commande. pour une raison quelconque, cmake ne lit pas les drapeaux du fichier .cmake. :( .. merci sakra pour ta réponse ..
solti
8
-DCMAKE_CXX_FLAGS = "-fexceptions" Il ne devrait PAS y avoir d'espace entre le = et "
evandrix
Concernant ce que vous avez dit: "pour une raison quelconque, cmake ne lit pas les drapeaux du fichier .cmake." Assurez-vous de vider le cache existant. Cela peut être fait en supprimant tout du répertoire de construction avant de recréer cmake.
zaizen
1

Vous pouvez également ajouter des indicateurs de l'éditeur de liens à une cible spécifique à l'aide de la LINK_FLAGSpropriété:

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

Si vous souhaitez propager cette modification vers d'autres cibles, vous pouvez créer une cible factice à laquelle vous souhaitez vous lier.

kaveish
la source