Aggiungi automaticamente tutti i file in una cartella a una destinazione usando CMake?


163

Sto pensando di passare da un progetto multipiattaforma da sistemi di gestione build separati in Visual C ++, XCode e makefile a CMake.

Una caratteristica essenziale di cui ho bisogno è quella di aggiungere automaticamente tutti i file in una directory a una destinazione. Mentre questo è facile da fare con make, non è facilmente realizzabile con Visual C ++ e XCode (correggimi se sbaglio). È possibile farlo direttamente in CMake? Come?


Btw. in Visual Studio, almeno nei progetti C #, c'è un pulsante della barra degli strumenti in Esplora progetti, chiamato show all files. Rende visibili tutte le sottodirectory di un progetto, visualizzate in grigio se non contengono alcun file incluso logicamente nel progetto. Puoi includere queste directory tramite il menu di scelta rapida, che include tutti i file sorgente al loro interno, in modo ricorsivo :)
yeoman

Risposte:


229

È possibile. Ad esempio con file(GLOB:

cmake_minimum_required(VERSION 2.8)

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

add_executable(helloworld ${helloworld_SRC})

Si noti che ciò richiede la riesecuzione manuale di cmakeun file sorgente aggiunto o rimosso, poiché il sistema di generazione generato non sa quando chiedere a CMake di rigenerarsi e farlo ad ogni generazione aumenterebbe il tempo di compilazione.


11
Un'alternativa alla riesecuzione manuale di cmake è toccare il file CMakeLists.txt prima di eseguire make.
Seamus Connor,


8
> "Non è consigliabile utilizzare GLOB per raccogliere un elenco di file di origine dall'albero dei sorgenti. Se nessun file CMakeLists.txt cambia quando viene aggiunta o rimossa una fonte, il sistema di generazione generato non può sapere quando chiedere a CMake di rigenerarsi." Questo non è più raccomandato nei documenti CMAKE3.7 collegati da Hand1Cloud
triple,

4
qual è l'alternativa a GLOB allora?
Shayne,

13
Un modo migliore dalla v3.1 è suggerito qui: target_sources () crascit.com/2016/01/31/…
Sheen,

34

La risposta di Kleist sicuramente funziona, ma c'è un avvertimento importante:

Quando si scrive Makefilemanualmente, è possibile generare una SRCSvariabile utilizzando una funzione per selezionare tutto .cppe .hfile. Se in seguito viene aggiunto un file sorgente, la riesecuzione makelo includerà.

Tuttavia, CMake (con un comando simile file(GLOB ...)) genererà esplicitamente un elenco di file e lo inserirà nella generazione automatica Makefile. Se si dispone di un nuovo file di origine, sarà necessario rigenerare Makefilenuovamente eseguendo nuovamente cmake.

modifica: non è necessario rimuovere il Makefile.


4
Cmake non può essere semplicemente rieseguito, il che dovrebbe rimuovere / modificare il Makefile non aggiornato?
Ethan,

25
Questa non è una risposta, è un commento sulla risposta di @ Kleist.
Neowizard,

3
@Neowizard non nella terminologia StackOverflow.
Kara Deniz,

1
Questo commento è carino, ma è "standard", giusto? Il richiedente sta già usando cmake, quindi suggerire che make può essere "più intelligente" non è molto utile.
frankliuao,

Quindi c'è un modo per aggiungere nuovi file sorgente e quindi compilare senza rieseguire cmake?
artin

6

Estensione per la risposta di @Kleist :

Poiché CMake 3.12 l'opzione aggiuntiva CONFIGURE_DEPENDS è supportata da comandi file(GLOB)e file(GLOB_RECURSE). Con questa opzione non v'è alcun bisogno di manualmente -run re CMake dopo l'aggiunta / eliminazione di un file sorgente nella directory - CMake sarà ri-eseguire automaticamente sulla prossima generazione del progetto.

Tuttavia, l'opzione CONFIGURE_DEPENDS implica che la directory corrispondente verrà ricontrollata ogni volta che viene richiesta la compilazione , quindi il processo di compilazione richiederebbe più tempo che senza CONFIGURE_DEPENDS .

Anche con l' opzione CONFIGURE_DEPENDS disponibile, la documentazione di CMake non consiglia ancora di utilizzare file(GLOB)o file(GLOB_RECURSE)di raccogliere le fonti.


"La documentazione di CMake non consiglia ancora di utilizzare file(GLOB)o file(GLOB_RECURSE)di raccogliere le fonti" Cosa raccomandano allora? Usi qualcos'altro per raccogliere le fonti o elencare manualmente ogni singolo file sorgente?
Thomas,

1
@Thomas: raccomandano di elencare manualmente ogni file sorgente. Questa risposta fornisce una grande spiegazione della raccomandazione.
Tsyvarev,

-2

Quindi perché non usare PowerShell per creare l'elenco dei file di origine per te. Dai un'occhiata a questo script

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;

Supponiamo di avere una cartella con questa struttura

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

Ora salva questo file come "generateSourceList.ps1" per esempio ed esegui lo script come

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

il file out.txt conterrà

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

La domanda è etichettata multipiattaforma - powershell non è multipiattaforma.
Reichhart,

@reichhart powershell funziona anche su Linux e Mac
nessuno il

Lo so. Ma non esiste un tag per PowerShell e "CMake" è già multipiattaforma. "Powershell" sarebbe una dipendenza aggiuntiva ed è molto raramente utilizzato su un sistema operativo diverso da Windows. Potresti trovare ancora più sviluppatori C # su Linux rispetto alle persone con PowerShell. E il fatto più importante è la domanda: "È possibile farlo direttamente in CMake? Come?"
Reichhart,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.