예제 #1
0
def install_rosdeps(base_path, source_path, rosdistro, no_color):
    # -r continue even with errors
    cmd = ['rosdep', 'install', '-r']
    underlays = config_cache.get_underlays_list_from_config_cmake(base_path)
    for underlay in underlays:
        cmd += ['--from-paths', underlay]
    cmd += ['--from-paths', source_path, '--ignore-src', '--rosdistro', rosdistro, '-y']
    env = os.environ.copy()
    try:
        builder.print_command_banner(cmd, source_path, color=not no_color)
        if no_color:
            builder.run_command(cmd, source_path, env=env)
        else:
            builder.run_command_colorized(cmd, source_path, env=env)
    except subprocess.CalledProcessError:
        return fmt('@{rf}Invoking @{boldon}"rosdep install failed')
예제 #2
0
def make_main():
    args = _parse_args()
    cmake_args = args.cmake_args

    # disable colors if asked
    if args.no_color:
        terminal_color.disable_ANSI_colors()

    # Default paths
    base_path = os.path.abspath('.')
    build_path = os.path.join(base_path, 'build')
    devel_path = os.path.join(base_path, 'devel')
    source_path = os.path.join(base_path, 'src')

    validate_build_space(base_path)  # raises a RuntimeError if there is a problem

    # Clear out previous temporaries if requested
    if args.pre_clean:
        console.pretty_print("Pre-cleaning before building.", console.cyan)
        shutil.rmtree(devel_path, ignore_errors=True)
        shutil.rmtree(build_path, ignore_errors=True)

    # check for new build
    if not os.path.exists(build_path):
        os.mkdir(build_path)
    #if not os.path.exists(devel_path):
    #    os.mkdir(devel_path)

    # ensure toplevel cmake file exists
    toplevel_cmake = os.path.join(source_path, 'CMakeLists.txt')
    if not os.path.exists(toplevel_cmake):
        return fmt('@{rf}No toplevel cmake file@')

    packages = find_packages(source_path, exclude_subspaces=True)

    # verify that specified package exists in workspace
    if args.pkg:
        packages_by_name = {p.name: path for path, p in packages.iteritems()}
        if args.pkg not in packages_by_name:
            raise RuntimeError('Package %s not found in the workspace' % args.pkg)

    # check if cmake must be run (either for a changed list of package paths or changed cmake arguments)
    force_cmake, _ = builder.cmake_input_changed(packages, build_path, cmake_args=cmake_args)

    # check if toolchain.cmake, config.cmake exist
    toolchain_cmd = "-DCMAKE_TOOLCHAIN_FILE=%s" % os.path.join(base_path, 'toolchain.cmake') if os.path.isfile(os.path.join(base_path, 'toolchain.cmake')) else None
    config_cmd = "-C%s" % os.path.join(base_path, 'config.cmake') if os.path.isfile(os.path.join(base_path, 'config.cmake')) else None

    # Help find catkin cmake and python
    unused_catkin_toplevel, catkin_python_path, unused_catkin_cmake_path = common.find_catkin()
    env = os.environ.copy()
    try:
        env['PYTHONPATH'] = env['PYTHONPATH'] + os.pathsep + catkin_python_path
    except KeyError:
        env['PYTHONPATH'] = catkin_python_path

    # consider calling cmake
    makefile = os.path.join(build_path, 'Makefile')
    if not os.path.exists(makefile) or args.force_cmake or force_cmake:
        cmd = ['cmake', source_path]
        if toolchain_cmd:
            cmd.append(toolchain_cmd)
        if config_cmd:
            cmd.append(config_cmd)
        cmd += cmake_args

        try:
            builder.print_command_banner(cmd, build_path, color=not args.no_color)
            if args.no_color:
                builder.run_command(cmd, build_path, env=env)
            else:
                builder.run_command_colorized(cmd, build_path, env=env)
        except subprocess.CalledProcessError:
            return fmt('@{rf}Invoking @{boldon}"cmake"@{boldoff} failed')
    else:
        cmd = ['make', 'cmake_check_build_system']
        try:
            builder.print_command_banner(cmd, build_path, color=not args.no_color)
            if args.no_color:
                builder.run_command(cmd, build_path, env=env)
            else:
                builder.run_command_colorized(cmd, build_path, env=env)
        except subprocess.CalledProcessError:
            return fmt('@{rf}Invoking @{boldon}"make cmake_check_build_system"@{boldoff} failed')

    # invoke make
    if args.install:
        cmd = ['make', 'install']
    elif args.tests:
        cmd = ['make', 'tests']
    elif args.run_tests:
        cmd = ['make', 'run_tests']
    else:
        cmd = ['make']
    jobs = args.jobs
    if args.jobs == '':
        cmd.append('-j')
    else:
        jobs = args.jobs
        if not jobs:
            if 'ROS_PARALLEL_JOBS' in os.environ:
                ros_parallel_jobs = os.environ['ROS_PARALLEL_JOBS']
                cmd += [arg for arg in ros_parallel_jobs.split(' ') if arg]
            else:
                jobs = multiprocessing.cpu_count()
        if jobs:
            cmd.append('-j%d' % jobs)
            cmd.append('-l%d' % jobs)
    cmd += args.make_args
    try:
        make_path = build_path
        if args.pkg:
            make_path = os.path.join(make_path, packages_by_name[args.pkg])
        builder.print_command_banner(cmd, make_path, color=not args.no_color)
        builder.run_command(cmd, make_path, env=env)
    except subprocess.CalledProcessError:
        return fmt('@{rf}Invoking @{boldon}"make"@{boldoff} failed')
예제 #3
0
def build_workspace_isolated(
    workspace='.',
    sourcespace=None,
    buildspace=None,
    develspace=None,
    installspace=None,
    merge=False,
    install=False,
    jobs=None,
    force_cmake=False,
    build_packages=None,
    quiet=False,
    cmake_args=[],
    make_args=[],
    catkin_cmake_path=None,
    catkin_python_path=None
):
    '''
    Runs ``cmake``, ``make`` and optionally ``make install`` for all
    catkin packages in sourcespace_dir.  It creates several folders
    in the current working directory. For non-catkin packages it runs
    ``cmake``, ``make`` and ``make install`` for each, installing it to
    the devel space or install space if the ``install`` option is specified.

    :param workspace: path to the current workspace, ``str``
    :param sourcespace: workspace folder containing catkin packages, ``str``
    :param buildspace: path to build space location, ``str``
    :param develspace: path to devel space location, ``str``
    :param installspace: path to install space (CMAKE_INSTALL_PREFIX), ``str``
    :param merge: if True, build each catkin package into the same
        devel space. does not work with non-catkin packages, ``bool``
    :param install: if True, install all packages to the install space,
        ``bool``
    :param jobs: number of parallel build jobs to run (make -jN -lN), ``int``
    :param force_cmake: (optional), if True calls cmake explicitly for each
        package, ``bool``
    :param colorize: if True, colorize cmake output and other messages,
        ``bool``
    :param build_packages: specific packages to build (all parent packages
        in the topological order must have been built before), ``str``
    :param quiet: if True, hides some build output, ``bool``
    :param cmake_args: additional arguments for cmake, ``[str]``
    :param make_args: additional arguments for make, ``[str]``
    '''
    # Should actually have alot of argument checks here, rather than
    # before feeding the function (makes for safe functions)

    console.pretty_print("Base Path: ", console.cyan)
    console.pretty_println("%s" % workspace, console.yellow)
    console.pretty_print("Build Path: ", console.cyan)
    console.pretty_println("%s" % buildspace, console.yellow)
    console.pretty_print("Source Path: ", console.cyan)
    console.pretty_println("%s" % sourcespace, console.yellow)
    console.pretty_print("Devel Path: ", console.cyan)
    console.pretty_println("%s" % develspace, console.yellow)
    console.pretty_print("Install Path: ", console.cyan)
    console.pretty_println("%s" % installspace, console.yellow)
    console.pretty_print("Catkin CMake Path: ", console.cyan)
    console.pretty_println("%s" % catkin_cmake_path, console.yellow)
    console.pretty_print("Catkin Python Path: ", console.cyan)
    console.pretty_println("%s" % catkin_python_path, console.yellow)
    # Find packages
    packages = find_packages(sourcespace, exclude_subspaces=True)
    if not packages:
        raise RuntimeError("No packages found in source space: %s" % sourcespace)

    # verify that specified package exists in workspace
    if build_packages:
        packages_by_name = {p.name: path for path, p in packages.iteritems()}
        unknown_packages = [p for p in build_packages if p not in packages_by_name]
        if unknown_packages:
            raise RuntimeError('Packages not found in the workspace: %s' % ', '.join(unknown_packages))

    # Report topological ordering
    ordered_packages = topological_order_packages(packages)
    unknown_build_types = []
    msg = []
    msg.append('@{pf}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + ('~' * len(str(len(ordered_packages)))))
    msg.append('@{pf}~~@|  traversing %d packages in topological order:' % len(ordered_packages))
    for path, package in ordered_packages:
        export_tags = [e.tagname for e in package.exports]
        if 'build_type' in export_tags:
            build_type_tag = [e.content for e in package.exports if e.tagname == 'build_type'][0]
        else:
            build_type_tag = 'catkin'
        if build_type_tag == 'catkin':
            msg.append('@{pf}~~@|  - @!@{bf}' + package.name + '@|')
        elif build_type_tag == 'cmake':
            msg.append(
                '@{pf}~~@|  - @!@{bf}' + package.name + '@|' +
                ' (@!@{cf}plain cmake@|)'
            )
        else:
            msg.append(
                '@{pf}~~@|  - @!@{bf}' + package.name + '@|' +
                ' (@{rf}unknown@|)'
            )
            unknown_build_types.append(package)
    msg.append('@{pf}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' + ('~' * len(str(len(ordered_packages)))))
    for index in range(len(msg)):
        msg[index] = fmt(msg[index])
    print('\n'.join(msg))

    # Error if there are packages with unknown build_types
    if unknown_build_types:
        raise RuntimeError('Can not build workspace with packages of unknown build_type.')

    # Check to see if the workspace has changed
    if not force_cmake:
        force_cmake, install_toggled = builder.cmake_input_changed(
            packages,
            buildspace,
            install=install,
            cmake_args=cmake_args,
            filename='catkin_make_isolated'
        )
        if force_cmake:
            print('The packages or cmake arguments have changed, forcing cmake invocation')
        elif install_toggled:
            print('The install argument has been toggled, forcing cmake invocation on plain cmake package')

    # Build packages
    original_develspace = copy.deepcopy(develspace)
    for index, path_package in enumerate(ordered_packages):
        path, package = path_package
        if not merge:
            develspace = os.path.join(original_develspace, package.name)
        if not build_packages or package.name in build_packages:
            try:
                export_tags = [e.tagname for e in package.exports]
                is_cmake_package = 'cmake' in [e.content for e in package.exports if e.tagname == 'build_type']
                builder.build_package(
                    path, package,
                    workspace, buildspace, develspace, installspace,
                    install, jobs, force_cmake or (install_toggled and is_cmake_package),
                    quiet, cmake_args, make_args,
                    number=index + 1, of=len(ordered_packages),
                    catkin_cmake_path=catkin_cmake_path,
                    catkin_python_path=catkin_python_path
                )
            except Exception as e:
                import traceback
                traceback.print_exc()
                builder.cprint(
                    '@{rf}@!<==@| ' +
                    'Failed to process package \'@!@{bf}' +
                    package.name + '@|\': \n  ' +
                    ('KeyboardInterrupt' if isinstance(e, KeyboardInterrupt)
                        else str(e))
                )
                if isinstance(e, subprocess.CalledProcessError):
                    cmd = ' '.join(e.cmd) if isinstance(e.cmd, list) else e.cmd
                    print(fmt("\n@{rf}Reproduce this error by running:"))
                    print(fmt("@{gf}@!==> @|") + cmd + "\n")
                sys.exit('Command failed, exiting.')
        else:
            builder.cprint("Skipping package: '@!@{bf}" + package.name + "@|'")

    # Provide a top level devel space environment setup script
    if not merge and not build_packages:
        # generate env.sh and setup.sh which relay to last devel space
        generated_env = os.path.join(original_develspace, 'env.sh')
        with open(generated_env, 'w') as f:
            f.write("""\
#!/usr/bin/env sh
# generated from catkin.builder module

{0} "$@"
""".format(os.path.join(develspace, 'env.sh')))
        os.chmod(generated_env, stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR)
        with open(os.path.join(original_develspace, 'setup.sh'), 'w') as f:
            f.write("""\
#!/usr/bin/env sh
# generated from catkin.builder module

. "{0}/setup.sh"
""".format(develspace))
        # generate setup.bash and setup.zsh for convenience
        variables = {'SETUP_DIR': original_develspace}
        with open(os.path.join(original_develspace, 'setup.bash'), 'w') as f:
            f.write(configure_file(os.path.join(catkin_cmake_path, 'templates', 'setup.bash.in'), variables))
        with open(os.path.join(original_develspace, 'setup.zsh'), 'w') as f:
            f.write(configure_file(os.path.join(catkin_cmake_path, 'templates', 'setup.zsh.in'), variables))
예제 #4
0
def make_main():
    args = _parse_args()
    cmake_args = args.cmake_args

    if args.no_color:
        terminal_color.disable_ANSI_colors()

    (base_path, build_path, devel_path, source_path) = common.get_default_paths()
    doc_path = config_cache.get_doc_prefix_from_config_cmake(base_path)

    validate_build_space(base_path)  # raises a RuntimeError if there is a problem

    # Install rosdeps if requested
    if args.install_rosdeps:
        install_rosdeps(base_path, source_path, settings.get_default_track(), args.no_color)
        return
    if args.install_rosdeps_track is not None:
        install_rosdeps(source_path, args.install_rosdeps_track, args.no_color)
        return

    # Clear out previous temporaries if requested
    if args.pre_clean:
        console.pretty_print("Pre-cleaning before building.", console.cyan)
        shutil.rmtree(devel_path, ignore_errors=True)
        shutil.rmtree(build_path, ignore_errors=True)
        shutil.rmtree(doc_path, ignore_errors=True)

    # check for new build
    if not os.path.exists(build_path):
        os.mkdir(build_path)
    #if not os.path.exists(devel_path):
    #    os.mkdir(devel_path)

    # ensure toplevel cmake file exists
    toplevel_cmake = os.path.join(source_path, 'CMakeLists.txt')
    if not os.path.exists(toplevel_cmake):
        return fmt('@{rf}No toplevel cmake file@')

    # did source paths get added to the original location?
    check_and_update_source_repo_paths(source_path)

    packages = find_packages(source_path, exclude_subspaces=True)

    # verify that specified package exists in workspace
    if args.pkg:
        packages_by_name = {p.name: path for path, p in packages.iteritems()}
        if args.pkg not in packages_by_name:
            raise RuntimeError('Package %s not found in the workspace' % args.pkg)

    # check if cmake must be run (either for a changed list of package paths or changed cmake arguments)
    force_cmake, _ = builder.cmake_input_changed(packages, build_path, cmake_args=cmake_args)

    # check if toolchain.cmake, config.cmake exist
    toolchain_cmd = "-DCMAKE_TOOLCHAIN_FILE=%s" % os.path.join(base_path, 'toolchain.cmake') if os.path.isfile(os.path.join(base_path, 'toolchain.cmake')) else None
    config_cmd = "-C%s" % os.path.join(base_path, 'config.cmake') if os.path.isfile(os.path.join(base_path, 'config.cmake')) else None

    # Help find catkin cmake and python
    unused_catkin_toplevel, catkin_python_path, unused_catkin_cmake_path = common.find_catkin(base_path)
    pkg_config_paths = common.generate_pkg_config_path(base_path)
    env = os.environ.copy()
    # PYTHONPATH
    # Don't add to the environment variable - this mucks up catkin's catkin_generated/setup_cached.py
    # environment later (how? I can't remember - something to do with the default underlay).
    # Maybe we can do away with this now catkin can look up install spaces?
    #try:
    #    env['PYTHONPATH'] = env['PYTHONPATH'] + os.pathsep + catkin_python_path
    #except KeyError:
    #    env['PYTHONPATH'] = catkin_python_path
    sys.path.append(catkin_python_path)
    # PKG_CONFIG_PATH
    for path in pkg_config_paths:
        try:
            env['PKG_CONFIG_PATH'] = env['PKG_CONFIG_PATH'] + os.pathsep + path
        except KeyError:
            env['PKG_CONFIG_PATH'] = path

    if args.doc_only:
        console.pretty_println('Generates documents only', console.bold_white)
        make_doc(source_path, doc_path, packages)
        return

    # consider calling cmake
    makefile = os.path.join(build_path, 'Makefile')
    if not os.path.exists(makefile) or args.force_cmake or force_cmake:
        cmd = ['cmake', source_path]
        if toolchain_cmd:
            cmd.append(toolchain_cmd)
        if config_cmd:
            cmd.append(config_cmd)
        cmd += cmake_args

        #new_env = common.generate_underlays_environment(base_path)
        try:
            builder.print_command_banner(cmd, build_path, color=not args.no_color)
            if args.no_color:
                builder.run_command(cmd, build_path, env=env)
            else:
                builder.run_command_colorized(cmd, build_path, env=env)
        except subprocess.CalledProcessError:
            return fmt('@{rf}Invoking @{boldon}"cmake"@{boldoff} failed')
    else:
        cmd = ['make', 'cmake_check_build_system']
        #new_env = common.generate_environment(base_path) # underlays + current workspace
        try:
            builder.print_command_banner(cmd, build_path, color=not args.no_color)
            if args.no_color:
                builder.run_command(cmd, build_path, env=env)
            else:
                builder.run_command_colorized(cmd, build_path, env=env)
        except subprocess.CalledProcessError:
            return fmt('@{rf}Invoking @{boldon}"make cmake_check_build_system"@{boldoff} failed')

    insert_yujin_make_signature(base_path, devel_path)

    # invoke make
    if not args.cmake_only:
        if args.target:
            cmd = ['make', args.target]
        elif args.install:
            cmd = ['make', 'install']
        elif args.tests:
            cmd = ['make', 'tests']
        elif args.run_tests:
            cmd = ['make', 'test']
        else:
            cmd = ['make']
        jobs = args.jobs
        if args.jobs == '':
            cmd.append('-j')
        else:
            jobs = args.jobs
            if not jobs:
                if 'ROS_PARALLEL_JOBS' in os.environ:
                    ros_parallel_jobs = os.environ['ROS_PARALLEL_JOBS']
                    cmd += [arg for arg in ros_parallel_jobs.split(' ') if arg]
                else:
                    jobs = multiprocessing.cpu_count()
            if jobs:
                cmd.append('-j%d' % jobs)
                cmd.append('-l%d' % jobs)
        cmd += args.make_args
        try:
            make_path = build_path
            if args.pkg:
                make_path = os.path.join(make_path, packages_by_name[args.pkg])
            builder.print_command_banner(cmd, make_path, color=not args.no_color)
            builder.run_command(cmd, make_path, env=env)
        except subprocess.CalledProcessError:
            return fmt('@{rf}Invoking @{boldon}"make"@{boldoff} failed')

    if args.doc:
        make_doc(source_path, doc_path, packages)