Ich bin ziemlich neu in CMake, und lesen Sie ein paar Tutorials, wie man es benutzt, und schrieb einige komplizierte 50 Zeilen CMake-Skript, um ein Programm für 3 verschiedene Compiler zu machen. Damit ist wahrscheinlich mein ganzes Wissen über CMake erschöpft.
Nun ist mein Problem, dass ich einige Quelltexte habe, deren Ordner ich nicht berühren möchte, wenn ich das Programm erstelle. Ich möchte, dass alle CMake- und make
-Ausgabedateien und -Ordner in ../Compile/
landen, also habe ich ein paar Variablen in meinem CMake-Skript dafür geändert, und es hat eine Zeit lang funktioniert, als ich so etwas auf meinem Laptop gemacht habe:
Compile$ cmake ../src
Compile$ make
Wo mit, dass ich eine saubere Ausgabe in den Ordner hatte ich're in jetzt, das ist genau das, was ich'm suchen.
Jetzt bin ich auf einen anderen Computer umgezogen und habe CMake 2.8.11.2 neu kompiliert, und ich bin fast wieder am Anfang! Es kompiliert das Ding immer in den src
-Ordner, wo sich meine CMakeLists.txt
befindet.
Der Teil, in dem ich das Verzeichnis in meinem CMake-Skript auswähle, ist dieser:
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
Übersehe ich etwas?
Es hört sich so an, als ob Sie ein out of source build wollen. Es gibt mehrere Möglichkeiten, wie Sie ein Out-of-Source-Build erstellen können.
Tun Sie, was Sie gerade getan haben, führen Sie
cd /pfad/zu/mein/build/ordner
cmake /pfad/zu/mein/quelle/ordner
was cmake veranlasst, einen build tree in /path/to/my/build/folder
für den source tree in /path/to/my/source/folder
zu erzeugen.
Sobald Sie ihn erstellt haben, merkt sich cmake, wo sich der Quellcode-Ordner befindet - Sie können also erneut cmake auf dem Build-Baum mit
cmake /pfad/zu/mein/build/ordner
oder sogar
cmake .
wenn Ihr aktuelles Verzeichnis bereits der Build-Ordner ist.
Verwenden Sie einige undokumentierte Optionen, um die Quell- und Bauverzeichnisse festzulegen:
cmake -B/path/to/my/build/folder -H/path/to/my/source/folder
was genau dasselbe tut wie (1), aber ohne die Abhängigkeit vom aktuellen Arbeitsverzeichnis.
CMake legt alle seine Ausgaben standardmäßig im Build-Tree ab. Wenn Sie also nicht großzügig ${CMAKE_SOURCE_DIR}
oder ${CMAKE_CURRENT_SOURCE_DIR}
in Ihren cmake-Dateien verwenden, sollte es Ihren Source-Tree nicht berühren.
Die größte Sache, die schief gehen kann, ist, wenn Sie zuvor einen Build-Tree in Ihrem Source-Tree erzeugt haben (d.h. Sie haben einen in source Build). Sobald Sie dies getan haben, tritt der zweite Teil von (1) oben in Kraft und cmake nimmt keine Änderungen an den Quell- oder Bauorten vor. Daher können Sie keinen Out-of-Source-Build für ein Quellverzeichnis mit einem In-Source-Build erstellen. Sie können dies recht einfach beheben, indem Sie (mindestens) CMakeCache.txt
aus dem Quellverzeichnis entfernen. Es gibt noch ein paar andere Dateien (meistens im CMakeFiles
Verzeichnis), die CMake generiert, die Sie ebenfalls entfernen sollten, aber diese werden cmake nicht dazu veranlassen, den Source-Tree als einen Build-Tree zu behandeln.
Da Out-of-Source-Builds oft wünschenswerter sind als In-Source-Builds, möchten Sie vielleicht Ihr cmake so modifizieren, dass es Out-of-Source-Builds benötigt:
# 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.cmake
auf Google, aber ich kann das Original nicht finden, und es ist kurz genug, um es hier vollständig aufzunehmen.
Leider hat cmake in der Regel bereits einige Dateien geschrieben, wenn das Makro aufgerufen wird. Obwohl es Sie also davon abhält, den Build tatsächlich durchzuführen, müssen Sie trotzdem CMakeCache.txt
und CMakeFiles
löschen.
Sie könnten es nützlich finden, die Pfade zu setzen, in die Binärdateien, Shared und Static Libraries geschrieben werden - in diesem Fall siehe how do I make cmake output into a 'bin' dir? (Disclaimer, ich habe die meistgewählte Antwort auf diese Frage...aber daher weiß ich es).
Es besteht kaum die Notwendigkeit, alle Variablen zu setzen, die Sie setzen. CMake setzt sie auf vernünftige Standardwerte. Sie sollten auf keinen Fall CMAKE_BINARY_DIR
oder CMAKE_CACHEFILE_DIR
ändern. Behandeln Sie diese als schreibgeschützt.
Entfernen Sie zuerst die vorhandene problematische Cache-Datei aus dem src-Verzeichnis:
cd src
rm CMakeCache.txt
cd ..
Dann entfernen Sie alle set()
-Befehle und tun:
cd Compile
rm -rf *
cmake ../src
Solange Sie sich beim Ausführen von CMake außerhalb des Quellverzeichnisses befinden, wird CMake das Quellverzeichnis nicht verändern, es sei denn, Ihre CMakeList fordert es explizit dazu auf.
Wenn Sie das geschafft haben, können Sie sich ansehen, wo CMake Dinge standardmäßig ablegt, und nur, wenn Sie mit den Standardverzeichnissen nicht zufrieden sind (wie z.B. der Standardwert von EXECUTABLE_OUTPUT_PATH
), ändern Sie nur die, die Sie brauchen. Und versuchen Sie, sie relativ zu CMAKE_BINARY_DIR
, CMAKE_CURRENT_BINARY_DIR
, PROJECT_BINARY_DIR
usw. anzugeben.
Wenn Sie sich die CMake-Dokumentation ansehen, werden Sie sehen, dass Variablen in semantische Abschnitte unterteilt sind. Außer unter sehr besonderen Umständen sollten Sie alle Variablen, die unter "Variablen, die Informationen liefern" aufgeführt sind, als schreibgeschützt in CMakeLists behandeln.
Sie sollten sich nicht auf einen fest kodierten Build-Verzeichnisnamen in Ihrem Skript verlassen, daher muss die Zeile mit ../Compile
geändert werden.
Das liegt daran, dass es dem Benutzer überlassen sein sollte, wo er kompiliert.
Verwenden Sie stattdessen eine der vordefinierten Variablen:
http://www.cmake.org/Wiki/CMake_Useful_Variables
(suchen Sie nach CMAKE_BINARY_DIR
und CMAKE_CURRENT_BINARY_DIR
)