Как использовать "современные" экспортированные цели CMake в контексте существующих библиотек

Я обновляю (очень старый) модуль поиска библиотеки. Таким образом, ситуация представляет собой существующую разделяемую библиотеку, которая использует сам CMake. Пользователи могут уже установить это где-нибудь, в репозитории или как угодно.

Теперь они хотят использовать это. Хороший способ был бы

find_package(Foo REQUIRED)
target_link_libraries(MyProject Foo::Foo)

Так вот и цель.

Вопрос в том, как будет выглядеть хороший find_package-Config или -Module, который позволит работать этому 2-х линейному модулю? Он должен соответствовать этим 2 требованиям:

  • Разрешить версии CMake использовать библиотеку старше той, которая использовалась для ее создания
  • Обеспечить, например, режим C++11. В Find-Module можно установить требование C++11 в зависимости от версии (cxx_std_11 (CMake 3.8+), cxx_alias_templates (CMake 3.1+), check_cxx_source_compiles с кодом C++11 и предупреждением для старых CMakes)

Есть 2 способа сделать это:

  1. Обновите модуль поиска для определения импортированной библиотеки Foo::Foo и настроить его правильно (используя свойства) и было бы неплохо также установить FOO_INCLUDE_DIR а также FOO_LIBRARIES для старых CMake без целей.
    Это довольно просто: просто используйте find_path а также find_library, установите импортированную цель и все готово. Работает с прямой и обратной совместимостью, поэтому можно найти даже старые версии.

Использование:
Пользовательские копии (самые свежие) FindFoo.cmake к его проекту, например, в cmake/Modules и очки CMAKE_MODULE_PATH к нему или скопировать FindFoo.cmake к некоторому пути CMake по умолчанию.

  1. Слушая Дэниела Пфайффера и Modern CMake, который говорит If you are the library author, don't make a Find<mypackage>.cmake script! Поэтому мы экспортируем и устанавливаем цели.
    Это немного грязно. Требуются следующие изменения:

    • добавлять EXPORTS FooTargets а также INCLUDES DESTINATION include в install(TARGETS (см. Pfeiffer #24), который в основном просто определяет экспорт. (Я действительно не понимаю, почему я хотел бы создать дополнительное имя для того, что уже имеет имя. Почему приведенная ниже команда не может просто ссылаться на цель?)
    • добавлять install(EXPORT FooTargets NAMESPACE Foo:: DESTINATION lib/cmake/Foo) который бы создал FooTargets.cmake в <CMAKE_INSTALL_PREFIX>/lib/cmake/Foo который определяет цель Foo::Foo (надеюсь) со всеми его зависимостями
    • Добавить "что-то" создание FooConfigVersion.cmake возможно с помощью write_basic_package_version_file что, насколько я понимаю, жестко кодирует версию этого файла
    • Создать FooConfig.cmake которые могут использовать find_dependency искать библиотеки, от которых зависит Foo FooTargets.cmake
    • устанавливать FooConfig.cmake а также FooConfigVersion.cmake в lib/cmake/Foo
    • модифицировать target_include_directories использовать отдельный BUILD_INTERFACE а также INSTALL_INTERFACE пути

Использование:
find_package автоматически находит FooConfig.cmake а также FooConfigVersion.cmake когда Foo ищется.

Поэтому модуль Config должен быть предпочтительным, но я вижу следующие проблемы:

  • Процесс выглядит сложнее
  • Его нельзя использовать, чтобы позволить пользователям находить более старые версии библиотеки (которые не использовали этот подход)
  • Он исключает всех (библиотечных) пользователей со старым CMake (2.8.11, вероятно, является минимально необходимым здесь)
  • Для сборки самой библиотеки требуется более новая версия CMake.
  • Требование C++11 кажется очень сложным для кодирования

Так можем ли мы решить требования с помощью CMake-Config? Ответ должен дать решение или, по крайней мере, обоснованное "невозможно". Следует также решить проблемы, изложенные в конце.

Последнее замечание: я думаю, что это хорошая запись вики, если она не существует.

0 ответов

Другие вопросы по тегам