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')
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')
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))
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)