def make_package_lines(deps_str, sysdeps_str, with_messages, project_path): PACKAGE_LINES = ''' ## Generate added messages and services with any dependencies listed here %(comment_symbol)sgenerate_messages( %(comment_symbol)s DEPENDENCIES %(msg_dependencies)s %(comment_symbol)s) # catkin_package parameters: http://ros.org/doc/groovy/api/catkin/html/dev_guide/generated_cmake_api.html#catkin-package # TODO: fill in what other packages will need to use this package catkin_package( DEPENDS %(sysdependencies)s # TODO CATKIN_DEPENDS %(dependencies)s INCLUDE_DIRS %(include_dir)s# TODO include LIBRARIES # TODO ) include_directories(%(include_dir)s ${Boost_INCLUDE_DIR} ${catkin_INCLUDE_DIRS}) ''' comment_symbol = '' if with_messages else '#' msg_dependencies = set() msg_dependencies.update(utils.get_message_dependencies(project_path)) msg_dependencies.update(utils.get_service_dependencies(project_path)) msg_dependencies.update(utils.get_action_dependencies(project_path)) if utils.get_action_files(project_path): msg_dependencies.add('actionlib_msgs') dependencies = deps_str if deps_str.strip() else '# TODO add dependencies' include_dirs = set() if os.path.exists(os.path.join(project_path, 'include')): include_dirs.add('include') if 'Eigen' in sysdeps_str: include_dirs.add('${EIGEN_INCLUDE_DIRS}') return PACKAGE_LINES % { 'comment_symbol': comment_symbol, 'msg_dependencies': ' '.join(msg_dependencies), 'dependencies': dependencies, 'sysdependencies': sysdeps_str, 'include_dir': ' '.join(include_dirs) }
def make_from_manifest(manifest_xml_str, package_name, version, architecture_independent, metapackage, bugtracker_url, replaces, conflicts, package_path, maintainer_emails): """ Return a package.xml sturcture filled with the data from the given manifest_xml_str. >>> manifest_xml_str = '\ <package>\ <description brief="one line of text">\ long description goes here, \ <em>XHTML is allowed</em>\ </description>\ <author>Alice/[email protected], Bob/[email protected]</author>\ <license>BSD</license>\ <url>http://pr.willowgarage.com/</url>\ <logo>http://pr.willowgarage.com/blog/photos/sensor_head1_500.jpg</logo>\ <depend package="pkgname"/>\ <depend package="common"/>\ <rosdep name="python" />\ <versioncontrol type="svn"\ url="https://playerstage.svn.sourceforge.net/svnroot/playerstage/code/player/trunk"/>\ <export>\ <cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>\ <cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib\ -Wl,-rpath,-L${prefix}lib -lrosthread -framework CoreServices"/>\ </export>\ </package>\ ' >>> pkg_xml = make_from_manifest( # doctest: +ELLIPSIS ... manifest_xml_str, ... package_name='my_pkg', version='0.1.2', ... architecture_independent=False, ... metapackage=False, ... bugtracker_url='https://github.com/ros/my_pkg/issues', ... replaces=[], conflicts=[]) >>> import xml.etree.ElementTree as ET >>> pkg = ET.XML(pkg_xml) """ # collect and save infos from the manifest.xml file manifest = ET.XML(manifest_xml_str) description = xml_lib.xml_find(manifest, 'description').text.strip() authors_str = xml_lib.xml_find(manifest, 'author').text authors = parse_authors_field(authors_str) licenses_str = xml_lib.xml_find(manifest, 'license').text licenses = SPACE_COMMA_RX.split(licenses_str) website_url = xml_lib.xml_find(manifest, 'url').text maintainers = [(a, {'email': maintainer_emails.get(a, '')}) if is_a_string(a) else a for a in authors] depend_tags = manifest.findall('depend') depends = [d.attrib['package'] for d in depend_tags] export_tags = xml_lib.xml_find(manifest, 'export').getchildren() exports = [(e.tag, e.attrib) for e in export_tags] depends = set(depends) depends.update(utils.get_message_dependencies(package_path)) depends.update(utils.get_service_dependencies(package_path)) depends.update(utils.get_action_dependencies(package_path)) depends.discard(package_name) build_depends = set(depends) run_depends = set(depends) if utils.get_message_files(package_path) or \ utils.get_service_files(package_path) or \ utils.get_action_files(package_path): build_depends.add('message_generation') run_depends.add('message_generation') build_depends.add('message_runtime') run_depends.add('message_runtime') if utils.get_action_files(package_path): build_depends.add('actionlib_msgs') run_depends.add('actionlib_msgs') # put the collected infos into a new (package.)xml structure xml = create_project_xml(package_name=package_name, version=version, description=description, maintainers=maintainers, licenses=licenses, website_url=website_url, bugtracker_url=bugtracker_url, authors=authors, build_depends=build_depends, run_depends=run_depends, test_depends=depends, replaces=replaces, conflicts=conflicts, exports=exports, architecture_independent=architecture_independent, metapackage=metapackage) # Most dependencies are build and run depends. Comment out only the # test_depend dependencies. for name in ['test_depend']: xml = xml_lib.comment_out_tags_named(xml, name) return xml
def convert_snippet(name, funargs, project_path): """ Do all replacements that can be done for a single snippet without looking at anything else. """ snippet = '%s%s' % (name, funargs) converted = False with_messages = utils.get_message_files(project_path) or \ utils.get_service_files(project_path) or \ utils.get_action_files(project_path) for a, b in conversions: if a == name.strip(): if b is not None: snippet = snippet.replace(a, b) else: snippet = comment( snippet, '\n# CATKIN_MIGRATION: removed during catkin migration') converted = True break if not converted: for a, b in manual_conversions: if a == name.strip(): snippet = comment(snippet, '\n# CATKIN_MIGRATION\n%s' % b) converted = True break if not converted: if 'include' == name.strip(): if 'rosbuild' in funargs or 'actionbuild.cmake' in funargs or 'cfgbuild.cmake' in funargs: snippet = comment( snippet, '\n# CATKIN_MIGRATION: removed during catkin migration') converted = True if not converted: if 'rosbuild_genmsg' == name.strip(): if utils.get_message_files(project_path): snippet = 'add_message_files(\n FILES\n' + ''.join(' %s\n' % (filename,) for filename in utils.get_message_files(project_path)) + ')' else: snippet = comment( snippet, '\n# CATKIN_MIGRATION: removed during catkin migration') converted = True elif 'rosbuild_gensrv' == name.strip(): snippet = 'add_service_files(\n FILES\n' + ''.join(' %s\n' % (filename,) for filename in utils.get_service_files(project_path)) + ')' converted = True elif 'genaction' == name.strip(): snippet = 'add_action_files(\n FILES\n' + ''.join(' %s\n' % (filename,) for filename in utils.get_action_files(project_path)) + ')' converted = True elif 'rosbuild_add_executable' == name.strip(): snippet = 'add_executable' + funargs target = funargs.strip()[1:-1].split()[0].strip() snippet += '\ntarget_link_libraries(%s ${catkin_LIBRARIES})' % (target,) snippet += '\nadd_dependencies(%s ${catkin_EXPORTED_TARGETS})' % (target,) if with_messages: snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_generate_messages_cpp)' % (target,) if utils.get_config_files(project_path): snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_gencfg)' % (target,) converted = True elif 'rosbuild_add_library' == name.strip(): snippet = 'add_library' + funargs target = funargs.strip()[1:-1].split()[0].strip() snippet += '\ntarget_link_libraries(%s ${catkin_LIBRARIES})' % (target,) snippet += '\nadd_dependencies(%s ${catkin_EXPORTED_TARGETS})' % (target,) if with_messages: snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_generate_messages_cpp)' % (target,) if utils.get_config_files(project_path): snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_gencfg)' % (target,) converted = True elif 'add_custom_target' == name.strip(): target = funargs.strip()[1:-1].split()[0].strip() snippet += '\nadd_dependencies(%s ${catkin_EXPORTED_TARGETS})' % (target,) if with_messages: snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_generate_messages_cpp)' % (target,) if utils.get_config_files(project_path): snippet += '\nadd_dependencies(%s ${PROJECT_NAME}_gencfg)' % (target,) converted = True elif 'add_custom_command' == name.strip(): target = funargs.strip()[1:-1].split()[1].strip() snippet += '\nadd_custom_command(OUTPUT %s APPEND DEPENDS ${catkin_EXPORTED_TARGETS})' % (target,) if with_messages: snippet += '\nadd_custom_command(OUTPUT %s APPEND DEPENDS ${PROJECT_NAME}_generate_messages_cpp)' % (target,) if utils.get_config_files(project_path): snippet += '\nadd_custom_command(OUTPUT %s APPEND DEPENDS ${PROJECT_NAME}_gencfg)' % (target,) converted = True elif 'gencfg' == name.strip(): snippet = 'generate_dynamic_reconfigure_options(\n' + ''.join(' cfg/%s\n' % (filename,) for filename in utils.get_config_files(project_path)) + ')' converted = True elif 'rosbuild_add_compile_flags' == name.strip(): args = funargs.strip()[1:-1].split() snippet = 'set_target_properties(%s PROPERTIES COMPILE_FLAGS %s)' % ( args[0], ' '.join(args[1:]), ) converted = True elif 'set' == name.strip() and ( 'EXECUTABLE_OUTPUT_PATH' in funargs or 'LIBRARY_OUTPUT_PATH' in funargs): snippet = comment(snippet, '\n# CATKIN_MIGRATION: removed during catkin migration') converted = True return snippet
def convert_cmake(project_path, cmakelists_path=None, manifest_xml_path=None): # handle default arguments if not cmakelists_path: cmakelists_path = os.path.join(project_path, 'CMakeLists.txt') if not manifest_xml_path: manifest_xml_path = os.path.join(project_path, 'manifest.xml') project_name = os.path.basename(os.path.abspath(project_path)) print('Converting %s' % cmakelists_path, file=sys.stderr) with open(cmakelists_path, 'r') as f_in: content = f_in.read() # get dependencies from manifest file catkin_depends, system_depends = get_dependencies(manifest_xml_path, project_path) catkin_depends.update(utils.get_message_dependencies(project_path)) catkin_depends.update(utils.get_service_dependencies(project_path)) catkin_depends.update(utils.get_action_dependencies(project_path)) catkin_depends.discard(project_name) if utils.get_message_files(project_path) or \ utils.get_service_files(project_path) or \ utils.get_action_files(project_path): catkin_depends.add('message_generation') catkin_depends.add('message_runtime') if utils.get_action_files(project_path): catkin_depends.add('actionlib_msgs') if 'eigen' in system_depends: system_depends.remove('eigen') system_depends.add('Eigen') # anything that looks like a macro or function call tokens = list(parse(content)) # storing the originals allows interactive mode where user confirms each # change result = tokens[:1] original = tokens[:1] boost_components = set() # find replacement for each snippet. Chunks are (funcall, argslist, # otherlines) first_boost = -1 for count, (name, fun_args, rest) in enumerate(chunks(tokens[1:], 3)): oldsnippet = '%s%s' % (name, fun_args) original.append(oldsnippet) newsnippet, components = convert_boost_snippet(name, fun_args) if newsnippet is None: newsnippet = convert_snippet(name, fun_args, project_path) if newsnippet != oldsnippet: result.append(newsnippet) else: result.append(None) else: if first_boost < 0: first_boost = count * 2 + 1 boost_components = boost_components.union(components) result.append(newsnippet) result.append(None) original.append(rest) if boost_components: # reverse order due to insert result.insert(first_boost, 'include_directories(${Boost_INCLUDE_DIRS})\n') result.insert( first_boost, 'find_package(Boost REQUIRED COMPONENTS %s)\n' % ' '.join(boost_components)) original.insert(first_boost, '') original.insert(first_boost, '') result_string = '' lines = content.splitlines() if not [l for l in lines if 'catkin_package' in l]: header = make_header_lines(project_name, ' '.join(catkin_depends)) result_string += ('\n'.join(header)) if utils.get_python_packages(project_path): result_string += '\ncatkin_python_setup()\n' added_package_lines = False def my_make_package_lines(): with_messages = ('add_message_files' in result_string or 'add_service_files' in result_string or 'add_action_files' in result_string) return make_package_lines(' '.join(catkin_depends), ' '.join(system_depends), with_messages, project_path) for (old_snippet, new_snippet) in zip(original, result): if old_snippet or new_snippet: this_snippet = new_snippet or old_snippet if not added_package_lines and ( 'add_library' in this_snippet or 'add_executable' in this_snippet or 'add_custom' in this_snippet): result_string += my_make_package_lines() added_package_lines = True result_string += this_snippet if not added_package_lines: result_string += my_make_package_lines() if utils.get_scripts(project_path): result_string += '\ninstall(PROGRAMS %s DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})\n' % ( ' '.join(utils.get_scripts(project_path)), ) return result_string