2011-12-21 10 views
9

Mam wielkopojęciową bazę kodu, która buduje kilkadziesiąt bibliotek i kilka plików wykonywalnych.jakie jest właściwe zastosowanie dyrektywy CMake "project"

Baza kodów jest podzielona hierarchicznie, a biblioteki są budowane na niemal każdym poziomie.

Przeszedłem i umieściłem plik CMakeLists.txt w każdym katalogu, aby zbudować każdą bibliotekę.

W każdym CMakeLists.txt użyłem dyrektywy "projekt (xxx)". To zdefiniowało dla mnie zmienne PROJECT_NAME, PROJECT_SOURCE_DIR i PROJECT_BINARY_DIR, których rozsądnie używam.

Jednak jedna z drużyn jest niezadowolona z tego podejścia, ponieważ nie może znaleźć prawdziwych przykładów na świecie. Często przytacza przykłady KitWare, ponieważ nie stosują tego podejścia i dlatego też nie powinniśmy tego robić.

Proponowane przez niego alternatywne podejście polega na ustawieniu tych zmiennych w każdym pliku makefile, który wydaje się podobny do tego, co daje "projekt".

Naprawdę nie widzę jego punktu i robię małe postępy w przekonaniu go inaczej. Czy ktoś może rzucić jakiekolwiek światło na wady stosowania dyrektywy projektowej w ten sposób?

Rzucam się na twoją zbiorową mądrość?

+0

Jak korzystać ze zmiennych 'PROJECT_NAME',' PROJECT_SOURCE_DIR' i 'PROJECT_BINARY_DIR'? Czy te biblioteki są niezależne, czy są tylko częściami głównej biblioteki/aplikacji? –

+0

Używam tych zmiennych w makrach generujących kod źródłowy. Tworzę cel najwyższego poziomu o nazwie $ {PROJECT_NAME} _SPDEF, na którym mogą polegać inne projekty, aby wymusić ich generację. Używam również zmiennych _DIR, aby umieścić wygenerowany kod w odpowiedniej lokalizacji. – ScaryAardvark

Odpowiedz

12

Po pierwsze umożliwia korzystanie z <projectName>_BINARY_DIR i <projectName>_SOURCE_DIR, ale to nie jest główna zaleta. Jeśli nadasz CMake nazwę projektu, to wygeneruje cele budowy dla każdego z podprojektów w ich własnych katalogach. Oznacza to, że niezależnie od tego, czy używasz GNU Make, Eclipse CDT, XCode, czy innego obsługiwanego generatora, możesz samodzielnie budować podprojekty. Na przykład z GNU Make każdy podprojekt ma własny pełny system kompilacji z własnego katalogu.

Dostęp do bieżącej nazwy projektu można uzyskać przez PROJECT_NAME, a nazwa projektu głównego przez CMAKE_PROJECT_NAME.

Edycja: Właśnie zdałem sobie sprawę, że poniżej będzie standardowe zachowanie CMake dla dowolnego z celów budowy, czy są to projekty, czy nie. Zatrzymam go tutaj dla ogólnych informacji, ale nie jest to istotne dla odpowiedzi:

Załóżmy, że mam bibliotekę C++ i mogę wygenerować trzy pliki binarne; Main i tests/test1 i examples/ex1. Mogę albo uruchomić make w katalogu, który nazwałem CMake z ALL, uruchomić make ex1, albo zmienić katalog na examples/ i zbudować przykłady z make z tego katalogu. Spowoduje to zbudowanie wszystkich zależnych projektów i bibliotek, nawet jeśli znajdują się one gdzieś w strukturze katalogów, ale nie będą budować Main ani tests/test1 lub nie będą w nich działać żadne biblioteki, od których one polegają. Jeśli następnie uruchomię make z głównego katalogu, nie będzie on odbudowywał żadnej z bibliotek, które zależą od bibliotek, o ile ich źródło się nie zmieniło.

+1

Możliwość posiadania "cd" na dowolnym poziomie hierarchii kompilacji i "robienia wszystkiego" i posiadania wszystkich artefaktów z tego poziomu jest dla mnie wielką wygraną. Dzięki. – ScaryAardvark

+0

@ScaryAardvark Możliwość uruchamiania różnych poleceń dla różnych kompilatorów i dodawania różnych kodów z różnymi systemami operacyjnymi jest naprawdę przyjemna, a ponadto bardzo proste jest wykonywanie dość zaawansowanych operacji za pomocą kilku linii kodu. Kompresuję zasoby za pomocą 'zip' przy pomocy CMake, który działa dobrze na każdej platformie/IDE/toolchain. Ułatwia to także kompilację krzyżową dla ARM itp. Powinieneś również sprawdzić wbudowany system testowy CMake, [CTest] (http://www.vtk.org/Wiki/CMake_Testing_With_CTest). Istnieją również wtyczki CMake dla systemów CI takich jak Jenkins. –

+0

Tak, znam to. Jedno z pytań dotyczyło tego, w jaki sposób cmake obsługuje inną wersję tego samego kompilatora ... tzn. Mamy jedną sekcję naszego drzewa projektu, którą można skompilować tylko pod sunstudio11, a większość z nich potrzebuje sunstudio12. Myślę, że zadam jeszcze jedno pytanie, ale dziękuję :) – ScaryAardvark

0

Jeśli biblioteki są naprawdę niezależnymi projektami, warto użyć polecenia project. Jednakże, jeśli nie są, zamiast tego po prostu dodaję je jako podkatalogi w katalogu głównym CmakeLists.txt. Możesz użyć zmiennych CMAKE_CURRENT_SOURCE_DIR i CMAKE_CURRENT_BINARY_DIR, jeśli potrzebujesz znać katalogi, które są aktualnie przetwarzane.

+0

Czy istnieje CMAKE_CURRENT_PROJECT. Jeśli tak, to widzę twój punkt, ale jeśli muszę użyć set() do stworzenia tej zmiennej (lub czegoś podobnego), dlaczego nie użyć "projektu" i mieć wszystkie zmienne stworzone dla mnie. – ScaryAardvark

0

Znalazłem dobry przykład użycia tego dzisiaj: dodanie dokumentacji Doxygen.

Używam CMake (i Ninja) do budowania moich osobistych projektów C++. Zdecydowałem się na kaprysy, aby dodać dokumentację Doxygen do jednego z moich prawie kompletnych, ale nieudokumentowanych wysiłków. Pomyślałem także, że fajnie byłoby dodać go do innych projektów, gdy tylko opracuję, jak zrobić to jak najbardziej ogólne.

Najpierw wygenerowałem standardowy szablon Doxygen i zmieniłem jego nazwę.

cd my_projects/projectx 
doxygen -g Doxyfile 
mv Doxyfile Doxyfile.in 

Uwaga na rozszerzenie .in. Prawdopodobnie nie jest to konieczne, ale konwencjonalne, jeśli dobrze rozumiem.

Następnie dodałem następujący blok kodu do mojego pliku CMakeLists.txt, tuż przed zdefiniowaniem moich celów (nie jestem pewien, czy jest to ważne, ale CMake czasami jest wybredny w odniesieniu do sekwencji niektórych poleceń).

FIND_PACKAGE(Doxygen) 
IF("${DOXYGEN_FOUND}" MATCHES "^YES$") 
    CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 
        ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
        @ONLY) 
    ADD_CUSTOM_TARGET( doc ALL 
         COMMAND ${DOXYGEN_EXECUTABLE} 
         ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 
         COMMENT "Doxygenating..." 
         VERBATIM) 
ENDIF() 

Spowoduje to utworzenie nowego celu o nazwie doc. Określenie ALL dodaje go do domyślnego celu "all", ale jest to opcjonalne. Podanie @ONLY zapewnia, że ​​dowolne zmienne typu "$ {zmienne}" nie będą rozwijane przez CONFIGURE_FILE, tylko typy "@ variable @". Trochę myląco (przynajmniej dla mnie), CMAKE_CURRENT_SOURCE_DIR wydaje się odnosić do katalogu projektu i CMAKE_CURRENT_BINARY_DIR do katalogu budowania.

Wreszcie, i to jest miejsce, w którym PROJECT_NAME i inni wchodzili, edytowałem Doxyfile.in.

Jest to początek mojego nowego Doxyfile.in:

DOXYFILE_ENCODING  = UTF-8 
PROJECT_NAME   = "@[email protected]" 
PROJECT_NUMBER   = @[email protected] 
PROJECT_BRIEF   = 
PROJECT_LOGO   = @[email protected]/res/doc_logo-200x55.png 
OUTPUT_DIRECTORY  = @[email protected]/doc 

Masz pomysł, myślę. Kiedy już to w pełni uogólnisz (czy to słowo?) Mogę skopiować to do moich innych projektów i tak długo jak będę tagować mój kod, będę miał wszędzie dobrą dokumentację.

Ogłoszenie PROJECT_BRIEF nie zostało określone. Nie skończyłem z tym i wciąż mam kilka pustych miejsc, o które mógłbym pomyśleć. Na przykład PROJECT_VERSION_TWEAK w rzeczywistości jeszcze niczego nie zawiera. Będę musiał znaleźć sposób na zdobycie mojego numeru kompilacji.

Powiązane problemy