From 39399503390dbf469aa4e7e51bbc23581b730190 Mon Sep 17 00:00:00 2001 From: Daniel Mesham Date: Wed, 27 Sep 2023 10:07:08 +0200 Subject: [PATCH] Reduce repeated template parsing to speed up builds * Separate writing arguments files from the builds of each generator or type support target. * Write all arguments files first, before generating files. * Generate all files for each IDL template at once, avoiding repeated template parsing. Signed-off-by: Daniel Mesham --- rosidl_cmake/CMakeLists.txt | 8 ++ .../bin/rosidl_cmake_generate_interfaces | 40 ++++++ .../cmake/rosidl_generate_interfaces.cmake | 20 ++- .../rosidl_write_additional_context.cmake | 105 ++++++++++++++++ .../rosidl_write_generator_arguments.cmake | 8 +- rosidl_cmake/rosidl_cmake-extras.cmake | 1 + rosidl_generator_c/CMakeLists.txt | 4 - rosidl_generator_c/bin/rosidl_generator_c | 42 ------- rosidl_generator_c/cmake/register_c.cmake | 12 +- ...sidl_generator_c_generate_interfaces.cmake | 38 +----- .../rosidl_generator_c_write_arguments.cmake | 86 +++++++++++++ .../rosidl_generator_c-extras.cmake.in | 1 - .../rosidl_generator_c/__init__.py | 14 ++- rosidl_generator_cpp/CMakeLists.txt | 4 - rosidl_generator_cpp/bin/rosidl_generator_cpp | 38 ------ rosidl_generator_cpp/cmake/register_cpp.cmake | 12 +- ...dl_generator_cpp_generate_interfaces.cmake | 64 +--------- ...rosidl_generator_cpp_write_arguments.cmake | 68 +++++++++++ .../rosidl_generator_cpp-extras.cmake.in | 1 - .../rosidl_generator_cpp/__init__.py | 13 +- ...type_description_generate_interfaces.cmake | 24 ++-- ...generator_type_description-extras.cmake.in | 2 +- rosidl_pycommon/rosidl_pycommon/__init__.py | 114 +++++++++++++++++- .../rosidl_pycommon/generator_config.py | 84 +++++++++++++ .../CMakeLists.txt | 4 - .../bin/rosidl_typesupport_introspection_c | 31 ----- ..._introspection_c_generate_interfaces.cmake | 50 +------- ...port_introspection_c_write_arguments.cmake | 56 +++++++++ ...ypesupport_introspection_c-extras.cmake.in | 11 +- .../__init__.py | 16 ++- .../CMakeLists.txt | 4 - .../bin/rosidl_typesupport_introspection_cpp | 31 ----- ...ntrospection_cpp_generate_interfaces.cmake | 52 +------- ...rt_introspection_cpp_write_arguments.cmake | 57 +++++++++ ...esupport_introspection_cpp-extras.cmake.in | 10 +- .../__init__.py | 16 ++- 36 files changed, 730 insertions(+), 411 deletions(-) create mode 100644 rosidl_cmake/bin/rosidl_cmake_generate_interfaces create mode 100644 rosidl_cmake/cmake/rosidl_write_additional_context.cmake delete mode 100755 rosidl_generator_c/bin/rosidl_generator_c create mode 100644 rosidl_generator_c/cmake/rosidl_generator_c_write_arguments.cmake delete mode 100755 rosidl_generator_cpp/bin/rosidl_generator_cpp create mode 100644 rosidl_generator_cpp/cmake/rosidl_generator_cpp_write_arguments.cmake create mode 100644 rosidl_pycommon/rosidl_pycommon/generator_config.py delete mode 100755 rosidl_typesupport_introspection_c/bin/rosidl_typesupport_introspection_c create mode 100644 rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_write_arguments.cmake delete mode 100755 rosidl_typesupport_introspection_cpp/bin/rosidl_typesupport_introspection_cpp create mode 100644 rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_write_arguments.cmake diff --git a/rosidl_cmake/CMakeLists.txt b/rosidl_cmake/CMakeLists.txt index 89ee21ad6..16a239693 100644 --- a/rosidl_cmake/CMakeLists.txt +++ b/rosidl_cmake/CMakeLists.txt @@ -7,6 +7,9 @@ find_package(ament_cmake_python REQUIRED) ament_python_install_package(${PROJECT_NAME}) +set(rosidl_cmake_generate_interfaces_BIN "${CMAKE_CURRENT_SOURCE_DIR}/bin/rosidl_cmake_generate_interfaces") +normalize_path(rosidl_cmake_generate_interfaces_BIN "${rosidl_cmake_generate_interfaces_BIN}") + if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() @@ -16,6 +19,11 @@ ament_package( CONFIG_EXTRAS "rosidl_cmake-extras.cmake" ) +install( + PROGRAMS bin/rosidl_cmake_generate_interfaces + DESTINATION lib/rosidl_cmake +) + install( DIRECTORY cmake DESTINATION share/${PROJECT_NAME} diff --git a/rosidl_cmake/bin/rosidl_cmake_generate_interfaces b/rosidl_cmake/bin/rosidl_cmake_generate_interfaces new file mode 100644 index 000000000..0f2da0631 --- /dev/null +++ b/rosidl_cmake/bin/rosidl_cmake_generate_interfaces @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys + +try: + from rosidl_pycommon import generate_files_from_arguments_files +except ImportError: + # modifying sys.path and importing the Python package with the same + # name as this script does not work on Windows + rosidl_pycommon_root = os.path.dirname(os.path.dirname(__file__)) + rosidl_pycommon_module = os.path.join( + rosidl_pycommon_root, 'rosidl_pycommon', '__init__.py') + if not os.path.exists(rosidl_pycommon_module): + raise + from importlib.machinery import SourceFileLoader + + loader = SourceFileLoader('rosidl_pycommon', rosidl_pycommon_module) + rosidl_pycommon = loader.load_module() + generate_files_from_arguments_files = rosidl_pycommon.generate_files_from_arguments_files + + +def main(argv=sys.argv[1:]): + parser = argparse.ArgumentParser( + description='Generate the ROS interfaces.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument( + '--generator-arguments-files', + required=True, + help='The location of the files containing the generator arguments') + args = parser.parse_args(argv) + + print(args.generator_arguments_files) + + generate_files_from_arguments_files(args.generator_arguments_files) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake b/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake index f491ef7ea..5ced5dd58 100644 --- a/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake +++ b/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -277,6 +277,24 @@ macro(rosidl_generate_interfaces target) list(APPEND rosidl_generate_interfaces_ABS_IDL_FILES "${_abs_idl_file}") endforeach() + # Create the type descriptions for use when writing the generator arguments files + ament_execute_extensions("rosidl_create_type_descriptions_extensions") + + # Write the generator argument files for all registered languages and type supports + set(rosidl_generator_arguments_files) + ament_execute_extensions("rosidl_write_generator_arguments_extensions") + + find_package(Python3 REQUIRED COMPONENTS Interpreter) + + # Generate the interface source files for all registered languages and type supports + set(rosidl_cmake_generate_interfaces_BIN "${rosidl_cmake_DIR}/../../../lib/rosidl_cmake/rosidl_cmake_generate_interfaces") + execute_process( + COMMAND ${Python3_EXECUTABLE} ${rosidl_cmake_generate_interfaces_BIN} + --generator-arguments-files "${rosidl_generator_arguments_files}" + ECHO_OUTPUT_VARIABLE + ) + + # Build the interfaces from the generated files ament_execute_extensions("rosidl_generate_idl_interfaces") # check for extensions registered with the previous extension point diff --git a/rosidl_cmake/cmake/rosidl_write_additional_context.cmake b/rosidl_cmake/cmake/rosidl_write_additional_context.cmake new file mode 100644 index 000000000..6cf3ed6b4 --- /dev/null +++ b/rosidl_cmake/cmake/rosidl_write_additional_context.cmake @@ -0,0 +1,105 @@ +# Copyright 2023 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 a JSON / YAML file containing additional context data for expanding +# IDL templates +# +# +# @public +# +function(rosidl_write_additional_context output_file) + + set(OPTIONAL_ONE_VALUE_KEYWORDS + "DISABLE_DESCRIPTION_CODEGEN") + set(OPTIONAL_MULTI_VALUE_KEYWORDS + "TYPE_SUPPORTS") + + cmake_parse_arguments( + ARG + "" + "${OPTIONAL_ONE_VALUE_KEYWORDS}" + "${OPTIONAL_MULTI_VALUE_KEYWORDS}" + ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "rosidl_write_additional_context() called with unused " + "arguments: ${ARG_UNPARSED_ARGUMENTS}") + endif() + + # create folder + get_filename_component(output_path "${output_file}" PATH) + file(MAKE_DIRECTORY "${output_path}") + + # open object + file(WRITE "${output_file}" + "{") + + set(first_element TRUE) + + # write string values + foreach(one_value_argument ${OPTIONAL_ONE_VALUE_KEYWORDS}) + if(DEFINED ARG_${one_value_argument}) + # write conditional comma and mandatory newline + if(NOT first_element) + file(APPEND "${output_file}" ",") + else() + set(first_element FALSE) + endif() + file(APPEND "${output_file}" "\n") + + string(TOLOWER "${one_value_argument}" key) + string(REPLACE "\\" "\\\\" value "${ARG_${one_value_argument}}") + file(APPEND "${output_file}" + " \"${key}\": \"${value}\"") + endif() + endforeach() + + # write array values + foreach(multi_value_argument ${OPTIONAL_MULTI_VALUE_KEYWORDS}) + if(ARG_${multi_value_argument}) + # write conditional comma and mandatory newline and indentation + if(NOT first_element) + file(APPEND "${output_file}" ",") + else() + set(first_element FALSE) + endif() + file(APPEND "${output_file}" "\n") + + # write key, open array + string(TOLOWER "${multi_value_argument}" key) + file(APPEND "${output_file}" + " \"${key}\": [\n") + + # write array values, last without trailing colon + list(GET ARG_${multi_value_argument} -1 last_value) + list(REMOVE_AT ARG_${multi_value_argument} -1) + foreach(value ${ARG_${multi_value_argument}}) + string(REPLACE "\\" "\\\\" value "${value}") + file(APPEND "${output_file}" + " \"${value}\",\n") + endforeach() + string(REPLACE "\\" "\\\\" last_value "${last_value}") + file(APPEND "${output_file}" + " \"${last_value}\"\n") + + # close array + file(APPEND "${output_file}" + " ]") + endif() + endforeach() + + # close object + file(APPEND "${output_file}" + "\n}\n") +endfunction() diff --git a/rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake b/rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake index bc289d0b4..34510603c 100644 --- a/rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake +++ b/rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake @@ -1,4 +1,4 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. +# Copyright 2023 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. @@ -23,12 +23,14 @@ function(rosidl_write_generator_arguments output_file) "PACKAGE_NAME") set(OPTIONAL_ONE_VALUE_KEYWORDS "OUTPUT_DIR" - "TEMPLATE_DIR") + "TEMPLATE_DIR" + "ADDITIONAL_CONTEXT_FILE") set(REQUIRED_MULTI_VALUE_KEYWORDS # only require one of them "IDL_TUPLES" "NON_IDL_TUPLES" - "ROS_INTERFACE_FILES") + "ROS_INTERFACE_FILES" + "GENERATOR_FILES") set(OPTIONAL_MULTI_VALUE_KEYWORDS "ROS_INTERFACE_DEPENDENCIES" # since the dependencies can be empty "TARGET_DEPENDENCIES" diff --git a/rosidl_cmake/rosidl_cmake-extras.cmake b/rosidl_cmake/rosidl_cmake-extras.cmake index 1ebda4e89..808091650 100644 --- a/rosidl_cmake/rosidl_cmake-extras.cmake +++ b/rosidl_cmake/rosidl_cmake-extras.cmake @@ -32,6 +32,7 @@ find_package(rosidl_adapter) # not required, being used when available include("${rosidl_cmake_DIR}/rosidl_generate_interfaces.cmake") include("${rosidl_cmake_DIR}/rosidl_get_typesupport_target.cmake") include("${rosidl_cmake_DIR}/rosidl_target_interfaces.cmake") +include("${rosidl_cmake_DIR}/rosidl_write_additional_context.cmake") include("${rosidl_cmake_DIR}/rosidl_write_generator_arguments.cmake") include("${rosidl_cmake_DIR}/string_camel_case_to_lower_case_underscore.cmake") diff --git a/rosidl_generator_c/CMakeLists.txt b/rosidl_generator_c/CMakeLists.txt index 15e72d29e..c33ba2ad2 100644 --- a/rosidl_generator_c/CMakeLists.txt +++ b/rosidl_generator_c/CMakeLists.txt @@ -34,10 +34,6 @@ ament_package( CONFIG_EXTRAS "rosidl_generator_c-extras.cmake.in" ) -install( - PROGRAMS bin/rosidl_generator_c - DESTINATION lib/rosidl_generator_c -) install( DIRECTORY cmake resource DESTINATION share/${PROJECT_NAME} diff --git a/rosidl_generator_c/bin/rosidl_generator_c b/rosidl_generator_c/bin/rosidl_generator_c deleted file mode 100755 index e1d45678a..000000000 --- a/rosidl_generator_c/bin/rosidl_generator_c +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys - -try: - from rosidl_generator_c import generate_c -except ImportError: - # modifying sys.path and importing the Python package with the same - # name as this script does not work on Windows - rosidl_generator_c_root = os.path.dirname(os.path.dirname(__file__)) - rosidl_generator_c_module = os.path.join( - rosidl_generator_c_root, 'rosidl_generator_c', '__init__.py') - if not os.path.exists(rosidl_generator_c_module): - raise - from importlib.machinery import SourceFileLoader - - loader = SourceFileLoader('rosidl_generator_c', rosidl_generator_c_module) - rosidl_generator_c = loader.load_module() - generate_c = rosidl_generator_c.generate_c - - -def main(argv=sys.argv[1:]): - parser = argparse.ArgumentParser( - description='Generate the C ROS interfaces.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( - '--generator-arguments-file', - required=True, - help='The location of the file containing the generator arguments') - parser.add_argument( - '--disable-description-codegen', action='store_true', - help='If set, disable the generation of static type description ' - 'code to reduce binary size.') - args = parser.parse_args(argv) - - generate_c(args.generator_arguments_file, args.disable_description_codegen) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/rosidl_generator_c/cmake/register_c.cmake b/rosidl_generator_c/cmake/register_c.cmake index 7f6b84b17..087943fb2 100644 --- a/rosidl_generator_c/cmake/register_c.cmake +++ b/rosidl_generator_c/cmake/register_c.cmake @@ -1,4 +1,4 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. +# Copyright 2023 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. @@ -12,17 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -macro(rosidl_generator_c_extras BIN GENERATOR_FILES TEMPLATE_DIR) +macro(rosidl_generator_c_extras GENERATOR_FILES TEMPLATE_DIR) find_package(ament_cmake_core QUIET REQUIRED) find_package(rosidl_generator_type_description QUIET REQUIRED) + + ament_register_extension( + "rosidl_write_generator_arguments_extensions" + "rosidl_generator_c" + "rosidl_generator_c_write_arguments.cmake") ament_register_extension( "rosidl_generate_idl_interfaces" "rosidl_generator_c" "rosidl_generator_c_generate_interfaces.cmake") - normalize_path(BIN "${BIN}") - set(rosidl_generator_c_BIN "${BIN}") - normalize_path(GENERATOR_FILES "${GENERATOR_FILES}") set(rosidl_generator_c_GENERATOR_FILES "${GENERATOR_FILES}") diff --git a/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake b/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake index 10cae3297..f4a718baf 100644 --- a/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake +++ b/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake @@ -1,4 +1,4 @@ -# Copyright 2015-2018 Open Source Robotics Foundation, Inc. +# Copyright 2015-2023 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. @@ -50,8 +50,9 @@ foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) endforeach() endforeach() +set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json") + set(target_dependencies - "${rosidl_generator_c_BIN}" ${rosidl_generator_c_GENERATOR_FILES} "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.c.em" @@ -71,6 +72,7 @@ set(target_dependencies "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.h.em" ${rosidl_generate_interfaces_ABS_IDL_FILES} + ${generator_arguments_file} ${_dependency_files}) foreach(dep ${target_dependencies}) if(NOT EXISTS "${dep}") @@ -78,38 +80,6 @@ foreach(dep ${target_dependencies}) endif() endforeach() -get_target_property(_target_sources ${rosidl_generate_interfaces_TARGET} SOURCES) -set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json") -rosidl_write_generator_arguments( - "${generator_arguments_file}" - PACKAGE_NAME "${PROJECT_NAME}" - IDL_TUPLES "${rosidl_generate_interfaces_c_IDL_TUPLES}" - ROS_INTERFACE_DEPENDENCIES "${_dependencies}" - OUTPUT_DIR "${_output_path}" - TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}" - TARGET_DEPENDENCIES ${target_dependencies} - TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}" - ROS_INTERFACE_FILES "${_target_sources}" -) - -find_package(Python3 REQUIRED COMPONENTS Interpreter) - -set(disable_description_codegen_arg) -if(ROSIDL_GENERATOR_C_DISABLE_TYPE_DESCRIPTION_CODEGEN) - set(disable_description_codegen_arg "--disable-description-codegen") -endif() - -add_custom_command( - OUTPUT ${_generated_headers} ${_generated_sources} - COMMAND Python3::Interpreter - ARGS ${rosidl_generator_c_BIN} - --generator-arguments-file "${generator_arguments_file}" - ${disable_description_codegen_arg} - DEPENDS ${target_dependencies} - COMMENT "Generating C code for ROS interfaces" - VERBATIM -) - # generate header to switch between export and import for a specific package set(_visibility_control_file "${_output_path}/msg/rosidl_generator_c__visibility_control.h") diff --git a/rosidl_generator_c/cmake/rosidl_generator_c_write_arguments.cmake b/rosidl_generator_c/cmake/rosidl_generator_c_write_arguments.cmake new file mode 100644 index 000000000..aec108a7f --- /dev/null +++ b/rosidl_generator_c/cmake/rosidl_generator_c_write_arguments.cmake @@ -0,0 +1,86 @@ +# Copyright 2023 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. + +find_package(rcutils REQUIRED) +find_package(rosidl_cmake REQUIRED) +find_package(rosidl_runtime_c REQUIRED) +find_package(rosidl_typesupport_interface REQUIRED) + +set(rosidl_generate_interfaces_c_IDL_TUPLES + ${rosidl_generate_interfaces_IDL_TUPLES}) +set(_output_path "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c/${PROJECT_NAME}") + +set(_dependency_files "") +set(_dependencies "") +foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) + foreach(_idl_file ${${_pkg_name}_IDL_FILES}) + rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") + list(APPEND _dependency_files "${_abs_idl_file}") + list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") + endforeach() +endforeach() + +set(target_dependencies + ${rosidl_generator_c_GENERATOR_FILES} + "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/empty__description.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/full__description.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__description.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__functions.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__functions.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__struct.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__type_support.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__type_support.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/msg__functions.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/msg__functions.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/msg__struct.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/msg__type_support.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.c.em" + "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.h.em" + ${rosidl_generate_interfaces_ABS_IDL_FILES} + ${_dependency_files}) +foreach(dep ${target_dependencies}) + if(NOT EXISTS "${dep}") + message(FATAL_ERROR "Target dependency '${dep}' does not exist") + endif() +endforeach() + +set(additional_context_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__additional_context.json") +set(disable_description_codegen_arg "false") +if(ROSIDL_GENERATOR_C_DISABLE_TYPE_DESCRIPTION_CODEGEN) + set(disable_description_codegen_arg "true") +endif() +rosidl_write_additional_context( + "${additional_context_file}" + DISABLE_DESCRIPTION_CODEGEN "${disable_description_codegen_arg}" +) + +set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json") +rosidl_write_generator_arguments( + "${generator_arguments_file}" + PACKAGE_NAME "${PROJECT_NAME}" + IDL_TUPLES "${rosidl_generate_interfaces_c_IDL_TUPLES}" + ROS_INTERFACE_DEPENDENCIES "${_dependencies}" + OUTPUT_DIR "${_output_path}" + TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}" + TARGET_DEPENDENCIES ${target_dependencies} + TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}" + ROS_INTERFACE_FILES "${_target_sources}" + GENERATOR_FILES "${rosidl_generator_c_GENERATOR_FILES}" + ADDITIONAL_CONTEXT_FILE ${additional_context_file} +) + +list(APPEND rosidl_generator_arguments_files ${generator_arguments_file}) diff --git a/rosidl_generator_c/rosidl_generator_c-extras.cmake.in b/rosidl_generator_c/rosidl_generator_c-extras.cmake.in index 48ff0d8f8..9b9581c85 100644 --- a/rosidl_generator_c/rosidl_generator_c-extras.cmake.in +++ b/rosidl_generator_c/rosidl_generator_c-extras.cmake.in @@ -5,7 +5,6 @@ set(rosidl_generator_c_LIBRARY_TYPE "@rosidl_generator_c_LIBRARY_TYPE@") include("${CMAKE_CURRENT_LIST_DIR}/register_c.cmake") rosidl_generator_c_extras( - "${rosidl_generator_c_DIR}/../../../lib/rosidl_generator_c/rosidl_generator_c" "${rosidl_generator_c_DIR}/../../../@PYTHON_INSTALL_DIR@/rosidl_generator_c/__init__.py" "${rosidl_generator_c_DIR}/../resource" ) diff --git a/rosidl_generator_c/rosidl_generator_c/__init__.py b/rosidl_generator_c/rosidl_generator_c/__init__.py index 50bb60b9e..0a49f9e73 100644 --- a/rosidl_generator_c/rosidl_generator_c/__init__.py +++ b/rosidl_generator_c/rosidl_generator_c/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. +# Copyright 2023 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. @@ -28,8 +28,8 @@ from rosidl_pycommon import generate_files -def generate_c(generator_arguments_file, disable_description_codegen=False): - mapping = { +def get_template_mapping(): + return { 'idl.h.em': '%s.h', 'idl__description.c.em': 'detail/%s__description.c', 'idl__functions.c.em': 'detail/%s__functions.c', @@ -38,6 +38,10 @@ def generate_c(generator_arguments_file, disable_description_codegen=False): 'idl__type_support.c.em': 'detail/%s__type_support.c', 'idl__type_support.h.em': 'detail/%s__type_support.h', } + + +def generate_c(generator_arguments_file, disable_description_codegen=False): + mapping = get_template_mapping() return generate_files( generator_arguments_file, mapping, post_process_callback=prefix_with_bom_if_necessary, @@ -57,6 +61,10 @@ def prefix_with_bom_if_necessary(content): return content +# def post_process_callback(content): +# return prefix_with_bom_if_necessary(content) + + BASIC_IDL_TYPES_TO_C = { 'float': 'float', 'double': 'double', diff --git a/rosidl_generator_cpp/CMakeLists.txt b/rosidl_generator_cpp/CMakeLists.txt index 68d3b087c..12326ea31 100644 --- a/rosidl_generator_cpp/CMakeLists.txt +++ b/rosidl_generator_cpp/CMakeLists.txt @@ -18,10 +18,6 @@ ament_package( CONFIG_EXTRAS "rosidl_generator_cpp-extras.cmake.in" ) -install( - PROGRAMS bin/rosidl_generator_cpp - DESTINATION lib/rosidl_generator_cpp -) install( DIRECTORY cmake resource DESTINATION share/${PROJECT_NAME} diff --git a/rosidl_generator_cpp/bin/rosidl_generator_cpp b/rosidl_generator_cpp/bin/rosidl_generator_cpp deleted file mode 100755 index a63e1b5b7..000000000 --- a/rosidl_generator_cpp/bin/rosidl_generator_cpp +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys - -try: - from rosidl_generator_cpp import generate_cpp -except ImportError: - # modifying sys.path and importing the Python package with the same - # name as this script does not work on Windows - rosidl_generator_cpp_root = os.path.dirname(os.path.dirname(__file__)) - rosidl_generator_cpp_module = os.path.join( - rosidl_generator_cpp_root, 'rosidl_generator_cpp', '__init__.py') - if not os.path.exists(rosidl_generator_cpp_module): - raise - from importlib.machinery import SourceFileLoader - - loader = SourceFileLoader('rosidl_generator_cpp', rosidl_generator_cpp_module) - rosidl_generator_cpp = loader.load_module() - generate_cpp = rosidl_generator_cpp.generate_cpp - - -def main(argv=sys.argv[1:]): - parser = argparse.ArgumentParser( - description='Generate the C++ ROS interfaces.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( - '--generator-arguments-file', - required=True, - help='The location of the file containing the generator arguments') - args = parser.parse_args(argv) - - generate_cpp(args.generator_arguments_file) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/rosidl_generator_cpp/cmake/register_cpp.cmake b/rosidl_generator_cpp/cmake/register_cpp.cmake index 6c0eaba86..d803a49c9 100644 --- a/rosidl_generator_cpp/cmake/register_cpp.cmake +++ b/rosidl_generator_cpp/cmake/register_cpp.cmake @@ -1,4 +1,4 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. +# Copyright 2023 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. @@ -12,17 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -macro(rosidl_generator_cpp_extras BIN GENERATOR_FILES TEMPLATE_DIR) +macro(rosidl_generator_cpp_extras GENERATOR_FILES TEMPLATE_DIR) find_package(ament_cmake_core QUIET REQUIRED) find_package(rosidl_generator_type_description QUIET REQUIRED) + + ament_register_extension( + "rosidl_write_generator_arguments_extensions" + "rosidl_generator_cpp" + "rosidl_generator_cpp_write_arguments.cmake") ament_register_extension( "rosidl_generate_idl_interfaces" "rosidl_generator_cpp" "rosidl_generator_cpp_generate_interfaces.cmake") - normalize_path(BIN "${BIN}") - set(rosidl_generator_cpp_BIN "${BIN}") - normalize_path(GENERATOR_FILES "${GENERATOR_FILES}") set(rosidl_generator_cpp_GENERATOR_FILES "${GENERATOR_FILES}") diff --git a/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake index 7b91c2559..3072baa6d 100644 --- a/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake +++ b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -44,68 +44,6 @@ configure_file( ) list(APPEND _generated_headers "${_visibility_control_file}") -set(_dependency_files "") -set(_dependencies "") -foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) - foreach(_idl_file ${${_pkg_name}_IDL_FILES}) - rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") - list(APPEND _dependency_files "${_abs_idl_file}") - list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") - endforeach() -endforeach() - -set(target_dependencies - "${rosidl_generator_cpp_BIN}" - ${rosidl_generator_cpp_GENERATOR_FILES} - "${rosidl_generator_cpp_TEMPLATE_DIR}/action__builder.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/action__struct.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/action__traits.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/action__type_support.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/idl.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__builder.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__struct.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__traits.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__type_support.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__builder.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__struct.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__traits.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__type_support.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__builder.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__struct.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__traits.hpp.em" - "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__type_support.hpp.em" - ${rosidl_generate_interfaces_ABS_IDL_FILES} - ${_dependency_files}) -foreach(dep ${target_dependencies}) - if(NOT EXISTS "${dep}") - message(FATAL_ERROR "Target dependency '${dep}' does not exist") - endif() -endforeach() - -set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_cpp__arguments.json") -rosidl_write_generator_arguments( - "${generator_arguments_file}" - PACKAGE_NAME "${PROJECT_NAME}" - IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" - ROS_INTERFACE_DEPENDENCIES "${_dependencies}" - OUTPUT_DIR "${_output_path}" - TEMPLATE_DIR "${rosidl_generator_cpp_TEMPLATE_DIR}" - TARGET_DEPENDENCIES ${target_dependencies} - TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}" -) - -find_package(Python3 REQUIRED COMPONENTS Interpreter) - -add_custom_command( - OUTPUT ${_generated_headers} - COMMAND Python3::Interpreter - ARGS ${rosidl_generator_cpp_BIN} - --generator-arguments-file "${generator_arguments_file}" - DEPENDS ${target_dependencies} - COMMENT "Generating C++ code for ROS interfaces" - VERBATIM -) - # INTERFACE libraries can't have file-level dependencies in CMake, # so make a custom target depending on the generated files # TODO(sloretz) make this target name less generic than "__cpp" when other diff --git a/rosidl_generator_cpp/cmake/rosidl_generator_cpp_write_arguments.cmake b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_write_arguments.cmake new file mode 100644 index 000000000..161f8f07b --- /dev/null +++ b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_write_arguments.cmake @@ -0,0 +1,68 @@ +# Copyright 2023 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_cpp/${PROJECT_NAME}") + +set(_dependency_files "") +set(_dependencies "") +foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) + foreach(_idl_file ${${_pkg_name}_IDL_FILES}) + rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") + list(APPEND _dependency_files "${_abs_idl_file}") + list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") + endforeach() +endforeach() + +set(target_dependencies + ${rosidl_generator_cpp_GENERATOR_FILES} + "${rosidl_generator_cpp_TEMPLATE_DIR}/action__builder.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/action__struct.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/action__traits.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/action__type_support.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/idl.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__builder.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__struct.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__traits.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/idl__type_support.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__builder.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__struct.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__traits.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/msg__type_support.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__builder.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__struct.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__traits.hpp.em" + "${rosidl_generator_cpp_TEMPLATE_DIR}/srv__type_support.hpp.em" + ${rosidl_generate_interfaces_ABS_IDL_FILES} + ${_dependency_files}) +foreach(dep ${target_dependencies}) + if(NOT EXISTS "${dep}") + message(FATAL_ERROR "Target dependency '${dep}' does not exist") + endif() +endforeach() + +set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_cpp__arguments.json") +rosidl_write_generator_arguments( + "${generator_arguments_file}" + PACKAGE_NAME "${PROJECT_NAME}" + IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" + ROS_INTERFACE_DEPENDENCIES "${_dependencies}" + OUTPUT_DIR "${_output_path}" + TEMPLATE_DIR "${rosidl_generator_cpp_TEMPLATE_DIR}" + TARGET_DEPENDENCIES ${target_dependencies} + TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}" + GENERATOR_FILES "${rosidl_generator_cpp_GENERATOR_FILES}" +) + +list(APPEND rosidl_generator_arguments_files ${generator_arguments_file}) diff --git a/rosidl_generator_cpp/rosidl_generator_cpp-extras.cmake.in b/rosidl_generator_cpp/rosidl_generator_cpp-extras.cmake.in index 703ced5e2..231c11d5a 100644 --- a/rosidl_generator_cpp/rosidl_generator_cpp-extras.cmake.in +++ b/rosidl_generator_cpp/rosidl_generator_cpp-extras.cmake.in @@ -2,7 +2,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/register_cpp.cmake") rosidl_generator_cpp_extras( - "${rosidl_generator_cpp_DIR}/../../../lib/rosidl_generator_cpp/rosidl_generator_cpp" "${rosidl_generator_cpp_DIR}/../../../@PYTHON_INSTALL_DIR@/rosidl_generator_cpp/__init__.py" "${rosidl_generator_cpp_DIR}/../resource" ) diff --git a/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py b/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py index b076fd3ed..dd1f355af 100644 --- a/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py +++ b/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -28,14 +28,17 @@ from rosidl_pycommon import generate_files -def generate_cpp(generator_arguments_file): - mapping = { +def get_template_mapping(): + return { 'idl.hpp.em': '%s.hpp', 'idl__builder.hpp.em': 'detail/%s__builder.hpp', 'idl__struct.hpp.em': 'detail/%s__struct.hpp', 'idl__traits.hpp.em': 'detail/%s__traits.hpp', 'idl__type_support.hpp.em': 'detail/%s__type_support.hpp', } + +def generate_cpp(generator_arguments_file): + mapping = get_template_mapping() return generate_files( generator_arguments_file, mapping, post_process_callback=prefix_with_bom_if_necessary) @@ -52,6 +55,10 @@ def prefix_with_bom_if_necessary(content): return content +def post_process_callback(content): + return prefix_with_bom_if_necessary(content) + + MSG_TYPE_TO_CPP = { 'boolean': 'bool', 'octet': 'unsigned char', # TODO change to std::byte with C++17 diff --git a/rosidl_generator_type_description/cmake/rosidl_generator_type_description_generate_interfaces.cmake b/rosidl_generator_type_description/cmake/rosidl_generator_type_description_generate_interfaces.cmake index bae15d0ee..e3fc167a0 100644 --- a/rosidl_generator_type_description/cmake/rosidl_generator_type_description_generate_interfaces.cmake +++ b/rosidl_generator_type_description/cmake/rosidl_generator_type_description_generate_interfaces.cmake @@ -62,17 +62,21 @@ rosidl_write_generator_arguments( INCLUDE_PATHS "${_dependency_paths}" ) -# Create custom command and target to generate the hash output -add_custom_command( - COMMAND Python3::Interpreter - ARGS - ${rosidl_generator_type_description_BIN} - --generator-arguments-file "${_generator_arguments_file}" - OUTPUT ${_generated_files} - DEPENDS ${target_dependencies} - COMMENT "Generating type hashes for ROS interfaces" - VERBATIM +# Execute command to generate the hash output +set(cmd + "${Python3_EXECUTABLE}" ${rosidl_generator_type_description_BIN} + --generator-arguments-file "${_generator_arguments_file}") +execute_process( + COMMAND ${cmd} + OUTPUT_QUIET + ERROR_VARIABLE error + RESULT_VARIABLE result ) +if(NOT result EQUAL 0) + string(REPLACE ";" " " cmd_str "${cmd}") + message(FATAL_ERROR + "execute_process(${cmd_str}) returned error code ${result}:\n${error}") +endif() set(_target "${rosidl_generate_interfaces_TARGET}__rosidl_generator_type_description") add_custom_target(${_target} DEPENDS ${_generated_files}) diff --git a/rosidl_generator_type_description/rosidl_generator_type_description-extras.cmake.in b/rosidl_generator_type_description/rosidl_generator_type_description-extras.cmake.in index eefe59a1b..d23e894b1 100644 --- a/rosidl_generator_type_description/rosidl_generator_type_description-extras.cmake.in +++ b/rosidl_generator_type_description/rosidl_generator_type_description-extras.cmake.in @@ -1,7 +1,7 @@ find_package(ament_cmake_core QUIET REQUIRED) ament_register_extension( - "rosidl_generate_idl_interfaces" + "rosidl_create_type_descriptions_extensions" "rosidl_generator_type_description" "rosidl_generator_type_description_generate_interfaces.cmake") diff --git a/rosidl_pycommon/rosidl_pycommon/__init__.py b/rosidl_pycommon/rosidl_pycommon/__init__.py index deae9bcc7..c8c88fc01 100644 --- a/rosidl_pycommon/rosidl_pycommon/__init__.py +++ b/rosidl_pycommon/rosidl_pycommon/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. +# Copyright 2023 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. @@ -14,6 +14,7 @@ from io import StringIO import json +from multiprocessing import Pool import os import pathlib import re @@ -22,6 +23,7 @@ import em from rosidl_parser.definition import IdlLocator from rosidl_parser.parser import parse_idl_file +from rosidl_pycommon.generator_config import GeneratorConfig def convert_camel_case_to_lower_case_underscore(value): @@ -121,6 +123,116 @@ def generate_files( return generated_files +def generate_files_for_idl_tuple(args): + """ + Generate source files for a specific IDL tuple, using a set of generator configurations. + Each configuration is defined by an arguments file. + + Argument tuple format: ( + IDL tuple, + list of GeneratorConfig configurations + ) + """ + idl_tuple, configs_for_idl_tuple = args + + # Parse IDl file + idl_parts = idl_tuple.rsplit(':', 1) + assert len(idl_parts) == 2 + locator = IdlLocator(*idl_parts) + idl_rel_path = pathlib.Path(idl_parts[1]) + try: + idl_file = parse_idl_file(locator) + + # Generate code from templates according to each of the generator configs + generated_files = [] + for config in configs_for_idl_tuple: + template_basepath = pathlib.Path(config.arguments['template_dir']) + for template_filename in config.mapping.keys(): + assert (template_basepath / template_filename).exists(), \ + 'Could not find template: ' + template_filename + + latest_target_timestamp = get_newest_modification_time(config.arguments['target_dependencies']) + + type_description_files = {} + for description_tuple in config.arguments.get('type_description_tuples', []): + tuple_parts = description_tuple.split(':', 1) + assert len(tuple_parts) == 2 + type_description_files[tuple_parts[0]] = tuple_parts[1] + + ros_interface_files = {} + for ros_interface_file in config.arguments.get('ros_interface_files', []): + p = pathlib.Path(ros_interface_file) + # e.g. ('msg', 'Empty') + key = (p.suffix[1:], p.stem) + ros_interface_files[key] = p + + type_description_info = None + if type_description_files: + type_hash_file = type_description_files[idl_parts[1]] + with open(type_hash_file, 'r') as f: + type_description_info = json.load(f) + + idl_stem = idl_rel_path.stem + if not config.keep_case: + idl_stem = convert_camel_case_to_lower_case_underscore(idl_stem) + + type_source_key = (idl_rel_path.parts[-2], idl_stem) + type_source_file = ros_interface_files.get(type_source_key, locator.get_absolute_path()) + + data = { + 'package_name': config.arguments['package_name'], + 'interface_path': idl_rel_path, + 'content': idl_file.content, + 'type_description_info': type_description_info, + 'type_source_file': type_source_file, + } + if config.additional_context is not None: + data.update(config.additional_context) + + # Expand templates + for template_file, generated_filename in config.mapping.items(): + generated_file = os.path.join( + config.arguments['output_dir'], str(idl_rel_path.parent), + generated_filename % idl_stem) + generated_files.append(generated_file) + + expand_template( + os.path.basename(template_file), data, + generated_file, minimum_timestamp=latest_target_timestamp, + template_basepath=template_basepath, + post_process_callback=config.post_process_callback) + + return generated_files + + except Exception as e: + print('Error processing idl file: ' + str(locator.get_absolute_path()), file=sys.stderr) + raise(e) + + +def generate_files_from_arguments_files(arguments_files = ""): + # Get mapping of IDL files to configs and type descriptions + configs_for_idl_tuple = {} + arg_file_list = arguments_files.split(";") + for arg_file in arg_file_list: + config = GeneratorConfig(arg_file) + for idl_tuple in config.arguments.get('idl_tuples', []): + idl_parts = idl_tuple.rsplit(':', 1) + assert len(idl_parts) == 2 + + if idl_tuple in configs_for_idl_tuple: + configs_for_idl_tuple[idl_tuple].append(config) + else: + configs_for_idl_tuple[idl_tuple] = [config] + + pool = Pool() + generated_files_per_idl_tuple = pool.map( + generate_files_for_idl_tuple, + ((idl_tuple, configs_for_idl_tuple[idl_tuple]) for idl_tuple in configs_for_idl_tuple.keys())) + generated_files = [file for file_list in generated_files_per_idl_tuple for file in file_list ] + + return generated_files + + template_prefix_path = [] diff --git a/rosidl_pycommon/rosidl_pycommon/generator_config.py b/rosidl_pycommon/rosidl_pycommon/generator_config.py new file mode 100644 index 000000000..8a660fd73 --- /dev/null +++ b/rosidl_pycommon/rosidl_pycommon/generator_config.py @@ -0,0 +1,84 @@ +# Copyright 2023 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. + +import json +import os +import pathlib + + +def read_json_file(input_file): + with open(input_file, mode='r', encoding='utf-8') as h: + return json.load(h) + + +def get_generator_module(module_name, module_path): + if not os.path.exists(module_path): + raise + + from importlib.machinery import SourceFileLoader + + loader = SourceFileLoader(module_name, module_path) + generator_files_module = loader.load_module() + return generator_files_module + + +def find_generator_module(module_name, generator_files): + for generator_file in generator_files: + generator_file_module_path = os.path.normpath(generator_file) + generator_file_module = get_generator_module(module_name, generator_file_module_path) + + if hasattr(generator_file_module, 'get_template_mapping'): + # Found module with expected attributes + return generator_file_module + + raise ModuleNotFoundError("Could not find generator module for '" + module_name + "' in: " + generator_files) + + +class GeneratorConfig: + + def __init__(self, arguments_file): + print(f"\n\nArg file = {arguments_file}\n\n") + self.arguments_file = arguments_file + self.arguments = read_json_file(self.arguments_file) + + # Create a unique module name from the arguments file + module_name = self.arguments_file.rsplit('/', 1)[-1].rsplit('__', 1)[0] + + generator_files_module = find_generator_module(module_name, self.arguments['generator_files']) + + # Get template mapping (required) + if not hasattr(generator_files_module, 'get_template_mapping'): + raise NotImplementedError("Missing function 'get_template_mapping()' in generator module for " + module_name) + self.mapping = generator_files_module.get_template_mapping() + # Check that templates exist + template_basepath = pathlib.Path(self.arguments['template_dir']) + for template_filename in self.mapping.keys(): + assert (template_basepath / template_filename).exists(), \ + 'Could not find template: ' + template_filename + + # Additional context (optional) + self.additional_context = None + if 'additional_context_file' in self.arguments: + print(f"Got additional_context_file: {self.arguments['additional_context_file']}") + self.additional_context = read_json_file(self.arguments['additional_context_file']) + + # Keep case (optional) + self.keep_case = False + if hasattr(generator_files_module, 'should_keep_case'): + self.keep_case = generator_files_module.should_keep_case() + + # Post-process callback (optional) + self.post_process_callback = None + if hasattr(generator_files_module, 'post_process_callback'): + self.post_process_callback = generator_files_module.post_process_callback diff --git a/rosidl_typesupport_introspection_c/CMakeLists.txt b/rosidl_typesupport_introspection_c/CMakeLists.txt index a2d9b60e7..57642f584 100644 --- a/rosidl_typesupport_introspection_c/CMakeLists.txt +++ b/rosidl_typesupport_introspection_c/CMakeLists.txt @@ -53,10 +53,6 @@ ament_package( CONFIG_EXTRAS "rosidl_typesupport_introspection_c-extras.cmake.in" ) -install( - PROGRAMS bin/rosidl_typesupport_introspection_c - DESTINATION lib/rosidl_typesupport_introspection_c -) install( DIRECTORY cmake resource DESTINATION share/${PROJECT_NAME} diff --git a/rosidl_typesupport_introspection_c/bin/rosidl_typesupport_introspection_c b/rosidl_typesupport_introspection_c/bin/rosidl_typesupport_introspection_c deleted file mode 100755 index e20111d5b..000000000 --- a/rosidl_typesupport_introspection_c/bin/rosidl_typesupport_introspection_c +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import sys - -from rosidl_typesupport_introspection_c import generate_c -from typing import List - - -def main(argv: List[str] = sys.argv[1:]): - """ - Generate the C introspection type support for ROS interfaces. - - :param argv: The command-line arguments to be parsed. Defaults to - sys.argv[1:]. - :type argv: List[str] - """ - parser = argparse.ArgumentParser( - description='Generate the C type support to dynamically handle ROS messages.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( - '--generator-arguments-file', - required=True, - help='The location of the file containing the generator arguments') - args = parser.parse_args(argv) - - generate_c(args.generator_arguments_file) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_generate_interfaces.cmake b/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_generate_interfaces.cmake index b5cd93b25..103c902fa 100644 --- a/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_generate_interfaces.cmake +++ b/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_generate_interfaces.cmake @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -38,55 +38,7 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES}) "${_output_path}/${_parent_folder}/detail/${_header_name}__type_support.c") endforeach() -set(_dependency_files "") -set(_dependencies "") -foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) - foreach(_idl_file ${${_pkg_name}_IDL_FILES}) - rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") - list(APPEND _dependency_files "${_abs_idl_file}") - list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") - endforeach() -endforeach() - -set(target_dependencies - "${rosidl_typesupport_introspection_c_BIN}" - ${rosidl_typesupport_introspection_c_GENERATOR_FILES} - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/idl__rosidl_typesupport_introspection_c.h.em" - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/idl__type_support.c.em" - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/msg__rosidl_typesupport_introspection_c.h.em" - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/msg__type_support.c.em" - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/srv__rosidl_typesupport_introspection_c.h.em" - "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/srv__type_support.c.em" - ${rosidl_generate_interfaces_ABS_IDL_FILES} - ${_dependency_files}) -foreach(dep ${target_dependencies}) - if(NOT EXISTS "${dep}") - message(FATAL_ERROR "Target dependency '${dep}' does not exist") - endif() -endforeach() - set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_typesupport_introspection_c__arguments.json") -rosidl_write_generator_arguments( - "${generator_arguments_file}" - PACKAGE_NAME "${PROJECT_NAME}" - IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" - ROS_INTERFACE_DEPENDENCIES "${_dependencies}" - OUTPUT_DIR "${_output_path}" - TEMPLATE_DIR "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}" - TARGET_DEPENDENCIES ${target_dependencies} -) - -find_package(Python3 REQUIRED COMPONENTS Interpreter) - -add_custom_command( - OUTPUT ${_generated_header_files} ${_generated_source_files} - COMMAND Python3::Interpreter - ARGS ${rosidl_typesupport_introspection_c_BIN} - --generator-arguments-file "${generator_arguments_file}" - DEPENDS ${target_dependencies} - COMMENT "Generating C introspection for ROS interfaces" - VERBATIM -) # generate header to switch between export and import for a specific package set(_visibility_control_file diff --git a/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_write_arguments.cmake b/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_write_arguments.cmake new file mode 100644 index 000000000..1adae1048 --- /dev/null +++ b/rosidl_typesupport_introspection_c/cmake/rosidl_typesupport_introspection_c_write_arguments.cmake @@ -0,0 +1,56 @@ +# Copyright 2023 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_typesupport_introspection_c/${PROJECT_NAME}") + +set(_dependency_files "") +set(_dependencies "") +foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) + foreach(_idl_file ${${_pkg_name}_IDL_FILES}) + rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") + list(APPEND _dependency_files "${_abs_idl_file}") + list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") + endforeach() +endforeach() + +set(target_dependencies + ${rosidl_typesupport_introspection_c_GENERATOR_FILES} + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/idl__rosidl_typesupport_introspection_c.h.em" + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/idl__type_support.c.em" + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/msg__rosidl_typesupport_introspection_c.h.em" + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/msg__type_support.c.em" + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/srv__rosidl_typesupport_introspection_c.h.em" + "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}/srv__type_support.c.em" + ${rosidl_generate_interfaces_ABS_IDL_FILES} + ${_dependency_files}) +foreach(dep ${target_dependencies}) + if(NOT EXISTS "${dep}") + message(FATAL_ERROR "Target dependency '${dep}' does not exist") + endif() +endforeach() + +set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_typesupport_introspection_c__arguments.json") +rosidl_write_generator_arguments( + "${generator_arguments_file}" + PACKAGE_NAME "${PROJECT_NAME}" + IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" + ROS_INTERFACE_DEPENDENCIES "${_dependencies}" + OUTPUT_DIR "${_output_path}" + TEMPLATE_DIR "${rosidl_typesupport_introspection_c_TEMPLATE_DIR}" + TARGET_DEPENDENCIES ${target_dependencies} + GENERATOR_FILES "${rosidl_typesupport_introspection_c_GENERATOR_FILES}" +) + +list(APPEND rosidl_generator_arguments_files ${generator_arguments_file}) diff --git a/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c-extras.cmake.in b/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c-extras.cmake.in index 004a1e627..4c9816128 100644 --- a/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c-extras.cmake.in +++ b/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c-extras.cmake.in @@ -10,16 +10,17 @@ set(rosidl_typesupport_introspection_c_LIBRARY_TYPE find_package(rosidl_generator_c QUIET) find_package(ament_cmake_core QUIET REQUIRED) + +ament_register_extension( + "rosidl_write_generator_arguments_extensions" + "rosidl_typesupport_introspection_c" + "rosidl_typesupport_introspection_c_write_arguments.cmake") + ament_register_extension( "rosidl_generate_idl_interfaces" "rosidl_typesupport_introspection_c" "rosidl_typesupport_introspection_c_generate_interfaces.cmake") -set(rosidl_typesupport_introspection_c_BIN - "${rosidl_typesupport_introspection_c_DIR}/../../../lib/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c") -normalize_path(rosidl_typesupport_introspection_c_BIN - "${rosidl_typesupport_introspection_c_BIN}") - set(rosidl_typesupport_introspection_c_GENERATOR_FILES "${rosidl_typesupport_introspection_c_DIR}/../../../@PYTHON_INSTALL_DIR@/rosidl_typesupport_introspection_c/__init__.py") normalize_path(rosidl_typesupport_introspection_c_GENERATOR_FILES diff --git a/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c/__init__.py b/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c/__init__.py index 8a728f9a5..388f79146 100644 --- a/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c/__init__.py +++ b/rosidl_typesupport_introspection_c/rosidl_typesupport_introspection_c/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2021 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -15,6 +15,14 @@ from rosidl_pycommon import generate_files +def get_template_mapping(): + return { + 'idl__rosidl_typesupport_introspection_c.h.em': + 'detail/%s__rosidl_typesupport_introspection_c.h', + 'idl__type_support.c.em': 'detail/%s__type_support.c', + } + + def generate_c(generator_arguments_file: str): """ Generate the C implementation of the type support. @@ -23,9 +31,5 @@ def generate_c(generator_arguments_file: str): arguments for the generator. :type generator_arguments_file: str """ - mapping = { - 'idl__rosidl_typesupport_introspection_c.h.em': - 'detail/%s__rosidl_typesupport_introspection_c.h', - 'idl__type_support.c.em': 'detail/%s__type_support.c', - } + mapping = get_template_mapping() return generate_files(generator_arguments_file, mapping) diff --git a/rosidl_typesupport_introspection_cpp/CMakeLists.txt b/rosidl_typesupport_introspection_cpp/CMakeLists.txt index 12892d1bb..e71ee950e 100644 --- a/rosidl_typesupport_introspection_cpp/CMakeLists.txt +++ b/rosidl_typesupport_introspection_cpp/CMakeLists.txt @@ -61,10 +61,6 @@ ament_package( CONFIG_EXTRAS "rosidl_typesupport_introspection_cpp-extras.cmake.in" ) -install( - PROGRAMS bin/rosidl_typesupport_introspection_cpp - DESTINATION lib/rosidl_typesupport_introspection_cpp -) install( DIRECTORY cmake resource DESTINATION share/${PROJECT_NAME} diff --git a/rosidl_typesupport_introspection_cpp/bin/rosidl_typesupport_introspection_cpp b/rosidl_typesupport_introspection_cpp/bin/rosidl_typesupport_introspection_cpp deleted file mode 100755 index 3e2e2cede..000000000 --- a/rosidl_typesupport_introspection_cpp/bin/rosidl_typesupport_introspection_cpp +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import sys - -from rosidl_typesupport_introspection_cpp import generate_cpp -from typing import List - - -def main(argv: List[str] = sys.argv[1:]): - """ - Generate the C++ introspection type support for ROS interfaces. - - :param argv: The command-line arguments to be parsed. Defaults to - sys.argv[1:]. - :type argv: List[str] - """ - parser = argparse.ArgumentParser( - description='Generate the C++ type support to dynamically handle ROS messages.', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( - '--generator-arguments-file', - required=True, - help='The location of the file containing the generator arguments') - args = parser.parse_args(argv) - - generate_cpp(args.generator_arguments_file) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_generate_interfaces.cmake b/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_generate_interfaces.cmake index 60c7cef7a..f461b59ed 100644 --- a/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_generate_interfaces.cmake +++ b/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_generate_interfaces.cmake @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -38,56 +38,6 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES}) "${_output_path}/${_parent_folder}/detail/${_header_name}__type_support.cpp") endforeach() -set(_dependency_files "") -set(_dependencies "") -foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) - foreach(_idl_file ${${_pkg_name}_IDL_FILES}) - rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") - list(APPEND _dependency_files "${_abs_idl_file}") - list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") - endforeach() -endforeach() - -set(target_dependencies - "${rosidl_typesupport_introspection_cpp_BIN}" - ${rosidl_typesupport_introspection_cpp_GENERATOR_FILES} - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/idl__rosidl_typesupport_introspection_cpp.hpp.em" - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/idl__type_support.cpp.em" - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/msg__rosidl_typesupport_introspection_cpp.hpp.em" - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/msg__type_support.cpp.em" - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/srv__rosidl_typesupport_introspection_cpp.hpp.em" - "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/srv__type_support.cpp.em" - ${rosidl_generate_interfaces_ABS_IDL_FILES} - ${_dependency_files}) -foreach(dep ${target_dependencies}) - if(NOT EXISTS "${dep}") - message(FATAL_ERROR "Target dependency '${dep}' does not exist") - endif() -endforeach() - -set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_typesupport_introspection_cpp__arguments.json") -rosidl_write_generator_arguments( - "${generator_arguments_file}" - PACKAGE_NAME "${PROJECT_NAME}" - IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" - ROS_INTERFACE_DEPENDENCIES "${_dependencies}" - OUTPUT_DIR "${_output_path}" - TEMPLATE_DIR "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}" - TARGET_DEPENDENCIES ${target_dependencies} -) - -find_package(Python3 REQUIRED COMPONENTS Interpreter) - -add_custom_command( - OUTPUT ${_generated_header_files} ${_generated_source_files} - COMMAND Python3::Interpreter - ARGS ${rosidl_typesupport_introspection_cpp_BIN} - --generator-arguments-file "${generator_arguments_file}" - DEPENDS ${target_dependencies} - COMMENT "Generating C++ introspection for ROS interfaces" - VERBATIM -) - set(_target_suffix "__rosidl_typesupport_introspection_cpp") add_library(${rosidl_generate_interfaces_TARGET}${_target_suffix} ${rosidl_typesupport_introspection_cpp_LIBRARY_TYPE} diff --git a/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_write_arguments.cmake b/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_write_arguments.cmake new file mode 100644 index 000000000..f3dc0b923 --- /dev/null +++ b/rosidl_typesupport_introspection_cpp/cmake/rosidl_typesupport_introspection_cpp_write_arguments.cmake @@ -0,0 +1,57 @@ +# Copyright 2023 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_typesupport_introspection_cpp/${PROJECT_NAME}") + +set(_dependency_files "") +set(_dependencies "") +foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) + foreach(_idl_file ${${_pkg_name}_IDL_FILES}) + rosidl_find_package_idl(_abs_idl_file "${_pkg_name}" "${_idl_file}") + list(APPEND _dependency_files "${_abs_idl_file}") + list(APPEND _dependencies "${_pkg_name}:${_abs_idl_file}") + endforeach() +endforeach() + +set(target_dependencies + "${rosidl_typesupport_introspection_cpp_BIN}" + ${rosidl_typesupport_introspection_cpp_GENERATOR_FILES} + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/idl__rosidl_typesupport_introspection_cpp.hpp.em" + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/idl__type_support.cpp.em" + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/msg__rosidl_typesupport_introspection_cpp.hpp.em" + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/msg__type_support.cpp.em" + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/srv__rosidl_typesupport_introspection_cpp.hpp.em" + "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}/srv__type_support.cpp.em" + ${rosidl_generate_interfaces_ABS_IDL_FILES} + ${_dependency_files}) +foreach(dep ${target_dependencies}) + if(NOT EXISTS "${dep}") + message(FATAL_ERROR "Target dependency '${dep}' does not exist") + endif() +endforeach() + +set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_typesupport_introspection_cpp__arguments.json") +rosidl_write_generator_arguments( + "${generator_arguments_file}" + PACKAGE_NAME "${PROJECT_NAME}" + IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}" + ROS_INTERFACE_DEPENDENCIES "${_dependencies}" + OUTPUT_DIR "${_output_path}" + TEMPLATE_DIR "${rosidl_typesupport_introspection_cpp_TEMPLATE_DIR}" + TARGET_DEPENDENCIES ${target_dependencies} + GENERATOR_FILES "${rosidl_typesupport_introspection_cpp_GENERATOR_FILES}" +) + +list(APPEND rosidl_generator_arguments_files ${generator_arguments_file}) diff --git a/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp-extras.cmake.in b/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp-extras.cmake.in index c90641b9a..0e787b5c0 100644 --- a/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp-extras.cmake.in +++ b/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp-extras.cmake.in @@ -10,16 +10,16 @@ set(rosidl_typesupport_introspection_cpp_LIBRARY_TYPE find_package(rosidl_generator_cpp QUIET) find_package(ament_cmake_core QUIET REQUIRED) + +ament_register_extension( + "rosidl_write_generator_arguments_extensions" + "rosidl_typesupport_introspection_cpp" + "rosidl_typesupport_introspection_cpp_write_arguments.cmake") ament_register_extension( "rosidl_generate_idl_interfaces" "rosidl_typesupport_introspection_cpp" "rosidl_typesupport_introspection_cpp_generate_interfaces.cmake") -set(rosidl_typesupport_introspection_cpp_BIN - "${rosidl_typesupport_introspection_cpp_DIR}/../../../lib/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp") -normalize_path(rosidl_typesupport_introspection_cpp_BIN - "${rosidl_typesupport_introspection_cpp_BIN}") - set(rosidl_typesupport_introspection_cpp_GENERATOR_FILES "${rosidl_typesupport_introspection_cpp_DIR}/../../../@PYTHON_INSTALL_DIR@/rosidl_typesupport_introspection_cpp/__init__.py") normalize_path(rosidl_typesupport_introspection_cpp_GENERATOR_FILES diff --git a/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp/__init__.py b/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp/__init__.py index 7457e2a60..ccc52aa0e 100644 --- a/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp/__init__.py +++ b/rosidl_typesupport_introspection_cpp/rosidl_typesupport_introspection_cpp/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2014-2018 Open Source Robotics Foundation, Inc. +# Copyright 2014-2023 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. @@ -15,6 +15,14 @@ from rosidl_pycommon import generate_files +def get_template_mapping(): + return { + 'idl__rosidl_typesupport_introspection_cpp.hpp.em': + 'detail/%s__rosidl_typesupport_introspection_cpp.hpp', + 'idl__type_support.cpp.em': 'detail/%s__type_support.cpp', + } + + def generate_cpp(generator_arguments_file: str): """ Generate the C++ implementation of the type support. @@ -23,9 +31,5 @@ def generate_cpp(generator_arguments_file: str): arguments for the generator. :type generator_arguments_file: str """ - mapping = { - 'idl__rosidl_typesupport_introspection_cpp.hpp.em': - 'detail/%s__rosidl_typesupport_introspection_cpp.hpp', - 'idl__type_support.cpp.em': 'detail/%s__type_support.cpp', - } + mapping = get_template_mapping() return generate_files(generator_arguments_file, mapping)