CMake Ausgabe- / Erstellungsverzeichnis

115

Ich bin ziemlich neu in CMake und habe ein paar Tutorials zur Verwendung gelesen und einige komplizierte 50 Zeilen CMake-Skript geschrieben, um ein Programm für 3 verschiedene Compiler zu erstellen. Damit ist wahrscheinlich mein gesamtes Wissen über CMake abgeschlossen.

Jetzt ist mein Problem, dass ich einen Quellcode habe, dessen Ordner ich beim Erstellen des Programms nicht berühren / durcheinander bringen möchte. Ich möchte, dass alle CMake- und makeAusgabedateien und -ordner gespeichert werden. Deshalb ../Compile/habe ich einige Variablen in meinem CMake-Skript geändert, und es hat einige Zeit funktioniert, als ich so etwas auf meinem Laptop gemacht habe:

Compile$ cmake ../src
Compile$ make

Wo ich damit eine saubere Ausgabe in dem Ordner hatte, in dem ich mich gerade befinde, ist genau das, wonach ich suche.

Jetzt bin ich auf einen anderen Computer umgezogen und habe CMake 2.8.11.2 neu kompiliert, und ich bin fast wieder auf dem ersten Platz! Es kompiliert das Ding immer in den srcOrdner, in dem sich my CMakeLists.txtbefindet.

Der Teil, in dem ich das Verzeichnis in meinem CMake-Skript auswähle, ist folgender:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

Und jetzt endet es immer mit:

-- Build files have been written to: /.../src

Vermisse ich etwas

Der Quantenphysiker
quelle
4
Es ist nicht erforderlich, alle von Ihnen festgelegten Variablen festzulegen. CMake setzt sie auf vernünftige Standardeinstellungen. Sie sollten auf keinen Fall ändern CMAKE_BINARY_DIRoder CMAKE_CACHEFILE_DIR. Was passiert, wenn Sie alle diese set()Anrufe entfernen und dies einfach tun cd Compile; rm -rf *; cmake ../src?
Angew ist nicht mehr stolz auf SO
5
Solange Sie sich beim Ausführen von CMake außerhalb des Quellverzeichnisses befinden, wird das Quellverzeichnis grundsätzlich nicht geändert, es sei denn, Ihre CMakeList weist dies ausdrücklich an.
Angew ist nicht mehr stolz auf SO
@Angew Danke für den Tipp, der überrascht! Ich habe all diese Zeilen entfernt und nur cmake ../src verwendet und es hat wie ein Zauber funktioniert! Das ist so überraschend, weil ich es schon einmal versucht habe, als ich CMake zum ersten Mal lernte und es nicht funktioniert hat. Bitte setzen Sie Ihre Antwort in eine offizielle Antwort, um Ihnen das große fette Häkchen zu geben :)
The Quantum Physicist
1
Was mich gerettet hat, war die Bemerkung von @Adam Bowen, dass "Sie keinen Out-of-Source-Build für ein Quellverzeichnis mit einem In-Source-Build erstellen können"
Aur Saraf,

Antworten:

60

Es ist nicht erforderlich, alle von Ihnen festgelegten Variablen festzulegen. CMake setzt sie auf vernünftige Standardeinstellungen. Sie sollten auf keinen Fall ändern CMAKE_BINARY_DIRoder CMAKE_CACHEFILE_DIR. Behandeln Sie diese als schreibgeschützt.

Entfernen Sie zuerst die vorhandene problematische Cache-Datei aus dem src-Verzeichnis:

cd src
rm CMakeCache.txt
cd ..

Entfernen Sie dann alle set()Befehle und führen Sie folgende Schritte aus:

cd Compile
rm -rf *
cmake ../src

Solange Sie sich beim Ausführen von CMake außerhalb des Quellverzeichnisses befinden, wird das Quellverzeichnis nur geändert, wenn Ihre CMakeList dies ausdrücklich anweist.

Sobald dies funktioniert hat, können Sie überprüfen, wo CMake die Dinge standardmäßig ablegt. Nur wenn Sie mit den Standardspeicherorten (z. B. dem Standardwert von EXECUTABLE_OUTPUT_PATH) nicht zufrieden sind , ändern Sie nur die benötigten Speicherorte . Und versuchen , sie zu relativ auszudrücken CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIRusw.

Wenn Sie sich die CMake-Dokumentation ansehen, sehen Sie Variablen, die in semantische Abschnitte unterteilt sind. Mit Ausnahme ganz besonderer Umstände sollten Sie alle unter "Variablen, die Informationen bereitstellen" aufgeführten in MSakeLists als schreibgeschützt behandeln.

Angew ist nicht mehr stolz auf SO
quelle
2
Ich habe angefangen, cmake mit Builds im src-Verzeichnis zu verwenden ... diese Technik ist anfangs fehlgeschlagen. Nachdem ich alle cmake-Build-Dateien / Caches im src-Verzeichnis gelöscht hatte, funktionierte diese Technik. Vielen Dank!
Avi Tevet
18
Vielleicht ist es besser, nicht zu raten rm -rf *. Es ist nicht schön, wenn es cd Compilefehlschlägt ...
Roman
2
@Roman Ich betrachte solche Befehlszeilenbeispiele als ziemlich Pseudocode. Es ist weniger ausführlich und genauer als die Eingabe von "Geben Sie das Verzeichnis ein Compile, löschen Sie alles dort und führen Sie CMake mit einem Pfad zum Quellverzeichnis aus." Ich gehe von einem gesunden Menschenverstand und einem Urteil des Lesers aus.
Angew ist nicht mehr stolz auf SO
@AviTevet: Ich denke das ist die richtige Antwort. Wenn sich im Quellverzeichnis cmake-Cache-Dateien aus einem früheren cmake-Aufruf befinden, kann cmake kein anderes Verzeichnis für die generierten Dateien auswählen, es sei denn, Sie löschen alle alten aus dem Quellverzeichnis. Meiner Meinung nach ziemlich gebrochenes Verhalten von CMake. Warum schreibst du keine andere Antwort?
Jo So
112

Es hört sich so an, als ob Sie einen Out-of-Source-Build wünschen . Es gibt verschiedene Möglichkeiten, einen Out-of-Source-Build zu erstellen.

  1. Mach was du getan hast, lauf

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder

    was bewirkt , dass ein Cmake erzeugen build Baum in /path/to/my/build/folderdem Quellbaum in /path/to/my/source/folder.

    Sobald Sie es erstellt haben, merkt sich cmake, wo sich der Quellordner befindet, sodass Sie cmake im Build-Baum mit erneut ausführen können

    cmake /path/to/my/build/folder

    oder auch

    cmake .

    Wenn Ihr aktuelles Verzeichnis bereits der Build-Ordner ist.

  2. Verwenden Sie für CMake 3.13 oder höher diese Optionen, um die Quelle festzulegen und Ordner zu erstellen

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. Verwenden Sie für ältere CMake einige undokumentierte Optionen, um die Quelle festzulegen und Ordner zu erstellen :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    Dies wird genau das Gleiche tun wie (1), jedoch ohne das Vertrauen in das aktuelle Arbeitsverzeichnis.

CMake setzt alle seine Ausgänge in dem Build - Baum standardmäßig so , wenn Sie großzügig verwenden ${CMAKE_SOURCE_DIR}oder ${CMAKE_CURRENT_SOURCE_DIR}in Ihrer cmake Datei, sollte es nicht Ihren berührt Quellbaum .

Das Größte, was schief gehen kann, ist, wenn Sie zuvor einen Build-Baum in Ihrem Quellbaum generiert haben (dh Sie haben einen In-Source- Build). Sobald Sie dies getan haben, wird der zweite Teil von (1) oben aktiviert, und cmake nimmt keine Änderungen an der Quelle oder den Build-Speicherorten vor. Daher können Sie keinen Out-of-Source-Build für ein Quellverzeichnis mit einem In-Source-Build erstellen . Sie können dies ziemlich einfach beheben, indem Sie (mindestens) CMakeCache.txtaus dem Quellverzeichnis entfernen . Es gibt einige andere Dateien (meistens im CMakeFilesVerzeichnis), die CMake generiert und die Sie ebenfalls entfernen sollten. Diese führen jedoch nicht dazu, dass cmake den Quellbaum als Build-Baum behandelt.

Da Out-of-Source-Builds häufig wünschenswerter sind als In-Source-Builds, möchten Sie Ihr cmake möglicherweise so ändern, dass Out-of-Source-Builds erforderlich sind:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

Das obige Makro stammt von einem häufig verwendeten Modul namens MacroOutOfSourceBuild. Es gibt zahlreiche Quellen für MacroOutOfSourceBuild.cmakeGoogle, aber ich kann das Original anscheinend nicht finden und es ist kurz genug, um es hier vollständig aufzunehmen.

Leider hat cmake in der Regel ein paar Dateien , die von der Zeit geschrieben das Makro aufgerufen wird, so dass , obwohl es Sie tatsächlich die Durchführung der Build stoppen werden Sie noch brauchen, zu löschen CMakeCache.txtund CMakeFiles.

Es kann hilfreich sein, die Pfade festzulegen, in die Binärdateien, gemeinsam genutzte und statische Bibliotheken geschrieben werden. In diesem Fall wird angezeigt, wie die cmake-Ausgabe in ein 'bin'-Verzeichnis umgewandelt wird. (Haftungsausschluss, ich habe die beste Antwort auf diese Frage ... aber so weiß ich davon).

Adam Bowen
quelle
Eigentlich ist die Option, den -S-H
Quellordner festzulegen
@ smac89 Danke! Es sieht so aus, als hätten sie sie in 3.13 dokumentiert - ich habe die Antwort aktualisiert, um das moderne CMake widerzuspiegeln.
Adam Bowen
8

Aus meinem Kommentar eine Antwort machen:

Falls jemand das getan hat, was ich getan habe, wurde zunächst alle Build-Dateien in das Quellverzeichnis gestellt:

cd src
cmake .

cmake wird ein Bündel von Build - Dateien und Cache - Dateien speichern ( CMakeCache.txt, CMakeFiles, cmake_install.cmake, usw.) in der srcRicht.

Um zu einem Out-of-Source-Build zu wechseln, musste ich alle diese Dateien entfernen. Dann könnte ich tun, was @Angew in seiner Antwort empfohlen hat:

mkdir -p src/build
cd src/build
cmake ..
Avi Tevet
quelle
7

Ab CMake Wiki :

CMAKE_BINARY_DIR Wenn Sie In-Source erstellen, entspricht dies CMAKE_SOURCE_DIR, andernfalls ist dies das Verzeichnis der obersten Ebene Ihres Build-Baums

Vergleichen Sie diese beiden Variablen, um festzustellen, ob die Erstellung außerhalb der Quelle gestartet wurde

Damkrat
quelle
6

Sie sollten sich nicht auf einen fest codierten Build-Verzeichnisnamen in Ihrem Skript verlassen, daher muss die Zeile mit ../Compilegeändert werden.

Dies liegt daran, dass es dem Benutzer überlassen bleiben sollte, wo er kompiliert.

Verwenden Sie stattdessen eine der vordefinierten Variablen: http://www.cmake.org/Wiki/CMake_Useful_Variables (suchen Sie nach CMAKE_BINARY_DIRund CMAKE_CURRENT_BINARY_DIR)

Michał Walenciak
quelle
2
Dies ist genau das, wonach ich gesucht habe - CMAKE_CURRENT_BINARY_DIRwürde normalerweise über den aktuellen binären Erstellungspfad berichten. Kann möglicherweise zum Festlegen der abhängigen libs / bin-Builds verwendet werden.
Parasrish