Merge topic 'doc-relocatable-usage-requirements'

3af13782 Help: Update discussion of relocable packages in cmake-packages(7)
227992c3 Help: Reorganize and refine discussion of relocatable packages
031d894f Help: Place relocatable package notes in their own subsections
6e331ce9 Help: Fix typo in cmake-packages(7) manual
ba9b9d79 Help: Fix syntax in non-relocatable usage requirements example
This commit is contained in:
Brad King 2015-04-03 13:38:04 -04:00 committed by CMake Topic Stage
commit b6b77bb750
10 changed files with 153 additions and 117 deletions

View File

@ -55,5 +55,8 @@ installation prefix. For example:
$<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib
)
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
.. include:: /include/INTERFACE_INCLUDE_DIRECTORIES_WARNING.txt

View File

@ -49,9 +49,6 @@ CMake will also propagate :ref:`usage requirements <Target Usage Requirements>`
from linked library targets. Usage requirements of dependencies affect
compilation of sources in the ``<target>``.
.. |INTERFACE_PROPERTY_LINK| replace:: :prop_tgt:`INTERFACE_LINK_LIBRARIES`
.. include:: /include/INTERFACE_LINK_LIBRARIES_WARNING.txt
If an ``<item>`` is a library in a Mac OX framework, the ``Headers``
directory of the framework will also be processed as a
:ref:`usage requirement <Target Usage Requirements>`. This has the same
@ -153,3 +150,9 @@ will not be used in OLD handling of :policy:`CMP0003` or :policy:`CMP0004`.
See the :manual:`cmake-generator-expressions(7)` manual for available
expressions. See the :manual:`cmake-buildsystem(7)` manual for more on
defining buildsystem properties.
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: :prop_tgt:`INTERFACE_LINK_LIBRARIES`
.. include:: /include/INTERFACE_LINK_LIBRARIES_WARNING.txt

View File

@ -1,30 +1,18 @@
Note that it is not advisable to populate the ``INSTALL_INTERFACE`` of the
|INTERFACE_PROPERTY_LINK| of a target with paths for dependencies.
That would hard-code into installed packages the include directory paths
for dependencies **as found on the machine the package was made on**.
|INTERFACE_PROPERTY_LINK| of a target with absolute paths to the include
directories of dependencies. That would hard-code into installed packages
the include directory paths for dependencies
**as found on the machine the package was made on**.
The ``INSTALL_INTERFACE`` of the |INTERFACE_PROPERTY_LINK| is only
suitable for specifying the required include directories of the target itself,
not its dependencies.
suitable for specifying the required include directories for headers
provided with the target itself, not those provided by the transitive
dependencies listed in its :prop_tgt:`INTERFACE_LINK_LIBRARIES` target
property. Those dependencies should themselves be targets that specify
their own header locations in |INTERFACE_PROPERTY_LINK|.
That is, code like this is incorrect for targets which will be used to
generate :manual:`cmake-packages(7)`:
.. code-block:: cmake
target_include_directories(mylib INTERFACE
$<INSTALL_INTERFACE:${Boost_INCLUDE_DIRS};${OtherDep_INCLUDE_DIRS}>
)
Dependencies must provide their own :ref:`IMPORTED targets <Imported Targets>`
which have their own |INTERFACE_PROPERTY_LINK| populated
appropriately. Those :ref:`IMPORTED targets <Imported Targets>` may then be
used with the :command:`target_link_libraries` command for ``mylib``.
That way, when a consumer uses the installed package, the
consumer will run the appropriate :command:`find_package` command to find
the dependencies on their own machine and populate the
:ref:`IMPORTED targets <Imported Targets>` with appropriate paths. See
:ref:`Creating Packages` for more. Note that many modules currently shipped
with CMake do not currently provide :ref:`IMPORTED targets <Imported Targets>`.
See the :ref:`Creating Relocatable Packages` section of the
:manual:`cmake-packages(7)` manual for discussion of additional care
that must be taken when specifying usage requirements while creating
packages for redistribution.

View File

@ -1,23 +1,10 @@
Note that it is not advisable to populate the
|INTERFACE_PROPERTY_LINK| of a target with paths for dependencies.
That would hard-code into installed packages the include directory paths
|INTERFACE_PROPERTY_LINK| of a target with absolute paths to dependencies.
That would hard-code into installed packages the library file paths
for dependencies **as found on the machine the package was made on**.
That is, code like this is incorrect for targets which will be used to
generate :manual:`cmake-packages(7)`:
.. code-block:: cmake
target_link_libraries(mylib INTERFACE
${Boost_LIBRARIES};${OtherDep_LIBRARIES}
)
Dependencies must provide their own :ref:`IMPORTED targets <Imported Targets>`
which have their own :prop_tgt:`IMPORTED_LOCATION` populated
appropriately. That way, when a consumer uses the installed package, the
consumer will run the appropriate :command:`find_package` command to find
the dependencies on their own machine and populate the
:ref:`IMPORTED targets <Imported Targets>` with appropriate paths. See
:ref:`Creating Packages` for more. Note that many modules currently shipped
with CMake do not currently provide :ref:`IMPORTED targets <Imported Targets>`.
See the :ref:`Creating Relocatable Packages` section of the
:manual:`cmake-packages(7)` manual for discussion of additional care
that must be taken when specifying usage requirements while creating
packages for redistribution.

View File

@ -143,6 +143,11 @@ use particular :prop_tgt:`COMPILE_OPTIONS` or
the properties must be **requirements**, not merely recommendations or
convenience.
See the :ref:`Creating Relocatable Packages` section of the
:manual:`cmake-packages(7)` manual for discussion of additional care
that must be taken when specifying usage requirements while creating
packages for redistribution.
Target Properties
-----------------

View File

@ -373,38 +373,6 @@ 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.
Note that 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 relevnt to dependencies.
That would hard-code into installed packages the include directory or library
paths for dependencies **as found on the machine the package was made on**.
That is, code like this is incorrect for targets which will be used to
generate config file packages:
.. code-block:: cmake
target_link_libraries(ClimbingStats INTERFACE
${Boost_LIBRARIES};${OtherDep_LIBRARIES}>
)
target_include_directories(ClimbingStats INTERFACE
$<INSTALL_INTERFACE:${Boost_INCLUDE_DIRS};${OtherDep_INCLUDE_DIRS}>
)
Dependencies must provide their own :ref:`IMPORTED targets <Imported Targets>`
which have their own :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` and
:prop_tgt:`IMPORTED_LOCATION` populated appropriately. Those
:ref:`IMPORTED targets <Imported Targets>` may then be
used with the :command:`target_link_libraries` command for ``ClimbingStats``.
That way, when a consumer uses the installed package, the
consumer will run the appropriate :command:`find_package` command (via the
find_dependency macro described below) to find
the dependencies on their own machine and populate the
:ref:`IMPORTED targets <Imported Targets>` with appropriate paths. Note that
many modules currently shipped with CMake do not currently provide
:ref:`IMPORTED targets <Imported Targets>`.
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
@ -418,6 +386,9 @@ 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
@ -429,44 +400,6 @@ 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.
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>>
)
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.
This can also be extended to cover dependencies:
.. code-block:: cmake
@ -526,6 +459,111 @@ 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

View File

@ -22,5 +22,8 @@ installation prefix. For example:
$<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib
)
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: ``INTERFACE_INCLUDE_DIRECTORIES``
.. include:: /include/INTERFACE_INCLUDE_DIRECTORIES_WARNING.txt

View File

@ -17,5 +17,8 @@ with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: ``INTERFACE_LINK_LIBRARIES``
.. include:: /include/INTERFACE_LINK_LIBRARIES_WARNING.txt

View File

@ -24,5 +24,8 @@ property if policy :policy:`CMP0022` is ``NEW``.
This property is deprecated. Use :prop_tgt:`INTERFACE_LINK_LIBRARIES`
instead.
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: ``LINK_INTERFACE_LIBRARIES``
.. include:: /include/INTERFACE_LINK_LIBRARIES_WARNING.txt

View File

@ -13,5 +13,8 @@ property if policy :policy:`CMP0022` is ``NEW``.
This property is deprecated. Use :prop_tgt:`INTERFACE_LINK_LIBRARIES`
instead.
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. |INTERFACE_PROPERTY_LINK| replace:: ``LINK_INTERFACE_LIBRARIES_<CONFIG>``
.. include:: /include/INTERFACE_LINK_LIBRARIES_WARNING.txt