Wie füge ich einer CMake-Datei einen Linker oder ein Kompilierungsflag hinzu?

220

Ich benutze den arm-linux-androideabi-g++Compiler. Wenn ich versuche, ein einfaches "Hallo Welt!" Programm kompiliert es gut. Wenn ich es durch Hinzufügen einer einfachen Ausnahmebehandlung in diesem Code teste, funktioniert es auch (nach dem Hinzufügen -fexceptions.. Ich denke, es ist standardmäßig deaktiviert).

Dies ist für ein Android-Gerät und ich möchte nur CMake verwenden, nicht ndk-build.

Zum Beispiel - first.cpp

#include <iostream>

using namespace std;

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

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

Es funktioniert ohne Probleme ...

Das Problem ... Ich versuche, die Datei mit einer CMake-Datei zu kompilieren.

Ich möchte das -fexceptionsals Flagge hinzufügen . Ich habe es mit versucht

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

und

set ( CMAKE_C_FLAGS "fexceptions")

Es wird weiterhin ein Fehler angezeigt.

Solti
quelle
Im Moment habe ich das gleiche Problem und probiere verschiedene Dinge aus. Hänge ein wenig und ich poste eine Antwort. Für Kompilierungsflags gibt es einen unreinen, aber einfachen Weg: add_definitions ("- truc")
Offirmo
Für eine aktuellere Diskussion zu dieser Frage (insbesondere wenn Sie CMake 3.x oder neuer verwenden): Was ist die moderne Methode zum Setzen allgemeiner Kompilierungsflags in CMake? .
ComicSansMS
Wenn die Link-Flags, die Sie möchten, auf die Konfiguration von rpath abzielen, werfen Sie einen Blick auf die spezifischen CMake-rpath-Befehle gitlab.kitware.com/cmake/community/wikis/doc/cmake/…
Gabriel Devillers

Antworten:

243

Angenommen, Sie möchten diese Flags hinzufügen (besser deklarieren Sie sie in einer Konstanten):

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

Es gibt verschiedene Möglichkeiten, sie hinzuzufügen:

  1. Die einfachste (nicht sauber, aber einfach und bequem und funktioniert nur für das gleichzeitige Kompilieren von Flags, C & C ++):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  2. Anhängen an entsprechende CMake-Variablen:

    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. Unter Verwendung von Zieleigenschaften vgl. doc CMake kompiliert Flag-Zieleigenschaft und muss den Zielnamen kennen.

    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} )

Im Moment benutze ich Methode 2.

Offirmo
quelle
4
Warum ist add_definitions () unrein?
leinaD_natipaC
14
@leinaD_natipaC: In der offiziellen Dokumentation heißt es: Mit diesem Befehl können beliebige Flags hinzugefügt werden, es sollen jedoch Präprozessordefinitionen hinzugefügt werden . Ich denke deshalb.
Benoit Blanchon
Obwohl dies die akzeptierte Antwort ist, die CMAKE im sehr alten Stil zeigt, lesen Sie in der Antwort von @vitaut nach, wie jeder neue CMAKE-Code in Bezug auf die Kompilierungszeitparameter strukturiert werden sollte
Harald Scheirich,
1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")ist kürzer und sauberer alsset(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
blutiger
165

In neueren Versionen von CMake können Sie Compiler und Linker - Flags für ein einzelnes Ziel mit gesetzt target_compile_optionsund target_link_librariesjeweils (ja, die letzteren Sätze Linker - Optionen zu):

target_compile_options(first-test PRIVATE -fexceptions)

Der Vorteil dieser Methode besteht darin, dass Sie die Weitergabe von Optionen an andere Ziele steuern können, die von diesem über PUBLICund abhängen PRIVATE.

Ab CMake 3.13 können Sie auch target_link_optionsLinker-Optionen hinzufügen, um die Absicht klarer zu machen.

vitaut
quelle
2
Ich habe versucht, es zu benutzen: target_compile_options(main_static PRIVATE --static)aber es scheint nicht zu funktionieren, eine Idee warum?
Paweł Szczur
2
-staticist wahrscheinlich ein Linker, keine Compiler-Option. Versuchen Sie es weiterzugeben target_link_libraries.
Vitaut
9
Oh, target_link_librariesich habe diesen Teil des Dokuments verpasst: "Geben Sie Bibliotheken oder Flags an, die beim Verknüpfen eines bestimmten Ziels verwendet werden sollen." Vielen Dank.
Paweł Szczur
3
Neu hinzugefügt: CMake 3.13 bietet target_link_optionseine übersichtlichere Möglichkeit, Linker-Flags anzugeben. Sie sollten die Verwendung target_link_librariesvon Linker-Flags in Zukunft vermeiden und target_link_optionsstattdessen verwenden.
ComicSansMS
1
Es gibt auch add_compile_options - siehe stackoverflow.com/questions/39501481/… und in jüngerer Zeit add_link_options
Bruce Adams
46

Versuchen Sie, die Variable CMAKE_CXX_FLAGSanstelle von CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")

Die Variable CMAKE_C_FLAGSwirkt sich nur auf den C-Compiler aus, Sie kompilieren jedoch C ++ - Code.

Das Hinzufügen des Flags zu CMAKE_EXE_LINKER_FLAGSist redundant.

Sakra
quelle
Ich habe das versucht, aber es gibt immer noch Fehler. Ist gesetzt (CMAKE_CXX_FLAGS "-fexceptions") die einzige Möglichkeit, das Compiler-Flag anzugeben.
Solti
3
Ich habe das Problem gelöst, aber nicht auf gute Weise. Es ist eine schlechte Problemumgehung. Ich habe -DCMAKE_CXX_FLAGS = "-fexceptions" in der Befehlszeile gemacht. Aus irgendeinem Grund liest cmake keine Flags aus der .cmake-Datei. :( .. danke sakra für deine
antwort
8
-DCMAKE_CXX_FLAGS = "-fexceptions" Es sollte KEIN Leerzeichen zwischen = und "
evandrix
Zu dem, was Sie gesagt haben: "Aus irgendeinem Grund liest cmake keine Flags aus der .cmake-Datei." Stellen Sie sicher, dass Sie den vorhandenen Cache leeren. Dies kann erreicht werden, indem alles aus dem Build-Verzeichnis gelöscht wird, bevor cmake erneut ausgeführt wird.
Zaizen
1

Sie können einem bestimmten Ziel auch Linker-Flags hinzufügen, indem Sie die LINK_FLAGSEigenschaft verwenden:

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

Wenn Sie diese Änderung auf andere Ziele übertragen möchten, können Sie ein Dummy-Ziel erstellen, mit dem eine Verknüpfung hergestellt werden soll.

kaveish
quelle