Directory di output / build di CMake


116

Sono abbastanza nuovo in CMake e ho letto alcuni tutorial su come usarlo e ho scritto alcune complicate 50 righe di script CMake per creare un programma per 3 diversi compilatori. Questo probabilmente conclude tutta la mia conoscenza in CMake.

Ora il mio problema è che ho del codice sorgente, la cui cartella non voglio toccare / fare confusione quando creo il programma. Voglio che tutti makei file e le cartelle di CMake e di output vengano inseriti ../Compile/, quindi ho modificato alcune variabili nel mio script CMake per questo, e ha funzionato per qualche tempo quando ho fatto qualcosa del genere sul mio laptop:

Compile$ cmake ../src
Compile$ make

Dove con quello ho avuto un output pulito nella cartella in cui mi trovo in questo momento, che è esattamente quello che sto cercando.

Ora sono passato a un altro computer, ho ricompilato CMake 2.8.11.2 e sono quasi tornato al punto di partenza! Compila sempre la cosa nella srccartella in cui CMakeLists.txtsi trova my .

La parte in cui scelgo la directory nel mio script CMake è questa:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

E ora finisce sempre con:

-- Build files have been written to: /.../src

Mi sto perdendo qualcosa?


4
Non è necessario impostare tutte le variabili che stai impostando. CMake li imposta su valori predefiniti ragionevoli. Si dovrebbe non modificare CMAKE_BINARY_DIRo CMAKE_CACHEFILE_DIR. Cosa succede se rimuovi tutte queste set()chiamate e lo fai cd Compile; rm -rf *; cmake ../src?
Angew non è più orgoglioso di SO

5
Fondamentalmente, fintanto che sei fuori dalla directory di origine quando esegui CMake, non modificherà la directory di origine a meno che il tuo CMakeList non glielo dica esplicitamente.
Angew non è più orgoglioso di SO

@Angew Grazie per il suggerimento, il che è sorprendente! Ho rimosso tutte quelle linee e ho usato cmake ../src e ha funzionato a meraviglia! Questo è così sorprendente perché l'ho provato prima quando stavo imparando CMake per la prima volta e non ha funzionato. Per favore inserisci la tua risposta in una risposta ufficiale per darti il ​​grande segno di spunta :)
The Quantum Physicist

1
Ciò che mi ha salvato è stata l'osservazione di @Adam Bowen secondo cui "non è possibile creare una build out-of-source per una directory di origine con una build in-source"
Aur Saraf

Risposte:


60

Non è necessario impostare tutte le variabili che stai impostando. CMake li imposta su valori predefiniti ragionevoli. Si dovrebbe non modificare CMAKE_BINARY_DIRo CMAKE_CACHEFILE_DIR. Trattali come di sola lettura.

Rimuovere prima il file di cache problematico esistente dalla directory src:

cd src
rm CMakeCache.txt
cd ..

Quindi rimuovere tutti i set()comandi e fare:

cd Compile
rm -rf *
cmake ../src

Finché sei fuori dalla directory di origine quando esegui CMake, non modificherà la directory di origine a meno che il tuo CMakeList non glielo dica esplicitamente.

Una volta che hai funzionato, puoi guardare dove CMake inserisce le cose per impostazione predefinita e solo se non sei soddisfatto delle posizioni predefinite (come il valore predefinito di EXECUTABLE_OUTPUT_PATH), modifica solo quelle di cui hai bisogno. E cercare di esprimere il loro rispetto a CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, PROJECT_BINARY_DIRetc.

Se guardi la documentazione di CMake, vedrai le variabili partizionate in sezioni semantiche. Salvo circostanze molto speciali, dovresti trattare tutte quelle elencate in "Variabili che forniscono informazioni" come di sola lettura all'interno di CMakeLists.


2
Ho iniziato a usare cmake con build nella directory src ... questa tecnica inizialmente non è riuscita. Una volta cancellati tutti i file / cache di build di cmake nella directory src, questa tecnica ha funzionato. Grazie!
Avi Tevet

18
Forse è meglio non consigliarne l'utilizzo rm -rf *. Non è carino se cd Compilefallisce ...
Roman

2
@Roman Considero questi esempi della riga di comando praticamente uno pseudo-codice. È meno dettagliato e più preciso che digitare "entra nella directory Compile, elimina tutto lì, quindi esegui CMake con un percorso alla directory di origine". Presumo il buonsenso e il giudizio di base da parte del lettore.
Angew non è più orgoglioso di SO

@AviTevet: Penso che questa sia la risposta corretta. Se ci sono file di cache di cmake da una precedente invocazione di cmake all'interno della directory dei sorgenti, non farai a cmake di scegliere un'altra directory per i file generati, a meno che tu non cancelli tutti i vecchi dalla directory dei sorgenti. Comportamento piuttosto rotto da CMake secondo me. Perché non scrivi un'altra risposta?
Jo So

113

Sembra che tu voglia una build fuori dal codice sorgente . Ci sono un paio di modi per creare una build fuori dal codice sorgente.

  1. Fai quello che stavi facendo, corri

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder

    che farà sì che CMake per generare un albero di compilazione in /path/to/my/build/folderper la struttura di origine in /path/to/my/source/folder.

    Dopo averlo creato, cmake ricorda dove si trova la cartella sorgente, quindi puoi rieseguire cmake nell'albero di compilazione con

    cmake /path/to/my/build/folder

    o anche

    cmake .

    se la tua directory corrente è già la cartella build.

  2. Per CMake 3.13 o versioni successive, utilizza queste opzioni per impostare l'origine e le cartelle di compilazione

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. Per le versioni precedenti di CMake, utilizza alcune opzioni non documentate per impostare l'origine e creare le cartelle :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    che farà esattamente la stessa cosa di (1), ma senza fare affidamento sulla directory di lavoro corrente.

CMake inserisce tutti i suoi output nell'albero di compilazione per impostazione predefinita, quindi a meno che tu non stia usando liberamente ${CMAKE_SOURCE_DIR}o ${CMAKE_CURRENT_SOURCE_DIR}nei tuoi file cmake, non dovrebbe toccare il tuo albero dei sorgenti .

La cosa più grande che può andare storta è se hai precedentemente generato un albero di compilazione nel tuo albero dei sorgenti (cioè hai un build nel codice sorgente ). Una volta fatto ciò, la seconda parte di (1) sopra entra in gioco e cmake non apporta alcuna modifica alla sorgente o alle posizioni di build. Pertanto, non è possibile creare una build out-of-source per una directory di origine con una build in-source . Puoi risolvere questo problema abbastanza facilmente rimuovendo (almeno) CMakeCache.txtdalla directory di origine. Ci sono alcuni altri file (principalmente inCMakeFiles directory) generati da CMake che dovresti rimuovere, ma questi non faranno sì che cmake tratti l'albero dei sorgenti come un albero di compilazione.

Poiché le build out-of-source sono spesso più desiderabili delle build in-source, potresti voler modificare il tuo cmake per richiedere build fuori dal sorgente:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

La macro sopra proviene da un modulo comunemente usato chiamato MacroOutOfSourceBuild. Ci sono numerose fonti per MacroOutOfSourceBuild.cmakesu Google ma non riesco a trovare l'originale ed è abbastanza breve da includerlo qui per intero.

Sfortunatamente cmake di solito ha scritto alcuni file nel momento in cui viene richiamata la macro, quindi anche se ti impedirà di eseguire effettivamente la compilazione, dovrai comunque eliminare CMakeCache.txte CMakeFiles.

Potresti trovare utile impostare i percorsi in cui vengono scritti i binari, le librerie condivise e statiche - nel qual caso vedi come faccio a creare l'output di cmake in una directory 'bin'? (disclaimer, ho la risposta più votata su questa domanda ... ma è così che lo so).


In realtà l'opzione per impostare la cartella di origine è -S, non-H
smac89

@ smac89 Grazie! Sembra che li abbiano documentati nella 3.13: ho aggiornato la risposta per riflettere il moderno CMake.
Adam Bowen

8

Trasformando il mio commento in una risposta:

Nel caso qualcuno avesse fatto quello che ho fatto io, che è stato iniziare mettendo tutti i file di build nella directory dei sorgenti:

cd src
cmake .

CMake metterà un gruppo di file di build e file di cache ( CMakeCache.txt, CMakeFiles, cmake_install.cmake, ecc) nella srcdir.

Per passare a una build fuori dal codice sorgente, ho dovuto rimuovere tutti quei file. Quindi potrei fare ciò che @Angew ha raccomandato nella sua risposta:

mkdir -p src/build
cd src/build
cmake ..

7

A partire da CMake Wiki :

CMAKE_BINARY_DIR se stai compilando in-source, questo è lo stesso di CMAKE_SOURCE_DIR, altrimenti questa è la directory di primo livello del tuo albero di build

Confronta queste due variabili per determinare se è stata avviata la build out-of-source


6

Non dovresti fare affidamento su un nome della directory di compilazione hardcoded nello script, quindi la riga con ../Compiledeve essere modificata.

È perché dovrebbe essere l'utente dove compilare.

Invece di utilizzare una delle variabili predefinite: http://www.cmake.org/Wiki/CMake_Useful_Variables (cerca CMAKE_BINARY_DIRe CMAKE_CURRENT_BINARY_DIR)


2
questo è esattamente quello che stavo cercando - CMAKE_CURRENT_BINARY_DIR, in genere parlerebbe del percorso di compilazione binario corrente. Può essere usato per impostare le build libs / bin dipendenti.
parasrish
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.