2012-04-04 9 views
6

powiedzmy istnieje następująca struktura katalogu:Nakładające zależności między bibliotekami w CMake

projects 
    | 
    +--lib1 
    | | 
    | +-CMakeFiles.txt 
    | 
    +--lib2 
    | | 
    | +-CMakeFiles.txt 
    | 
    +--test 
     | 
     +-CMakeFiles.txt 

LIB1/CMakeFiles.txt:

cmake_minimum_required(VERSION 2.0) 

add_library(lib1 STATIC lib1.cpp) 

Lib2/CMakeFiles.txt:

cmake_minimum_required(VERSION 2.0) 

add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1) 
add_library(lib2 STATIC lib2.cpp) 
target_link_libraries(lib2 lib1) 

Test /CMakeFiles.txt:

cmake_minimum_required(VERSION 2.0) 
project(test) 

add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1) 
add_subdirectory(../lib2 ${CMAKE_CURRENT_BINARY_DIR}/lib2) 

add_executable(test main.cpp) 
target_link_libraries(test lib1 lib2) 

tj. lib2 zależy od lib1 i test zależy od nich obu. (Wiem, że technicznie statyczne biblioteki nie "łączą", ale to tylko przykład).

Problem polega na tym, że przy obecnej konfiguracji lib1 kompiluje się dwa razy - pierwszy raz znajduje się w katalogu testowym "test", a drugi raz w "test/katalog_budowy/lib2/katalog_budowy". Chciałbym tego uniknąć.

Chcę móc dodać zależność od biblioteki lib1, lib2 lub obu (przy użyciu add_subdirectory) do dowolnego projektu znajdującego się w innym miejscu. Tak więc przenoszenie CMakeFiles nie jest opcją. Chciałbym także uniknąć kilku kompilacji biblioteki.

Jak mogę to zrobić?

cmake-2.8.4 WinXP SP3

--EDIT-- najwyższego poziomu cmakelists nie jest opcją, ponieważ chcę zachować czyste katalogu najwyższego poziomu i móc zawierać bibliotek w innych projektach który może znajdować się w innym miejscu. Ponieważ jest to system Windows, nie mogę "zainstalować całego systemu" - nie chcę stracić możliwości przełączania kompilatora w locie. Biblioteki narzędziowe zbudowane przy użyciu różnych kompilatorów będą używać różnych bibliotek środowiska wykonawczego C/ABI, w wyniku czego będą niezgodne.

Odpowiedz

4

Z CMake, zależności bibliotek są przechodnie, więc nie powinieneś dwukrotnie wywoływać add_subdirectory w test/CMakeFiles.txt (ani nie musisz podawać lib1 jako zależności od test, ponieważ jest to już zależność od lib2).

Możesz modyfikować CMAKFiles test.txt do:

cmake_minimum_required(VERSION 2.8.7) # Prefer the most current version possible 
project(test) 

add_subdirectory(../lib2 ${CMAKE_CURRENT_BINARY_DIR}/lib2) 

add_executable(test main.cpp) 
target_link_libraries(test lib2) 

Ponadto, powinieneś usunąć cmake_minimum_required połączeń z non-projektowych plików CMakeFiles.txt (lib nich). W celu uzyskania dalszych informacji, uruchom:

cmake --help-policy CMP0000 


Taka konfiguracja będzie nadal powodować wszystkie libs rekompilacji jeśli dodać podobną podkatalogu test2 oraz projekt, który zależy od lib1 i lib2. Jeśli naprawdę nie chcesz mieć najwyższego poziomu CMakeFiles.txt w projects/, utkniesz w tym, co robisz, lub możesz użyć polecenia export lub install.

utworzy plik, który może być include d przez inne projekty i który importuje cele do projektu, który wywołuje include.

install może zainstalować biblioteki do innego wspólnego podkatalogu projects/. W zależności od struktury katalogów źródłowych może to przynieść korzyści polegające na udostępnianiu nagłówków interfejsu API tylko zależnym projektom.

Jednak obie te opcje wymagają przebudowania (i zainstalowania) zależnych projektów bibliotecznych, jeśli zostały zmodyfikowane, podczas gdy bieżąca konfiguracja obejmuje wszystkie zależne obiekty docelowe w projekcie, więc wszelkie zmiany w pliku źródłowym w zależności biblioteka spowoduje, że twój cel test przestanie być aktualny.

Aby uzyskać szczegółowe informacje export i install uruchom:

cmake --help-command export 
cmake --help-command install 
+1

Mogą wystąpić przypadki, w których można jednoznacznie przypisać zależność lib1 do biblioteki lib2 lub odwrotnie. Ale są też typowe przypadki, w których luźno sprzężono moduły, które chcesz zbudować (pomyśl o różnych wtyczkach), które współdzielą zależności. Na przykład masz prog1, który ma zależność lib1 i lib2 i masz prog2, który ma zależność lib2 i lib3. A teraz, jeśli chcesz mieć różne kombinacje (na przykład nie potrzebujesz prog2 w tym przypadku, więc po prostu go nie dołączaj), może to być problem, jeśli lib2 jest zależnością prog2, ponieważ nie jest już dostępna . – user518450

+1

user518450 ma poprawny punkt; w moim przypadku mam sytuację, w której zarówno aplikacja (zwana testem w przykładzie) jak i lib2 zawiera kod używający lib1, ale zależność od lib2 do lib1 jest warunkowa, ponieważ zależy od funkcji włączonych w lib2. Zatem lib2 może lub nie może być zależna od lib1. Nie trzeba dodawać, że chciałbym znaleźć rozwiązanie tego problemu. – psyill

+1

@psyill sprawdź poniżej moją odpowiedź z nagłówkami-strażnikami. działa jak urok w tego rodzaju sytuacjach. – user518450

0

Być może dodaj najwyższy poziom CMakeLists.txt do swoich projektów reż. Coś takiego:

project(YourProjects) 

add_subdirectory(lib1) 
add_subdirectory(lib2) 
add_subdirectory(test) 

To powinno wystarczyć i da Ci plik-rozwiązania lub plik_użytkownika w swoim katalogu głównym najwyższego poziomu. Powinieneś następnie usunąć add_subdirectory(../lib1 ... z projektów lib1 i lib2, ale zamiast tego po prostu je połączyć. CMake będzie wiedział, jak znaleźć lib1 i lib2 podczas kompilacji testu.

tj. w LIB2:

project(lib2) 
add_library(lib2 STATIC lib2.cpp) 
target_link_libraries(lib2 lib1) 

w teście:

project(test) 
add_executable(test main.cpp) 
target_link_libraries(test lib1 lib2) 

dodatkowy bonus: dostaniesz Makefile/solutionfiles dla LIB2 budynku (z LIB1 zależnej) w katalogu LIB2 ...

+0

najwyższego poziomu cmakelists nie jest rozwiązaniem. Teraz, gdybyś mógł powiedzieć, jak umożliwić cmake wiedzieć, że jest inny projekt w innym miejscu ... – SigTerm

+0

Oczywiście, nie wiedziałem o dodatkowym wymogu zabraniającym cmaklistom najwyższego poziomu ... Wiesz, że nadal możesz "instalować" pakiety w systemie Windows, np przez określenie CMAKE_INSTALL_PREFIX podczas uruchamiania CMake? Jeśli to konieczne, możesz również zmienić prefiks instalacji, gdy nadal znajduje się w domyślnym pliku C: \ Program Files. –

+0

Czy rozważałeś oddzielenie wszystkich swoich bibliotek i aplikacji i napisanie poprawnych plików "BuildConfig.cmake", a następnie użycie find_package w każdym projekcie? –

11

Innym rozwiązaniem jest dodanie strażnika na górze podkatalogu-CMakeLists.txt:

if(TARGET targetname) 
    return() 
endif(TARGET targetname) 

co spowoduje cmake nie robi nic, gdy drugi raz zostanie dodany podkatalog (jeśli oczywiście w tym pliku jest określana nazwa docelowa).

Doprowadzi to do zbudowania biblioteki w pewnym uporządkowanym miejscu (w zależności od tego, który moduł został dodany jako pierwszy) w drzewie budowy/drzewa, ale będzie budowane tylko raz i będzie łączone wszędzie.

W przykładzie, należy dodać

if(TARGET lib1) 
    return() 
endif(TARGET lib1) 

na szczycie LIB1/CMakeFiles.txt

Powiązane problemy