Skip to content

Commit 8b7c7a1

Browse files
add API Version Management under Ament CMake page. (#6116) (#6119)
(cherry picked from commit d40b914) Signed-off-by: Tomoya.Fujita <[email protected]> Co-authored-by: Tomoya Fujita <[email protected]>
1 parent 48cbc78 commit 8b7c7a1

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
@@ -671,3 +671,95 @@ Once added, you can register them using the ament_environment_hooks function in
671671
)
672672
673673
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>`__.
674+
675+
API Version Management
676+
----------------------
677+
678+
ROS 2 provides automatic version header generation through ``ament_generate_version_header``, which creates compile-time macros for API versioning and feature detection.
679+
This is particularly useful for maintaining backward compatibility and conditionally enabling features based on library versions.
680+
681+
.. note::
682+
683+
The ``ament_generate_version_header`` functionality is designed for C, C++, and other C-based languages only.
684+
It generates C/C++ header files with preprocessor macros and is not applicable to Python or other non-C-based packages.
685+
686+
Understanding auto-generated version macros
687+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
688+
689+
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.
690+
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.
691+
692+
The generated version macros follow this naming convention:
693+
694+
- ``<PACKAGE_NAME>_VERSION_MAJOR``: Major version number
695+
- ``<PACKAGE_NAME>_VERSION_MINOR``: Minor version number
696+
- ``<PACKAGE_NAME>_VERSION_PATCH``: Patch version number
697+
- ``<PACKAGE_NAME>_VERSION``: Combined version as a single integer (major * 10000 + minor * 100 + patch)
698+
- ``<PACKAGE_NAME>_VERSION_STR``: String representation of the version (e.g., "1.2.3")
699+
- ``<PACKAGE_NAME>_VERSION_GTE(major, minor, patch)``: Macro to check if version is greater than or equal to specified version
700+
701+
For example, ``rclcpp`` provides macros like:
702+
703+
- ``RCLCPP_VERSION_MAJOR``
704+
- ``RCLCPP_VERSION_MINOR``
705+
- ``RCLCPP_VERSION_PATCH``
706+
- ``RCLCPP_VERSION``
707+
- ``RCLCPP_VERSION_STR``
708+
- ``RCLCPP_VERSION_GTE(major, minor, patch)``
709+
710+
Generating version headers for your package
711+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
712+
713+
To generate version headers for your own package, add the following to your ``CMakeLists.txt``:
714+
715+
.. code-block:: cmake
716+
717+
find_package(ament_cmake_gen_version_h REQUIRED)
718+
ament_generate_version_header(my_library)
719+
720+
This generates a header file at ``<build_dir>/my_library/version.h`` that can be included in your code:
721+
722+
.. code-block:: cpp
723+
724+
#include "my_library/version.h"
725+
726+
The version information is automatically extracted from the ``<version>`` tag in your ``package.xml``.
727+
728+
By default, the generated header file is placed in the build directory under ``<package_name>/version.h``.
729+
You can customize the output location:
730+
731+
.. code-block:: cmake
732+
733+
ament_generate_version_header(my_library HEADER_PATH "my_library/my_version.h")
734+
735+
Using version macros for API negotiation
736+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
737+
738+
Version macros enable runtime and compile-time feature detection, which is essential for writing portable code across different ROS 2 distributions.
739+
740+
While ROS 2 guarantees ABI (Application Binary Interface) compatibility within the same distribution, new interfaces and features can be backported.
741+
This means that within a single distribution, different API versions may be available depending on which patch release is installed.
742+
Version macros allow developers to check if a specific feature is available before using it.
743+
744+
Example: Version checking
745+
~~~~~~~~~~~~~~~~~~~~~~~~~
746+
747+
.. code-block:: cpp
748+
749+
#include "rclcpp/version.h"
750+
751+
// Check if new feature is available
752+
#if RCLCPP_VERSION_GTE(28, 3, 0)
753+
use_new_api_with_feature();
754+
#else
755+
use_old_api_without_feature();
756+
#endif
757+
758+
Best practices
759+
~~~~~~~~~~~~~~
760+
761+
- **Check before using new features**: Always use version macros when utilizing features that may not be available in older versions of a library.
762+
- **Provide fallback implementations**: When possible, provide alternative implementations for older API versions to maintain backward compatibility.
763+
- **Document version requirements**: Clearly document the minimum required versions for specific features in your package documentation.
764+
- **Test across versions**: If your package needs to support multiple ROS 2 distributions, test it against the minimum supported version.
765+
- **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)