Mit CMake automatisch alle Dateien in einem Ordner zu einem Ziel hinzufügen?


162

Ich denke darüber nach, ein plattformübergreifendes Projekt von separaten Build-Management-Systemen in Visual C ++, XCode und Makefiles auf CMake umzustellen.

Eine wesentliche Funktion, die ich benötige, ist das automatische Hinzufügen aller Dateien in einem Verzeichnis zu einem Ziel. Dies ist zwar einfach mit make zu tun, mit Visual C ++ und XCode jedoch nicht einfach (korrigieren Sie mich, wenn ich falsch liege). Ist es möglich, dies direkt in CMake zu tun? Wie?


Übrigens. In In Visual Studio gibt es zumindest in C # -Projekten im Projektexplorer eine Symbolleistenschaltfläche mit dem Namen Alle Dateien anzeigen. Es macht alle Unterverzeichnisse eines Projekts sichtbar und ausgegraut, wenn sie keine logisch im Projekt enthaltenen Dateien enthalten. Sie können diese Verzeichnisse über das Kontextmenü einschließen, das alle darin enthaltenen Quelldateien rekursiv enthält :)
yeoman

Antworten:


228

Es ist möglich. ZB mit file(GLOB:

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
    "*.h"
    "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

Beachten Sie, dass dies ein manuelles erneutes Ausführen erfordert , cmakewenn eine Quelldatei hinzugefügt oder entfernt wird, da das generierte Build-System nicht weiß, wann CMake zur Regeneration aufgefordert werden soll, und dies bei jedem Build die Build-Zeit verlängern würde.


11
Eine Alternative zum manuellen erneuten Ausführen von cmake besteht darin, die Datei CMakeLists.txt vor dem Ausführen von make zu berühren.
Seamus Connor


8
> "Wir empfehlen, GLOB nicht zum Sammeln einer Liste von Quelldateien aus Ihrem Quellbaum zu verwenden. Wenn sich beim Hinzufügen oder Entfernen einer Quelle keine CMakeLists.txt-Datei ändert, kann das generierte Build-System nicht wissen, wann CMake zur Neuerstellung aufgefordert werden soll." Dies wird in CMAKE3.7-Dokumenten, die von Hand1Cloud verlinkt wurden, nicht mehr empfohlen
dreifach

4
Was ist dann die Alternative zu GLOB?
Shayne

12
Ein besserer Weg seit v3.1 wird hier vorgeschlagen: target_sources () crascit.com/2016/01/31/…
Sheen

34

Die Antwort von Kleist funktioniert sicherlich, aber es gibt eine wichtige Einschränkung:

Wenn Sie eine Makefilemanuell schreiben , können Sie eine SRCSVariable mithilfe einer Funktion zum Auswählen aller Dateien .cppund .hDateien generieren . Wenn eine Quelldatei später hinzugefügt wird, wird sie durch erneutes Ausführen eingeschlossen make.

CMake (mit einem Befehl wie file(GLOB ...)) generiert jedoch explizit eine Dateiliste und platziert sie in der automatisch generierten Makefile. Wenn Sie eine neue Quelldatei haben, müssen Sie diese Makefiledurch erneutes Ausführen neu generieren cmake.

Bearbeiten: Das Makefile muss nicht entfernt werden.


4
Kann cmake nicht einfach erneut ausgeführt werden, wodurch das veraltete Makefile entfernt / geändert werden sollte?
Ethan

24
Dies ist keine Antwort, sondern ein Kommentar zu @ Kleists Antwort.
Neowizard

3
@Neowizard nicht in der Stackoverflow-Terminologie.
Kara Deniz

1
Dieser Kommentar ist nett, aber "Standard", oder? Der Fragesteller verwendet bereits cmake, daher ist es nicht hilfreich, vorzuschlagen, dass make "intelligenter" sein kann.
Frankliuao

Gibt es also eine Möglichkeit, neue Quelldateien hinzuzufügen und dann zu erstellen, ohne cmake erneut auszuführen?
Artin

5

Erweiterung für @Kleist Antwort :

Da CMake 3.12 zusätzliche Option CONFIGURE_DEPENDS wird unterstützt durch Befehle file(GLOB)und file(GLOB_RECURSE). Mit dieser Option ist es keine Bedürfnisse zu manuell wieder laufen CMake nach Hinzufügen / Löschen einer Quelldatei in dem Verzeichnis - CMake neu laufen automatisch wird auf der nächsten Erstellen des Projekts.

Die Option CONFIGURE_DEPENDS impliziert jedoch, dass das entsprechende Verzeichnis jedes Mal überprüft wird, wenn eine Erstellung angefordert wird, sodass der Erstellungsprozess mehr Zeit in Anspruch nehmen würde als ohne CONFIGURE_DEPENDS .

Selbst mit der verfügbaren Option CONFIGURE_DEPENDS empfiehlt die CMake-Dokumentation immer noch nicht , die Quellen zu verwenden file(GLOB)oder file(GLOB_RECURSE)zu sammeln.


-2

Warum also nicht Powershell verwenden, um die Liste der Quelldateien für Sie zu erstellen? Schauen Sie sich dieses Skript an

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;


$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

Angenommen, Sie haben einen Ordner mit dieser Struktur

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

Speichern Sie diese Datei nun beispielsweise als "generateSourceList.ps1" und führen Sie das Skript als aus

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

Die Datei out.txt enthält

set(SOURCE "A/a.cpp" "B/b.cpp")

Die Frage ist plattformübergreifend markiert - Powershell ist nicht plattformübergreifend.
Reichhart

@reichhart Powershell funktioniert auch unter Linux und Mac
niemand

Ich weiß. Aber es gibt kein Tag für Powershell und "CMake" ist bereits plattformübergreifend. "Powershell" wäre eine zusätzliche Abhängigkeit und wird unter anderen Betriebssystemen als Windows sehr selten verwendet. Unter Linux finden Sie möglicherweise noch mehr C # -Entwickler als Leute mit Powershell. Und die wichtigste Tatsache ist die Frage: "Ist es möglich, dies direkt in CMake zu tun? Wie?"
Reichhart
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.