Próbuję uzyskać system kompilacji na różnych platformach działający przy użyciu CMake. Teraz oprogramowanie ma kilka zależności. Sam je skompilowałem i zainstalowałem w swoim systemie.
Przykładowe pliki, które zostały zainstalowane:
-- Installing: /usr/local/share/SomeLib/SomeDir/somefile
-- Installing: /usr/local/share/SomeLib/SomeDir/someotherfile
-- Installing: /usr/local/lib/SomeLib/somesharedlibrary
-- Installing: /usr/local/lib/SomeLib/cmake/FindSomeLib.cmake
-- Installing: /usr/local/lib/SomeLib/cmake/HelperFile.cmake
Teraz CMake ma, find_package()
który otwiera Find*.cmake
plik i wyszukuje bibliotekę w systemie i definiuje niektóre zmienne, takie jak SomeLib_FOUND
itp.
Mój CMakeLists.txt zawiera coś takiego:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
Pierwsze polecenie określa, gdzie CMake wyszukuje po Find*.cmake
i dodałem katalog, w SomeLib
którym FindSomeLib.cmake
można znaleźć, więc find_package()
działa zgodnie z oczekiwaniami.
Ale jest to trochę dziwne, ponieważ jednym z powodów, dla których find_package()
istnieje, jest ucieczka od niekrzyżowych ścieżek zakodowanych na sztywno.
Jak to się zwykle robi? Czy powinienem skopiować cmake/
katalog SomeLib
do mojego projektu i ustawić CMAKE_MODULE_PATH
relatywnie?
Odpowiedzi:
Polecenie
find_package
ma dwa tryby:Module
tryb iConfig
tryb. Próbujesz użyćModule
trybu, kiedy faktycznie potrzebujeszConfig
trybu.Tryb modułu
Find<package>.cmake
plik znajdujący się w Twoim projekcie. Coś takiego:CMakeLists.txt
zadowolony:Zwróć uwagę, że
CMAKE_MODULE_PATH
ma to wysoki priorytet i może być przydatne, gdy musisz przepisać standardowyFind<package>.cmake
plik.Tryb konfiguracji (instalacja)
<package>Config.cmake
plik znajdujący się na zewnątrz i utworzony nainstall
polecenie innego projektu (Foo
na przykład).foo
biblioteka:Uproszczona wersja pliku konfiguracyjnego:
Domyślnie projekt instalowany w
CMAKE_INSTALL_PREFIX
katalogu:Tryb konfiguracji (użyj)
Służy
find_package(... CONFIG)
do dołączaniaFooConfig.cmake
do zaimportowanego celufoo
:Zwróć uwagę, że importowany cel jest wysoce konfigurowalny. Zobacz moją odpowiedź .
Aktualizacja
źródło
configure_package_config_file
. Przy okazji, jeśli masz inne sugestie, możesz wysłać mi prośbę o ściągnięcie.bin/lib
(spróbuj zainstalować plik wykonywalny i uruchomić go w systemie Windows). Przestrzenie nazw wyglądają bardzo ładnie, więc też je zachowam :) Dodałem teżmonolithic
build.Jeśli pracujesz,
cmake
aby wygenerowaćSomeLib
siebie (powiedzmy jako część superkonstrukcji), rozważ użycie rejestru pakietów użytkowników . Nie wymaga to zakodowanych ścieżek i jest wieloplatformowe. W systemie Windows (w tym mingw64) działa za pośrednictwem rejestru. Jeśli przyjrzysz się, w jaki sposób lista prefiksów instalacyjnych jest tworzona przezCONFIG
tryb polecenia find_packages () , zobaczysz, że jednym z elementów jest Rejestr pakietów użytkownika.Krótkie instrukcje
Skojarz cele
SomeLib
, których potrzebujesz, poza tym zewnętrznym projektem, dodając je do zestawu eksportu wCMakeLists.txt
plikach, w których zostały utworzone:Utwórz
XXXConfig.cmake
plik dlaSomeLib
jego${CMAKE_CURRENT_BUILD_DIR}
i zapisz tę lokalizację w Rejestrze pakietu użytkownika, dodając dwa wywołania export () doCMakeLists.txt
powiązanego zSomeLib
:Wydaj
find_package(SomeLib REQUIRED)
komendę wCMakeLists.txt
pliku projektu, od którego zależy,SomeLib
bez "niezakodowanych na stałe ścieżek nie międzyplatformowych" majstrowania przy rozszerzeniuCMAKE_MODULE_PATH
.Kiedy to może być właściwe podejście
To podejście jest prawdopodobnie najbardziej odpowiednie w sytuacjach, w których nigdy nie będziesz używać oprogramowania poniżej katalogu kompilacji (np. Kompilujesz krzyżowo i nigdy nie instalujesz niczego na swoim komputerze lub tworzysz oprogramowanie tylko po to, aby uruchomić testy w katalog budowania), ponieważ tworzy dowiązanie do pliku .cmake w wyjściu "build", które może być tymczasowe.
Ale jeśli w rzeczywistości nigdy nie instalujesz
SomeLib
w swoim przepływie pracy, wywołanieEXPORT(PACKAGE <name>)
pozwala uniknąć zakodowanej ścieżki. I oczywiście, jeśli instalujeszSomeLib
, prawdopodobnie znasz swoją platformęCMAKE_MODULE_PATH
itp., Więc doskonała odpowiedź @ user2288008 będzie Cię obejmować.źródło
Nie musisz określać ścieżki modułu jako takiej. CMake jest dostarczany z własnym zestawem wbudowanych skryptów find_package, a ich lokalizacja to domyślna CMAKE_MODULE_PATH.
Bardziej normalnym przypadkiem użycia dla projektów zależnych, które zostały CMakeified, byłoby użycie polecenia external_project CMake, a następnie dołączenie pliku Use [Project] .cmake z podprojektu. Jeśli potrzebujesz tylko skryptu Find [Project] .cmake, skopiuj go z podprojektu i do kodu źródłowego własnego projektu, a wtedy nie będziesz musiał rozszerzać CMAKE_MODULE_PATH, aby znaleźć podprojekt na poziomie systemu.
źródło
their location is in the default CMAKE_MODULE_PATH
domyślnieCMAKE_MODULE_PATH
jest pustyCMAKE_MODULE_PATH
Jest pusty w systemie Windows.Jeśli nie ufasz, że CMake ma ten moduł, to - tak, zrób to - w pewnym sensie: skopiuj
find_SomeLib.cmake
i jego zależności do swojegocmake/
katalogu. To właśnie robię jako pomoc. To jednak brzydkie rozwiązanie.Zauważ, że
FindFoo.cmake
każdy z modułów jest rodzajem pomostu między zależnością platformy a niezależnością platformy - szukają w różnych miejscach specyficznych dla platformy, aby uzyskać ścieżki w zmiennych, których nazwy są niezależne od platformy.źródło