# Copyright 2016-2018 Proyectos y Sistemas de Mantenimiento SL (eProsima). # # 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 struct import os import sys if os.name == 'nt': import win32con import win32file import pywintypes __overlapped = pywintypes.OVERLAPPED() elif os.name == 'posix': import fcntl else: raise RuntimeError('PortaLocker only defined for nt and posix platforms') from rosidl_cmake import convert_camel_case_to_lower_case_underscore from rosidl_cmake import expand_template from rosidl_cmake import extract_message_types from rosidl_cmake import get_newest_modification_time from rosidl_parser import parse_message_file from rosidl_parser import parse_service_file from rosidl_parser import validate_field_types from shutil import copyfile from pathlib import Path def generate_micro_ros_agent_xml_support(args): pkg_name = args['package_name'] known_msg_types = extract_message_types( pkg_name, args['ros_interface_files'], args.get('ros_interface_dependencies', [])) functions = { 'get_header_filename_from_msg_name': convert_camel_case_to_lower_case_underscore, } # Set file format file_format = ".xml" ros2_prefix = "rt/" # Check destination dir dest_dir = args['output_dir'] if not os.path.exists(dest_dir): os.makedirs(dest_dir) # Check source dir srcs_dir = os.path.join(dest_dir, "srcs") if not os.path.exists(srcs_dir): os.makedirs(srcs_dir) # Copy all included xml files for filename in os.listdir(args['template_dir']): if filename.endswith(file_format): template_src_path = os.path.join(args['template_dir'], filename) template_dest_path = os.path.join(srcs_dir, filename) if not os.path.isfile(template_dest_path): copyfile(template_src_path, template_dest_path) # Iterate throw all msgs/srvs for idl_file in args['ros_interface_files']: extension = os.path.splitext(idl_file)[1] if extension == '.msg': spec = parse_message_file(pkg_name, idl_file) validate_field_types(spec, known_msg_types) subfolder = os.path.basename(os.path.dirname(idl_file)) data = { 'spec': spec, 'pkg': spec.base_type.pkg_name, 'msg': spec.msg_name, 'type': spec.base_type.type, 'subfolder': subfolder, } data.update(functions) # Generate source file path src_file = os.path.join(srcs_dir, "%s_%s_%s.xml" % (spec.base_type.pkg_name, subfolder, spec.msg_name)) # Publisher file_content = " \n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " \n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " NO_KEY\n" file_content += " %s%s_%s_%s\n" % (ros2_prefix, spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " %s::%s::dds_::%s_\n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " \n" file_content += " KEEP_LAST\n" file_content += " 5\n" file_content += " \n" file_content += " \n" file_content += " TRANSIENT_LOCAL\n" file_content += " \n" file_content += " \n" file_content += " \n" # Subscriber file_content += " \n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " \n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " NO_KEY\n" file_content += " %s%s_%s_%s\n" % (ros2_prefix, spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " %s::%s::dds_::%s_\n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " \n" file_content += " KEEP_LAST\n" file_content += " 5\n" file_content += " \n" file_content += " \n" file_content += " TRANSIENT_LOCAL\n" file_content += " \n" file_content += " \n" file_content += " \n" # Topic file_content += " \n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " %s%s_%s_%s\n" % (ros2_prefix, spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " %s::%s::dds_::%s_\n" % (spec.base_type.pkg_name, subfolder, spec.msg_name) file_content += " \n" # Write file content fd1 = open(src_file, "w") if os.name == 'nt': # Lock hfile1 = win32file._get_osfhandle(fd1.fileno()) win32file.LockFileEx(hfile1, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped) # Write fd1.write(file_content) # Unlock win32file.UnlockFileEx(hfile1, 0, -0x10000, __overlapped) elif os.name == 'posix': # Lock fcntl.flock(fd1.fileno(), fcntl.LOCK_EX) # Write fd1.write(file_content) # Unlock fcntl.flock(fd1.fileno(), fcntl.LOCK_UN) fd1.close() # Open collect file collec_file = os.path.join(args['output_dir'], "DEFAULT_FASTRTPS_PROFILES.xml") fd2 = open(collec_file, "w") if os.name == 'nt': # Lock hfile2 = win32file._get_osfhandle(fd2.fileno()) win32file.LockFileEx(hfile2, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped) # Generate head fd2.write("\n") # Append all files contents for filename in os.listdir(srcs_dir): if filename.endswith(".xml"): # Open fd3 = open(os.path.join(srcs_dir, filename), "r+") # Lock hfile3 = win32file._get_osfhandle(fd3.fileno()) win32file.LockFileEx(hfile3, win32con.LOCKFILE_EXCLUSIVE_LOCK, 0, -0x10000, __overlapped) # Write fd2.write(fd3.read()) # Unlock win32file.UnlockFileEx(hfile3, 0, -0x10000, __overlapped) fd3.close() # Generate tail fd2.write("\n") # UnLock win32file.UnlockFileEx(hfile2, 0, -0x10000, __overlapped) elif os.name == 'posix': # Lock fcntl.flock(fd2.fileno(), fcntl.LOCK_EX) # Generate head fd2.write("\n") # Append all files contents for filename in os.listdir(srcs_dir): if filename.endswith(".xml"): # Open fd3 = open(os.path.join(srcs_dir, filename), "r+") # Lock fcntl.flock(fd3, fcntl.LOCK_EX) # Write fd2.write(fd3.read()) # Unlock fcntl.flock(fd3.fileno(), fcntl.LOCK_UN) # Close fd3.close() # Generate tail fd2.write("\n") # UnLock fcntl.flock(fd2.fileno(), fcntl.LOCK_UN) # Close file fd2.close() #elif extension == '.srv': #data = {'spec': spec} #data.update(functions) #if not os.path.exists(args['output_dir']): # os.makedirs(args['output_dir']) #f = open(os.path.join(args['output_dir'], 'demofile.txt'), 'w+') #f.write("%s\n" % spec) #f.close() return 0