Skip to content

Commit

Permalink
Fix numerous inconsistencies in ament-cmake-docs w.r.t installation o…
Browse files Browse the repository at this point in the history
…f linkage, and target installation (#3805) (#3811)

* Fix numerous inconsistencies in ament-cmake-docs

* Nodes need a special RUNTIME directory to be recognized by ROS 2 CLI
* The order of creating the export set and using it was not intuitive
* target_link_libraries was missing linkage type which is not
  recommended
* It did not show to install nodes and libraries at the same time
* The installation of headers was overly complex since the install
  directory is the same for all headers
* HAS_LIBRARY_TARGET wasn't explained that it's only needed if you are
  installing libraries

* Updates from review.

Signed-off-by: Ryan Friedman <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
(cherry picked from commit 42ccd72)

Co-authored-by: Ryan <[email protected]>
  • Loading branch information
mergify[bot] and Ryanf55 authored Jul 31, 2023
1 parent 6cf7197 commit 582f762
Showing 1 changed file with 21 additions and 20 deletions.
41 changes: 21 additions & 20 deletions source/How-To-Guides/Ament-CMake-Documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The basic outline of the ``CMakeLists.txt`` of an ament package contains:

.. code-block:: cmake
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.8)
project(my_project)
ament_package()
Expand Down Expand Up @@ -74,14 +74,14 @@ The following best practice is proposed:

- only cpp files are explicitly referenced in the call to ``add_library`` or ``add_executable``

- allow to find headers via
- find headers via

.. code-block:: cmake
target_include_directories(my_target
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
This adds all files in the folder ``${CMAKE_CURRENT_SOURCE_DIR}/include`` to the public interface during build time and all files in the include folder (relative to ``${CMAKE_INSTALL_DIR}``) when being installed.

Expand All @@ -98,7 +98,7 @@ As an example, suppose we want to link ``my_target`` against the linear algebra
.. code-block:: cmake
find_package(Eigen3 REQUIRED)
ament_target_dependencies(my_target Eigen3)
ament_target_dependencies(my_library PUBLIC Eigen3::Eigen)
It includes the necessary headers and libraries and their dependencies to be correctly found by the project.
It will also ensure that the include directories of all dependencies are ordered correctly when using overlay workspaces.
Expand All @@ -109,14 +109,13 @@ The recommended way in modern CMake is to only use targets, exporting and linkin
CMake targets are namespaced, similar to C++.
For instance, ``Eigen3`` defines the target ``Eigen3::Eigen``.

At least until ``Crystal Clemmys`` target names are not supported in the ``ament_target_dependencies`` macro.
Sometimes it will be necessary to call the ``target_link_libaries`` CMake function.
In the example of Eigen3, the call should then look like

.. code-block:: cmake
find_package(Eigen3 REQUIRED)
target_link_libraries(my_target Eigen3::Eigen)
target_link_libraries(my_target PUBLIC Eigen3::Eigen)
This will also include necessary headers, libraries and their dependencies, but in contrast to ``ament_target_dependencies`` it might not correctly order the dependencies when using overlay workspaces.

Expand All @@ -130,48 +129,50 @@ Building a Library

When building a reusable library, some information needs to be exported for downstream packages to easily use it.

.. code-block:: cmake
First, install the headers files which should be available to clients.

ament_export_targets(my_libraryTargets HAS_LIBRARY_TARGET)
ament_export_dependencies(some_dependency)
.. code-block:: cmake
install(
DIRECTORY include/
DESTINATION include
DESTINATION include/${PROJECT_NAME}
)
Next, install the targets and create the export set ``export_${PROJECT_NAME}``.
The include directory is custom to support overlays in ``colcon``.

Add all the libraries for your project to the ``TARGETS`` argument.

.. code-block:: cmake
install(
TARGETS my_library
EXPORT my_libraryTargets
EXPORT export_${PROJECT_NAME}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(some_dependency)
Here, we assume that the folder ``include`` contains the headers which need to be exported.
Note that it is not necessary to put all headers into a separate folder, only those that should be included by clients.

Here is what's happening in the snippet above:

- The ``ament_export_targets`` macro exports the targets for CMake.
This is necessary to allow your library's clients to use the ``target_link_libraries(client my_library::my_library)`` syntax.
``ament_export_targets`` can take an arbitrary list of targets named as ``EXPORT`` in an install call and an additional option ``HAS_LIBRARY_TARGET``, which adds potential libraries to environment variables.
This is necessary to allow your library's clients to use the ``target_link_libraries(client PRIVATE my_library::my_library)`` syntax.
If the export set includes a library, add the option ``HAS_LIBRARY_TARGET`` to ``ament_export_targets``, which adds potential libraries to environment variables.

- The ``ament_export_dependencies`` exports dependencies to downstream packages.
This is necessary so that the user of the library does not have to call ``find_package`` for those dependencies, too.

- The first ``install`` commands installs the header files which should be available to clients.

.. warning::

Calling ``ament_export_targets``, ``ament_export_dependencies``, or other ament commands from a CMake subdirectory will not work as expected.
This is because the CMake subdirectory has no way of setting necessary variables in the parent scope where ``ament_package`` is called.

- The last large install command installs the library.
Archive and library files will be exported to the lib folder, runtime binaries will be installed to the bin folder and the path to installed headers is ``include``.

.. note::

Windows DLLs are treated as runtime artifacts and installed into the ``RUNTIME DESTINATION`` folder.
Expand Down

0 comments on commit 582f762

Please sign in to comment.