2011-12-13 12 views
9

Sono stato alle prese con questo per un po 'di tempo, e le mie avventure con cmake hanno portato solo a soluzioni hackish che sono abbastanza sicuro non sono corrette.Il modo giusto per strutturare il mio progetto C++ con cmake?

ho creato una libreria che si compone di diversi file, come segue:

-libfolder 
    -codepart1folder 
    -CMakeLists.txt 
    -codepart1.cpp 
    -codepart1.hpp 
    -codepart2folder 
    -codepart3folder 
    -lib.cpp 
    -lib.hpp 
    -CMakeLists.txt 

ho scritto un file CMakeLists per compilare la libreria (dopo un po 'di sperimentazione), e posso generare un file lib.a. Ora vorrei includere questo codice come libreria in altri progetti e accedervi tramite l'interfaccia in lib.hpp. Qual è il modo migliore per farlo in termini di struttura delle directory e cosa devo inserire in CMakeLists.txt nel mio progetto root?

Il mio tentativo attuale è stata quella di aggiungere -libfolder come sottocartella al mio progetto attuale, e aggiungere i comandi:

include_directories(${PROJECT_SOURCE_DIR}/libfolder) 
link_directories(${PROJECT_BINARY_DIR}/libfolder) 
add_subdirectory(libfolder) 
target_link_libraries(project lib) 

Quando eseguo make, la libreria compila bene, ma quando project.cpp compila, si lamenta di non poter trovare codepart1.hpp (che è incluso in lib.hpp, incluso da project.cpp).

Sospetto che questo sia il modo sbagliato per farlo, ma non posso navigare nella documentazione di CMake e trovare un buon tutorial sull'impostazione di progetti come questo. Per favore aiuto, guru di CMake!

+0

Forse non molto utile per cmake per-vedere, ma vorrei consigliarvi di dare un'occhiata a premake. Si avvicina alla maturità e ha molti vantaggi a cmake (uno è che è molto più veloce per mettersi al passo con esso, specialmente se conosci già lua). Puoi verificarlo su http://industriousone.com/what-premake. – Ylisar

+1

quindi, vuoi abilitare il tuo nuovo progetto per usare la libreria precedentemente costruita, o vuoi costruire entrambi da un meta-progetto sortof? – moooeeeep

risposta

2

Ok, quindi dopo aver consultato un collega di miniera che è un guru CMake, sembra CMake non ha il supporto per quello che sto cercando di fare, lasciando uno con 3 opzioni:

  1. Aggiungere tutti le dipendenze dai progetti padre CMakeLists.txt - non molto pulite, ma faranno funzionare la cosa. Dovrai farlo per ogni progetto a cui aggiungi il codice, e tornare indietro e correggere le cose se la tua libreria cambia.

  2. ripulire le intestazioni della libreria. Questo viene fatto attraverso alcuni hackery del compilatore. L'idea è di inoltrare-dichiarare ogni classe e utilizzare solo i puntatori o boost :: shared_ptr e quindi includere le dipendenze solo nel file cpp. In questo modo puoi creare il file cpp usando tutto il materiale findpackage, e ottieni il vantaggio di poter usare la lib includendo solo l'intestazione e il collegamento alla libreria.

  3. Cerca nei sistemi di costruzione. Avere un codice portatile e una compilazione rapida del codice con dipendenze complesse non è un problema risolto! Dalle mie indagini si è rivelato piuttosto complicato. Ho finito per adottare il mio sistema di build di colleghi che si è creato in cmake, usando le cose che ha raccolto da Google.

+0

+1, perché ripulire l'interfaccia in modo tale che non sia necessaria3 rdparty include-dirs è ancora meglio. –

5

Il modo pulito per importare un progetto CMake in un altro è tramite il comando find_package. La dichiarazione del pacchetto viene eseguita utilizzando il comando export. Un vantaggio dell'utilizzo di find_package è che elimina la necessità di percorsi hard-code per i file del pacchetto.

Per quanto riguarda il file hpp mancante, non hai incluso codepart1folder, quindi non si trova nel percorso di inclusione.

+0

Ok ...da questa risposta non mi è chiaro se find_package ed export siano le cose giuste da usare in questo caso, o come lo farei. Potresti elaborare per favore? – dlants

+0

uso include_directories ($ {} PROJECT_SOURCE_DIR/libfolder/codepart1folder) – LeDYoM

1

Guardando il tuo post non sembra aggiungere "codepart1folder" agli include ovunque. Come voi compresi codepart1.hpp come:

#include <codepart1.hpp> 
#include "codepart1folder/codepart1.hpp" 

non credo ci sia un modo accettato standard per strutturare progetti cmake. Ho esaminato un sacco di repository cmake e tendono ad avere differenze. Personalmente faccio la seguente:

-project 
    CMakeLists.txt 
    -build 
    -cmake 
     OptionalCmakeModule.cmake 
    -src 
     -Main 
      Main.cpp 
      Main.hpp 
     -DataStructs 
      SomeTree.hpp 
      SomeObject.hpp 
     -Debug 
      Debug.hpp 
     -UI 
      Window.hpp 
      Window.cpp 

sostanza che scarica tutto il codice sorgente in 1 directory, quindi si esegue un fuori fonte costruire con: 'mkdir costruire & & cd costruire & & cmake .. & & make 'nella cartella principale dei progetti.

Se si dispone di librerie separate come parte del progetto, è possibile che si desideri una directory libs separata con un'altra sottocartella per la propria lib specifica.

Ho alcuni dei miei repository su: https://github.com/dcbishop/ se si desidera esaminare i file CMakeLists.txt.

I principali problemi con la mia struttura di progetto sono che io uso il FILE_GLOB che è apparentemente il modo 'sbagliato' di fare le cose (se si aggiungono file dopo l'esecuzione di 'cmake ..' allora non saranno presi Quando fai un 'fai').Non ho capito quale sia il modo "giusto" per farlo (da quello che vedo è necessario tenere un elenco separato di file). Io uso solo 1 file CMakeLists.txt.

Alcuni progetti scelgono anche di separare i file cpp e hpp in directory separate. Quindi avresti una cartella include e src (almeno per i file hpp che devono essere usati esternamente). Penso che sarebbe principalmente per progetti che sono principalmente grandi biblioteche. Farebbe anche l'installazione di file header molto più semplice.

+0

codepart1folder è incluso nel file CMakeLists.txt all'interno libfolder. Sembra sbagliato per me avere per aggiungere tutte le sottocartelle, comprende e collegamenti nel CMakeLists.txt nella cartella del progetto, dal momento che project.cpp non dipende da nessuno di loro - solo lib.hpp fa. Nel vostro albero, immaginare che ci sia una project2 che definisce una biblioteca e voglio usare Progetto2 come sottoparte di progetto. – dlants

+0

@JohnSavage. Ma è la strada giusta ... vorrei creare una variabile LIB_INCLUDE_DIRS nella lib-progetto, che è "esportato" al CMakeCache contenente tutto il necessario dipendente-dirs includono. Quindi supponiamo che la variabile sarà presente quando cmake-ing Project. –

+0

+1 per i link github – hAcKnRoCk

0

Probabilmente si sta perdendo

include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder) 

In tal caso si potrebbe desiderare di set(CMAKE_INCLUDE_CURRENT_DIR on) aggiungere tutte le cartelle alla variabile includere percorso della directory.

Controllare l'output di cmake sulla riga di comando se le cartelle di inclusione corrette sono impostate o meno. Inoltre puoi sempre usare message() come "stampa debugging" per le variabili cmake. In caso di directory include, tuttavia, è necessario leggere la proprietà della directory per vedere cosa si trova effettivamente nelle directory di inclusione.

get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) 
message("inc_dirs = ${inc_dirs}") 

Spero che questo aiuta a capire ciò che manca.

Modifica

Ho appena visto i suoi commenti su codepart1folder aggiunto nel libfolder. È disponibile solo nel percorso include_directory di libfolder e non viene propagato nella cartella principale. Poiché l'inclusione codepart1.hpp è presente in lib.hpp, tuttavia è necessario averlo anche disponibile nel percorso del progetto, altrimenti si otterranno degli errori di dichiarazione mancanti quando si costruisce il progetto.

+0

Ok, quindi questo è il mio problema. Sento che non dovrei andare e ri-includere tutte le mie sottocartelle nel progetto principale. lib è un pezzo di codice autonomo con il proprio CMakeLists.txt e si compila bene in lib.a. Non voglio dover collegare tutto in tutti i progetti in cui voglio utilizzarlo. – dlants

+1

Quindi dovresti interfacciare correttamente la tua lib. – Bort

Problemi correlati