2010-02-19 2 views
8

Ich bin damit beschäftigt, meinen Build-Prozess von msbuild nach cmake zu portieren, um besser mit der gcc toolchain umgehen zu können (was viel schneller Code für einige der numerischen Dinge erzeugt, die ich mache) .cmake: Arbeiten mit mehreren Ausgabekonfigurationen

Nun, ich würde gerne Cmake, um mehrere Versionen der Ausgabe, Zeug wie eine Version mit sse2, eine andere mit x64, und so weiter. CMake scheint jedoch am natürlichsten zu funktionieren, wenn Sie einfach eine Reihe von Flags (zB "sse2_enable" und "platform") haben und dann eine Ausgabe basierend auf diesen Plattformen generieren.

Was ist der beste Weg, um mit mehreren Ausgangskonfigurationen wie diesem zu arbeiten? Intuitiv möchte ich über eine große Anzahl von Flag-Kombinationen iterieren und die gleichen CMakeLists.txt-Dateien für jede Kombination erneut ausführen - aber natürlich können Sie nicht die innerhalb der CMakeLists.txt-Dateien (AFAIK) ausdrücken.

Antwort

4

Es gab hier nicht viel Aktivität, also habe ich mir selbst eine praktikable Lösung ausgedacht. Es ist wahrscheinlich nicht ideal, also wenn Sie eine bessere Idee haben, fügen Sie sie bitte hinzu!

Nun ist es schwer zu iterieren configs in Cmake zu bauen, weil Cmake des entscheidenden Variablen in Funktionsumfang Leben nicht - so zum Beispiel, das heißt, wenn Sie include_directories(X) das X-Verzeichnis tun in der Liste enthalten bleibt auch nach der Funktion beendet.

Verzeichnisse haben einen Gültigkeitsbereich - und während normalerweise jedes Eingabeverzeichnis einem Ausgabeverzeichnis entspricht, können Sie mehrere Ausgabeverzeichnisse haben.

So sieht meine Lösung wie folgt aus:

project(FooAllConfigs) 

set(FooVar 2) 
set(FooAnotherVar b) 
add_subdirectory("project_dir" "out-2b") 
set(FooVar 5) 
set(FooAnotherVar c) 
add_subdirectory("project_dir" "out-5c") 
set(FooVar 3) 
set(FooAnotherVar b) 
add_subdirectory("project_dir" "out-3b") 
set(FooVar 3) 
set(FooAnotherVar c) 
add_subdirectory("project_dir" "out-3c") 

Das normale Projekt dir eine CMakeLists.txt Datei mit Code enthält dann die entsprechende enthält und Compiler-Optionen, die globalen Variablen im FooAllConfigs Projekt gegeben einzurichten und es bestimmt auch ein Build-Suffix, das an alle Build-Ausgaben angehängt wird - jede sogar indirekt eingeschlossene Ausgabe (z. B. wie von add_executable generiert) muss einen eindeutigen Namen haben.

Das funktioniert gut für mich.

6

Der empfohlene Weg, um dies zu tun, ist einfach mehrere Build-Verzeichnisse zu haben. Von jedem aus rufen Sie einfach cmake mit den erforderlichen Einstellungen an.

Zum Beispiel Sie tun könnten, im Quellverzeichnis Basis starten (Linux-Shell-Syntax verwenden, aber die Idee ist die gleiche): ist

mkdir build-sse2 && cd build-sse2 
cmake .. -DENABLE_SSE2 # or whatever to enable it in your CMakeLists.txt 
make 

cd .. 

mkdir build-x64 && cd build-x64 
cmake .. -DENABLE_X64 # or whatever again... 
make 

diese Weise wird jedes Build-Verzeichnis vollständig voneinander getrennt.

Dies ermöglicht Ihnen, ein Verzeichnis für Debug, ein anderes für Release und ein anderes für Cross-Compilierung zu haben.

+1

Es gibt jedoch mehrere Probleme mit diesem Ansatz. Zuallererst erfordert es mehrere Aufrufe zum cmake & make für wenig Gewinn, aber es führt zu einer zusätzlichen Komplexität: cmake ist * plattformübergreifend *, aber Shell-Skripting ist es nicht. Zweitens verlangsamt es die Dinge ein wenig; Normalerweise können Sie make -j verwenden, um alle verschiedenen Kombinationen auf nette Multithread-Weise zu erstellen, aber mit dem Multiple-Cmake-Ansatz müssen Sie manuell parallelisieren (und höhere Speicherbelegungen und Lade- und Verlangsamungen akzeptieren, da die separaten Instanzen keine make machen) kooperieren). Der Vorteil ist, dass es Namenskonflikte bewältigen kann. –

+0

Ein weiterer Nachteil: Ein zweiter Anwendungsfall war die Erstellung mehrerer Builds für verschiedene CPUs und die Auswahl der besten zur Laufzeit - und dann ist es wirklich notwendig, dass das Endergebnis von mehreren Builds desselben Subs abhängt -Projekt. –

+0

Deshalb habe ich mich für die andere Lösung entschieden - aber Ihre ist definitiv kanonischer und arbeitet (mit den oben genannten Nachteilen) allgemeiner - danke für Ihren Beitrag! –