-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add rosidl_generator_cpp templates for actions (#312)
* Defined rosidl_generator_cpp templates for actions * Removed unneeded includes in action.hpp.em * Added logic bits for ActionSpecation * Fixed action.hpp.em template * Added support for action files in rosidl_generator_c * Updates parse_action_string() use case within rosidl_actions. * Recovering rosidl_generate_action_interfaces * Deduplicate action target names * call rosidl_generate_action_interfaces() * Pass package dependencies to action generation * Full action pipeline builds for C and C++ * Line length * Two blank lines between top level definitions * parse_action_string returns ActionSpecification * rosidl_generator_cpp creates CMake target instead of library for actions * rosidl_generator_c creates target for actions not library * Add builtin_interfaces dep * Fix more hardcoded stuff * msg and serv don't depend on action templates * Addressed peer review comments * Install visibility file * Macro to make sure _AMENT variables are set in global scope * Fix copy paste error in target name variable
- Loading branch information
1 parent
29c4a9f
commit 075fe35
Showing
17 changed files
with
701 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
rosidl_cmake/cmake/rosidl_generate_action_interfaces.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# Copyright 2018 Open Source Robotics Foundation, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# Generate Interfaces for Actions | ||
# | ||
# This executes the extension point ``rosidl_generate_action_interfaces``. | ||
# An extension of this type should expect a list of `.action` files and | ||
# generate new files in response. | ||
# Extensions should create a target that generates the files with the input | ||
# `.action` file as a dependency. | ||
# | ||
# :param target: the _name of the generation target, | ||
# specific generators might use the _name as a prefix for their own | ||
# generation step | ||
# :type target: string | ||
# :param ARGN: a list of include directories where each value might | ||
# be either an absolute path or path relative to the | ||
# CMAKE_INSTALL_PREFIX. | ||
# :type ARGN: list of strings | ||
# :param DEPENDENCY_PACKAGE_NAMES: Packages with interface files generation | ||
# should depend on | ||
# :type DEPENDENCY_PACKAGE_NAMES: list of strings | ||
# :param TARGET_DEPENDENCIES: cmake targets or files the generated target | ||
# should depend on | ||
# :type TARGET_DEPENDENCIES: list of strings | ||
# :param LIBRARY_NAME: the base name of the library, specific generators might | ||
# append their own suffix | ||
# :type LIBRARY_NAME: string | ||
# :param SKIP_INSTALL: if set skip installing the interface files | ||
# :type SKIP_INSTALL: option | ||
# :param ADD_LINTER_TESTS: if set lint the interface files using | ||
# the ``ament_lint`` package | ||
# :type ADD_LINTER_TESTS: option | ||
# | ||
# @public | ||
# | ||
macro(rosidl_generate_action_interfaces target) | ||
cmake_parse_arguments(_ARG_RGAI | ||
"ADD_LINTER_TESTS;SKIP_INSTALL" | ||
"LIBRARY_NAME" "TARGET_DEPENDENCIES" | ||
${ARGN}) | ||
if(NOT _ARG_RGAI_UNPARSED_ARGUMENTS) | ||
message(FATAL_ERROR "rosidl_generate_action_interfaces() called without any idl " | ||
"files") | ||
endif() | ||
|
||
set(_rgai_idl_files ${_ARG_RGAI_UNPARSED_ARGUMENTS}) | ||
|
||
# Create a custom target | ||
set(_rgai_sub_target "${target}+generate_action_interfaces") | ||
add_custom_target( | ||
${_rgai_sub_target} ALL | ||
DEPENDS | ||
${_rgai_idl_files} | ||
${_ARG_RGAI_TARGET_DEPENDENCIES} | ||
SOURCES | ||
${_rgai_idl_files} | ||
) | ||
|
||
# downstream packages need to depend on action_msgs for cancel and status messages | ||
list_append_unique(_ARG_RGAI_DEPENDENCY_PACKAGE_NAMES "action_msgs") | ||
# downstream packages need to depend on builtin_interfaces for builtin_interfaces/Time | ||
list_append_unique(_ARG_RGAI_DEPENDENCY_PACKAGE_NAMES "builtin_interfaces") | ||
ament_export_dependencies(action_msgs) | ||
ament_export_dependencies(builtin_interfaces) | ||
|
||
# A target name that generators may want to use to prefix their own target names | ||
set(rosidl_generate_action_interfaces_TARGET ${target}) | ||
# Give extensions a list of .action files to generate interfaces from | ||
set(rosidl_generate_action_interfaces_IDL_FILES ${_rgai_idl_files}) | ||
# TODO(sloretz) Where is LIBRARY_NAME used? | ||
set(rosidl_generate_action_interfaces_LIBRARY_NAME ${_ARG_RGAI_LIBRARY_NAME}) | ||
# If true the extension should not install anything it generates | ||
set(rosidl_generate_action_interfaces_SKIP_INSTALL ${_ARG_RGAI_SKIP_INSTALL}) | ||
# If true the extension should create tests for language specific linters | ||
set(rosidl_generate_action_interfaces_ADD_LINTER_TESTS ${_ARG_RGAI_ADD_LINTER_TESTS}) | ||
# Packages that generated code should depend on | ||
set(rosidl_generate_action_interfaces_DEPENDENCY_PACKAGE_NAMES ${_ARG_RGAI_DEPENDENCY_PACKAGE_NAMES}) | ||
ament_execute_extensions("rosidl_generate_action_interfaces") | ||
|
||
add_dependencies(${target} ${_rgai_sub_target}) | ||
endmacro() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
rosidl_generator_c/cmake/rosidl_generator_c_generate_action_interfaces.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
# Copyright 2018 Open Source Robotics Foundation, Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
set(_output_path | ||
"${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c/${PROJECT_NAME}") | ||
set(_generated_files "") | ||
|
||
foreach(_idl_file ${rosidl_generate_action_interfaces_IDL_FILES}) | ||
get_filename_component(_extension "${_idl_file}" EXT) | ||
get_filename_component(_parent_folder "${_idl_file}" DIRECTORY) | ||
get_filename_component(_parent_folder "${_parent_folder}" NAME) | ||
if(_extension STREQUAL ".action") | ||
set(_allowed_parent_folders "action") | ||
if(NOT _parent_folder IN_LIST _allowed_parent_folders) | ||
message(FATAL_ERROR "Interface file with unknown parent folder: ${_idl_file}") | ||
endif() | ||
else() | ||
message(FATAL_ERROR "Interface file with unknown extension: ${_idl_file}") | ||
endif() | ||
get_filename_component(_msg_name "${_idl_file}" NAME_WE) | ||
string_camel_case_to_lower_case_underscore("${_msg_name}" _header_name) | ||
list(APPEND _generated_files | ||
"${_output_path}/${_parent_folder}/${_header_name}.h" | ||
"${_output_path}/${_parent_folder}/${_header_name}__type_support.h" | ||
) | ||
endforeach() | ||
|
||
set(_dependency_files "") | ||
set(_dependencies "") | ||
foreach(_pkg_name ${rosidl_generate_action_interfaces_DEPENDENCY_PACKAGE_NAMES}) | ||
foreach(_idl_file ${${_pkg_name}_INTERFACE_FILES}) | ||
get_filename_component(_extension "${_idl_file}" EXT) | ||
if(_extension STREQUAL ".msg") | ||
set(_abs_idl_file "${${_pkg_name}_DIR}/../${_idl_file}") | ||
normalize_path(_abs_idl_file "${_abs_idl_file}") | ||
list(APPEND _dependency_files "${_abs_idl_file}") | ||
list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") | ||
endif() | ||
endforeach() | ||
endforeach() | ||
|
||
set(target_dependencies | ||
"${rosidl_generator_c_BIN}" | ||
${rosidl_generator_c_GENERATOR_FILES} | ||
"${rosidl_generator_c_TEMPLATE_DIR}/action.h.em" | ||
"${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.h.em" | ||
${rosidl_generate_action_interfaces_IDL_FILES} | ||
${_dependency_files}) | ||
foreach(dep ${target_dependencies}) | ||
if(NOT EXISTS "${dep}") | ||
get_property(is_generated SOURCE "${dep}" PROPERTY GENERATED) | ||
if(NOT ${_is_generated}) | ||
message(FATAL_ERROR "Target dependency '${dep}' does not exist") | ||
endif() | ||
endif() | ||
endforeach() | ||
|
||
set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__generate_action_interfaces__arguments.json") | ||
rosidl_write_generator_arguments( | ||
"${generator_arguments_file}" | ||
PACKAGE_NAME "${PROJECT_NAME}" | ||
ROS_INTERFACE_FILES "${rosidl_generate_action_interfaces_IDL_FILES}" | ||
ROS_INTERFACE_DEPENDENCIES "${_dependencies}" | ||
OUTPUT_DIR "${_output_path}" | ||
TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}" | ||
TARGET_DEPENDENCIES ${target_dependencies} | ||
) | ||
|
||
add_custom_command( | ||
OUTPUT ${_generated_files} | ||
COMMAND ${PYTHON_EXECUTABLE} ${rosidl_generator_c_BIN} | ||
--generator-arguments-file "${generator_arguments_file}" | ||
DEPENDS ${target_dependencies} | ||
COMMENT "Generating C++ type support dispatch for ROS interfaces" | ||
VERBATIM | ||
) | ||
|
||
# generate header to switch between export and import for a specific package | ||
set(_visibility_control_file | ||
"${_output_path}/action/rosidl_generator_c__visibility_control.h") | ||
string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UPPER) | ||
configure_file( | ||
"${rosidl_generator_c_TEMPLATE_DIR}/rosidl_generator_c__action_visibility_control.h.in" | ||
"${_visibility_control_file}" | ||
@ONLY | ||
) | ||
list(APPEND _generated_files ${_visibility_control_file}) | ||
|
||
set(_target_suffix "__c__actions") | ||
|
||
if(TARGET ${rosidl_generate_action_interfaces_TARGET}${_target_suffix}) | ||
message(WARNING "Custom target ${rosidl_generate_action_interfaces_TARGET}${_target_suffix} already exists") | ||
else() | ||
add_custom_target( | ||
${rosidl_generate_action_interfaces_TARGET}${_target_suffix} | ||
DEPENDS | ||
${_generated_files} | ||
) | ||
endif() | ||
|
||
add_dependencies( | ||
${rosidl_generate_action_interfaces_TARGET} | ||
${rosidl_generate_action_interfaces_TARGET}${_target_suffix} | ||
) | ||
|
||
if(NOT rosidl_generate_action_interfaces_SKIP_INSTALL) | ||
if(NOT _generated_files STREQUAL "") | ||
install( | ||
FILES ${_generated_files} | ||
DESTINATION "include/${PROJECT_NAME}/action" | ||
) | ||
endif() | ||
ament_export_include_directories(include) | ||
endif() | ||
|
||
if(BUILD_TESTING AND rosidl_generate_action_interfaces_ADD_LINTER_TESTS) | ||
if(NOT _generated_files STREQUAL "") | ||
find_package(ament_cmake_cppcheck REQUIRED) | ||
ament_cppcheck( | ||
TESTNAME "cppcheck_rosidl_generator_c_generate_action_interfaces" | ||
"${_output_path}") | ||
|
||
find_package(ament_cmake_cpplint REQUIRED) | ||
get_filename_component(_cpplint_root "${_output_path}" DIRECTORY) | ||
ament_cpplint( | ||
TESTNAME "cpplint_rosidl_generator_c_generate_action_interfaces" | ||
# the generated code might contain longer lines for templated types | ||
MAX_LINE_LENGTH 999 | ||
ROOT "${_cpplint_root}" | ||
"${_output_path}") | ||
|
||
find_package(ament_cmake_uncrustify REQUIRED) | ||
ament_uncrustify( | ||
TESTNAME "uncrustify_rosidl_generator_c_generate_action_interfaces" | ||
# the generated code might contain longer lines for templated types | ||
MAX_LINE_LENGTH 999 | ||
"${_output_path}") | ||
endif() | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// generated from rosidl_generator_c/resource/action.h.em | ||
// generated code does not contain a copyright notice | ||
|
||
@####################################################################### | ||
@# EmPy template for generating <action>.hp files | ||
@# | ||
@# Context: | ||
@# - spec (rosidl_parser.ActionSpecification) | ||
@# Parsed specification of the .action file | ||
@# - subfolder (string) | ||
@# The subfolder / subnamespace of the message, usually 'action' | ||
@# - get_header_filename_from_msg_name (function) | ||
@####################################################################### | ||
@ | ||
@{ | ||
header_guard_parts = [ | ||
spec.pkg_name, subfolder, | ||
get_header_filename_from_msg_name(spec.action_name) + '_h'] | ||
header_guard_variable = '__'.join([x.upper() for x in header_guard_parts]) + '_' | ||
}@ | ||
|
||
#ifndef @(header_guard_variable) | ||
#define @(header_guard_variable) | ||
|
||
#ifdef __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
|
||
#include <action_msgs/msg/goal_info.h> | ||
#include <action_msgs/msg/goal_status_array.h> | ||
#include <action_msgs/srv/cancel_goal.h> | ||
|
||
#include <@(spec.pkg_name)/@(subfolder)/@(get_header_filename_from_msg_name(spec.action_name))__feedback.h> | ||
#include <@(spec.pkg_name)/@(subfolder)/@(get_header_filename_from_msg_name(spec.action_name))__goal.h> | ||
#include <@(spec.pkg_name)/@(subfolder)/@(get_header_filename_from_msg_name(spec.action_name))__result.h> | ||
#include "@(spec.pkg_name)/@(subfolder)/@(get_header_filename_from_msg_name(spec.action_name))__type_support.h" | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // @(header_guard_variable) |
Oops, something went wrong.