.. cmake-manual-description: CMake Packages Reference cmake-packages(7) ***************** .. only:: html or latex .. contents:: Introduction ============ Packages provide dependency information to CMake based buildsystems. Packages are found with the :command:`find_package` command. The result of using ``find_package`` is either a set of :prop_tgt:`IMPORTED` targets, or a set of variables corresponding to build-relevant information. Using Packages ============== CMake provides direct support for two forms of packages, `Config-file Packages`_ and `Find-module Packages`_. Indirect support for ``pkg-config`` packages is also provided via the :module:`FindPkgConfig` module. In all cases, the basic form of :command:`find_package` calls is the same: .. code-block:: cmake find_package(Qt4 4.7.0 REQUIRED) # CMake provides a Qt4 find-module find_package(Qt5Core 5.1.0 REQUIRED) # Qt provides a Qt5 package config file. find_package(LibXml2 REQUIRED) # Use pkg-config via the LibXml2 find-module In cases where it is known that a package configuration file is provided by upstream, and only that should be used, the ``CONFIG`` keyword may be passed to :command:`find_package`: .. code-block:: cmake find_package(Qt5Core 5.1.0 CONFIG REQUIRED) find_package(Qt5Gui 5.1.0 CONFIG) Similarly, the ``MODULE`` keyword says to use only a find-module: .. code-block:: cmake find_package(Qt4 4.7.0 MODULE REQUIRED) Specifying the type of package explicitly improves the error message shown to the user if it is not found. Both types of packages also support specifying components of a package, either after the ``REQUIRED`` keyword: .. code-block:: cmake find_package(Qt5 5.1.0 CONFIG REQUIRED Widgets Xml Sql) or as a separate ``COMPONENTS`` list: .. code-block:: cmake find_package(Qt5 5.1.0 COMPONENTS Widgets Xml Sql) or as a separate ``OPTIONAL_COMPONENTS`` list: .. code-block:: cmake find_package(Qt5 5.1.0 COMPONENTS Widgets OPTIONAL_COMPONENTS Xml Sql ) Handling of ``COMPONENTS`` and ``OPTIONAL_COMPONENTS`` is defined by the package. Config-file Packages -------------------- A config-file package is a set of files provided by upstreams for downstreams to use. CMake searches in a number of locations for package configuration files, as described in the :command:`find_package` documentation. The most simple way for a CMake user to tell :manual:`cmake(1)` to search in a non-standard prefix for a package is to set the ``CMAKE_PREFIX_PATH`` cache variable. Config-file packages are provided by upstream vendors as part of development packages, that is, they belong with the header files and any other files provided to assist downsteams in using the package. A set of variables which provide package status information are also set automatically when using a config-file package. The ``_FOUND`` variable is set to true or false, depending on whether the package was found. The ``_DIR`` cache variable is set to the location of the package configuration file. Find-module Packages -------------------- A find module is a file with a set of rules for finding the required pieces of a dependency, primarily header files and libraries. Typically, a find module is needed when the upstream is not built with CMake, or is not CMake-aware enough to otherwise provide a package configuration file. Unlike a package configuration file, it is not shipped with upstream, but is used by downstream to find the files by guessing locations of files with platform-specific hints. Unlike the case of an upstream-provided package configuration file, no single point of reference identifies the package as being found, so the ``_FOUND`` variable is not automatically set by the :command:`find_package` command. It can still be expected to be set by convention however and should be set by the author of the Find-module. Similarly there is no ``_DIR`` variable, but each of the artifacts such as library locations and header file locations provide a separate cache variable. See the :manual:`cmake-developer(7)` manual for more information about creating Find-module files. Package Layout ============== A config-file package consists of a `Package Configuration File`_ and optionally a `Package Version File`_ provided with the project distribution. Package Configuration File -------------------------- Consider a project ``Foo`` that installs the following files:: /include/foo-1.2/foo.h /lib/foo-1.2/libfoo.a It may also provide a CMake package configuration file:: /lib/cmake/foo-1.2/FooConfig.cmake with content defining :prop_tgt:`IMPORTED` targets, or defining variables, such as: .. code-block:: cmake # ... # (compute PREFIX relative to file location) # ... set(Foo_INCLUDE_DIRS ${PREFIX}/include/foo-1.2) set(Foo_LIBRARIES ${PREFIX}/lib/foo-1.2/libfoo.a) If another project wishes to use ``Foo`` it need only to locate the ``FooConfig.cmake`` file and load it to get all the information it needs about package content locations. Since the package configuration file is provided by the package installation it already knows all the file locations. The :command:`find_package` command may be used to search for the package configuration file. This command constructs a set of installation prefixes and searches under each prefix in several locations. Given the name ``Foo``, it looks for a file called ``FooConfig.cmake`` or ``foo-config.cmake``. The full set of locations is specified in the :command:`find_package` command documentation. One place it looks is:: /lib/cmake/Foo*/ where ``Foo*`` is a case-insensitive globbing expression. In our example the globbing expression will match ``/lib/cmake/foo-1.2`` and the package configuration file will be found. Once found, a package configuration file is immediately loaded. It, together with a package version file, contains all the information the project needs to use the package. Package Version File -------------------- When the :command:`find_package` command finds a candidate package configuration file it looks next to it for a version file. The version file is loaded to test whether the package version is an acceptable match for the version requested. If the version file claims compatibility the configuration file is accepted. Otherwise it is ignored. The name of the package version file must match that of the package configuration file but has either ``-version`` or ``Version`` appended to the name before the ``.cmake`` extension. For example, the files:: /lib/cmake/foo-1.3/foo-config.cmake /lib/cmake/foo-1.3/foo-config-version.cmake and:: /lib/cmake/bar-4.2/BarConfig.cmake /lib/cmake/bar-4.2/BarConfigVersion.cmake are each pairs of package configuration files and corresponding package version files. When the :command:`find_package` command loads a version file it first sets the following variables: ``PACKAGE_FIND_NAME`` The name ``PACKAGE_FIND_VERSION`` Full requested version string ``PACKAGE_FIND_VERSION_MAJOR`` Major version if requested, else 0 ``PACKAGE_FIND_VERSION_MINOR`` Minor version if requested, else 0 ``PACKAGE_FIND_VERSION_PATCH`` Patch version if requested, else 0 ``PACKAGE_FIND_VERSION_TWEAK`` Tweak version if requested, else 0 ``PACKAGE_FIND_VERSION_COUNT`` Number of version components, 0 to 4 The version file must use these variables to check whether it is compatible or an exact match for the requested version and set the following variables with results: ``PACKAGE_VERSION`` Full provided version string ``PACKAGE_VERSION_EXACT`` True if version is exact match ``PACKAGE_VERSION_COMPATIBLE`` True if version is compatible ``PACKAGE_VERSION_UNSUITABLE`` True if unsuitable as any version Version files are loaded in a nested scope so they are free to set any variables they wish as part of their computation. The find_package command wipes out the scope when the version file has completed and it has checked the output variables. When the version file claims to be an acceptable match for the requested version the find_package command sets the following variables for use by the project: ``_VERSION`` Full provided version string ``_VERSION_MAJOR`` Major version if provided, else 0 ``_VERSION_MINOR`` Minor version if provided, else 0 ``_VERSION_PATCH`` Patch version if provided, else 0 ``_VERSION_TWEAK`` Tweak version if provided, else 0 ``_VERSION_COUNT`` Number of version components, 0 to 4 The variables report the version of the package that was actually found. The ```` part of their name matches the argument given to the :command:`find_package` command. Creating Packages ================= Usually, the upstream depends on CMake itself and can use some CMake facilities for creating the package files. Consider an upstream which provides a single shared library: .. code-block:: cmake project(UpstreamLib) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) set(Upstream_VERSION 3.4.1) include(GenerateExportHeader) add_library(ClimbingStats SHARED climbingstats.cpp) generate_export_header(ClimbingStats) install(TARGETS ClimbingStats EXPORT ClimbingStatsTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) install( FILES climbingstats.h "${CMAKE_CURRENT_BINARY_DIR}/climbingstats_export.h" DESTINATION include COMPONENT Devel ) include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfigVersion.cmake" VERSION ${Upstream_VERSION} COMPATIBILITY AnyNewerVersion ) export(EXPORT ClimbingStatsTargets FILE "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsTargets.cmake" NAMESPACE Upstream:: ) configure_file(cmake/ClimbingStatsConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfig.cmake" COPY_ONLY ) set(ConfigPackageLocation lib/cmake/ClimbingStats) install(EXPORT ClimbingStatsTargets FILE ClimbingStatsTargets.cmake NAMESPACE Upstream:: DESTINATION ${ConfigPackageLocation} ) install( FILES cmake/ClimbingStatsConfig.cmake "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfigVersion.cmake" DESTINATION ${ConfigPackageLocation} COMPONENT Devel ) The :module:`CMakePackageConfigHelpers` module provides a macro for creating a simple ``ConfigVersion.cmake`` file. This file sets the version of the package. It is read by CMake when :command:`find_package` is called to determine the compatibility with the requested version, and to set some version-specific variables ``_VERSION``, ``_VERSION_MAJOR``, ``_VERSION_MINOR`` etc. The :command:`install(EXPORT)` command is used to export the targets in the ``ClimbingStatsTargets`` export-set, defined previously by the :command:`install(TARGETS)` command. This command generates the ``ClimbingStatsTargets.cmake`` file to contain :prop_tgt:`IMPORTED` targets, suitable for use by downsteams and arranges to install it to ``lib/cmake/ClimbingStats``. The generated ``ClimbingStatsConfigVersion.cmake`` and a ``cmake/ClimbingStatsConfig.cmake`` are installed to the same location, completing the package. A ``NAMESPACE`` with double-colons is specified when exporting the targets for installation. This convention of double-colons gives CMake a hint that the name is an :prop_tgt:`IMPORTED` target when it is used by downstreams with the :command:`target_link_libraries` command. This way, CMake can issue a diagnostic if the package providing it has not yet been found. In this case, when using :command:`install(TARGETS)` the ``INCLUDES DESTINATION`` was specified. This causes the ``IMPORTED`` targets to have their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` populated with the ``include`` directory in the :variable:`CMAKE_INSTALL_PREFIX`. When the ``IMPORTED`` target is used by downsteam, it automatically consumes the entries from that property. In this case, the ``ClimbingStatsConfig.cmake`` file could be as simple as: .. code-block:: cmake include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake") As this allows downstreams to use the ``IMPORTED`` targets. If any macros should be provided by the ``ClimbingStats`` package, they should be in a separate file which is installed to the same location as the ``ClimbingStatsConfig.cmake`` file, and included from there. The :command:`export(EXPORT)` command creates an :prop_tgt:`IMPORTED` targets definition file which is specific to the build-tree. This can similiarly be used with a suitable package configuration file and package version file to define a package for the build tree which may be used without installation. Consumers of the build tree can simply ensure that the :variable:`CMAKE_PREFIX_PATH` contains the build directory, or set the ``ClimbingStats_DIR`` to ``/ClimbingStats`` in the cache. This can also be extended to cover dependencies: .. code-block:: cmake # ... add_library(ClimbingStats SHARED climbingstats.cpp) generate_export_header(ClimbingStats) find_package(Stats 2.6.4 REQUIRED) target_link_libraries(ClimbingStats PUBLIC Stats::Types) As the ``Stats::Types`` target is a ``PUBLIC`` dependency of ``ClimbingStats``, downsteams must also find the ``Stats`` package and link to the ``Stats::Types`` library. The ``Stats`` package should be found in the ``ClimbingStatsConfig.cmake`` file to ensure this. The ``find_dependency`` macro from the :module:`CMakeFindDependencyMacro` helps with this by propagating whether the package is ``REQUIRED``, or ``QUIET`` etc. All ``REQUIRED`` dependencies of a package should be found in the ``Config.cmake`` file: .. code-block:: cmake include(CMakeFindDependencyMacro) find_dependency(Stats 2.6.4) include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsMacros.cmake") The ``find_dependency`` macro also sets ``ClimbingStats_FOUND`` to ``False`` if the dependency is not found, along with a diagnostic that the ``ClimbingStats`` package can not be used without the ``Stats`` package. If ``COMPONENTS`` are specified when the downstream uses :command:`find_package`, they are listed in the ``_FIND_COMPONENTS`` variable. If a particular component is non-optional, then the ``_FIND_REQUIRED_`` will be true. This can be tested with logic in the package configuration file: .. code-block:: cmake include(CMakeFindDependencyMacro) find_dependency(Stats 2.6.4) include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsMacros.cmake") set(_supported_components Plot Table) foreach(_comp ${ClimbingStats_FIND_COMPONENTS}) if (NOT ";${_supported_components};" MATCHES _comp) set(ClimbingStats_FOUND False) set(ClimbingStats_NOTFOUND_MESSAGE "Specified unsupported component: ${_comp}") endif() include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStats${_comp}Targets.cmake") endforeach() Here, the ``ClimbingStats_NOTFOUND_MESSAGE`` is set to a diagnosis that the package could not be found because an invalid component was specified. This message variable can be set for any case where the ``_FOUND`` variable is set to ``False``, and will be displayed to the user.