2010-01-21 3 views
42

Desidero trovare tutti i file .c in una directory e aggiungerli tutti ai file SRC per compilare in cmake. Come posso farlo in CMakeList.txt.come trovare tutti i file * .c per il sistema di build Cmake

per makefile regolari posso creare

SPECIFIED_SRC_FILE = $(foreach d,$(SPECIFIED_SRC_DIRS),$(wildcard $(addprefix $(d)/*,*.c))) 

ma non ho potuto ottenere come fare qualcosa di simile in CMakeList.txt.

+1

Nota che "raccogliere tutti i file di origine con glob" è ** non consigliato ** in CMake: * Non è consigliabile utilizzare 'GLOB' per raccogliere un elenco di file di origine dall'albero dei sorgenti. Se nessun file 'CMakeLists.txt' cambia quando una sorgente viene aggiunta o rimossa, il sistema di generazione generato non può sapere quando chiedere a CMake di rigenerare. * - da [documentazione] (https://cmake.org/cmake/help/ v3.7/command/file.html) –

+0

@FranklinYu esiste un'alternativa che non richieda la scrittura manuale di ogni nome di file? –

+1

@Ciro Se vuoi evitare di scrivere ogni nome di file, allora penso che "foreach" menzionato da OP sia la strada da percorrere. Tuttavia, il team di CMake sembra raccomandare * di scrivere manualmente ogni nome di file *. –

risposta

39

Prova questo:

AUX_SOURCE_DIRECTORY

Trova tutti i file sorgente in una directory.

AUX_SOURCE_DIRECTORY(dir VARIABLE) 

raccoglie i nomi di tutti i file di origine nella directory specificata e memorizza l'elenco nella variabile fornito. Questo comando è destinato a per essere utilizzato dai progetti che utilizzano l'istanziazione del modello esplicita. I file di istanziazione dei modelli possono essere archiviati in una sottodirectory "Templates" e raccolti automaticamente utilizzando questo comando per evitare di elencare manualmente tutte le istanze .

Si è tentati di utilizzare questo comando per evitare di scrivere l'elenco dei file sorgente per una destinazione libreria o eseguibile. Mentre questo sembra funzionare, non è possibile per CMake generare un sistema di generazione che sappia quando è stato aggiunto un nuovo file sorgente . Normalmente il sistema di generazione generato sa quando è necessario rieseguire CMake perché il file CMakeLists.txt è modificato per aggiungere una nuova origine. Quando la sorgente viene aggiunta alla directory senza modificare questo file, è necessario eseguire manualmente eseguire nuovamente CMake per generare un sistema di generazione che incorpori il nuovo file.

+11

assicurati di leggere l'ultima parte che inizia con "Si sta tentando di usare questo comando per evitare ..." – SaoPauloooo

+1

@SaoPauloooo, come viene scritto successivamente, "Cmake non è in grado di generare un buildsystem che sappia quando un nuovo il file sorgente è stato aggiunto ". Questo comando è la risposta più vicina alla domanda dell'OP. Bene per me. – whitequark

0

È possibile utilizzare AUX_SOURCE_DIRECTORY come @whitequark descritto, ma non sarà davvero funzionare come previsto, come CMake non sarà in grado di determinare quando vengono aggiunti nuovi file (che è una specie di tutto punto con l'utilizzo di un carattere jolly).

+2

AUX_SOURCE_DIRECTORY viene eseguito correttamente per ora. Grazie mille. AUX_SOURCE_DIRECTORY ($ {} PROJECT_INC_DIR controllo/src CTR_SOURCES) ADD_EXECUTABLE ($ {} EXE_NAME $ {} CTR_SOURCES) –

41

E il buon vecchio globbing?

FILE(GLOB MyCSources *.c) 
ADD_EXECUTABLE(MyExecutable ${MyCSources}) 
+0

Questa grande opera, ma vuol evitare l'avvertimento (che CMake non si sa quando vengono aggiunti nuovi file) in le altre due risposte? – kylewm

+1

No, non è così. Sarà comunque necessario rieseguire CMake dopo aver aggiunto un nuovo file. –

+8

(che si è rivelato perfetto per le mie esigenze ... più semplice che modificare CMakeList ogni volta che aggiungi un file sorgente) – kylewm

1

Sì, avete due opzioni. Supponiamo che la struttura della cartella sia simile a questa.

├── autopilot 
      │   ├── _AutoPilot.cpp 
      │   ├── _AutoPilot.h 
      │   └── action 
      │    ├── ActionBase.cpp 
      │    ├── ActionBase.h 
      │    ├── APcopter 
      │    │   ├── APcopter_avoid.cpp 
      │    │   ├── APcopter_avoid.h 

Se si sta per utilizzare AUX_SOURCE_DIRECTORY è necessario aggiungere CMakeLists.txt ognuno di sottodirectory. Quindi devi includere e collegare tutte quelle sottodirectory. Questo è un compito abbastanza difficile. Quindi puoi GLOB e fare il lavoro molto facilmente. Questo è come è fatto.

file(GLOB autopilot_sources ./*.cpp ./*/*.cpp ./*/*/*.cpp ./*/*/*/*.cpp ./*.c ./*/*.c ./*/*/*.c ./*/*/*/*.c) 
    SET(autopilot ${autopilot_sources}) 

Se si desidera creare una libreria utilizzando sopra il codice sorgente di questo è il comando:

ADD_LIBRARY (autopilot ${autopilot}) 
    TARGET_LINK_LIBRARIES (autopilot) 

Se si desidera creare un file eseguibile utilizzando sopra il codice sorgente di questo è il comando:

ADD_EXECUTABLE(autopilot ${autopilot}) 
0

GLOB_RECURSE esempio ricorsivo

Rende fondamentalmente la * andare anche in sottodirectory:

cmake_minimum_required(VERSION 3.0) 
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.c") 
add_executable(main ${SOURCES}) 

E poi le nostre fonti è stato possibile individuare per esempio come:

src/main.c 
src/d/a.c 
src/d/a.h 

E main.c utilizza #include "d/a.h" e a.c utilizza #include "a.h".

Uso GLOB_RECURSE sul livello superiore CMake (cioè "*.c" anziché "src/*.c") è probabilmente una cattiva idea, come si può raccogliere .c file generati da CMake sé che sono posti sotto build/.

Esempio eseguibile on GitHub.