Automatycznie dodawać wszystkie pliki w folderze do celu przy użyciu CMake?

163

Rozważam przejście projektu wieloplatformowego z oddzielnych systemów zarządzania kompilacją w Visual C ++, XCode i makefile na CMake.

Jedną z podstawowych funkcji, których potrzebuję, jest automatyczne dodawanie wszystkich plików w katalogu do celu. Chociaż jest to łatwe do zrobienia w make, nie jest to łatwe do wykonania w Visual C ++ i XCode (popraw mnie, jeśli się mylę). Czy można to zrobić bezpośrednio w CMake? W jaki sposób?

martjno
źródło
Przy okazji. w programie Visual Studio, przynajmniej w projektach C #, w eksploratorze projektów znajduje się przycisk paska narzędzi o nazwie Pokaż wszystkie pliki. Powoduje, że wszystkie podkatalogi projektu są widoczne i wyszarzone, jeśli nie zawierają żadnych plików logicznie uwzględnionych w projekcie. Możesz dołączyć te katalogi za pomocą menu kontekstowego, które obejmuje wszystkie pliki źródłowe w nich, rekurencyjnie :)
yeoman

Odpowiedzi:

228

To jest możliwe. Np. Z file(GLOB:

cmake_minimum_required(VERSION 2.8)

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

add_executable(helloworld ${helloworld_SRC})

Zauważ, że wymaga to ręcznego ponownego uruchomienia, cmakejeśli plik źródłowy zostanie dodany lub usunięty, ponieważ wygenerowany system kompilacji nie wie, kiedy poprosić CMake o ponowne wygenerowanie, a robienie tego przy każdej kompilacji wydłuży czas kompilacji.

Kleist
źródło
11
Alternatywą dla ręcznego ponownego uruchomienia cmake jest dotknięcie pliku CMakeLists.txt przed uruchomieniem make.
Seamus Connor
8
> „Nie zalecamy używania GLOB do zbierania listy plików źródłowych z drzewa źródłowego. Jeśli żaden plik CMakeLists.txt nie zmienia się po dodaniu lub usunięciu źródła, wówczas wygenerowany system kompilacji nie może wiedzieć, kiedy poprosić CMake o ponowne wygenerowanie.” Nie jest to już zalecane w dokumentach CMAKE3.7, do których prowadzi Hand1Cloud
potrójny
4
jaka jest zatem alternatywa dla GLOB?
Shayne,
13
Lepszy sposób od wersji 3.1 jest sugerowany tutaj: target_sources () crascit.com/2016/01/31/...
Sheen
34

Odpowiedź Kleista z pewnością działa, ale jest ważne zastrzeżenie:

Kiedy piszesz Makefileręcznie, możesz wygenerować SRCSzmienną za pomocą funkcji zaznaczania wszystkich plików .cppi .h. Jeśli plik źródłowy zostanie później dodany, ponowne uruchomienie makebędzie go zawierać.

Jednak CMake (z poleceniem takim jak file(GLOB ...)) jawnie wygeneruje listę plików i umieści ją w automatycznie generowanym pliku Makefile. Jeśli masz nowy plik źródłowy, będziesz musiał ponownie wygenerować plik Makefileprzez ponowne uruchomienie cmake.

edycja: nie ma potrzeby usuwania pliku Makefile.

kara deniz
źródło
4
Nie można po prostu ponownie uruchomić cmake, co powinno usunąć / zmodyfikować nieaktualny plik Makefile?
Ethan
25
To nie jest odpowiedź, to komentarz na temat odpowiedzi @ Kleista.
Neowizard
3
@Neowizard nie jest w terminologii Stackoverflow.
kara deniz
1
Ten komentarz jest fajny, ale jest „standardowy”, prawda? Pytający już używa cmake, więc sugerowanie, że make może być „mądrzejszy”, nie jest zbyt pomocne.
frankliuao
Czy jest więc sposób na dodanie nowych plików źródłowych, a następnie kompilację bez ponownego uruchamiania cmake?
artin
6

Rozszerzenie dla odpowiedzi @Kleist :

Od CMake 3.12 dodatkowa opcja CONFIGURE_DEPENDS jest obsługiwana przez polecenia file(GLOB)i file(GLOB_RECURSE). Dzięki tej opcji nie ma potrzeby do ręcznie ponownie uruchomić CMake Po dodaniu / usunięciu pliku źródłowego w katalogu - CUpewnij zostanie ponownie uruchomiony automatycznie na następny budowania projektu.

Jednak opcja CONFIGURE_DEPENDS oznacza, że ​​odpowiedni katalog będzie ponownie sprawdzany za każdym razem, gdy zażądane jest zbudowanie, więc proces budowania zajmie więcej czasu niż bez CONFIGURE_DEPENDS .

Nawet z dostępną opcją CONFIGURE_DEPENDS, dokumentacja CMake nadal nie zaleca używania file(GLOB)ani file(GLOB_RECURSE)do zbierania źródeł.

Tsyvarev
źródło
„Dokumentacja CMake nadal nie zaleca używania file(GLOB)ani file(GLOB_RECURSE)zbierania źródeł”. Co zatem zalecają? Używasz czegoś innego do zbierania źródeł lub ręcznego wyświetlania każdego pliku źródłowego?
Thomas
1
@Thomas: Zalecają ręczne wyświetlenie każdego pliku źródłowego. Ta odpowiedź stanowi świetne wyjaśnienie zalecenia.
Tsyvarev
-2

Dlaczego więc nie skorzystać z PowerShell, aby utworzyć listę plików źródłowych? Spójrz na ten skrypt

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;

Załóżmy, że masz folder o takiej strukturze

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

Teraz zapisz ten plik na przykład jako „generationSourceList.ps1” i uruchom skrypt jako

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

Plik out.txt będzie zawierał

set(SOURCE "A/a.cpp" "B/b.cpp")
alcoforado
źródło
Pytanie jest otagowane na wielu platformach - program PowerShell nie jest na wielu platformach.
reichhart
@reichhart PowerShell działa na Linux i Mac, a także
Noone
Wiem. Ale nie ma tagu dla PowerShell, a „CMake” jest już wieloplatformowy. „Powershell” byłby dodatkową zależnością i jest bardzo rzadko używany w innych systemach operacyjnych niż Windows. Możesz znaleźć nawet więcej programistów C # w systemie Linux niż ludzi z PowerShell. A najważniejszym faktem jest pytanie: "Czy można to zrobić bezpośrednio w CMake? Jak?"
reichhart