CMake: какой смысл искать пакет() если вам все равно нужно указать путь к модулю CMAKE?
Я пытаюсь получить систему сборки кросс-plattform, работающую с использованием CMake. Теперь программное обеспечение имеет несколько зависимостей. Я сам их скомпилировал и установил в своей системе.
некоторые примеры файлов, которые были установлены:
-- 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
теперь CMake имеет find_package()
открывающий Find*.cmake
файл и ищет библиотеки в системе и определяет некоторые переменные, такие как SomeLib_FOUND
etc.
Мои CMakeLists.txt содержит что-то вроде это:
set(CMAKE_MODULE_PATH "/usr/local/lib/SomeLib/cmake/;${CMAKE_MODULE_PATH}")
find_package(SomeLib REQUIRED)
первая команда определяет, где CMake ищет после Find*.cmake
и я добавил каталог SomeLib
здесь FindSomeLib.cmake
, так что find_package()
строительство
как и ожидалось.
но это немного странно, потому что одна из причин, почему find_package()
существует, чтобы уйти от не-кросс-plattform жестко закодированных путей.
как это обычно делается? Я должен скопировать
4 ответа:
команда
find_package
имеет два режима:Module
режим иConfig
режим. Ты пытаешься ... используйтеModule
режим, когда вам действительно нужноConfig
режим.режим модуль
расположенном внутри ваш проект. Что-то вроде этого:
CMakeLists.txt cmake/FindFoo.cmake cmake/FindBoo.cmake
CMakeLists.txt
содержание:list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") find_package(Foo REQUIRED) # FOO_INCLUDE_DIR, FOO_LIBRARIES find_package(Boo REQUIRED) # BOO_INCLUDE_DIR, BOO_LIBRARIES include_directories("${FOO_INCLUDE_DIR}") include_directories("${BOO_INCLUDE_DIR}") add_executable(Bar Bar.hpp Bar.cpp) target_link_libraries(Bar ${FOO_LIBRARIES} ${BOO_LIBRARIES})
обратите внимание, что
CMAKE_MODULE_PATH
имеет высокий приоритет и может быть полезно, когда вам нужно переписать стандартный .режим настройки (установить)
расположенном за пределами и произведен
install
команда другого проекта (Foo
например).
foo
библиотека:> cat CMakeLists.txt cmake_minimum_required(VERSION 2.8) project(Foo) add_library(foo Foo.hpp Foo.cpp) install(FILES Foo.hpp DESTINATION include) install(TARGETS foo DESTINATION lib) install(FILES FooConfig.cmake DESTINATION lib/cmake/Foo)
упрощенная версия файла config:
> cat FooConfig.cmake add_library(foo STATIC IMPORTED) find_library(FOO_LIBRARY_PATH foo HINTS "${CMAKE_CURRENT_LIST_DIR}/../../") set_target_properties(foo PROPERTIES IMPORTED_LOCATION "${FOO_LIBRARY_PATH}")
по умолчанию проект установлен в :
> cmake -H. -B_builds > cmake --build _builds --target install -- Install configuration: "" -- Installing: /usr/local/include/Foo.hpp -- Installing: /usr/local/lib/libfoo.a -- Installing: /usr/local/lib/cmake/Foo/FooConfig.cmake
режим настройки (использовать)
использовать
find_package(... CONFIG)
включитьFooConfig.cmake
с импортированной целиfoo
:> cat CMakeLists.txt cmake_minimum_required(VERSION 2.8) project(Boo) # import library target `foo` find_package(Foo CONFIG REQUIRED) add_executable(boo Boo.cpp Boo.hpp) target_link_libraries(boo foo) > cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON > cmake --build _builds Linking CXX executable Boo /usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a
обратите внимание, что импортируемые цель очень настраиваемые. Смотрите мой ответ.
обновление
как это обычно делается? Я должен скопировать
cmake/
каталог SomeLib в мой проект и установить CMAKE_MODULE_PATH относительно?Если вы не доверяете CMake иметь этот модуль, то -да, делать это. Вот что я делаю в качестве запасного варианта.
отметим, что
FindFoo.cmake
модули каждый вид моста между платформ-зависимостью и платформ-независимостью-они смотрят в различных платформ-специфических местах для того чтобы получить пути внутри переменные, имена которых не зависят от платформы.
не нужно для указания пути модуля как такового. CMake поставляется со своим собственным набором встроенных скриптов find_package, и их расположение находится в пути CMAKE_MODULE_PATH по умолчанию.
более нормальным вариантом использования для зависимых проектов, которые были CMakeified, было бы использовать команду External_project CMake, а затем включить Use[Project].файл cmake из подпроекта. Если вам просто нужно найти[проект].cmake скрипт, скопируйте его из подпроекта и в свой собственный исходный код проекта, и тогда вам не нужно будет увеличивать CMAKE_MODULE_PATH для того, чтобы найти подпроект на системном уровне.
если вы используете
cmake
для созданияSomeLib
себя (скажем, как часть superbuild), рассмотреть возможность использования Реестр Пакетов Пользователей. Это не требует жестко закодированных путей и является кросс-платформенным. В Windows (включая mingw64) он работает через реестр. Если вы изучите, как список префиксов установки строится с помощьюCONFIG
режим find_packages () команда, вы увидите, что реестр пакетов пользователей является одним из элементы.краткое how-to
связать цели
SomeLib
что вам нужно вне этого внешнего проекта, добавив их в набор экспорта вCMakeLists.txt
файлы, в которых они создаются:add_library(thingInSomeLib ...) install(TARGETS thingInSomeLib Export SomeLib-export DESTINATION lib)
создать на
SomeLib
в своем${CMAKE_CURRENT_BUILD_DIR}
и сохраните это место в реестре пакетов пользователей, добавив два вызова в export () доCMakeLists.txt
связанные сSomeLib
:export(EXPORT SomeLib-export NAMESPACE SomeLib:: FILE SomeLibConfig.cmake) # Create SomeLibConfig.cmake export(PACKAGE SomeLib) # Store location of SomeLibConfig.cmake
ваш вопрос
find_package(SomeLib REQUIRED)
commmand вCMakeLists.txt
файл проекта, который зависит отSomeLib
без" не кросс-платформенных жестко закодированных путей " возиться сCMAKE_MODULE_PATH
.когда это может быть правильный подход
этот подход, вероятно, лучше всего подходит для ситуаций, когда вы никогда не будете использовать свое программное обеспечение ниже каталога сборки (например, вы перекрестно компилируете и никогда ничего не устанавливаете на свой машина, или вы создаете программное обеспечение только для запуска тестов в каталоге сборки), так как он создает ссылку на a .файл cmake в вашем выводе "build", который может быть временным.
но если вы никогда не устанавливаете
SomeLib
в вашем рабочем процессе, вызовEXPORT(PACKAGE <name>)
позволяет избежать жесткого пути. И, конечно же, если вы устанавливаетеSomeLib
, вы, наверное, знаете свои платформы,CMAKE_MODULE_PATH
и т. д., Так что отличный ответ @user2288008 будет у вас покрыт.