documentation utilisateur ament_cmake

ament_cmake est le système de construction pour les packages basés sur CMake dans ROS 2 (en particulier, il sera utilisé pour la plupart sinon tous les projets C/C++). Il s’agit d’un ensemble de scripts améliorant CMake et ajoutant des fonctionnalités pratiques pour les auteurs de packages. Connaître les bases de CMake sera très utile, un tutoriel officiel peut être trouvé ici.

Bases

Un aperçu de base de CMake peut être produit en utilisant ros2 pkg create <package_name> sur la ligne de commande. Les informations de construction de base sont ensuite rassemblées dans deux fichiers : le package.xml et le CMakeLists.txt. Le package.xml doit contenir toutes les dépendances et un peu de métadonnées pour permettre à colcon de trouver le bon ordre de construction pour vos packages, d’installer les dépendances requises dans CI ainsi que de fournir les informations pour une version avec bloom ``. Le ``CMakeLists.txt contient les commandes pour construire et empaqueter les exécutables et les bibliothèques et sera l’objet principal de ce document.

Aperçu du projet de base

Le schéma de base du CMakeLists.txt d’un package ament contient :

cmake_minimum_required(VERSION 3.5)
project(my_project)

ament_package()

L’argument de project sera le nom du package et doit être identique au nom du package dans package.xml.

La configuration du projet est effectuée par ament_package() et cet appel doit se produire exactement une fois par package. ament_package() installe le package.xml, enregistre le paquet avec l’index ament et installe les fichiers de configuration (et éventuellement cible) pour CMake afin qu’il puisse être trouvé par d’autres paquets en utilisant find_package` `. Étant donné que ``ament_package() rassemble beaucoup d’informations à partir de CMakeLists.txt, il devrait être le dernier appel dans votre CMakeLists.txt. Bien qu’il soit possible de suivre les appels à ament_package() par des appels aux fonctions install copiant fichiers et répertoires, il est plus simple de garder ament_package() le dernier appel.

ament_package peut recevoir des arguments supplémentaires :

  • CONFIG_EXTRAS : une liste de fichiers CMake (modèles .cmake ou .cmake.in développés par configure_file()) qui devraient être disponibles pour les clients du paquet. Pour un exemple d’utilisation de ces arguments, consultez la discussion dans Ajout de ressources. Pour plus d’informations sur l’utilisation des fichiers modèles, consultez la documentation officielle.

  • CONFIG_EXTRAS_POST : identique à CONFIG_EXTRAS, mais l’ordre dans lequel les fichiers sont ajoutés diffère. Alors que les fichiers CONFIG_EXTRAS sont inclus avant les fichiers générés pour les appels ament_export_*, les fichiers de CONFIG_EXTRAS_POST sont inclus après.

Au lieu d’ajouter à ament_package, vous pouvez également ajouter à la variable ${PROJECT_NAME}_CONFIG_EXTRAS et ${PROJECT_NAME}_CONFIG_EXTRAS_POST avec le même effet. La seule différence est encore une fois l’ordre dans lequel les fichiers sont ajoutés avec l’ordre total suivant :

  • fichiers ajoutés par CONFIG_EXTRAS

  • fichiers ajoutés en ajoutant à ${PROJECT_NAME}_CONFIG_EXTRAS

  • fichiers ajoutés en ajoutant à ${PROJECT_NAME}_CONFIG_EXTRAS_POST

  • fichiers ajoutés par CONFIG_EXTRAS_POST

Ajout de fichiers et d’en-têtes

Il y a deux cibles principales à construire : les bibliothèques et les exécutables qui sont respectivement construits par add_library et add_executable.

Avec la séparation des fichiers d’en-tête et de l’implémentation en C/C++, il n’est pas toujours nécessaire d’ajouter les deux fichiers comme argument à add_library/add_executable.

La meilleure pratique suivante est proposée :

  • si vous construisez une bibliothèque, placez tous les en-têtes qui doivent être utilisables par les clients et doivent donc être installés dans un sous-répertoire du dossier include nommé comme le paquet, tandis que tous les autres fichiers (.c/.cpp` ` et les fichiers d'en-tête qui ne doivent pas être exportés) se trouvent dans le dossier ``src.

  • seuls les fichiers cpp sont explicitement référencés dans l’appel à add_library ou add_executable

  • permettre de trouver des en-têtes via

target_include_directories(my_target
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>)

Cela ajoute tous les fichiers du dossier ${CMAKE_CURRENT_SOURCE_DIR}/include à l’interface publique pendant la construction et tous les fichiers du dossier d’inclusion (par rapport à ${CMAKE_INSTALL_DIR}) lors de l’installation.

En principe, l’utilisation d’expressions de générateur ici n’est pas nécessaire si les deux dossiers sont appelés include et de niveau supérieur par rapport à ${CMAKE_CURRENT_SOURCE_DIR} et ${CMAKE_INSTALL_DIR}, mais c’est très courant .

Ajout de dépendances

Il existe deux façons de lier vos packages à une nouvelle dépendance.

La première méthode recommandée consiste à utiliser la macro ament ament_target_dependencies. Par exemple, supposons que nous voulions lier my_target à la bibliothèque d’algèbre linéaire Eigen3.

find_package(Eigen3 REQUIRED)
ament_target_dependencies(my_target Eigen3)

Il comprend les en-têtes et bibliothèques nécessaires et leurs dépendances pour être correctement trouvés par le projet. Cela garantira également que les répertoires d’inclusion de toutes les dépendances sont correctement ordonnés lors de l’utilisation d’espaces de travail superposés.

La deuxième façon est d’utiliser target_link_libraries.

La méthode recommandée dans CMake moderne consiste à n’utiliser que des cibles, à les exporter et à les lier. Les cibles CMake ont un espace de noms, similaire à C++. Par exemple, Eigen3 définit la cible Eigen3::Eigen.

Au moins jusqu’à ce que les noms de cible Crystal Clemmys ne soient pas pris en charge dans la macro ament_target_dependencies. Parfois, il sera nécessaire d’appeler la fonction CMake target_link_libaries. Dans l’exemple de Eigen3, l’appel devrait alors ressembler à

find_package(Eigen3 REQUIRED)
target_link_libraries(my_target Eigen3::Eigen)

Cela inclura également les en-têtes nécessaires, les bibliothèques et leurs dépendances, mais contrairement à ament_target_dependencies, il se peut que les dépendances ne soient pas correctement ordonnées lors de l’utilisation d’espaces de travail superposés.

Note

Il ne devrait jamais être nécessaire de find_package une bibliothèque qui n’est pas explicitement nécessaire mais qui est une dépendance d’une autre dépendance qui est explicitement nécessaire. Si tel est le cas, signalez un bogue sur le paquet correspondant.

Construire une bibliothèque

Lors de la création d’une bibliothèque réutilisable, certaines informations doivent être exportées pour que les packages en aval puissent les utiliser facilement.

ament_export_targets(my_libraryTargets HAS_LIBRARY_TARGET)
ament_export_dependencies(some_dependency)

install(
  DIRECTORY include/
  DESTINATION include
)

install(
  TARGETS my_library
  EXPORT my_libraryTargets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

Ici, nous supposons que le dossier include contient les en-têtes qui doivent être exportés. Notez qu’il n’est pas nécessaire de placer tous les en-têtes dans un dossier séparé, uniquement ceux qui doivent être inclus par les clients.

Voici ce qui se passe dans l’extrait ci-dessus :

  • La macro ament_export_targets exporte les cibles pour CMake. Ceci est nécessaire pour permettre aux clients de votre bibliothèque d’utiliser la syntaxe target_link_libraries(client my_library::my_library). ament_export_targets peut prendre une liste arbitraire de cibles nommées EXPORT dans un appel d’installation et une option supplémentaire HAS_LIBRARY_TARGET, qui ajoute des bibliothèques potentielles aux variables d’environnement.

  • Le ament_export_dependencies exporte les dépendances vers les packages en aval. Ceci est nécessaire pour que l’utilisateur de la bibliothèque n’ait pas à appeler find_package pour ces dépendances également.

  • La première commande install installe les fichiers d’en-tête qui devraient être disponibles pour les clients.

Avertissement

L’appel de ament_export_targets, ament_export_dependencies ou d’autres commandes ament à partir d’un sous-répertoire CMake ne fonctionnera pas comme prévu. C’est parce que le sous-répertoire CMake n’a aucun moyen de définir les variables nécessaires dans la portée parent où ament_package est appelé.

  • La dernière grande commande d’installation installe la bibliothèque. Les fichiers d’archive et de bibliothèque seront exportés vers le dossier lib, les binaires d’exécution seront installés dans le dossier bin et le chemin vers les en-têtes installés est include.

Note

Les DLL Windows sont traitées comme des artefacts d’exécution et installées dans le dossier RUNTIME DESTINATION. Il est donc conseillé de ne pas omettre l’installation RUNTIME même lors du développement de bibliothèques sur des systèmes basés sur Unix.

  • En ce qui concerne le include directory, la commande d’installation ajoute uniquement des informations à CMake, elle n’installe pas réellement le dossier includes. Ceci est fait en copiant les en-têtes via install(DIRECTORY <dir> DESTINATION <dest>) comme décrit ci-dessus.

  • La notation EXPORT de l’appel d’installation nécessite une attention supplémentaire : elle installe les fichiers CMake pour la cible my_library. Il est nommé exactement comme l’argument dans ament_export_targets et pourrait être nommé comme la bibliothèque. Cependant, cela empêchera alors d’utiliser la méthode ament_target_dependencies pour inclure votre bibliothèque. Pour permettre une flexibilité totale, il est conseillé de faire précéder la cible d’exportation avec quelque chose comme <target>Targets.

  • Tous les chemins d’installation sont relatifs à CMAKE_INSTALL_PREFIX, qui est déjà défini correctement par colcon/ament

Deux fonctions supplémentaires peuvent être utilisées mais sont superflues pour les installations basées sur la cible :

ament_export_include_directories(include)
ament_export_libraries(my_library)

La première macro marque le répertoire des répertoires d’inclusion exportés (ceci est réalisé par INCLUDES DESTINATION dans l’appel cible install). La deuxième macro marque l’emplacement de la bibliothèque installée (ceci est fait par l’argument HAS_LIBRARY_TARGET dans l’appel à ament_export_targets).

Certaines des macros peuvent prendre différents types d’arguments pour les exportations non ciblées, mais comme la méthode recommandée pour Make moderne consiste à utiliser des cibles, nous ne les aborderons pas ici. La documentation de ces options se trouve dans le code source lui-même.

Options du compilateur et de l’éditeur de liens

ROS 2 cible les compilateurs qui respectent les standards C++14 et C99 jusqu’au moins Crystal Clemmys. Des versions plus récentes pourraient être ciblées à l’avenir et sont référencées ici. Par conséquent, il est d’usage de définir les drapeaux CMake correspondants :

if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

Pour garder le code propre, les compilateurs doivent lancer des avertissements pour le code douteux et ces avertissements doivent être corrigés.

Il est recommandé de couvrir au moins les niveaux d’avertissement suivants :

  • Pour Visual Studio, les avertissements W1 par défaut sont conservés

  • Pour GCC et Clang : -Wall -Wextra -Wpedantic sont requis et -Wshadow -Werror sont conseillés (ce dernier fait des erreurs d’avertissement).

Bien que CMake moderne conseille d’ajouter des indicateurs de compilateur sur une base cible, c’est-à-dire d’appeler

target_compile_options(my_target PRIVATE -Wall)

il est actuellement recommandé d’utiliser la fonction au niveau du répertoire add_compile_options(-Wall) pour ne pas encombrer le code avec des options de compilation basées sur la cible pour tous les exécutables et les tests.

Créer des bibliothèques sous Windows

Étant donné que Linux, Mac et Windows sont tous des plates-formes officiellement prises en charge, pour avoir un impact maximal, tout package doit également être construit sur Windows. Le format de bibliothèque Windows applique la visibilité des symboles : chaque symbole qui doit être utilisé à partir d’un client doit être explicitement exporté par la bibliothèque (et les symboles de données doivent être implicitement importés).

Pour que cela reste compatible avec les builds Clang et GCC, il est conseillé d’utiliser la logique du wiki GCC. Pour l’utiliser pour un paquet appelé my_library :

target_compile_definitions(my_library PRIVATE "MY_LIBRARY_BUILDING_LIBRARY")

Pour plus de détails, voir Visibilité des symboles Windows dans le document Trucs et astuces Windows.

Test et peluchage

Afin de séparer les tests de la construction de la bibliothèque avec colcon, encapsulez tous les appels aux linters et aux tests dans une condition :

if(BUILD_TESTING)
  find_package(ament_cmake_gtest REQUIRED)
  ament_add_gtest(<tests>)
endif()

peluchage

Il est conseillé d’utiliser l’appel combiné de ament_lint_auto :

find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()

Cela exécutera les linters comme défini dans le package.xml. Il est recommandé d’utiliser l’ensemble de linters défini par le package ament_lint_common. Les linters individuels qui y sont inclus, ainsi que leurs fonctions, peuvent être vus dans les ament_lint_common docs.

Les linters fournis par ament peuvent également être ajoutés séparément, au lieu d’exécuter ament_lint_auto. Un exemple de la façon de procéder peut être trouvé dans la documentation ament_cmake_lint_cmake.

Essai

Ament contient des macros CMake pour simplifier la configuration des GTests. Appel:

find_package(ament_cmake_gtest)
ament_add_gtest(some_test <test_sources>)

pour ajouter un GTest. Il s’agit alors d’une cible régulière qui peut être liée à d’autres bibliothèques (comme la bibliothèque du projet). Les macros ont des paramètres supplémentaires :

  • APPEND_ENV : ajoute des variables d’environnement. Par exemple, vous pouvez ajouter au chemin du préfixe ament en appelant :

find_package(ament_cmake_gtest REQUIRED)
ament_add_gtest(some_test <test_sources>
  APPEND_ENV PATH=some/addtional/path/for/testing/resources)
  • APPEND_LIBRARY_DIRS : ajoute des bibliothèques afin qu’elles puissent être trouvées par l’éditeur de liens lors de l’exécution. Cela peut être réalisé en définissant des variables d’environnement telles que PATH sous Windows et LD_LIBRARY_PATH sous Linux, mais cela rend la plate-forme d’appel spécifique.

  • ENV : définit les variables d’environnement (même syntaxe que APPEND_ENV).

  • TIMEOUT : définissez un délai de test en secondes. La valeur par défaut pour les GTests est de 60 secondes. Par example:

ament_add_gtest(some_test <test_sources> TIMEOUT 120)
  • SKIP_TEST : saute ce test (sera affiché comme « réussi » dans la sortie de la console).

  • SKIP_LINKING_MAIN_LIBRARIES : ne pas lier avec GTest.

  • WORKING_DIRECTORY : définit le répertoire de travail pour le test.

Sinon, le répertoire de travail par défaut est le CMAKE_CURRENT_BINARY_DIR, qui est décrit dans la documentation CMake.

De même, il existe une macro CMake pour configurer GTest incluant GMock :

find_package(ament_cmake_gmock REQUIRED)
ament_add_gmock(some_test <test_sources>)

Il a les mêmes paramètres supplémentaires que ament_add_gtest.

Ament d’extension

Il est possible d’enregistrer des macros/fonctions supplémentaires avec ament_cmake et de l’étendre de plusieurs manières.

Ajouter une fonction/macro à ament

L’extension de ament signifie souvent que vous souhaitez que certaines fonctions soient disponibles pour d’autres packages. La meilleure façon de fournir la macro aux packages clients est de l’enregistrer avec ament.

Cela peut être fait en ajoutant la variable ${PROJECT_NAME}_CONFIG_EXTRAS, qui est utilisée par ament_package() via

list(APPEND ${PROJECT_NAME}_CONFIG_EXTRAS
  path/to/file.cmake"
  other/pathto/file.cmake"
)

Alternativement, vous pouvez directement ajouter les fichiers à l’appel ament_package() :

ament_package(CONFIG_EXTRAS
  path/to/file.cmake
  other/pathto/file.cmake
)

Ajout aux points d’extension

En plus des fichiers simples avec des fonctions pouvant être utilisées dans d’autres packages, vous pouvez également ajouter des extensions à ament. Ces extensions sont des scripts qui sont exécutés avec la fonction qui définit le point d’extension. Le cas d’utilisation le plus courant pour les extensions ament est probablement l’enregistrement des générateurs de messages rosidl : lors de l’écriture d’un générateur, vous souhaitez normalement générer tous les messages et services avec votre générateur également sans modifier le code des packages de définition de message/service. Ceci est possible en enregistrant le générateur en tant qu’extension de rosidl_generate_interfaces.

A titre d’exemple, voir

ament_register_extension(
  "rosidl_generate_interfaces"
  "rosidl_generator_cpp"
  "rosidl_generator_cpp_generate_interfaces.cmake")

qui enregistre la macro rosidl_generator_cpp_generate_interfaces.cmake pour le package rosidl_generator_cpp au point d’extension rosidl_generate_interfaces. Lorsque le point d’extension est exécuté, cela déclenchera l’exécution du script rosidl_generator_cpp_generate_interfaces.cmake ici. En particulier, cela appellera le générateur chaque fois que la fonction rosidl_generate_interfaces sera exécutée.

Le point d’extension le plus important pour les générateurs, mis à part rosidl_generate_interfaces, est ament_package, qui exécutera simplement des scripts avec l’appel ament_package(). Ce point d’extension est utile lors de l’enregistrement des ressources (voir ci-dessous).

ament_register_extension est une fonction qui prend exactement trois arguments :

  • extension_point : le nom du point d’extension (la plupart du temps, ce sera l’un des ament_package ou rosidl_generate_interfaces)

  • package_name : le nom du package contenant le fichier CMake (c’est-à-dire le nom du projet dans lequel le fichier est écrit)

  • cmake_filename : le fichier CMake exécuté lorsque le point d’extension est exécuté

Note

Il est possible de définir des points d’extension personnalisés de la même manière que ament_package et rosidl_generate_interfaces, mais cela ne devrait pas être nécessaire.

Ajout de points d’extension

Très rarement, il peut être intéressant de définir un nouveau point d’extension à ament.

Les points d’extension peuvent être enregistrés dans une macro afin que toutes les extensions soient exécutées lorsque la macro correspondante est appelée. Faire cela:

  • Définissez et documentez un nom pour votre extension (par exemple my_extension_point), qui est le nom passé à la macro ament_register_extension lors de l’utilisation du point d’extension.

  • Dans la macro/fonction qui doit exécuter l’appel des extensions :

ament_execute_extensions(my_extension_point)

Les extensions Ament fonctionnent en définissant une variable contenant le nom du point d’extension et en la remplissant avec les macros à exécuter. Lors de l’appel de ament_execute_extensions, les scripts définis dans la variable sont alors exécutés les uns après les autres.

Ajout de ressources

Surtout lors du développement de plugins ou de packages qui autorisent les plugins, il est souvent essentiel d’ajouter des ressources à un package ROS à partir d’un autre (par exemple, un plugin). Des exemples peuvent être des plugins pour des outils utilisant pluginlib.

Ceci peut être réalisé en utilisant l’indice d’ament (également appelé « indice de ressources »).

L’indice d’ament expliqué

Pour plus de détails sur la conception et les intentions, voir ici

En principe, l’index d’ament est contenu dans un dossier du dossier install/share de votre package. Il contient des sous-dossiers superficiels nommés d’après différents types de ressources. Au sein du sous-dossier, chaque package fournissant ladite ressource est référencé par son nom avec un « fichier marqueur ». Le fichier peut contenir tout contenu nécessaire pour obtenir les ressources, par ex. chemins relatifs vers les répertoires d’installation de la ressource, il peut aussi être simplement vide.

Pour donner un exemple, envisagez de fournir des plugins d’affichage pour RViz : Lorsque vous fournissez des plugins RViz dans un projet nommé my_rviz_displays qui sera lu par le pluginlib, vous fournirez un fichier plugin_description.xml, qui sera installé et utilisé par le pluginlib pour charger les plugins. Pour ce faire, le plugin_description.xml est enregistré en tant que ressource dans le resource_index via

pluginlib_export_plugin_description_file(rviz_common plugins_description.xml)

Lors de l’exécution de colcon build, cela installe un fichier my_rviz_displays dans un sous-dossier rviz_common__pluginlib__plugin dans le resource_index. Les fabriques de plugins de rviz_common sauront rassembler des informations à partir de tous les dossiers nommés rviz_common__pluginlib__plugin pour les packages qui exportent des plugins. Le fichier marqueur pour les fabriques pluginlib contient un chemin relatif du dossier d’installation vers le fichier plugins_description.xml (et le nom de la bibliothèque comme nom de fichier marqueur). Avec ces informations, le pluginlib peut charger la bibliothèque et savoir quels plugins charger à partir du fichier plugin_description.xml.

Comme deuxième exemple, envisagez la possibilité de laisser vos propres plugins RViz utiliser vos propres maillages personnalisés. Les maillages sont chargés au démarrage afin que le propriétaire du plugin n’ait pas à s’en occuper, mais cela implique que RViz doit connaître les maillages. Pour cela, RViz propose une fonction :

register_rviz_ogre_media_exports(DIRECTORIES <my_dirs>)

Cela enregistre les répertoires en tant que ressource ogre_media dans l’index ament. En bref, il installe un fichier nommé d’après le projet qui appelle la fonction dans un sous-dossier appelé rviz_ogre_media_exports. Le fichier contient les chemins relatifs du dossier d’installation vers les répertoires répertoriés dans les macros. Au démarrage, RViz peut désormais rechercher tous les dossiers appelés rviz_ogre_media_exports et charger les ressources dans tous les dossiers fournis. Ces recherches sont effectuées à l’aide de ament_index_cpp (ou ament_index_py pour les packages Python).

Dans les sections suivantes, nous explorerons comment ajouter vos propres ressources à l’index d’ament et fournirons les meilleures pratiques pour le faire.

Interrogation de l’index d’ament

Si nécessaire, il est possible d’interroger l’index d’ament pour les ressources via CMake. Pour cela, trois fonctions :

ament_index_has_resource : obtenez un chemin de préfixe vers la ressource si elle existe avec les paramètres suivants :

  • var : le paramètre de sortie : remplissez cette variable avec FALSE si la ressource n’existe pas ou le préfixe du chemin vers la ressource sinon

  • resource_type : le type de la ressource (par exemple, rviz_common__pluginlib__plugin)

  • resource_name : le nom de la ressource qui correspond généralement au nom du package ayant ajouté la ressource de type resource_type (par exemple, rviz_default_plugins)

ament_index_get_resource : obtient le contenu d’une ressource spécifique, c’est-à-dire le contenu du fichier marqueur dans l’index d’ament.

  • var : le paramètre de sortie : rempli avec le contenu du fichier marqueur de ressource s’il existe.

  • resource_type : le type de la ressource (par exemple, rviz_common__pluginlib__plugin)

  • resource_name : le nom de la ressource qui correspond généralement au nom du package ayant ajouté la ressource de type resource_type (par exemple, rviz_default_plugins)

  • PREFIX_PATH : Le chemin du préfixe à rechercher (généralement, le ament_index_get_prefix_path() par défaut suffira).

Notez que ament_index_get_resource générera une erreur si la ressource n’existe pas, il peut donc être nécessaire de vérifier en utilisant ament_index_has_resource.

ament_index_get_resources : récupère tous les packages qui ont enregistré des ressources d’un type spécifique à partir de l’index

  • var : Paramètre de sortie : rempli avec une liste de noms de tous les packages qui ont enregistré une ressource de type_ressource

  • resource_type : le type de la ressource (par exemple, rviz_common__pluginlib__plugin)

  • PREFIX_PATH : Le chemin du préfixe à rechercher (généralement, le ament_index_get_prefix_path() par défaut suffira).

Ajout à l’index des aments

La définition d’une ressource nécessite deux informations :

  • un nom pour la ressource qui doit être unique,

  • une mise en page du fichier marqueur, qui peut être n’importe quoi et peut aussi être vide (c’est vrai par exemple pour la ressource « package » marquant un package ROS 2)

Pour la ressource de maillage RViz, les choix correspondants étaient :

  • rviz_ogre_media_exports comme nom de la ressource,

  • chemin d’installation chemins relatifs vers tous les dossiers contenant des ressources. Cela vous permettra déjà d’écrire la logique d’utilisation de la ressource correspondante dans votre package.

Pour permettre aux utilisateurs d’enregistrer facilement des ressources pour votre package, vous devez en outre fournir des macros ou des fonctions telles que la fonction pluginlib ou la fonction rviz_ogre_media_exports.

Pour enregistrer une ressource, utilisez la fonction ament ament_index_register_resource. Cela créera et installera les fichiers marqueurs dans le fichier resource_index. Par exemple, l’appel correspondant pour rviz_ogre_media_exports est le suivant :

ament_index_register_resource(rviz_ogre_media_exports CONTENT ${OGRE_MEDIA_RESOURCE_FILE})

Cela installe un fichier nommé comme ${PROJECT_NAME} dans un dossier rviz_ogre_media_exports dans le resource_index avec le contenu donné par la variable ${OGRE_MEDIA_RESOURCE_FILE}. La macro a un certain nombre de paramètres qui peuvent être utiles :

  • le premier paramètre (sans nom) est le nom de la ressource, qui équivaut au nom du dossier dans le resource_index

  • CONTENT : Le contenu du fichier marqueur sous forme de chaîne. Il peut s’agir d’une liste de chemins relatifs, etc. CONTENT ne peut pas être utilisé avec CONTENT_FILE.

  • CONTENT_FILE : Le chemin vers un fichier qui sera utilisé pour créer le fichier marqueur. Le fichier peut être un fichier simple ou un fichier modèle développé avec configure_file(). CONTENT_FILE ne peut pas être utilisé avec CONTENT.

  • PACKAGE_NAME : le nom du package/de la bibliothèque exportant la ressource, qui correspond au nom du fichier marqueur. La valeur par défaut est ${PROJECT_NAME}.

  • AMENT_INDEX_BINARY_DIR : Le chemin de base de l’index d’ament généré. Sauf si vraiment nécessaire, utilisez toujours la valeur par défaut ${CMAKE_BINARY_DIR}/ament_cmake_index.

  • SKIP_INSTALL : ignore l’installation du fichier marqueur.

Puisqu’il n’existe qu’un seul fichier marqueur par package, c’est généralement un problème si la fonction/macro CMake est appelée deux fois par le même projet. Cependant, pour les grands projets, il peut être préférable de diviser les appels enregistrant les ressources.

Par conséquent, il est préférable de laisser une macro enregistrant une ressource telle que register_rviz_ogre_media_exports.cmake ne remplir que certaines variables. Le véritable appel à ament_index_register_resource peut alors être ajouté dans une extension ament à ament_package. Puisqu’il ne doit y avoir qu’un seul appel à ament_package par projet, il n’y aura toujours qu’un seul endroit où la ressource sera enregistrée. Dans le cas de rviz_ogre_media_exports cela revient à la stratégie suivante :

  • La macro register_rviz_ogre_media_exports prend une liste de dossiers et les ajoute à une variable appelée OGRE_MEDIA_RESOURCE_FILE.

  • Une autre macro appelée register_rviz_ogre_media_exports_hook appelle ament_index_register_resource si ${OGRE_MEDIA_RESOURCE_FILE} n’est pas vide.

  • Le fichier register_rviz_ogre_media_exports_hook.cmake est enregistré en tant qu’extension ament dans un troisième fichier register_rviz_ogre_media_exports_hook-extras.cmake via l’appel

ament_register_extension("ament_package" "rviz_rendering"
  "register_rviz_ogre_media_exports_hook.cmake")
  • Les fichiers register_rviz_ogre_media_exports.cmake et register_rviz_ogre_media_exports_hook-extra.cmake sont enregistrés en tant que CONFIG_EXTRA avec ament_package().