Help: Update discussion of relocable packages in cmake-packages(7)

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.
This commit is contained in:
Brad King 2015-04-03 09:57:05 -04:00
parent 227992c3a6
commit 3af137824d
1 changed files with 45 additions and 19 deletions

View File

@ -475,6 +475,10 @@ without installation. Consumers of the build tree can simply ensure that the
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, Packages created by :command:`install(EXPORT)` are designed to be relocatable,
using paths relative to the location of the package itself. When defining 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 the interface of a target for ``EXPORT``, keep in mind that the include
@ -509,34 +513,56 @@ This also applies to paths referencing external dependencies.
It is not advisable to populate any properties which may contain It is not advisable to populate any properties which may contain
paths, such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` and paths, such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` and
:prop_tgt:`INTERFACE_LINK_LIBRARIES`, with paths relevant to dependencies. :prop_tgt:`INTERFACE_LINK_LIBRARIES`, with paths relevant to dependencies.
That would hard-code into installed packages the include directory or library For example, this code may not work well for a relocatable package:
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 .. code-block:: cmake
target_link_libraries(ClimbingStats INTERFACE target_link_libraries(ClimbingStats INTERFACE
${Boost_LIBRARIES} ${OtherDep_LIBRARIES} ${Foo_LIBRARIES} ${Bar_LIBRARIES}
) )
target_include_directories(ClimbingStats INTERFACE target_include_directories(ClimbingStats INTERFACE
"$<INSTALL_INTERFACE:${Boost_INCLUDE_DIRS};${OtherDep_INCLUDE_DIRS}>" "$<INSTALL_INTERFACE:${Foo_INCLUDE_DIRS};${Bar_INCLUDE_DIRS}>"
) )
Dependencies must provide their own :ref:`IMPORTED targets <Imported Targets>` The referenced variables may contain the absolute paths to libraries
which have their own :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` and and include directories **as found on the machine the package was made on**.
:prop_tgt:`IMPORTED_LOCATION` populated appropriately. Those This would create a package with hard-coded paths to dependencies and not
:ref:`IMPORTED targets <Imported Targets>` may then be suitable for relocation.
used with the :command:`target_link_libraries` command for ``ClimbingStats``.
That way, when a consumer uses the installed package, the Ideally such dependencies should be used through their own
consumer will run the appropriate :command:`find_package` command (via the :ref:`IMPORTED targets <Imported Targets>` that have their own
find_dependency macro described below) to find :prop_tgt:`IMPORTED_LOCATION` and usage requirement properties
the dependencies on their own machine and populate the such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` populated
:ref:`IMPORTED targets <Imported Targets>` with appropriate paths. Note that appropriately. Those imported targets may then be used with
many modules currently shipped with CMake do not currently provide the :command:`target_link_libraries` command for ``ClimbingStats``:
:ref:`IMPORTED targets <Imported Targets>`.
.. 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`: