def print_command_banner(cmd, cwd, color): if color: # Prepare for printing cmd_str = sanitize(' '.join(cmd)) cwd_str = sanitize(cwd) # Print command notice cprint('@{bf}####') cprint('@{bf}#### Running command: @!"%s"@|@{bf} in @!"%s"' % (cmd_str, cwd_str)) cprint('@{bf}####') else: print('####') print('#### Running command: "%s" in "%s"' % (' '.join(cmd), cwd)) print('####')
def test_terminal_colors(self): # since other test might disable ansi colors # we need to ensure it is enabled enable_ANSI_colors() assert ansi('reset') != '' test = '@_This is underlined@|' rslt = '\033[4mThis is underlined\033[0m\033[0m' assert fmt(test) == rslt test = 'This has bad stuff @! @/ @_ @| OK!' test = sanitize(test) rslt = 'This has bad stuff @! @/ @_ @| OK!\033[0m' assert fmt(test) == rslt test = char(2018) test = sanitize(test) rslt = char(2018) assert test == rslt
def colorize_line(line): cline = sanitize(line) cline = cline.replace( '-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~', '-- @{pf}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@|' ) if line.startswith('-- ~~'): # -- ~~ - cline = cline.replace('~~ ', '@{pf}~~ @|') cline = cline.replace(' - ', ' - @!@{bf}') cline = cline.replace('(', '@|(') cline = cline.replace('(plain cmake)', '@|(@{rf}plain cmake@|)') cline = cline.replace('(unknown)', '@|(@{yf}unknown@|)') if line.startswith('-- +++'): # -- +++ add_subdirectory(package) cline = cline.replace('+++', '@!@{gf}+++@|') cline = cline.replace('kin package: \'', 'kin package: \'@!@{bf}') cline = cline.replace(')', '@|)') cline = cline.replace('\'\n', '@|\'\n') cline = cline.replace('cmake package: \'', 'cmake package: \'@!@{bf}') cline = cline.replace('\'\n', '@|\'\n') if line.startswith('-- ==>'): cline = cline.replace('-- ==>', '-- @!@{bf}==>@|') if line.lower().startswith('warning'): # WARNING cline = ansi('yf') + cline if line.startswith('CMake Warning'): # CMake Warning... cline = cline.replace('CMake Warning', '@{yf}@!CMake Warning@|') if line.startswith('ERROR:'): # ERROR: cline = cline.replace('ERROR:', '@!@{rf}ERROR:@|') if line.startswith('CMake Error'): # CMake Error... cline = cline.replace('CMake Error', '@{rf}@!CMake Error@|') if line.startswith('Call Stack (most recent call first):'): # CMake Call Stack cline = cline.replace('Call Stack (most recent call first):', '@{cf}@_Call Stack (most recent call first):@|') return fmt(cline)
def build_cmake_package( path, package, workspace, buildspace, develspace, installspace, install, force_cmake, quiet, last_env, cmake_args, make_args, destdir=None, use_ninja=False, use_nmake=False, use_gmake=False ): # Notify the user that we are processing a plain cmake package cprint( "Processing @{cf}plain cmake@| package: '@!@{bf}" + package.name + "@|'" ) # Make the build dir if install: build_dir_name = '%s%sinstall' % (package.name, os.sep) else: build_dir_name = '%s%sdevel' % (package.name, os.sep) build_dir = _check_build_dir(build_dir_name, workspace, buildspace) # Check last_env if last_env is not None: cprint(blue_arrow + " Building with env: " + "'{0}'".format(sanitize(last_env))) # Check for Makefile and maybe call cmake if not use_ninja: makefile_name = 'Makefile' else: makefile_name = 'build.ninja' makefile = os.path.join(build_dir, makefile_name) install_target = installspace if install else develspace if not os.path.exists(makefile) or force_cmake: # Call cmake cmake_cmd = [ 'cmake', os.path.dirname(package.filename), '-DCMAKE_INSTALL_PREFIX=' + install_target ] cmake_cmd.extend(cmake_args) isolation_print_command(' '.join(cmake_cmd), build_dir) if last_env is not None: cmake_cmd = [last_env] + cmake_cmd run_command_colorized(cmake_cmd, build_dir, quiet) else: print('%s exists, skipping explicit cmake invocation...' % makefile_name) # Check to see if cmake needs to be run via make if use_ninja: make_check_cmake_cmd = ['ninja', 'build.ninja'] elif use_nmake: make_check_cmake_cmd = ['nmake', 'cmake_check_build_system'] elif use_gmake: make_check_cmake_cmd = ['gmake', 'cmake_check_build_system'] else: make_check_cmake_cmd = ['make', 'cmake_check_build_system'] isolation_print_command(' '.join(make_check_cmake_cmd), build_dir) if last_env is not None: make_check_cmake_cmd = [last_env] + make_check_cmake_cmd run_command_colorized( make_check_cmake_cmd, build_dir, quiet ) # Run make if use_ninja: make_executable = 'ninja' elif use_nmake: make_executable = 'nmake' elif use_gmake: make_executable = 'gmake' else: make_executable = 'make' make_cmd = [make_executable] make_cmd.extend(handle_make_arguments(make_args, append_default_jobs_flags=not use_nmake)) isolation_print_command(' '.join(make_cmd), build_dir) if last_env is not None: make_cmd = [last_env] + make_cmd if install: run_command(make_cmd, build_dir, quiet) else: run_command(make_cmd, build_dir, quiet, add_env={'DESTDIR': ''}) # Make install make_install_cmd = [make_executable, 'install'] isolation_print_command(' '.join(make_install_cmd), build_dir) if last_env is not None: make_install_cmd = [last_env] + make_install_cmd run_command(make_install_cmd, build_dir, quiet) env_script = 'env' + ('.bat' if sys.platform == 'win32' else '.sh') # If an env script already exists, don't overwrite it if install and os.path.exists(prefix_destdir(os.path.join(install_target, env_script), destdir)): return cprint(blue_arrow + " Generating an " + env_script) # Generate env script for chaining to catkin packages # except if using --merge which implies that new_env_path equals last_env new_env_path = os.path.join(install_target, env_script) if install: new_env_path = prefix_destdir(new_env_path, destdir) if new_env_path != last_env: variables = { 'SETUP_DIR': install_target, 'SETUP_FILENAME': 'setup' } if not os.path.exists(os.path.dirname(new_env_path)): os.makedirs(os.path.dirname(new_env_path)) env_script_writer = write_env_bat if sys.platform == 'win32' else write_env_sh env_script_writer(dest_file=new_env_path, variables=variables) # Generate setup script for chaining to catkin packages # except if using --merge which implies that new_setup_path equals last_setup_env setup_script = 'setup' + ('.bat' if sys.platform == 'win32' else '.sh') new_setup_path = os.path.join(install_target, setup_script) if install: new_setup_path = prefix_destdir(new_setup_path, destdir) last_setup_env = os.path.join(os.path.dirname(last_env), setup_script) if last_env is not None else None if new_setup_path != last_setup_env: subs = {} # CMAKE_PREFIX_PATH uses forward slash on all platforms. subs['cmake_prefix_path'] = install_target.replace(os.sep, '/') subs['ld_path'] = os.path.join(install_target, 'lib') pythonpath = os.path.join(install_target, get_python_install_dir()) subs['pythonpath'] = pythonpath subs['pkgcfg_path'] = os.path.join(install_target, 'lib', 'pkgconfig') subs['path'] = os.path.join(install_target, 'bin') arch = get_multiarch() if arch: subs['ld_path'] = os.pathsep.join([subs['ld_path'], os.path.join(install_target, 'lib', arch)]) subs['pkgcfg_path'] = os.pathsep.join([subs['pkgcfg_path'], os.path.join(install_target, 'lib', arch, 'pkgconfig')]) if not os.path.exists(os.path.dirname(new_setup_path)): os.mkdir(os.path.dirname(new_setup_path)) setup_script_writer = write_setup_bat if sys.platform == 'win32' else write_setup_sh last_setup_basename = os.path.splitext(last_setup_env)[0] if last_setup_env is not None else None setup_script_writer(dest_file=new_setup_path, last_setup_basename=last_setup_basename, variables=subs) if sys.platform != 'win32': # generate setup.bash|zsh scripts setup_script_template = """\ #!/usr/bin/env {1} # generated from catkin.builder Python module CATKIN_SHELL={1} . "{0}/setup.sh" """ for shell in ['bash', 'zsh']: setup_path = os.path.join(install_target, 'setup.%s' % shell) if install: setup_path = prefix_destdir(setup_path, destdir) with open(setup_path, 'w') as f: f.write(setup_script_template.format(os.path.dirname(setup_path), shell))
def build_catkin_package( path, package, workspace, buildspace, develspace, installspace, install, force_cmake, quiet, last_env, cmake_args, make_args, destdir=None, use_ninja=False, use_nmake=False, use_gmake=False ): cprint( "Processing @{cf}catkin@| package: '@!@{bf}" + package.name + "@|'" ) # Make the build dir build_dir = _check_build_dir(package.name, workspace, buildspace) # Check last_env if last_env is not None: cprint( blue_arrow + " Building with env: " + "'{0}'".format(sanitize(last_env)) ) # Check for Makefile and maybe call cmake if not use_ninja: makefile_name = 'Makefile' else: makefile_name = 'build.ninja' makefile = os.path.join(build_dir, makefile_name) if not os.path.exists(makefile) or force_cmake: package_dir = os.path.dirname(package.filename) if not os.path.exists(os.path.join(package_dir, 'CMakeLists.txt')): export_tags = [e.tagname for e in package.exports] if 'metapackage' not in export_tags: print(colorize_line('Error: Package "%s" does not have a CMakeLists.txt file' % package.name)) sys.exit('Can not build catkin package without CMakeLists.txt file') # generate CMakeLists.txt for metpackages without one print(colorize_line('Warning: metapackage "%s" should have a CMakeLists.txt file' % package.name)) cmake_code = configure_file( get_metapackage_cmake_template_path(), {'name': package.name, 'metapackage_arguments': 'DIRECTORY "%s"' % package_dir}) cmakelists_txt = os.path.join(build_dir, 'CMakeLists.txt') with open(cmakelists_txt, 'w') as f: f.write(cmake_code) package_dir = build_dir # Run cmake cmake_cmd = [ 'cmake', package_dir, '-DCATKIN_DEVEL_PREFIX=' + develspace, '-DCMAKE_INSTALL_PREFIX=' + installspace ] cmake_cmd.extend(cmake_args) add_env = get_additional_environment(install, destdir, installspace) isolation_print_command(' '.join(cmake_cmd), build_dir, add_env=add_env) if last_env is not None: cmake_cmd = [last_env] + cmake_cmd try: run_command_colorized(cmake_cmd, build_dir, quiet, add_env=add_env) except subprocess.CalledProcessError as e: if os.path.exists(makefile): # remove Makefile to force CMake invocation next time os.remove(makefile) raise else: print('%s exists, skipping explicit cmake invocation...' % makefile_name) # Check to see if cmake needs to be run via make if use_ninja: make_check_cmake_cmd = ['ninja', 'build.ninja'] elif use_nmake: make_check_cmake_cmd = ['nmake', 'cmake_check_build_system'] elif use_gmake: make_check_cmake_cmd = ['gmake', 'cmake_check_build_system'] else: make_check_cmake_cmd = ['make', 'cmake_check_build_system'] add_env = get_additional_environment(install, destdir, installspace) isolation_print_command(' '.join(make_check_cmake_cmd), build_dir, add_env=add_env) if last_env is not None: make_check_cmake_cmd = [last_env] + make_check_cmake_cmd run_command_colorized( make_check_cmake_cmd, build_dir, quiet, add_env=add_env ) # Run make if use_ninja: make_executable = 'ninja' elif use_nmake: make_executable = 'nmake' elif use_gmake: make_executable = 'gmake' else: make_executable = 'make' make_cmd = [make_executable] make_cmd.extend(handle_make_arguments(make_args, append_default_jobs_flags=not use_nmake)) isolation_print_command(' '.join(make_cmd), build_dir) if last_env is not None: make_cmd = [last_env] + make_cmd run_command(make_cmd, build_dir, quiet) # Make install # NMake doesn't have an option to list target so try it anyway if install or use_nmake: if has_make_target(build_dir, 'install', use_ninja=use_ninja, use_nmake=use_nmake, use_gmake=use_gmake): make_install_cmd = [make_executable, 'install'] isolation_print_command(' '.join(make_install_cmd), build_dir) if last_env is not None: make_install_cmd = [last_env] + make_install_cmd run_command(make_install_cmd, build_dir, quiet) else: print(fmt( '@{yf}Package has no "@{boldon}install@{boldoff}" target, skipping "%s install" invocation...' % make_executable))
def isolation_print_command(cmd, path=None, add_env=None): cprint( blue_arrow + " " + sanitize(cmd) + "@|" + (" @!@{kf}in@| '@!" + sanitize(path) + "@|'" if path else '') + (" @!@{kf}with@| '@!" + ' '.join(['%s=%s' % (k, v) for k, v in add_env.items()]) + "@|'" if add_env else '') )
def build_cmake_package(path, package, workspace, buildspace, develspace, installspace, install, force_cmake, quiet, last_env, cmake_args, make_args, destdir=None, use_ninja=False, use_nmake=False): # Notify the user that we are processing a plain cmake package cprint("Processing @{cf}plain cmake@| package: '@!@{bf}" + package.name + "@|'") # Make the build dir if install: build_dir_name = '%s%sinstall' % (package.name, os.sep) else: build_dir_name = '%s%sdevel' % (package.name, os.sep) build_dir = _check_build_dir(build_dir_name, workspace, buildspace) # Check last_env if last_env is not None: cprint(blue_arrow + " Building with env: " + "'{0}'".format(sanitize(last_env))) # Check for Makefile and maybe call cmake if not use_ninja: makefile_name = 'Makefile' else: makefile_name = 'build.ninja' makefile = os.path.join(build_dir, makefile_name) install_target = installspace if install else develspace if not os.path.exists(makefile) or force_cmake: # Call cmake cmake_cmd = [ 'cmake', os.path.dirname(package.filename), '-DCMAKE_INSTALL_PREFIX=' + install_target ] cmake_cmd.extend(cmake_args) isolation_print_command(' '.join(cmake_cmd), build_dir) if last_env is not None: cmake_cmd = [last_env] + cmake_cmd run_command_colorized(cmake_cmd, build_dir, quiet) else: print('%s exists, skipping explicit cmake invocation...' % makefile_name) # Check to see if cmake needs to be run via make if use_ninja: make_check_cmake_cmd = ['ninja', 'build.ninja'] elif use_nmake: make_check_cmake_cmd = ['nmake', 'cmake_check_build_system'] else: make_check_cmake_cmd = ['make', 'cmake_check_build_system'] isolation_print_command(' '.join(make_check_cmake_cmd), build_dir) if last_env is not None: make_check_cmake_cmd = [last_env] + make_check_cmake_cmd run_command_colorized(make_check_cmake_cmd, build_dir, quiet) # Run make if use_ninja: make_executable = 'ninja' elif use_nmake: make_executable = 'nmake' else: make_executable = 'make' make_cmd = [make_executable] make_cmd.extend( handle_make_arguments(make_args, append_default_jobs_flags=not use_nmake)) isolation_print_command(' '.join(make_cmd), build_dir) if last_env is not None: make_cmd = [last_env] + make_cmd if install: run_command(make_cmd, build_dir, quiet) else: run_command(make_cmd, build_dir, quiet, add_env={'DESTDIR': ''}) # Make install make_install_cmd = [make_executable, 'install'] isolation_print_command(' '.join(make_install_cmd), build_dir) if last_env is not None: make_install_cmd = [last_env] + make_install_cmd run_command(make_install_cmd, build_dir, quiet) # If we are installing, and a env.sh exists, don't overwrite it if install and os.path.exists( prefix_destdir(os.path.join(install_target, 'env.sh'), destdir)): return cprint(blue_arrow + " Generating an env.sh") # Generate env.sh for chaining to catkin packages # except if using --merge which implies that new_env_path equals last_env new_env_path = os.path.join(install_target, 'env.sh') if install: new_env_path = prefix_destdir(new_env_path, destdir) if new_env_path != last_env: variables = {'SETUP_DIR': install_target, 'SETUP_FILENAME': 'setup'} if not os.path.exists(os.path.dirname(new_env_path)): os.makedirs(os.path.dirname(new_env_path)) with open(os.path.join(new_env_path), 'w') as f: f.write("""\ #!/usr/bin/env sh # generated from catkin.builder module if [ $# -eq 0 ] ; then /bin/echo "Usage: env.sh COMMANDS" /bin/echo "Calling env.sh without arguments is not supported anymore. \ Instead spawn a subshell and source a setup file manually." exit 1 fi # ensure to not use different shell type which was set before CATKIN_SHELL=sh # source {SETUP_FILENAME}.sh from same directory as this file . "$(cd "`dirname "$0"`" && pwd)/{SETUP_FILENAME}.sh" exec "$@" """.format(**variables)) os.chmod(new_env_path, stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR) # Generate setup.sh for chaining to catkin packages # except if using --merge which implies that new_setup_path equals last_setup_env new_setup_path = os.path.join(install_target, 'setup.sh') if install: new_setup_path = prefix_destdir(new_setup_path, destdir) last_setup_env = os.path.join(os.path.dirname(last_env), 'setup.sh') if last_env is not None else None if new_setup_path != last_setup_env: subs = {} subs['cmake_prefix_path'] = install_target + ":" subs['ld_path'] = os.path.join(install_target, 'lib') + ":" pythonpath = os.path.join(install_target, get_python_install_dir()) subs['pythonpath'] = pythonpath + ':' subs['pkgcfg_path'] = os.path.join(install_target, 'lib', 'pkgconfig') + ":" subs['path'] = os.path.join(install_target, 'bin') + ":" arch = get_multiarch() if arch: subs['ld_path'] += os.path.join(install_target, 'lib', arch) + ":" subs['pkgcfg_path'] += os.path.join(install_target, 'lib', arch, 'pkgconfig') + ":" if not os.path.exists(os.path.dirname(new_setup_path)): os.mkdir(os.path.dirname(new_setup_path)) with open(new_setup_path, 'w') as file_handle: file_handle.write("""\ #!/usr/bin/env sh # generated from catkin.builder module # remember type of shell if not already set if [ -z "$CATKIN_SHELL" ]; then CATKIN_SHELL=sh fi """) if last_env is not None: file_handle.write('. "%s.$CATKIN_SHELL"\n\n' % last_setup_env[:-3]) file_handle.write("""\ # detect if running on Darwin platform _UNAME=`uname -s` IS_DARWIN=0 if [ "$_UNAME" = "Darwin" ]; then IS_DARWIN=1 fi # Prepend to the environment export CMAKE_PREFIX_PATH="{cmake_prefix_path}$CMAKE_PREFIX_PATH" if [ $IS_DARWIN -eq 0 ]; then export LD_LIBRARY_PATH="{ld_path}$LD_LIBRARY_PATH" else export DYLD_LIBRARY_PATH="{ld_path}$DYLD_LIBRARY_PATH" fi export PATH="{path}$PATH" export PKG_CONFIG_PATH="{pkgcfg_path}$PKG_CONFIG_PATH" export PYTHONPATH="{pythonpath}$PYTHONPATH" """.format(**subs)) # generate setup.bash|zsh scripts for shell in ['bash', 'zsh']: setup_path = os.path.join(install_target, 'setup.%s' % shell) if install: setup_path = prefix_destdir(setup_path, destdir) with open(setup_path, 'w') as f: f.write("""\ #!/usr/bin/env {1} # generated from catkin.builder module CATKIN_SHELL={1} . "{0}/setup.sh" """.format(os.path.dirname(setup_path), shell))