Ejemplo n.º 1
0
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)
    }
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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