CMake - Entferne ein Kompilier-Flag für eine einzelne Übersetzungseinheit

21

Ich möchte ein Set-Compile-Flag für eine einzelne Übersetzungseinheit entfernen. Gibt es eine Möglichkeit, dies zu tun? (z. B. mit set_property ?)

Hinweis: Das Kompilier-Flag hat keine -fno-name Negation (aus welchem ​​Grund auch immer).

Ich habe es versucht:

%Vor%

ohne Glück. Die Eigenschaft, die ich entfernen möchte, ist Teil von CMAKE_CXX_FLAGS und funktioniert daher nicht.

    
gnzlbg 05.02.2015, 12:55
quelle

3 Antworten

7

Diese spezielle Lösung (?) funktioniert sowohl für Ziele als auch für einzelne Übersetzungseinheiten (eine einzelne .cpp -Datei). Es wird CMake 3.7 oder neuer benötigt, da wir alle vorhandenen Targes mit der Eigenschaft BUILDSYSTEM_TARGETS durchlaufen müssen, die in 3.7 hinzugefügt wurde. Wenn Sie 3.7 oder neuer nicht verwenden können, können Sie apply_global_cxx_flags_to_all_targets() anpassen, um eine Liste von Zielen zu übernehmen und sie manuell festzulegen. Beachten Sie, dass Sie die Makros als Proof-of-Concept betrachten sollten. Sie werden wahrscheinlich einige Verbesserungen und Verbesserungen für alle, aber sehr kleine Projekte benötigen.

Der erste Schritt besteht darin, alle vorhandenen Ziele zu durchlaufen und CMAKE_CXX_FLAGS auf jede davon anzuwenden. Wenn dies erledigt ist, löschen wir CMAKE_CXX_FLAGS . Unten finden Sie ein Makro, das dies tun wird. Dieses Makro sollte wahrscheinlich am unteren Rand der obersten Ebene CMakeLists.txt aufgerufen werden, wenn alle Ziele erstellt wurden, alle Flags gesetzt wurden usw. Es ist wichtig zu beachten, dass der Befehl get_property(_targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) auf Verzeichnisebene funktioniert, also if Wenn Sie add_subdirectory() verwenden, müssen Sie dieses Makro in der obersten Ebene CMakeLists.txt dieses Unterverzeichnisses aufrufen.

%Vor%

Dieses Makro erstellt zuerst eine Liste von CMAKE_CXX_FLAGS , dann erhält es eine Liste aller Ziele und wendet CMAKE_CXX_FLAGS auf jedes der Ziele an. Schließlich wird CMAKE_CXX_FLAGS gelöscht. _flag_sync_required wird verwendet, um anzugeben, ob ein erneutes Schreiben von zwischengespeicherten Variablen erzwungen werden muss.

Der nächste Schritt hängt davon ab, ob Sie ein Flag von einem Ziel oder von einer bestimmten Übersetzungseinheit entfernen möchten. Wenn Sie ein Flag von einem Ziel entfernen möchten, können Sie ein ähnliches Makro verwenden:

%Vor%

Das Entfernen eines Flags von einer bestimmten Übersetzungseinheit ist etwas komplizierter (es sei denn, ich habe etwas sehr vermisst). Wie auch immer, die Idee besteht darin, zunächst die Kompilierungsoptionen von dem Ziel zu erhalten, zu dem die Datei gehört, und dann diese Optionen auf alle Quelldateien in diesem Ziel anzuwenden, wodurch wir die Kompilierungsflags für einzelne Dateien bearbeiten können. Dazu führen wir eine Cache-Liste von Kompilierungsflags für jede Datei aus, von der wir Flags entfernen möchten. Wenn ein Remove angefordert wird, entfernen wir ihn aus der zwischengespeicherten Liste und setzen dann die verbleibenden Flags erneut um. Die Kompilierungsoptionen für das Ziel selbst sind gelöscht.

%Vor%

Beispiel

Wir haben diese sehr einfache Projektstruktur:

%Vor%

Nehmen wir an, dass foo.cpp gegen -Wunused-variable verstößt und wir dieses Flag für diese bestimmte Datei deaktivieren wollen. Für bar.cpp möchten wir -Werror deaktivieren. Für main.cpp möchten wir -O2 entfernen, aus welchen Gründen auch immer.

CMakeLists.txt

%Vor%

Wenn Sie stattdessen ein Flag aus einem Ziel entfernen möchten, verwenden Sie remove_flag_from_target() , zum Beispiel: remove_flag_from_target(MyTarget -O2)

Ergebnis

Ausgabe vor dem Anwenden von Makros

%Vor%

Ausgabe nach dem Anwenden von Makros

%Vor%

Schlussnotizen

Wie bereits erwähnt, sollte dies als Proof-of-Concept gesehen werden. Es gibt ein paar unmittelbare Probleme zu beachten:

  • Es berücksichtigt nur CMAKE_CXX_FLAGS (gemeinsam für alle Build-Typen), nicht CMAKE_CXX_FLAGS_<DEBUG|RELEASE> etc.
  • Die Makros können jeweils nur ein Flag behandeln
  • remove_flag_from_file() kann immer nur ein Ziel und eine Eingabedatei als Eingabe behandeln.
  • remove_flag_from_file() erwartet einen Dateinamen, keinen Pfad. Die Übergabe von source/foobar/foobar.cpp funktioniert nicht, da source/foobar/foobar.cpp mit foobar.cpp verglichen wird. Dies kann behoben werden, indem get_source_file_property() und die LOCATION -Eigenschaft verwendet wird und eine Vorbedingung gesetzt wird, dass _file ein vollständiger Pfad ist.
    • Was passiert, wenn ein Ziel zwei oder mehr Dateien mit demselben Namen hat?
  • remove_flag_from_file() kann wahrscheinlich optimiert und verbessert werden.
  • Der Aufruf von separate_arguments() setzt Unix voraus.

Die meisten davon sollten ziemlich einfach zu beheben sein.

Ich hoffe, dass Sie dadurch zumindest in die richtige Richtung gelenkt werden, um dieses Problem zu lösen. Lassen Sie es mich wissen, wenn ich etwas zur Antwort hinzufügen muss.

    
thomas_f 11.03.2018 04:05
quelle
4

Eine (nicht skalierbare und nicht portable) Lösung erstellt einen benutzerdefinierten Befehl mit modifizierten Flags. Ein minimales Beispiel, das ich funktionierte, ist das folgende:

%Vor%

Obwohl es alles andere als perfekt ist, funktioniert es, worauf es ankommt. Der separate_arguments war notwendig, weil ansonsten alle Leerzeichen in CUSTOM_FLAGS maskiert wurden (ich weiß nicht, wie ich diesen schnell lösen kann).

    
jepio 05.02.2015 14:02
quelle
4

Wenn es keine Option zum Kompilieren von Flag-Negierungen gibt (dies wäre die Standardmethode für CMake, die dies für Nicht-IDE-Konfiguratoren behandelt), müssen Sie dieses Kompilier-Flag aus CMAKE_CXX_FLAGS entfernen.

Mögliche Ansätze

  1. Machen Sie COMPILE_FLAGS zu einer Quelldateieigenschaft, die INHERITED von einer Verzeichniseigenschaft mit demselben Namen ist. Jetzt können Sie die Eigenschaft COMPILE_FLAGS jedes Verzeichnisses und jeder Quelldatei einzeln ändern:

    %Vor%
  2. Wenn eine Eigenschaft - wie COMPILE_OPTIONS - nur auf der Zielebene verfügbar ist, werden Sie müssen die Dateien, für die Sie unterschiedliche Einstellungen wünschen, in ein separates neues Ziel verschieben.

    Dies kann mit OBJECT-Bibliotheken geschehen:

    %Vor%

Referenzen

Florian 13.03.2018 20:50
quelle

Tags und Links