2015-02-20 21 views
7

Quando si crea un progetto utilizzando CMake e Make, è possibile eseguire make da una sottodirectory del proprio albero di compilazione (ovvero da una directory di seguito qualsiasi directory contiene il primo livello Makefile) e make (per quanto posso dire) costruire tutti gli obiettivi in ​​corrispondenza o al di sotto di quella directory. Ciò è dovuto al fatto che CMake genera un Makefile per ogni directory che contiene obiettivi, quindi quando si è in una directory con destinazioni, make trova Makefile per la costruzione di tali destinazioni.Ninja equivalente di Make "build from this directory down" (con CMake)?

Quando CMake genera file Ninja, tuttavia, genera solo unobuild.ninja file, che si trova al livello superiore della struttura di costruzione. Quindi chiamare ninja da una directory diversa dalla directory di livello superiore non riesce (anche l'opzione -f non funziona perché ninja non riesce a trovare il file rules.ninja).

Esiste un modo per emulare il comportamento di tipo "make-like" di creare target in corrispondenza di una directory? Per quanto posso dire, non ci sono bersagli Ninja che corrispondono a "tutti i bersagli a e sotto una particolare directory". (Questo potrebbe essere emulato usando obiettivi fasulli denominati dopo ogni directory che dipendono da tutti i target in e sotto quella directory, ma CMake non genera tali target per impostazione predefinita.)

risposta

0

Buona domanda. Mi piacerebbe sapere la risposta se la trovi. Sono appena in fase di transizione verso me stesso cmake + ninja.

Ho scoperto che non potevo creare obiettivi con lo stesso nome a diversi livelli (se c'è un modo che sarei interessato a sapere). Così ho adottato una convenzione di denominazione per diversi target E.g. name - builds program or library test.name - runs tests for the named program or library doxygen.name - build doxygen for the named program or library

per le gerarchie più profonde si può fare qualcosa di simile: doxygen.subproject doxygen.subproject.name

Con questo modello è possibile controllare esattamente ciò che è costruito, ma si deve eseguire il comando dalla cartella di compilazione di livello superiore. Penso che dopo essermi abituato a questo lo troverò più produttivo in quanto non c'è bisogno di cambiare directory prima di creare o eseguire qualcosa e anche se a volte c'è un po 'di tipizzazione in più, la cronologia della shell generalmente lo ha coperto.

Questo è implementato sotto il cofano utilizzando add_custom_target() e aggiungendo dipendenze appropriate. Io uso un macro per fare questo automaticamente in modo che una macro "add_doxygen()" aggiungerà il target Doxygen per il programma e fare l'obiettivo doxygen ad ogni livello più elevato dipendono su di esso utilizzando add_dependencies().

+1

Gli obiettivi in ​​Ninja non sono gerarchici, motivo per cui devono essere denominati in modo univoco. Utilizziamo uno script di compilazione personalizzato per garantire che CMake e Ninja vengano sempre eseguiti dalla stessa directory e utilizziamo sempre anche una directory di compilazione separata dalla nostra directory di origine. Ciò rende le build completamente pulite robuste e facili e ci consente di costruire per più piattaforme. –

+0

Sembra che tu abbia risposto alla domanda OP lì. Sto passando per la generazione di makefile per prima cosa dove non si applica. È stato utile mantenere la struttura originale (mantenendo le build di origine) come nella fase intermedia. Ci sarebbe bello aggiungere bersagli con lo stesso nome per ogni livello. Non sono del tutto sicuro se lo stesso cmake non lo consenta. Dopo tutto è possibile eseguire make make, make clean e fare test solo sulla sottostruttura in cui ci si trova. –

+0

I am the OP. Comunque, no, non credo che * CMake * non consenta nomi di obiettivi non univoci, sto solo spiegando perché Ninja lo fa. –

0

questo ha funzionato per me:

obiettivi
cd <build-root> 
DIRECTORY=<path-relative-to-build-root> 
ninja -t targets all | egrep "^${DIRECTORY}/" | egrep CXX_EXECUTABLE_LINKER | \ 
    sed -e 's/:.*//g' | xargs ninja 

ninja -t tutti - elenca tutti gli obiettivi (incluso il tipo di destinazione)

egrep "^ $ {RUBRICA} /" - Filtri lista di obiettivi da solo includi quelli nella directory desiderata

egrep CXX_EXECUTABLE_LINKER - limita gli obiettivi solo agli eseguibili C++. Puoi rimuovere o modificare questo per ottenere il set di obiettivi che ti interessa.

sed -e 's /:.*// g' - rimuove il tipo di target, ad es. ": CXX_EXECUTABLE_LINKER"

xargs ninja - invoca ninja per costruire gli obiettivi

3

ninja <DIR>/all funziona con le versioni recenti di Ninja (1.7.2). La versione 1.3.4 non lo consente.

Impossibile trovare un riferimento a questo the manual. Tuttavia, CMake ha documentato here:

Le versioni recenti del programma ninja possono costruire il progetto attraverso l'obiettivo "tutto". Viene inoltre fornito un obiettivo di "installazione".

Per ogni sottodirectory sotto/dir del progetto, obiettivi supplementari sono generati:

  • sub/dir/all
    Dipende su tutti gli obiettivi richiesti dalla sottodirectory.
  • sub/dir/install
    Esegue il passaggio di installazione nella sottodirectory, se presente.
  • sub/dir/test
    Esegue la fase di test nella sottodirectory, se presente.
  • sub/dir/pacchetto
    Esegue il passaggio del pacchetto nella sottodirectory, se presente.
+0

Fantastico! Ci proverò lunedì. –

+1

.... Ah. Questa sembra essere una funzione di CMake, non una funzionalità Ninja. (Non sono sicuro del motivo per cui la versione 1.3.4 non lo supporterebbe.) Le versioni recenti di CMake generano quei target con le dipendenze appropriate; Lo stesso Ninja non ha conoscenza della loro semantica. Sfortunatamente, la mia versione di CMake (3.2.2) sembra non essere abbastanza recente. –