Получение импортированных целей через `find_package`?

Руководство по CMake Qt 5 использует find_package и говорит:

Импортированные цели создаются для каждого модуля Qt. Импортируемые целевые имена должны быть предпочтительнее, чем использование такой переменной, как Qt5<Module>_LIBRARIES в командах CMake, таких как target_link_libraries.

Это специально для Qt или find_package генерировать импортированные цели для всех библиотек? Документация find_package в CMake 3.0 написано:

Когда пакет найден, информация о конкретном пакете предоставляется через переменные и импортированные цели, задокументированные самим пакетом.

И руководство для cmake-пакетов говорит:

Результат использования find_package это либо набор ИМПОРТИРОВАННЫХ целей, либо набор переменных, соответствующих информации, относящейся к сборке.

Но я не видел другого FindXXX.cmake -скрипт, где документация говорит, что импортированная цель создана.

2 ответа

Решение

find_package это двуглавый зверь в эти дни:

CMake обеспечивает прямую поддержку двух форм пакетов: пакетов с конфигурационными файлами и пакетов с поисковыми модулями.

Источник

Теперь, что это на самом деле означает?

Пакеты Find-module - это те, с которыми вы, вероятно, больше всего знакомы. Они выполняют скрипт кода CMake (такой как этот), который выполняет несколько вызовов таких функций, как find_library а также find_path выяснить, где найти библиотеку.

Большим преимуществом этого подхода является то, что он чрезвычайно универсален. Пока что-то есть в файловой системе, мы можем это найти. Большим недостатком является то, что он часто предоставляет немного больше информации, чем физическое местонахождение чего-либо. То есть результатом операции find-module обычно является просто набор путей к файловой системе. Это означает, что моделирование, такое как транзитивные зависимости или множественные конфигурации сборки, довольно сложно.

Это становится особенно болезненным, если то, что вы пытаетесь найти, было создано с помощью CMake. В этом случае у вас уже есть куча вещей, смоделированных в ваших скриптах сборки, которые вам теперь нужно тщательно реконструировать для скрипта поиска, чтобы он стал доступен для последующих проектов.

Это где пакеты конфигурационного файла светятся. В отличие от find-modules, результат запуска скрипта - это не просто набор путей, а создание полнофункциональных целей CMake. Для зависимого проекта похоже, что зависимости были построены как часть этого же проекта.

Это позволяет транспортировать гораздо больше информации очень удобным способом. Очевидным недостатком является то, что скрипты конфигурационного файла намного сложнее, чем скрипты поиска. Следовательно, вы не хотите писать их сами, но CMake сгенерирует их для вас. Или, скорее, сделайте так, чтобы зависимость предоставила конфигурационный файл как часть его развертывания, который затем можно просто загрузить с помощью find_package вызов. И это именно то, что делает Qt5.

Это также означает, что если ваш собственный проект является библиотекой, рассмотрите возможность создания файла конфигурации как часть процесса сборки. Это не самая простая функция CMake, но результаты довольно мощные.

Вот быстрое сравнение того, как эти два подхода обычно выглядят в коде CMake:

Стиль поиска модуля

find_package(foo)
target_link_libraries(bar ${FOO_LIBRARIES})
target_include_directories(bar ${FOO_INCLUDE_DIR})
# [...] potentially lots of other stuff that has to be set manually

Стиль конфигурационного файла

find_package(foo)
target_link_libraries(bar foo)
# magic!

tl; dr: Всегда предпочитайте пакеты с конфигурационным файлом, если их предоставляет зависимость. Если нет, используйте вместо этого скрипт поиска.

На самом деле нет "магии" с результатами find_package: эта команда просто ищет подходящую FindXXX.cmake скрипт и выполняет его.

Если набор скриптов Find XXX_LIBRARY переменная, то вызывающая сторона может использовать эту переменную.

Если скрипт поиска создает импортированные цели, то вызывающая сторона может использовать эти цели.

Если Find скрипт не устанавливает XXX_LIBRARY переменная, ни создает импортированные цели... хорошо, тогда использование сценария как-то отличается.

Документация для find_package описывает обычное использование скриптов Find. Но в любом случае вам необходимо обратиться к документации по конкретному сценарию (эта документация обычно содержится в самом сценарии).

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