Skip to content

Commit 7f6a4da

Browse files
committed
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.
1 parent 3491f4f commit 7f6a4da

File tree

36 files changed

+726
-407
lines changed

36 files changed

+726
-407
lines changed

rosidl_cmake/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ find_package(ament_cmake_python REQUIRED)
77

88
ament_python_install_package(${PROJECT_NAME})
99

10+
set(rosidl_cmake_generate_interfaces_BIN "${CMAKE_CURRENT_SOURCE_DIR}/bin/rosidl_cmake_generate_interfaces")
11+
normalize_path(rosidl_cmake_generate_interfaces_BIN "${rosidl_cmake_generate_interfaces_BIN}")
12+
1013
if(BUILD_TESTING)
1114
find_package(ament_lint_auto REQUIRED)
1215
ament_lint_auto_find_test_dependencies()
@@ -16,6 +19,11 @@ ament_package(
1619
CONFIG_EXTRAS "rosidl_cmake-extras.cmake"
1720
)
1821

22+
install(
23+
PROGRAMS bin/rosidl_cmake_generate_interfaces
24+
DESTINATION lib/rosidl_cmake
25+
)
26+
1927
install(
2028
DIRECTORY cmake
2129
DESTINATION share/${PROJECT_NAME}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import sys
6+
7+
try:
8+
from rosidl_pycommon import generate_files_from_arguments_files
9+
except ImportError:
10+
# modifying sys.path and importing the Python package with the same
11+
# name as this script does not work on Windows
12+
rosidl_pycommon_root = os.path.dirname(os.path.dirname(__file__))
13+
rosidl_pycommon_module = os.path.join(
14+
rosidl_pycommon_root, 'rosidl_pycommon', '__init__.py')
15+
if not os.path.exists(rosidl_pycommon_module):
16+
raise
17+
from importlib.machinery import SourceFileLoader
18+
19+
loader = SourceFileLoader('rosidl_pycommon', rosidl_pycommon_module)
20+
rosidl_pycommon = loader.load_module()
21+
generate_files_from_arguments_files = rosidl_pycommon.generate_files_from_arguments_files
22+
23+
24+
def main(argv=sys.argv[1:]):
25+
parser = argparse.ArgumentParser(
26+
description='Generate the ROS interfaces.',
27+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
28+
parser.add_argument(
29+
'--generator-arguments-files',
30+
required=True,
31+
help='The location of the files containing the generator arguments')
32+
args = parser.parse_args(argv)
33+
34+
print(args.generator_arguments_files)
35+
36+
generate_files_from_arguments_files(args.generator_arguments_files)
37+
38+
39+
if __name__ == '__main__':
40+
sys.exit(main())

rosidl_cmake/cmake/rosidl_generate_interfaces.cmake

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2014-2018 Open Source Robotics Foundation, Inc.
1+
# Copyright 2014-2023 Open Source Robotics Foundation, Inc.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -277,6 +277,24 @@ macro(rosidl_generate_interfaces target)
277277
list(APPEND rosidl_generate_interfaces_ABS_IDL_FILES "${_abs_idl_file}")
278278
endforeach()
279279

280+
# Create the type descriptions for use when writing the generator arguments files
281+
ament_execute_extensions("rosidl_create_type_descriptions_extensions")
282+
283+
# Write the generator argument files for all registered languages and type supports
284+
set(rosidl_generator_arguments_files)
285+
ament_execute_extensions("rosidl_write_generator_arguments_extensions")
286+
287+
find_package(Python3 REQUIRED COMPONENTS Interpreter)
288+
289+
# Generate the interface source files for all registered languages and type supports
290+
set(rosidl_cmake_generate_interfaces_BIN "${rosidl_cmake_DIR}/../../../lib/rosidl_cmake/rosidl_cmake_generate_interfaces")
291+
execute_process(
292+
COMMAND ${Python3_EXECUTABLE} ${rosidl_cmake_generate_interfaces_BIN}
293+
--generator-arguments-files "${rosidl_generator_arguments_files}"
294+
ECHO_OUTPUT_VARIABLE
295+
)
296+
297+
# Build the interfaces from the generated files
280298
ament_execute_extensions("rosidl_generate_idl_interfaces")
281299

282300
# check for extensions registered with the previous extension point
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Copyright 2023 Open Source Robotics Foundation, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
#
16+
# Generate a JSON / YAML file containing additional context data for expanding
17+
# IDL templates
18+
#
19+
#
20+
# @public
21+
#
22+
function(rosidl_write_additional_context output_file)
23+
24+
set(OPTIONAL_ONE_VALUE_KEYWORDS
25+
"DISABLE_DESCRIPTION_CODEGEN")
26+
set(OPTIONAL_MULTI_VALUE_KEYWORDS
27+
"TYPE_SUPPORTS")
28+
29+
cmake_parse_arguments(
30+
ARG
31+
""
32+
"${OPTIONAL_ONE_VALUE_KEYWORDS}"
33+
"${OPTIONAL_MULTI_VALUE_KEYWORDS}"
34+
${ARGN})
35+
if(ARG_UNPARSED_ARGUMENTS)
36+
message(FATAL_ERROR "rosidl_write_additional_context() called with unused "
37+
"arguments: ${ARG_UNPARSED_ARGUMENTS}")
38+
endif()
39+
40+
# create folder
41+
get_filename_component(output_path "${output_file}" PATH)
42+
file(MAKE_DIRECTORY "${output_path}")
43+
44+
# open object
45+
file(WRITE "${output_file}"
46+
"{")
47+
48+
set(first_element TRUE)
49+
50+
# write string values
51+
foreach(one_value_argument ${OPTIONAL_ONE_VALUE_KEYWORDS})
52+
if(DEFINED ARG_${one_value_argument})
53+
# write conditional comma and mandatory newline
54+
if(NOT first_element)
55+
file(APPEND "${output_file}" ",")
56+
else()
57+
set(first_element FALSE)
58+
endif()
59+
file(APPEND "${output_file}" "\n")
60+
61+
string(TOLOWER "${one_value_argument}" key)
62+
string(REPLACE "\\" "\\\\" value "${ARG_${one_value_argument}}")
63+
file(APPEND "${output_file}"
64+
" \"${key}\": \"${value}\"")
65+
endif()
66+
endforeach()
67+
68+
# write array values
69+
foreach(multi_value_argument ${OPTIONAL_MULTI_VALUE_KEYWORDS})
70+
if(ARG_${multi_value_argument})
71+
# write conditional comma and mandatory newline and indentation
72+
if(NOT first_element)
73+
file(APPEND "${output_file}" ",")
74+
else()
75+
set(first_element FALSE)
76+
endif()
77+
file(APPEND "${output_file}" "\n")
78+
79+
# write key, open array
80+
string(TOLOWER "${multi_value_argument}" key)
81+
file(APPEND "${output_file}"
82+
" \"${key}\": [\n")
83+
84+
# write array values, last without trailing colon
85+
list(GET ARG_${multi_value_argument} -1 last_value)
86+
list(REMOVE_AT ARG_${multi_value_argument} -1)
87+
foreach(value ${ARG_${multi_value_argument}})
88+
string(REPLACE "\\" "\\\\" value "${value}")
89+
file(APPEND "${output_file}"
90+
" \"${value}\",\n")
91+
endforeach()
92+
string(REPLACE "\\" "\\\\" last_value "${last_value}")
93+
file(APPEND "${output_file}"
94+
" \"${last_value}\"\n")
95+
96+
# close array
97+
file(APPEND "${output_file}"
98+
" ]")
99+
endif()
100+
endforeach()
101+
102+
# close object
103+
file(APPEND "${output_file}"
104+
"\n}\n")
105+
endfunction()

rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2015 Open Source Robotics Foundation, Inc.
1+
# Copyright 2023 Open Source Robotics Foundation, Inc.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -23,12 +23,14 @@ function(rosidl_write_generator_arguments output_file)
2323
"PACKAGE_NAME")
2424
set(OPTIONAL_ONE_VALUE_KEYWORDS
2525
"OUTPUT_DIR"
26-
"TEMPLATE_DIR")
26+
"TEMPLATE_DIR"
27+
"ADDITIONAL_CONTEXT_FILE")
2728

2829
set(REQUIRED_MULTI_VALUE_KEYWORDS # only require one of them
2930
"IDL_TUPLES"
3031
"NON_IDL_TUPLES"
31-
"ROS_INTERFACE_FILES")
32+
"ROS_INTERFACE_FILES"
33+
"GENERATOR_FILES")
3234
set(OPTIONAL_MULTI_VALUE_KEYWORDS
3335
"ROS_INTERFACE_DEPENDENCIES" # since the dependencies can be empty
3436
"TARGET_DEPENDENCIES"

rosidl_cmake/rosidl_cmake-extras.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ find_package(rosidl_adapter) # not required, being used when available
3232
include("${rosidl_cmake_DIR}/rosidl_generate_interfaces.cmake")
3333
include("${rosidl_cmake_DIR}/rosidl_get_typesupport_target.cmake")
3434
include("${rosidl_cmake_DIR}/rosidl_target_interfaces.cmake")
35+
include("${rosidl_cmake_DIR}/rosidl_write_additional_context.cmake")
3536
include("${rosidl_cmake_DIR}/rosidl_write_generator_arguments.cmake")
3637
include("${rosidl_cmake_DIR}/string_camel_case_to_lower_case_underscore.cmake")
3738

rosidl_generator_c/CMakeLists.txt

-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ ament_package(
3434
CONFIG_EXTRAS "rosidl_generator_c-extras.cmake.in"
3535
)
3636

37-
install(
38-
PROGRAMS bin/rosidl_generator_c
39-
DESTINATION lib/rosidl_generator_c
40-
)
4137
install(
4238
DIRECTORY cmake resource
4339
DESTINATION share/${PROJECT_NAME}

rosidl_generator_c/bin/rosidl_generator_c

-42
This file was deleted.

rosidl_generator_c/cmake/register_c.cmake

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
macro(rosidl_generator_c_extras BIN GENERATOR_FILES TEMPLATE_DIR)
15+
macro(rosidl_generator_c_extras GENERATOR_FILES TEMPLATE_DIR)
1616
find_package(ament_cmake_core QUIET REQUIRED)
1717
find_package(rosidl_generator_type_description QUIET REQUIRED)
18+
19+
ament_register_extension(
20+
"rosidl_write_generator_arguments_extensions"
21+
"rosidl_generator_c"
22+
"rosidl_generator_c_write_arguments.cmake")
1823
ament_register_extension(
1924
"rosidl_generate_idl_interfaces"
2025
"rosidl_generator_c"
2126
"rosidl_generator_c_generate_interfaces.cmake")
2227

23-
normalize_path(BIN "${BIN}")
24-
set(rosidl_generator_c_BIN "${BIN}")
25-
2628
normalize_path(GENERATOR_FILES "${GENERATOR_FILES}")
2729
set(rosidl_generator_c_GENERATOR_FILES "${GENERATOR_FILES}")
2830

rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake

+4-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2015-2018 Open Source Robotics Foundation, Inc.
1+
# Copyright 2015-2023 Open Source Robotics Foundation, Inc.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# 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})
5050
endforeach()
5151
endforeach()
5252

53+
set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json")
54+
5355
set(target_dependencies
54-
"${rosidl_generator_c_BIN}"
5556
${rosidl_generator_c_GENERATOR_FILES}
5657
"${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.h.em"
5758
"${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.c.em"
@@ -71,45 +72,14 @@ set(target_dependencies
7172
"${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.c.em"
7273
"${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.h.em"
7374
${rosidl_generate_interfaces_ABS_IDL_FILES}
75+
${generator_arguments_file}
7476
${_dependency_files})
7577
foreach(dep ${target_dependencies})
7678
if(NOT EXISTS "${dep}")
7779
message(FATAL_ERROR "Target dependency '${dep}' does not exist")
7880
endif()
7981
endforeach()
8082

81-
get_target_property(_target_sources ${rosidl_generate_interfaces_TARGET} SOURCES)
82-
set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json")
83-
rosidl_write_generator_arguments(
84-
"${generator_arguments_file}"
85-
PACKAGE_NAME "${PROJECT_NAME}"
86-
IDL_TUPLES "${rosidl_generate_interfaces_c_IDL_TUPLES}"
87-
ROS_INTERFACE_DEPENDENCIES "${_dependencies}"
88-
OUTPUT_DIR "${_output_path}"
89-
TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}"
90-
TARGET_DEPENDENCIES ${target_dependencies}
91-
TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}"
92-
ROS_INTERFACE_FILES "${_target_sources}"
93-
)
94-
95-
find_package(Python3 REQUIRED COMPONENTS Interpreter)
96-
97-
set(disable_description_codegen_arg)
98-
if(ROSIDL_GENERATOR_C_DISABLE_TYPE_DESCRIPTION_CODEGEN)
99-
set(disable_description_codegen_arg "--disable-description-codegen")
100-
endif()
101-
102-
add_custom_command(
103-
OUTPUT ${_generated_headers} ${_generated_sources}
104-
COMMAND Python3::Interpreter
105-
ARGS ${rosidl_generator_c_BIN}
106-
--generator-arguments-file "${generator_arguments_file}"
107-
${disable_description_codegen_arg}
108-
DEPENDS ${target_dependencies}
109-
COMMENT "Generating C code for ROS interfaces"
110-
VERBATIM
111-
)
112-
11383
# generate header to switch between export and import for a specific package
11484
set(_visibility_control_file
11585
"${_output_path}/msg/rosidl_generator_c__visibility_control.h")

0 commit comments

Comments
 (0)