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.
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.
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%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)
Ausgabe vor dem Anwenden von Makros
%Vor%Ausgabe nach dem Anwenden von Makros
%Vor%Wie bereits erwähnt, sollte dies als Proof-of-Concept gesehen werden. Es gibt ein paar unmittelbare Probleme zu beachten:
CMAKE_CXX_FLAGS
(gemeinsam für alle Build-Typen), nicht CMAKE_CXX_FLAGS_<DEBUG|RELEASE>
etc. 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.
remove_flag_from_file()
kann wahrscheinlich optimiert und verbessert werden. 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.
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).
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.
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:
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%