Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,20 @@ target_include_directories(${_target_name_lib}
${PythonExtra_INCLUDE_DIRS}
)

if(ROSIDL_ENABLE_PCH AND COMMAND target_precompile_headers)
target_precompile_headers(${_target_name_lib} PRIVATE
# _idl_pkg_typesupport_entry_point.c.em
<Python.h>
# _msg_pkg_typesupport_entry_point.c.em
<stdbool.h>
<stdint.h>
[["rosidl_runtime_c/visibility_control.h"]]
[["rosidl_runtime_c/message_type_support_struct.h"]]
[["rosidl_runtime_c/service_type_support_struct.h"]]
[["rosidl_runtime_c/action_type_support_struct.h"]]
)
endif()

# Check if numpy is in the include path
find_file(_numpy_h numpy/numpyconfig.h
PATHS ${PythonExtra_INCLUDE_DIRS}
Expand Down
52 changes: 46 additions & 6 deletions rosidl_generator_py/rosidl_generator_py/generate_py_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
# limitations under the License.

from ast import literal_eval
from concurrent.futures import ProcessPoolExecutor
from concurrent.futures import ThreadPoolExecutor
import keyword
from multiprocessing import cpu_count
import os
import pathlib
import sys
Expand Down Expand Up @@ -53,7 +56,15 @@
}


def generate_py(generator_arguments_file, typesupport_impls):
def _parse_elements_from_idl(idl_tuple: str):
idl_parts = idl_tuple.rsplit(':', 1)
assert len(idl_parts) == 2
locator = IdlLocator(*idl_parts)
idl_file = parse_idl_file(locator)
return idl_file.content.elements


def generate_py(generator_arguments_file, typesupport_impls, jobs=None):
mapping = {
'_idl.py.em': '_%s.py',
'_idl_support.c.em': '_%s_s.c',
Expand All @@ -66,22 +77,51 @@ def generate_py(generator_arguments_file, typesupport_impls):
# expand init modules for each directory
modules = {}
idl_content = IdlContent()
for idl_tuple in args.get('idl_tuples', []):
idl_tuples = list(args.get('idl_tuples', []))
parse_inputs = []

for idl_tuple in idl_tuples:
idl_parts = idl_tuple.rsplit(':', 1)
assert len(idl_parts) == 2

idl_rel_path = pathlib.Path(idl_parts[1])
idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
idl_stems.add(idl_rel_path.stem)

locator = IdlLocator(*idl_parts)
idl_file = parse_idl_file(locator)
idl_content.elements += idl_file.content.elements
parse_inputs.append(idl_tuple)

def _parse_all_with_executor(executor_cls, max_workers):
elements = []
with executor_cls(max_workers=max_workers) as executor:
parsed_elements = executor.map(
_parse_elements_from_idl, parse_inputs, chunksize=1)
for result in parsed_elements:
elements.extend(result)
return elements

if jobs is None or jobs <= 0:
jobs = min(cpu_count(), max(1, len(idl_tuples)))

if parse_inputs and jobs > 1:
try:
idl_content.elements += _parse_all_with_executor(
ProcessPoolExecutor, jobs)
except Exception as e:
print(
'[rosidl_generator_py] ProcessPoolExecutor failed '
f'({type(e).__name__}: {e}). '
'Falling back to ThreadPoolExecutor.',
file=sys.stderr)
idl_content.elements += _parse_all_with_executor(
ThreadPoolExecutor, jobs)
else:
for idl_tuple in parse_inputs:
idl_content.elements += _parse_elements_from_idl(idl_tuple)

# NOTE(sam): remove when a language specific name mangling is implemented

def print_warning_if_reserved_keyword(member_name, interface_type, interface_name):
if (keyword.iskeyword(member.name)):
if (keyword.iskeyword(member_name)):
print(
"Member name '{}' in the {} '{}' is a "
'reserved keyword in Python and is not supported '
Expand Down