Created
February 14, 2015 21:01
-
-
Save nevalsar/e9299bd32969c4c3e825 to your computer and use it in GitHub Desktop.
ROS setup files for workspace environment overlay on zsh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Software License Agreement (BSD License) | |
# | |
# Copyright (c) 2012, Willow Garage, Inc. | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# | |
# * Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above | |
# copyright notice, this list of conditions and the following | |
# disclaimer in the documentation and/or other materials provided | |
# with the distribution. | |
# * Neither the name of Willow Garage, Inc. nor the names of its | |
# contributors may be used to endorse or promote products derived | |
# from this software without specific prior written permission. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
# POSSIBILITY OF SUCH DAMAGE. | |
'''This file generates shell code for the setup.SHELL scripts to set environment variables''' | |
from __future__ import print_function | |
import argparse | |
import copy | |
import errno | |
import os | |
import platform | |
import sys | |
CATKIN_MARKER_FILE = '.catkin' | |
system = platform.system() | |
IS_DARWIN = (system == 'Darwin') | |
IS_WINDOWS = (system == 'Windows') | |
# subfolder of workspace prepended to CMAKE_PREFIX_PATH | |
ENV_VAR_SUBFOLDERS = { | |
'CMAKE_PREFIX_PATH': '', | |
'CPATH': 'include', | |
'LD_LIBRARY_PATH' if not IS_DARWIN else 'DYLD_LIBRARY_PATH': ['lib', os.path.join('lib', 'x86_64-linux-gnu')], | |
'PATH': 'bin', | |
'PKG_CONFIG_PATH': [os.path.join('lib', 'pkgconfig'), os.path.join('lib', 'x86_64-linux-gnu', 'pkgconfig')], | |
'PYTHONPATH': 'lib/python2.7/dist-packages', | |
} | |
def rollback_env_variables(environ, env_var_subfolders): | |
''' | |
Generate shell code to reset environment variables | |
by unrolling modifications based on all workspaces in CMAKE_PREFIX_PATH. | |
This does not cover modifications performed by environment hooks. | |
''' | |
lines = [] | |
unmodified_environ = copy.copy(environ) | |
for key in sorted(env_var_subfolders.keys()): | |
subfolders = env_var_subfolders[key] | |
if not isinstance(subfolders, list): | |
subfolders = [subfolders] | |
for subfolder in subfolders: | |
value = _rollback_env_variable(unmodified_environ, key, subfolder) | |
if value is not None: | |
environ[key] = value | |
lines.append(assignment(key, value)) | |
if lines: | |
lines.insert(0, comment('reset environment variables by unrolling modifications based on all workspaces in CMAKE_PREFIX_PATH')) | |
return lines | |
def _rollback_env_variable(environ, name, subfolder): | |
''' | |
For each catkin workspace in CMAKE_PREFIX_PATH remove the first entry from env[NAME] matching workspace + subfolder. | |
:param subfolder: str '' or subfoldername that may start with '/' | |
:returns: the updated value of the environment variable. | |
''' | |
value = environ[name] if name in environ else '' | |
env_paths = [path for path in value.split(os.pathsep) if path] | |
value_modified = False | |
if subfolder: | |
if subfolder.startswith(os.path.sep) or (os.path.altsep and subfolder.startswith(os.path.altsep)): | |
subfolder = subfolder[1:] | |
if subfolder.endswith(os.path.sep) or (os.path.altsep and subfolder.endswith(os.path.altsep)): | |
subfolder = subfolder[:-1] | |
for ws_path in _get_workspaces(environ, include_fuerte=True, include_non_existing=True): | |
path_to_find = os.path.join(ws_path, subfolder) if subfolder else ws_path | |
path_to_remove = None | |
for env_path in env_paths: | |
env_path_clean = env_path[:-1] if env_path and env_path[-1] in [os.path.sep, os.path.altsep] else env_path | |
if env_path_clean == path_to_find: | |
path_to_remove = env_path | |
break | |
if path_to_remove: | |
env_paths.remove(path_to_remove) | |
value_modified = True | |
new_value = os.pathsep.join(env_paths) | |
return new_value if value_modified else None | |
def _get_workspaces(environ, include_fuerte=False, include_non_existing=False): | |
''' | |
Based on CMAKE_PREFIX_PATH return all catkin workspaces. | |
:param include_fuerte: The flag if paths starting with '/opt/ros/fuerte' should be considered workspaces, ``bool`` | |
''' | |
# get all cmake prefix paths | |
env_name = 'CMAKE_PREFIX_PATH' | |
value = environ[env_name] if env_name in environ else '' | |
paths = [path for path in value.split(os.pathsep) if path] | |
# remove non-workspace paths | |
workspaces = [path for path in paths if os.path.isfile(os.path.join(path, CATKIN_MARKER_FILE)) or (include_fuerte and path.startswith('/opt/ros/fuerte')) or (include_non_existing and not os.path.exists(path))] | |
return workspaces | |
def prepend_env_variables(environ, env_var_subfolders, workspaces): | |
''' | |
Generate shell code to prepend environment variables | |
for the all workspaces. | |
''' | |
lines = [] | |
lines.append(comment('prepend folders of workspaces to environment variables')) | |
paths = [path for path in workspaces.split(os.pathsep) if path] | |
prefix = _prefix_env_variable(environ, 'CMAKE_PREFIX_PATH', paths, '') | |
lines.append(prepend(environ, 'CMAKE_PREFIX_PATH', prefix)) | |
for key in sorted([key for key in env_var_subfolders.keys() if key != 'CMAKE_PREFIX_PATH']): | |
subfolder = env_var_subfolders[key] | |
prefix = _prefix_env_variable(environ, key, paths, subfolder) | |
lines.append(prepend(environ, key, prefix)) | |
return lines | |
def _prefix_env_variable(environ, name, paths, subfolders): | |
''' | |
Return the prefix to prepend to the environment variable NAME, adding any path in NEW_PATHS_STR without creating duplicate or empty items. | |
''' | |
value = environ[name] if name in environ else '' | |
environ_paths = [path for path in value.split(os.pathsep) if path] | |
checked_paths = [] | |
for path in paths: | |
if not isinstance(subfolders, list): | |
subfolders = [subfolders] | |
for subfolder in subfolders: | |
path_tmp = path | |
if subfolder: | |
path_tmp = os.path.join(path_tmp, subfolder) | |
# exclude any path already in env and any path we already added | |
if path_tmp not in environ_paths and path_tmp not in checked_paths: | |
checked_paths.append(path_tmp) | |
prefix_str = os.pathsep.join(checked_paths) | |
if prefix_str != '' and environ_paths: | |
prefix_str += os.pathsep | |
return prefix_str | |
def assignment(key, value): | |
if not IS_WINDOWS: | |
return 'export %s="%s"' % (key, value) | |
else: | |
return 'set %s=%s' % (key, value) | |
def comment(msg): | |
if not IS_WINDOWS: | |
return '# %s' % msg | |
else: | |
return 'REM %s' % msg | |
def prepend(environ, key, prefix): | |
if key not in environ or not environ[key]: | |
return assignment(key, prefix) | |
if not IS_WINDOWS: | |
return 'export %s="%s$%s"' % (key, prefix, key) | |
else: | |
return 'set %s=%s%%%s%%' % (key, prefix, key) | |
def find_env_hooks(environ, cmake_prefix_path): | |
''' | |
Generate shell code with found environment hooks | |
for the all workspaces. | |
''' | |
lines = [] | |
lines.append(comment('found environment hooks in workspaces')) | |
generic_env_hooks = [] | |
generic_env_hooks_workspace = [] | |
specific_env_hooks = [] | |
specific_env_hooks_workspace = [] | |
generic_env_hooks_by_filename = {} | |
specific_env_hooks_by_filename = {} | |
generic_env_hook_ext = 'bat' if IS_WINDOWS else 'sh' | |
specific_env_hook_ext = environ['CATKIN_SHELL'] if not IS_WINDOWS and 'CATKIN_SHELL' in environ and environ['CATKIN_SHELL'] else None | |
# remove non-workspace paths | |
workspaces = [path for path in cmake_prefix_path.split(os.pathsep) if path and os.path.isfile(os.path.join(path, CATKIN_MARKER_FILE))] | |
for workspace in reversed(workspaces): | |
env_hook_dir = os.path.join(workspace, 'etc', 'catkin', 'profile.d') | |
if os.path.isdir(env_hook_dir): | |
for filename in sorted(os.listdir(env_hook_dir)): | |
if filename.endswith('.%s' % generic_env_hook_ext): | |
# remove previous env hook with same name if present | |
if filename in generic_env_hooks_by_filename: | |
i = generic_env_hooks.index(generic_env_hooks_by_filename[filename]) | |
generic_env_hooks.pop(i) | |
generic_env_hooks_workspace.pop(i) | |
# append env hook | |
generic_env_hooks.append(os.path.join(env_hook_dir, filename)) | |
generic_env_hooks_workspace.append(workspace) | |
generic_env_hooks_by_filename[filename] = generic_env_hooks[-1] | |
elif specific_env_hook_ext is not None and filename.endswith('.%s' % specific_env_hook_ext): | |
# remove previous env hook with same name if present | |
if filename in specific_env_hooks_by_filename: | |
i = specific_env_hooks.index(specific_env_hooks_by_filename[filename]) | |
specific_env_hooks.pop(i) | |
specific_env_hooks_workspace.pop(i) | |
# append env hook | |
specific_env_hooks.append(os.path.join(env_hook_dir, filename)) | |
specific_env_hooks_workspace.append(workspace) | |
specific_env_hooks_by_filename[filename] = specific_env_hooks[-1] | |
env_hooks = generic_env_hooks + specific_env_hooks | |
env_hooks_workspace = generic_env_hooks_workspace + specific_env_hooks_workspace | |
count = len(env_hooks) | |
lines.append(assignment('_CATKIN_ENVIRONMENT_HOOKS_COUNT', count)) | |
for i in range(count): | |
lines.append(assignment('_CATKIN_ENVIRONMENT_HOOKS_%d' % i, env_hooks[i])) | |
lines.append(assignment('_CATKIN_ENVIRONMENT_HOOKS_%d_WORKSPACE' % i, env_hooks_workspace[i])) | |
return lines | |
def _parse_arguments(args=None): | |
parser = argparse.ArgumentParser(description='Generates code blocks for the setup.SHELL script.') | |
parser.add_argument('--extend', action='store_true', help='Skip unsetting previous environment variables to extend context') | |
return parser.parse_known_args(args=args)[0] | |
if __name__ == '__main__': | |
try: | |
try: | |
args = _parse_arguments() | |
except Exception as e: | |
print(e, file=sys.stderr) | |
sys.exit(1) | |
# environment at generation time | |
CMAKE_PREFIX_PATH = '/home/routeaccess/projects/swarm_robotics/devel;/opt/ros/indigo'.split(';') | |
# prepend current workspace if not already part of CPP | |
base_path = os.path.dirname(__file__) | |
if base_path not in CMAKE_PREFIX_PATH: | |
CMAKE_PREFIX_PATH.insert(0, base_path) | |
CMAKE_PREFIX_PATH = os.pathsep.join(CMAKE_PREFIX_PATH) | |
environ = dict(os.environ) | |
lines = [] | |
if not args.extend: | |
lines += rollback_env_variables(environ, ENV_VAR_SUBFOLDERS) | |
lines += prepend_env_variables(environ, ENV_VAR_SUBFOLDERS, CMAKE_PREFIX_PATH) | |
lines += find_env_hooks(environ, CMAKE_PREFIX_PATH) | |
print('\n'.join(lines)) | |
# need to explicitly flush the output | |
sys.stdout.flush() | |
except IOError as e: | |
# and catch potantial "broken pipe" if stdout is not writable | |
# which can happen when piping the output to a file but the disk is full | |
if e.errno == errno.EPIPE: | |
print(e, file=sys.stderr) | |
sys.exit(2) | |
raise | |
sys.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# generated from catkin/cmake/template/setup.sh.in | |
# Sets various environment variables and sources additional environment hooks. | |
# It tries it's best to undo changes from a previously sourced setup file before. | |
# Supported command line options: | |
# --extend: skips the undoing of changes from a previously sourced setup file | |
# since this file is sourced either use the provided _CATKIN_SETUP_DIR | |
# or fall back to the destination set at configure time | |
: ${_CATKIN_SETUP_DIR:=/home/routeaccess/projects/swarm_robotics/devel} | |
_SETUP_UTIL="$_CATKIN_SETUP_DIR/_setup_util.py" | |
unset _CATKIN_SETUP_DIR | |
if [ ! -f "$_SETUP_UTIL" ]; then | |
echo "Missing Python script: $_SETUP_UTIL" | |
return 22 | |
fi | |
# detect if running on Darwin platform | |
_UNAME=`uname -s` | |
_IS_DARWIN=0 | |
if [ "$_UNAME" = "Darwin" ]; then | |
_IS_DARWIN=1 | |
fi | |
unset _UNAME | |
# make sure to export all environment variables | |
export CMAKE_PREFIX_PATH | |
export CPATH | |
if [ $_IS_DARWIN -eq 0 ]; then | |
export LD_LIBRARY_PATH | |
else | |
export DYLD_LIBRARY_PATH | |
fi | |
unset _IS_DARWIN | |
export PATH | |
export PKG_CONFIG_PATH | |
export PYTHONPATH | |
# remember type of shell if not already set | |
if [ -z "$CATKIN_SHELL" ]; then | |
CATKIN_SHELL=sh | |
fi | |
# invoke Python script to generate necessary exports of environment variables | |
_SETUP_TMP=`mktemp /tmp/setup.sh.XXXXXXXXXX` | |
if [ $? -ne 0 -o ! -f "$_SETUP_TMP" ]; then | |
echo "Could not create temporary file: $_SETUP_TMP" | |
return 1 | |
fi | |
CATKIN_SHELL=$CATKIN_SHELL "$_SETUP_UTIL" $@ > $_SETUP_TMP | |
_RC=$? | |
if [ $_RC -ne 0 ]; then | |
if [ $_RC -eq 2 ]; then | |
echo "Could not write the output of '$_SETUP_UTIL' to temporary file '$_SETUP_TMP': may be the disk if full?" | |
else | |
echo "Failed to run '\"$_SETUP_UTIL\" $@': return code $_RC" | |
fi | |
unset _RC | |
unset _SETUP_UTIL | |
rm -f $_SETUP_TMP | |
unset _SETUP_TMP | |
return 1 | |
fi | |
unset _RC | |
unset _SETUP_UTIL | |
. $_SETUP_TMP | |
rm -f $_SETUP_TMP | |
unset _SETUP_TMP | |
# source all environment hooks | |
_i=0 | |
while [ $_i -lt $_CATKIN_ENVIRONMENT_HOOKS_COUNT ]; do | |
eval _envfile=\$_CATKIN_ENVIRONMENT_HOOKS_$_i | |
unset _CATKIN_ENVIRONMENT_HOOKS_$_i | |
eval _envfile_workspace=\$_CATKIN_ENVIRONMENT_HOOKS_${_i}_WORKSPACE | |
unset _CATKIN_ENVIRONMENT_HOOKS_${_i}_WORKSPACE | |
# set workspace for environment hook | |
CATKIN_ENV_HOOK_WORKSPACE=$_envfile_workspace | |
. "$_envfile" | |
unset CATKIN_ENV_HOOK_WORKSPACE | |
_i=$((_i + 1)) | |
done | |
unset _i | |
unset _CATKIN_ENVIRONMENT_HOOKS_COUNT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
# generated from catkin/cmake/templates/setup.zsh.in | |
CATKIN_SHELL=zsh | |
# source setup.sh from same directory as this file | |
_CATKIN_SETUP_DIR=$(builtin cd -q "`dirname "$0"`" > /dev/null && pwd) | |
source "$_CATKIN_SETUP_DIR/setup.sh" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment