CMake имеет специфицированную c функцию, предназначенную для распространения find_package
, как это называется find_dependency
. Вы можете использовать его следующим образом:
include(CMakeFindDependencyMacro)
find_dependency(libutil)
CMake не будет экспортировать вызовы find_package
в созданные файлы. Вы должны сделать это вручную с помощью find_package
или find_dependency
. Разница в том, что find_dependency
будет правильно пересылать REQUIRED
и QUIET
.
Почему CMake пытается отправить -llibUtil
компоновщику?
При добавлении чего-либо в target_link_libraries
, есть два случая:
- Библиотека для ссылки является целью. В этом случае свойства интерфейса распространяются правильно, включая ссылки, если это необходимо.
- Это просто строка, в которой нет целей. В этом случае CMake предполагает, что это системная библиотека, и добавляет флаг
-l
.
, поскольку ссылка на libutil
является общедоступным c свойством libmain
все потребители libmain
будут также ссылаться на libutil
.
Поскольку вызов пакета поиска должен выполняться вручную, libutil
не является целью. Предполагается соединение с системной библиотекой, поэтому CMake сделает exe
с системной библиотекой с именем libutil
, которая не существует.
Вызов find_package(libUtil REQUIRED)
обеспечит exe
потребностью в использовании libutil
связывая цели вместо библиотек.
Как libUtil
может быть целью?
CMake цель (полностью) не привязана к каталогам. У вас может быть GLOBAL
и IMPORTED
целей, и вы можете иметь несколько целей по проектам. Представьте себе проект, который состоит из нескольких библиотек и исполняемых файлов. По аналогии можно сказать, что проекты CMake представляют собой решение Visual Studio, а цели CMake - проекты Visual Studio.
Теперь для импортированных целей. Они предназначены для представления целей, которые уже скомпилированы другим проектом, который вы либо установили, либо экспортировали в дерево сборки. Импортированная цель позволяет вам потреблять вещи из другого проекта так же, как обычная цель, как если бы вы объявили это. Импортируемые цели более точны, чем флаги компилятора: они несут, конечно, библиотеку, но также и то, как связать, необходимые флаги компилятора, включают каталоги и другие требования.
find_package
и find_dependency
предназначены для найти файл конфигурации, и они содержат информацию об импортированных целях. После этого, простая ссылка на него будет включать в себя каталоги, правильные флаги компоновщика и т. Д. c.
Хорошим примером проекта, экспортирующего несколько целей, является SFML, который экспортирует различные модули, такие как управление звуком, графикой и окнами. как отдельные статические / динамические c библиотеки.
Как можно избежать этой глупой ошибки?
CMake позволяет нам использовать пространства имен для целей. При использовании синтаксиса пространства имен он не может быть системной библиотекой. CMake выдаст ошибку, что цель не найдена, вместо попытки связать ее с несуществующей библиотекой.
install(
EXPORT ${PROJECT_NAME}Config
NAMESPACE libUtil
DESTINATION ${CMAKE_INSTALL_PREFIX}/cmake
)
И затем изменить ссылку на это:
target_link_libraries(${PROJECT_NAME} PUBLIC libUtil::libUtil)
Соглашение для имени пространства имен следует использовать то же имя, что и пакет.