CMAKE_BUILD_TYPE wird in CMakeLists.txt nicht verwendet

78

Ich habe Probleme, meine Standard-Build-Konfiguration auf "Release" zu setzen. In meiner Datei CMakeLists.txt setze ich CMAKE_BUILD_TYPE am Anfang der Datei mit:

#enable Release ALWAYS, configure vars
set(CMAKE_BUILD_TYPE Release)
set(EXECUTABLE_NAME "ParticleSimulator")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)

Beim Erstellen meines Projekts und Öffnen der Lösung wird jedoch immer der Debug-Modus angezeigt, der nicht in meiner CMakeLists-Datei angegeben ist. Was mache ich falsch?

Ich habe mir dort einige der anderen Fragen angesehen, aber nichts Spezielles für diese Frage gesehen.

Ein Kern der CMakeLists.txt .

Syntaktische Fruktose
quelle
Haben Sie Ihren CMake-Cache geleert? cmake.org/pipermail/cmake/2008-September/023808.html
usr1234567
@ usr1234567 Ja, und ich habe auch diese Datei gelesen. Ich muss etwas Dummes tun, das die CMAKE_BUILD_TYPEArbeit blockiert ...
Syntactic Fructose
@ usr1234567 Immer noch kein Glück ... Auch versucht, set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Configuration type" FORCE)was nicht funktioniert hat
Syntactic Fructose
4
3. Mal für die letzten 2 Tage)) set(CMAKE_BUILD_TYPE Release)Das ist nicht , wie es funktioniert. Aus Versehen funktioniert dies für den MakefileGenerator. Bei IDEs wie Xcode und Visual Studio wird diese Zeile ignoriert, da Release / Debug intern umgeschaltet wurde. Die Dokumentation ist ziemlich klar. Wenn Sie Ihre Build-Varianten einschränken möchten, müssen Sie CMAKE_CONFIGURATION_TYPES
@ruslo Schreiben Sie bitte Ihren Kommentar als Antwort.
usr1234567

Antworten:

204

Es gibt zwei Arten von Generatoren: Einzelkonfigurationen und Mehrfachkonfigurationen.

Einzelne Konfigurationen

Make-like-Generatoren: Unix-Makefiles , NMake-Makefiles , MinGW-Makefiles , ...

Den Konfigurationstyp legen Sie im Generierungsschritt fest:

cmake -H. -B_builds/Debug -DCMAKE_BUILD_TYPE=Debug "-GUnix Makefiles"

In diesem Fall lautet der Erstellungsschritt immer Debug :

> cmake --build _builds/Debug
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Debug # `--config` ignored
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Release # yep, ignored
/usr/bin/c++ -g ...

Multi-Konfiguration

IDE-Generatoren: Visual Studio , Xcode

CMAKE_BUILD_TYPE Beim Generieren wird der Schritt ignoriert. Beide:

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Debug "-GVisual Studio 12 2013 Win64"

und

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Release "-GVisual Studio 12 2013 Win64"

wird den gleichen Effekt haben:

Geben Sie hier die Bildbeschreibung ein

Dies liegt daran, dass alle Konfigurationen intern sind (dh _builds/msvc-opaque/Releaseund _builds/msvc-opaque/Debugoder etwas spielt keine Rolle). Sie können --configOptionen verwenden, um zu wechseln:

> cmake --build _builds --config Release
cl /O2 ...
> cmake --build _builds --config Debug
cl /Od ...

Steuerung (?)

Ja, du kannst. Definieren Sie einfach CMAKE_CONFIGURATION_TYPES :

# Somewhere in CMakeLists.txt
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}")

Standardausgabe:

-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release;MinSizeRel;RelWithDebInfo
-- Configuring done

Schreiben Sie es um:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;Release" "-GVisual Studio 12 2013 Win64"
-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release
-- Configuring done

Geben Sie hier die Bildbeschreibung ein

Sie können sogar Ihren eigenen Konfigurationstyp definieren:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;MyRelease" -DCMAKE_CXX_FLAGS_MYRELEASE="/My-Rel-flag" -DCMAKE_EXE_LINKER_FLAGS_MYRELEASE="/My-Linker-flags" "-GVisual Studio 12 2013 Win64"

Geben Sie hier die Bildbeschreibung ein

Und bauen:

cmake --build _builds --config MyRelease

Chaotisch (?)

Überhaupt nicht, wenn Sie den Trick kennen :) So erstellen / testen Sie die Konfiguration in den Erstellungsanweisungen eines Skripts / CI-Servers / der Dokumentation usw.:

> CONFIG=Debug
> cmake -H. -B_builds "-DCMAKE_BUILD_TYPE=${CONFIG}" # Set Debug to Makefile, ignored by IDE
> cmake --build _builds --config "${CONFIG}" # Build Debug in IDE, ignored by Makefile
> (cd _builds && ctest -VV -C "${CONFIG}") # Test Debug in IDE, ignored by Makefile

Schlechtes Muster

if(CMAKE_BUILD_TYPE STREQUAL Debug) # Burn it with fire!!!
set(CMAKE_BUILD_TYPE MySuperRelease) # Be ready to catch a bug from IDE user...

Gut

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --my-debug-flags")

Funktioniert gut.

target_compile_definitions(MyTarget PUBLIC "$<$<CONFIG:Debug>:MYDEBUG_MACRO>")

Vielen Dank! :) Sie sparen einen Tag für einen Programmierer.

Arbeitet für mich mit Makefile, ich bin glücklich ...

Ein Zitat aus einem schönen Buch eines netten Mannes, den Sie wahrscheinlich kennen (Hervorhebung von mir):

Warum sollten Sie sich die Mühe machen? Menschen, die auf einer Vielzahl von Systemen programmieren oder eine Vielzahl von Compilern verwenden, kümmern sich sehr darum, denn wenn sie dies nicht tun, müssen sie Zeit damit verschwenden , obskure Fehler zu finden und zu beheben. Leute, die behaupten, dass ihnen Portabilität egal ist, tun dies normalerweise, weil sie nur ein einziges System verwenden und das Gefühl haben, sich die Einstellung leisten zu können, dass die Sprache das ist, was mein Compiler implementiert. Dies ist eng und kurzsichtigAussicht. Wenn Ihr Programm erfolgreich ist, wird es wahrscheinlich portiert, sodass jemand Probleme im Zusammenhang mit implementierungsabhängigen Funktionen finden und beheben muss. Darüber hinaus müssen Programme häufig mit anderen Compilern für dasselbe System kompiliert werden, und selbst eine zukünftige Version Ihres bevorzugten Compilers kann einige Dinge anders machen als die aktuelle. Es ist viel einfacher, die Auswirkungen von Implementierungsabhängigkeiten beim Schreiben eines Programms zu kennen und zu begrenzen, als danach zu versuchen, das Chaos zu entwirren.

Peter Mortensen
quelle
9
Wow, das verdient eine Kopfgeldantwort, sobald es in 4 Stunden verfügbar ist. Vielen Dank für eine so ausführliche Antwort.
Syntaktische Fruktose
Bitte vergib mir meine Unwissenheit ... Wie genau setzen wir das CMAKE_BUILD_TYPEauf Release CmakeList.txt? Ich denke, es ist irgendwo im Abschnitt Control (?) , Aber ich habe Probleme beim Parsen, weil ich zu unerfahren bin. Beachten Sie auch, dass wir nur den Standardwert festlegen möchten. Die Geldstrafe des Benutzers überschreibt sie über die Befehlszeile.
JWW
3
Ich habe eine Antwort gefunden; -H.ist eine undokumentierte Funktion .
Wally
1
Ich sehe, Sie haben versucht, das Dokumentationsproblem zu beheben . Danke für den Versuch. :) Es gibt immer noch keine zufriedenstellende Antwort darauf, warum dies weder dokumentiert noch entfernt werden kann (wenn wirklich ein Risiko besteht).
Wally
2
@Muscampester nur zu Ihrer Information interessanteste Links und Erklärungen finden Sie auf dieser Seite
7

Sie können auch folgendes Snippet verwenden:

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
            "Default build type: RelWithDebInfo" FORCE)
endif()
adembudak
quelle
1
Leute, wenn Sie dann eine eingereichte Antwort ablehnen, finden Sie bitte ein paar Worte, um anzugeben, warum Sie es getan haben. Denn von allen vorgeschlagenen Antworten ist diese einfache die einzige, die für mich funktioniert hat. Und vorher habe ich hier die ähnliche "akzeptierte" Lösung gefunden: blog.kitware.com/cmake-and-the-default-build-type
Alex
5

Eine Möglichkeit besteht darin, dass eines der Submodule den CMAKE_BUILD_TYPEWert im Cache festgelegt hat, dh:

SET(CMAKE_BUILD_TYPE Debug CACHE) 

Dies bedeutet, dass dieser Wert von diesem Punkt bis zum Ende des Konfigurationslaufs dauerhaft aktualisiert wird.

Eine gute Möglichkeit, den Ort zu verfolgen, an dem sich dieser Wert geändert hat, ist die Verwendung von CMakes variable_watch . Fügen Sie in Ihrer Hauptdatei CMakelists.txtdie folgende Zeile hinzu

variable_watch(CMAKE_BUILD_TYPE)

Dadurch wird bei jedem Zugriff auf diese Variable der Standardfehler ausgegeben. Und um die Datei zu protokollieren, gehen Sie wie folgt vor:

cmake <your options> 2>variable_watch.log

Sie können etwas sehen wie:

CMake-Debug-Protokoll unter <...> / CMakeLists.txt: 184 (add_library): Auf die Variable "CMAKE_BUILD_TYPE" wurde mit READ_ACCESS mit dem Wert "Debug" zugegriffen.

Dann werden Sie wahrscheinlich die Punkte sehen, an denen CMAKE_BUILD_TYPE zum ersten Mal geändert wurde. Und von hier aus sind Sie viel näher dran, um die beleidigende CMake-Linie zu verfolgen.

Daniel Heilper
quelle