Skip to content

Commit b2a1783

Browse files
add API Version Management under Ament CMake page. (#6116) (#6117)
(cherry picked from commit d40b914) Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com> Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
1 parent f67e8e0 commit b2a1783

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

source/How-To-Guides/Ament-CMake-Documentation.rst

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,3 +654,95 @@ Once added, you can register them using the ament_environment_hooks function in
654654
)
655655
656656
Another example of using environment hooks for Gazebo plugin paths can be found in the official `ros_gz_project_template <https://github.com/gazebosim/ros_gz_project_template/tree/main/ros_gz_example_gazebo/hooks>`__.
657+
658+
API Version Management
659+
----------------------
660+
661+
ROS 2 provides automatic version header generation through ``ament_generate_version_header``, which creates compile-time macros for API versioning and feature detection.
662+
This is particularly useful for maintaining backward compatibility and conditionally enabling features based on library versions.
663+
664+
.. note::
665+
666+
The ``ament_generate_version_header`` functionality is designed for C, C++, and other C-based languages only.
667+
It generates C/C++ header files with preprocessor macros and is not applicable to Python or other non-C-based packages.
668+
669+
Understanding auto-generated version macros
670+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
671+
672+
Many ROS 2 C/C++ packages (such as ``rclcpp``, ``rcl``, and ``rmw``) automatically generate version header files containing macros that expose the library's version information.
673+
These version headers are generated from the ``package.xml`` file using the `ament_generate_version_header.cmake <https://github.com/ament/ament_cmake/blob/${ROS_DISTRO}/ament_cmake_gen_version_h/cmake/ament_generate_version_header.cmake>`__ script.
674+
675+
The generated version macros follow this naming convention:
676+
677+
- ``<PACKAGE_NAME>_VERSION_MAJOR``: Major version number
678+
- ``<PACKAGE_NAME>_VERSION_MINOR``: Minor version number
679+
- ``<PACKAGE_NAME>_VERSION_PATCH``: Patch version number
680+
- ``<PACKAGE_NAME>_VERSION``: Combined version as a single integer (major * 10000 + minor * 100 + patch)
681+
- ``<PACKAGE_NAME>_VERSION_STR``: String representation of the version (e.g., "1.2.3")
682+
- ``<PACKAGE_NAME>_VERSION_GTE(major, minor, patch)``: Macro to check if version is greater than or equal to specified version
683+
684+
For example, ``rclcpp`` provides macros like:
685+
686+
- ``RCLCPP_VERSION_MAJOR``
687+
- ``RCLCPP_VERSION_MINOR``
688+
- ``RCLCPP_VERSION_PATCH``
689+
- ``RCLCPP_VERSION``
690+
- ``RCLCPP_VERSION_STR``
691+
- ``RCLCPP_VERSION_GTE(major, minor, patch)``
692+
693+
Generating version headers for your package
694+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
695+
696+
To generate version headers for your own package, add the following to your ``CMakeLists.txt``:
697+
698+
.. code-block:: cmake
699+
700+
find_package(ament_cmake_gen_version_h REQUIRED)
701+
ament_generate_version_header(my_library)
702+
703+
This generates a header file at ``<build_dir>/my_library/version.h`` that can be included in your code:
704+
705+
.. code-block:: cpp
706+
707+
#include "my_library/version.h"
708+
709+
The version information is automatically extracted from the ``<version>`` tag in your ``package.xml``.
710+
711+
By default, the generated header file is placed in the build directory under ``<package_name>/version.h``.
712+
You can customize the output location:
713+
714+
.. code-block:: cmake
715+
716+
ament_generate_version_header(my_library HEADER_PATH "my_library/my_version.h")
717+
718+
Using version macros for API negotiation
719+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
720+
721+
Version macros enable runtime and compile-time feature detection, which is essential for writing portable code across different ROS 2 distributions.
722+
723+
While ROS 2 guarantees ABI (Application Binary Interface) compatibility within the same distribution, new interfaces and features can be backported.
724+
This means that within a single distribution, different API versions may be available depending on which patch release is installed.
725+
Version macros allow developers to check if a specific feature is available before using it.
726+
727+
Example: Version checking
728+
~~~~~~~~~~~~~~~~~~~~~~~~~
729+
730+
.. code-block:: cpp
731+
732+
#include "rclcpp/version.h"
733+
734+
// Check if new feature is available
735+
#if RCLCPP_VERSION_GTE(28, 3, 0)
736+
use_new_api_with_feature();
737+
#else
738+
use_old_api_without_feature();
739+
#endif
740+
741+
Best practices
742+
~~~~~~~~~~~~~~
743+
744+
- **Check before using new features**: Always use version macros when utilizing features that may not be available in older versions of a library.
745+
- **Provide fallback implementations**: When possible, provide alternative implementations for older API versions to maintain backward compatibility.
746+
- **Document version requirements**: Clearly document the minimum required versions for specific features in your package documentation.
747+
- **Test across versions**: If your package needs to support multiple ROS 2 distributions, test it against the minimum supported version.
748+
- **Use the GTE macro**: Prefer using the ``_VERSION_GTE(major, minor, patch)`` macro for version comparisons, as it provides a cleaner and more readable syntax than manually comparing individual version components.

0 commit comments

Comments
 (0)