3af137824d
Explain at the beginning of the section the requirements for a package to be relocatable to justify the rest of the section content. Generalize example to use fictional package names instead of real ones, especially because FindBoost provides no alternative yet. Reword the discussion to represent the preferred approach as "ideal" but also suggest workarounds when find modules do not provide the imported targets.
710 lines
26 KiB
ReStructuredText
710 lines
26 KiB
ReStructuredText
.. cmake-manual-description: CMake Packages Reference
|
|
|
|
cmake-packages(7)
|
|
*****************
|
|
|
|
.. only:: html
|
|
|
|
.. 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.
|
|
|
|
By setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to
|
|
``TRUE``, the ``PackageName`` package will not be searched, and will always
|
|
be ``NOTFOUND``.
|
|
|
|
.. _`Config File Packages`:
|
|
|
|
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 ``<Package>_FOUND``
|
|
variable is set to true or false, depending on whether the package was
|
|
found. The ``<Package>_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 ``<Package>_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 ``<Package>_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::
|
|
|
|
<prefix>/include/foo-1.2/foo.h
|
|
<prefix>/lib/foo-1.2/libfoo.a
|
|
|
|
It may also provide a CMake package configuration file::
|
|
|
|
<prefix>/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::
|
|
|
|
<prefix>/lib/cmake/Foo*/
|
|
|
|
where ``Foo*`` is a case-insensitive globbing expression. In our example the
|
|
globbing expression will match ``<prefix>/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::
|
|
|
|
<prefix>/lib/cmake/foo-1.3/foo-config.cmake
|
|
<prefix>/lib/cmake/foo-1.3/foo-config-version.cmake
|
|
|
|
and::
|
|
|
|
<prefix>/lib/cmake/bar-4.2/BarConfig.cmake
|
|
<prefix>/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 <package> 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:
|
|
|
|
``<package>_VERSION``
|
|
Full provided version string
|
|
|
|
``<package>_VERSION_MAJOR``
|
|
Major version if provided, else 0
|
|
|
|
``<package>_VERSION_MINOR``
|
|
Minor version if provided, else 0
|
|
|
|
``<package>_VERSION_PATCH``
|
|
Patch version if provided, else 0
|
|
|
|
``<package>_VERSION_TWEAK``
|
|
Tweak version if provided, else 0
|
|
|
|
``<package>_VERSION_COUNT``
|
|
Number of version components, 0 to 4
|
|
|
|
The variables report the version of the package that was actually found.
|
|
The ``<package>`` part of their name matches the argument given to the
|
|
:command:`find_package` command.
|
|
|
|
.. _`Creating Packages`:
|
|
|
|
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)
|
|
set_property(TARGET ClimbingStats PROPERTY VERSION ${Upstream_VERSION})
|
|
set_property(TARGET ClimbingStats PROPERTY SOVERSION 3)
|
|
set_property(TARGET ClimbingStats PROPERTY
|
|
INTERFACE_ClimbingStats_MAJOR_VERSION 3)
|
|
set_property(TARGET ClimbingStats APPEND PROPERTY
|
|
COMPATIBLE_INTERFACE_STRING ClimbingStats_MAJOR_VERSION
|
|
)
|
|
|
|
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"
|
|
COPYONLY
|
|
)
|
|
|
|
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 ``<Package>_VERSION``, ``<Package>_VERSION_MAJOR``,
|
|
``<Package>_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.
|
|
|
|
The generated :prop_tgt:`IMPORTED` targets have appropriate properties set
|
|
to define their :ref:`usage requirements <Target Usage Requirements>`, such as
|
|
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`,
|
|
:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` and other relevant built-in
|
|
``INTERFACE_`` properties. The ``INTERFACE`` variant of user-defined
|
|
properties listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and
|
|
other :ref:`Compatible Interface Properties` are also propagated to the
|
|
generated :prop_tgt:`IMPORTED` targets. In the above case,
|
|
``ClimbingStats_MAJOR_VERSION`` is defined as a string which must be
|
|
compatible among the dependencies of any depender. By setting this custom
|
|
defined user property in this version and in the next version of
|
|
``ClimbingStats``, :manual:`cmake(1)` will issue a diagnostic if there is an
|
|
attempt to use version 3 together with version 4. Packages can choose to
|
|
employ such a pattern if different major versions of the package are designed
|
|
to be incompatible.
|
|
|
|
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.
|
|
|
|
Creating a Package Configuration File
|
|
-------------------------------------
|
|
|
|
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.
|
|
|
|
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 ``<Package>_FIND_COMPONENTS`` variable. If a particular
|
|
component is non-optional, then the ``<Package>_FIND_REQUIRED_<comp>`` 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 "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.
|
|
|
|
Creating a Package Configuration File for the Build Tree
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The :command:`export(EXPORT)` command creates an :prop_tgt:`IMPORTED` targets
|
|
definition file which is specific to the build-tree, and is not relocatable.
|
|
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 ``<build_dir>/ClimbingStats`` in the cache.
|
|
|
|
.. _`Creating Relocatable Packages`:
|
|
|
|
Creating Relocatable Packages
|
|
-----------------------------
|
|
|
|
A relocatable package must not reference absolute paths of files on
|
|
the machine where the package is built that will not exist on the
|
|
machines where the package may be installed.
|
|
|
|
Packages created by :command:`install(EXPORT)` are designed to be relocatable,
|
|
using paths relative to the location of the package itself. When defining
|
|
the interface of a target for ``EXPORT``, keep in mind that the include
|
|
directories should be specified as relative paths which are relative to the
|
|
:variable:`CMAKE_INSTALL_PREFIX`:
|
|
|
|
.. code-block:: cmake
|
|
|
|
target_include_directories(tgt INTERFACE
|
|
# Wrong, not relocatable:
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/TgtName>
|
|
)
|
|
|
|
target_include_directories(tgt INTERFACE
|
|
# Ok, relocatable:
|
|
$<INSTALL_INTERFACE:include/TgtName>
|
|
)
|
|
|
|
The ``$<INSTALL_PREFIX>``
|
|
:manual:`generator expression <cmake-generator-expressions(7)>` may be used as
|
|
a placeholder for the install prefix without resulting in a non-relocatable
|
|
package. This is necessary if complex generator expressions are used:
|
|
|
|
.. code-block:: cmake
|
|
|
|
target_include_directories(tgt INTERFACE
|
|
# Ok, relocatable:
|
|
$<INSTALL_INTERFACE:$<$<CONFIG:Debug>:$<INSTALL_PREFIX>/include/TgtName>>
|
|
)
|
|
|
|
This also applies to paths referencing external dependencies.
|
|
It is not advisable to populate any properties which may contain
|
|
paths, such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` and
|
|
:prop_tgt:`INTERFACE_LINK_LIBRARIES`, with paths relevant to dependencies.
|
|
For example, this code may not work well for a relocatable package:
|
|
|
|
.. code-block:: cmake
|
|
|
|
target_link_libraries(ClimbingStats INTERFACE
|
|
${Foo_LIBRARIES} ${Bar_LIBRARIES}
|
|
)
|
|
target_include_directories(ClimbingStats INTERFACE
|
|
"$<INSTALL_INTERFACE:${Foo_INCLUDE_DIRS};${Bar_INCLUDE_DIRS}>"
|
|
)
|
|
|
|
The referenced variables may contain the absolute paths to libraries
|
|
and include directories **as found on the machine the package was made on**.
|
|
This would create a package with hard-coded paths to dependencies and not
|
|
suitable for relocation.
|
|
|
|
Ideally such dependencies should be used through their own
|
|
:ref:`IMPORTED targets <Imported Targets>` that have their own
|
|
:prop_tgt:`IMPORTED_LOCATION` and usage requirement properties
|
|
such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` populated
|
|
appropriately. Those imported targets may then be used with
|
|
the :command:`target_link_libraries` command for ``ClimbingStats``:
|
|
|
|
.. code-block:: cmake
|
|
|
|
target_link_libraries(ClimbingStats INTERFACE Foo::Foo Bar::Bar)
|
|
|
|
With this approach the package references its external dependencies
|
|
only through the names of :ref:`IMPORTED targets <Imported Targets>`.
|
|
When a consumer uses the installed package, the consumer will run the
|
|
appropriate :command:`find_package` commands (via the ``find_dependency``
|
|
macro described above) to find the dependencies and populate the
|
|
imported targets with appropriate paths on their own machine.
|
|
|
|
Unfortunately many :manual:`modules <cmake-modules(7)>` shipped with
|
|
CMake do not yet provide :ref:`IMPORTED targets <Imported Targets>`
|
|
because their development pre-dated this approach. This may improve
|
|
incrementally over time. Workarounds to create relocatable packages
|
|
using such modules include:
|
|
|
|
* When building the package, specify each ``Foo_LIBRARY`` cache
|
|
entry as just a library name, e.g. ``-DFoo_LIBRARY=foo``. This
|
|
tells the corresponding find module to populate the ``Foo_LIBRARIES``
|
|
with just ``foo`` to ask the linker to search for the library
|
|
instead of hard-coding a path.
|
|
|
|
* Or, after installing the package content but before creating the
|
|
package installation binary for redistribution, manually replace
|
|
the absolute paths with placeholders for substitution by the
|
|
installation tool when the package is installed.
|
|
|
|
.. _`Package Registry`:
|
|
|
|
Package Registry
|
|
================
|
|
|
|
CMake provides two central locations to register packages that have
|
|
been built or installed anywhere on a system:
|
|
|
|
* `User Package Registry`_
|
|
* `System Package Registry`_
|
|
|
|
The registries are especially useful to help projects find packages in
|
|
non-standard install locations or directly in their own build trees.
|
|
A project may populate either the user or system registry (using its own
|
|
means, see below) to refer to its location.
|
|
In either case the package should store at the registered location a
|
|
`Package Configuration File`_ (``<package>Config.cmake``) and optionally a
|
|
`Package Version File`_ (``<package>ConfigVersion.cmake``).
|
|
|
|
The :command:`find_package` command searches the two package registries
|
|
as two of the search steps specified in its documentation. If it has
|
|
sufficient permissions it also removes stale package registry entries
|
|
that refer to directories that do not exist or do not contain a matching
|
|
package configuration file.
|
|
|
|
.. _`User Package Registry`:
|
|
|
|
User Package Registry
|
|
---------------------
|
|
|
|
The User Package Registry is stored in a per-user location.
|
|
The :command:`export(PACKAGE)` command may be used to register a project
|
|
build tree in the user package registry. CMake currently provides no
|
|
interface to add install trees to the user package registry. Installers
|
|
must be manually taught to register their packages if desired.
|
|
|
|
On Windows the user package registry is stored in the Windows registry
|
|
under a key in ``HKEY_CURRENT_USER``.
|
|
|
|
A ``<package>`` may appear under registry key::
|
|
|
|
HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\<package>
|
|
|
|
as a ``REG_SZ`` value, with arbitrary name, that specifies the directory
|
|
containing the package configuration file.
|
|
|
|
On UNIX platforms the user package registry is stored in the user home
|
|
directory under ``~/.cmake/packages``. A ``<package>`` may appear under
|
|
the directory::
|
|
|
|
~/.cmake/packages/<package>
|
|
|
|
as a file, with arbitrary name, whose content specifies the directory
|
|
containing the package configuration file.
|
|
|
|
.. _`System Package Registry`:
|
|
|
|
System Package Registry
|
|
-----------------------
|
|
|
|
The System Package Registry is stored in a system-wide location.
|
|
CMake currently provides no interface to add to the system package registry.
|
|
Installers must be manually taught to register their packages if desired.
|
|
|
|
On Windows the system package registry is stored in the Windows registry
|
|
under a key in ``HKEY_LOCAL_MACHINE``. A ``<package>`` may appear under
|
|
registry key::
|
|
|
|
HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<package>
|
|
|
|
as a ``REG_SZ`` value, with arbitrary name, that specifies the directory
|
|
containing the package configuration file.
|
|
|
|
There is no system package registry on non-Windows platforms.
|
|
|
|
.. _`Disabling the Package Registry`:
|
|
|
|
Disabling the Package Registry
|
|
------------------------------
|
|
|
|
In some cases using the Package Registries is not desirable. CMake
|
|
allows to disable them using the following variables:
|
|
|
|
* :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` disables the
|
|
:command:`export(PACKAGE)` command.
|
|
* :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the
|
|
User Package Registry in all the :command:`find_package` calls.
|
|
* :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` disables
|
|
the System Package Registry in all the :command:`find_package` calls.
|
|
|
|
Package Registry Example
|
|
------------------------
|
|
|
|
A simple convention for naming package registry entries is to use content
|
|
hashes. They are deterministic and unlikely to collide
|
|
(:command:`export(PACKAGE)` uses this approach).
|
|
The name of an entry referencing a specific directory is simply the content
|
|
hash of the directory path itself.
|
|
|
|
If a project arranges for package registry entries to exist, such as::
|
|
|
|
> reg query HKCU\Software\Kitware\CMake\Packages\MyPackage
|
|
HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\MyPackage
|
|
45e7d55f13b87179bb12f907c8de6fc4 REG_SZ c:/Users/Me/Work/lib/cmake/MyPackage
|
|
7b4a9844f681c80ce93190d4e3185db9 REG_SZ c:/Users/Me/Work/MyPackage-build
|
|
|
|
or::
|
|
|
|
$ cat ~/.cmake/packages/MyPackage/7d1fb77e07ce59a81bed093bbee945bd
|
|
/home/me/work/lib/cmake/MyPackage
|
|
$ cat ~/.cmake/packages/MyPackage/f92c1db873a1937f3100706657c63e07
|
|
/home/me/work/MyPackage-build
|
|
|
|
then the ``CMakeLists.txt`` code:
|
|
|
|
.. code-block:: cmake
|
|
|
|
find_package(MyPackage)
|
|
|
|
will search the registered locations for package configuration files
|
|
(``MyPackageConfig.cmake``). The search order among package registry
|
|
entries for a single package is unspecified and the entry names
|
|
(hashes in this example) have no meaning. Registered locations may
|
|
contain package version files (``MyPackageConfigVersion.cmake``) to
|
|
tell :command:`find_package` whether a specific location is suitable
|
|
for the version requested.
|
|
|
|
Package Registry Ownership
|
|
--------------------------
|
|
|
|
Package registry entries are individually owned by the project installations
|
|
that they reference. A package installer is responsible for adding its own
|
|
entry and the corresponding uninstaller is responsible for removing it.
|
|
|
|
The :command:`export(PACKAGE)` command populates the user package registry
|
|
with the location of a project build tree. Build trees tend to be deleted by
|
|
developers and have no "uninstall" event that could trigger removal of their
|
|
entries. In order to keep the registries clean the :command:`find_package`
|
|
command automatically removes stale entries it encounters if it has sufficient
|
|
permissions. CMake provides no interface to remove an entry referencing an
|
|
existing build tree once :command:`export(PACKAGE)` has been invoked.
|
|
However, if the project removes its package configuration file from the build
|
|
tree then the entry referencing the location will be considered stale.
|