summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorhauptmech2013-01-17 13:03:34 +0100
committerBenjamin Chrétien2015-06-20 02:25:11 +0900
commit5c90be666022c1bdf8abffe316920b944851a9cd (patch)
treedb3469845d3bdb7867543bd17a1b509cba1eca27
downloadaur-5c90be666022c1bdf8abffe316920b944851a9cd.tar.gz
Squashed commits
-rw-r--r--.SRCINFO27
-rw-r--r--PKGBUILD42
-rw-r--r--PKGBUILD.rostemplate32
-rwxr-xr-xcreate-arch-ros-package-legacy.sh62
-rwxr-xr-xfix-python-scripts.sh17
-rwxr-xr-xgenerate-python-patch.sh20
-rwxr-xr-xgenerate_packages_makefile.py130
-rwxr-xr-xget_stack_dependencies.py55
-rwxr-xr-ximport_catkin_packages.py353
-rw-r--r--stack-install-tools.sh56
10 files changed, 794 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..ab67b5c27caf
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,27 @@
+pkgbase = ros-build-tools
+ pkgdesc = Utilities for building arch packages for ROS stacks.
+ pkgver = 0.0.1
+ pkgrel = 3
+ url = http://www.ros.org
+ arch = i686
+ arch = x86_64
+ license = BSD
+ source = fix-python-scripts.sh
+ source = stack-install-tools.sh
+ source = create-arch-ros-package-legacy.sh
+ source = PKGBUILD.rostemplate
+ source = get_stack_dependencies.py
+ source = generate_packages_makefile.py
+ source = generate-python-patch.sh
+ source = import_catkin_packages.py
+ md5sums = b2b4fd23abb8e9e7382ef9aeab2542f5
+ md5sums = 79ae7fb600e116623a42631d15d66a87
+ md5sums = ac82eca7efc9f0ff7e8b976a83692868
+ md5sums = f3378832c3ba121f7c9e17dc43c8b1d4
+ md5sums = d257f7f20384e894b0431ee61068aa96
+ md5sums = 563c9d1320a3a997db25d3087303dcfb
+ md5sums = 8d6d7eb89a12c449497b209f1a06655b
+ md5sums = 85fc98bd9df02afa0d8a27c01db78c66
+
+pkgname = ros-build-tools
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..9e9addb1f47b
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,42 @@
+# Maintainer: Sean Greenslade <zootboysean@gmail.com>
+
+pkgdesc='Utilities for building arch packages for ROS stacks.'
+url=http://www.ros.org
+
+pkgname='ros-build-tools'
+pkgver='0.0.1'
+arch=('i686' 'x86_64')
+pkgrel=3
+license=('BSD')
+makedepends=()
+depends=()
+
+pkg_destination_dir="/usr/share/ros-build-tools"
+
+source=('fix-python-scripts.sh'
+ 'stack-install-tools.sh'
+ 'create-arch-ros-package-legacy.sh'
+ 'PKGBUILD.rostemplate'
+ 'get_stack_dependencies.py'
+ 'generate_packages_makefile.py'
+ 'generate-python-patch.sh'
+ 'import_catkin_packages.py')
+
+build() {
+ return 0
+}
+package() {
+ mkdir -p ${pkgdir}${pkg_destination_dir}
+ for file in "${source[@]}"; do
+ cp $file ${pkgdir}${pkg_destination_dir}/$file
+ done
+}
+
+md5sums=('b2b4fd23abb8e9e7382ef9aeab2542f5'
+ '79ae7fb600e116623a42631d15d66a87'
+ 'ac82eca7efc9f0ff7e8b976a83692868'
+ 'f3378832c3ba121f7c9e17dc43c8b1d4'
+ 'd257f7f20384e894b0431ee61068aa96'
+ '563c9d1320a3a997db25d3087303dcfb'
+ '8d6d7eb89a12c449497b209f1a06655b'
+ '85fc98bd9df02afa0d8a27c01db78c66')
diff --git a/PKGBUILD.rostemplate b/PKGBUILD.rostemplate
new file mode 100644
index 000000000000..7c0e9489dbbc
--- /dev/null
+++ b/PKGBUILD.rostemplate
@@ -0,0 +1,32 @@
+
+pkgdesc='Fill me.'
+url='http://www.ros.org/'
+
+pkgname='ros-groovy-@PACKAGE_NAME@'
+pkgver='@STACK_VERSION@'
+arch=('i686' 'x86_64')
+pkgrel=1
+license=('BSD')
+makedepends=('ros-build-tools')
+
+ros_depends(@ROS_STACK_DEPENDENCIES)
+depends=(${ros_depends[@]})
+
+source=("@STACK_URL@"
+ '@STACK_NAME@.patch')
+md5sums=('@STACK_MD5@'
+ '@STACK_PATCH_MD5@')
+
+source /usr/share/ros-build-tools/stack-install-tools.sh
+source /opt/ros/@ROS_DISTRO@/setup.bash
+
+build() {
+ export ROS_PACKAGE_PATH=${srcdir}/stacks:$ROS_PACKAGE_PATH
+
+ mkdir -p ${srcdir}/stacks
+ [ -L ${srcdir}/stacks/@STACK_NAME@ ] || ln -sf ../@STACK_NAME@-${pkgver} ${srcdir}/stacks/@STACK_NAME@
+ cd $srcdir/stacks; patch -p0 -i "$srcdir/@STACK_NAME@.patch"
+ rosmake --no-rosdep -i @STACK_NAME@
+ install_ros_stack ${srcdir}/stacks/@STACK_NAME@ /opt/ros/@ROS_DISTRO@/stacks/@STACK_NAME@
+}
+
diff --git a/create-arch-ros-package-legacy.sh b/create-arch-ros-package-legacy.sh
new file mode 100755
index 000000000000..8dc73945d5f2
--- /dev/null
+++ b/create-arch-ros-package-legacy.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -e
+
+if [ -z "$3" ]; then
+ echo "Usage: $0 <distro> <stack> <version>"
+ exit 1
+fi
+
+DISTRO=$1
+STACK=$2
+PACKAGE=$(echo $STACK | sed 's/_/-/g')
+VERSION=$3
+URL=https://code.ros.org/svn/release/download/stacks/$STACK/$STACK-$VERSION/$STACK-$VERSION.tar.bz2
+
+PACKAGE_DIRECTORY=$(pwd)/$STACK
+
+if [ -d $PACKAGE_DIRECTORY ]; then
+ read -p "Directory $STACK already exists. Overwrite? (y/n) "
+ if ! [ "$REPLY" == "y" ]; then
+ exit 0
+ fi
+fi
+
+mkdir -p $PACKAGE_DIRECTORY
+cd $PACKAGE_DIRECTORY
+
+[ -f ${STACK}-${VERSION}.tar.bz2 ] || wget "$URL"
+if ! [ -f "${STACK}-${VERSION}.tar.bz2" ]; then
+ echo "Invalid stack name or version. Downloaded file does not match ${STACK}-${VERSION}.tar.bz2"
+ exit 1
+fi
+MD5=$(md5sum ${STACK}-${VERSION}.tar.bz2 | awk '{print $1}')
+
+cp /usr/share/ros-build-tools/PKGBUILD.rostemplate $PACKAGE_DIRECTORY/PKGBUILD
+
+mkdir $PACKAGE_DIRECTORY/tmp
+cd $PACKAGE_DIRECTORY/tmp
+tar xvjf $PACKAGE_DIRECTORY/${STACK}-${VERSION}.tar.bz2
+cp -r $PACKAGE_DIRECTORY/tmp/${STACK}-${VERSION} $PACKAGE_DIRECTORY/tmp/$STACK
+/usr/share/ros-build-tools/fix-python-scripts.sh $PACKAGE_DIRECTORY/tmp/$STACK
+diff -Naur ${STACK}-${VERSION} $STACK > $PACKAGE_DIRECTORY/$STACK.patch || true
+STACK_DEPENDENCIES=$(/usr/share/ros-build-tools/get-stack-dependencies.py $STACK/stack.xml \
+ | sed 's/_/-/g' | sed 's/^/ros-electric-/g' | sed 's/ / ros-electric-/g')
+cd $PACKAGE_DIRECTORY
+rm -r $PACKAGE_DIRECTORY/tmp
+
+PATCH_MD5=$(md5sum ${STACK}.patch | awk '{print $1}')
+
+sed -i "s/@PACKAGE_NAME@/$PACKAGE/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@STACK_NAME@/$STACK/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@STACK_VERSION@/$VERSION/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s?@STACK_URL@?$URL?g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@STACK_MD5@/$MD5/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@STACK_PATCH_MD5@/$PATCH_MD5/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@ROS_DISTRO@/$DISTRO/g" $PACKAGE_DIRECTORY/PKGBUILD
+sed -i "s/@ROS_STACK_DEPENDENCIES@/$STACK_DEPENDENCIES/g" $PACKAGE_DIRECTORY/PKGBUILD
+
+echo ""
+echo "PKGBUILD and patch created for stack $STACK."
+echo ""
+echo "Fill in dependencies and the stack description."
diff --git a/fix-python-scripts.sh b/fix-python-scripts.sh
new file mode 100755
index 000000000000..2bc55852b364
--- /dev/null
+++ b/fix-python-scripts.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 <directory>"
+ echo ""
+ echo "Makes sure that all python scripts use the python2 command"
+ exit 1
+fi
+
+for file in $(grep -rl 'env python *$' $1); do
+ if [ -z "$file" ]; then
+ echo "Error finding files."
+ exit 1
+ fi
+ sed -i 's/env python *$/env python2/g' $file
+done
+
diff --git a/generate-python-patch.sh b/generate-python-patch.sh
new file mode 100755
index 000000000000..b3c9f672802d
--- /dev/null
+++ b/generate-python-patch.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -e
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 <stack-archive.tar.bz2>"
+ exit 1
+fi
+
+SCRIPT_DIR=$(readlink -f `dirname $0`)
+STACK_ARCHIVE_FILE_NAME=$(basename $1)
+STACK_ARCHIVE_DIR_NAME=$(readlink -f `dirname $1`)
+
+STACK_NAME=${1%.tar.bz2}
+TMP_DIRECTORY_NAME=$(mktemp -d /tmp/${STACK_NAME}.XXXXXXXXXX)
+cd $TMP_DIRECTORY_NAME
+tar xjf ${STACK_ARCHIVE_DIR_NAME}/${STACK_ARCHIVE_FILE_NAME}
+cp -r ${STACK_NAME} ${STACK_NAME}-orig
+$SCRIPT_DIR/fix-python-scripts.sh ${TMP_DIRECTORY_NAME}/${STACK_NAME}
+diff -Naur ${STACK_NAME}-orig ${STACK_NAME}
diff --git a/generate_packages_makefile.py b/generate_packages_makefile.py
new file mode 100755
index 000000000000..b43364ae34b7
--- /dev/null
+++ b/generate_packages_makefile.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+
+import os.path
+import subprocess
+import sys
+
+
+MAKEFILE_TARGET = """
+.PHONY : %(package)s
+%(package)s: %(package)s/%(output_file)s
+
+%(package)s/%(output_file)s: %(dependency_string)s
+\tcd %(package)s; makepkg -i
+"""
+
+
+class InvalidPackage(Exception):
+ def __init__(self, package):
+ self.package = package
+
+ def __str__(self):
+ return repr(self.package)
+
+
+class Dependency(object):
+
+ def __init__(self, directory_name, package_name, dependencies, output_file):
+ self.directory_name = directory_name
+ self.package_name = package_name
+ self.dependencies = dependencies
+ self.output_file = output_file
+
+
+class DependencyCache(object):
+
+ def __init__(self):
+ self._dependencies = {}
+
+ def add_package_directory(self, name):
+ pkgbuild_file = os.path.realpath(name + '/PKGBUILD')
+ if not os.path.exists(pkgbuild_file):
+ raise InvalidPackage(name)
+ aur_package_name = get_package_name(pkgbuild_file)
+ if len(aur_package_name) == 0:
+ raise InvalidPackage(name)
+ dependencies = get_dependencies(pkgbuild_file)
+ output_file = get_pkgbuild_output_file(pkgbuild_file)
+ self._dependencies[aur_package_name] = Dependency(
+ name, aur_package_name, dependencies, output_file)
+
+ def get_package_names(self):
+ return list(self._dependencies.keys())
+
+ def get_packages(self):
+ return list(self._dependencies.values())
+
+ def get_package(self, name):
+ return self._dependencies[name]
+
+ def get_package_directory_name(self, name):
+ return self._dependencies[name].directory_name
+
+ def get_dependencies(self, package_name, remove_unknown=True):
+ package_dependencies = self._dependencies.get(package_name)
+ if package_dependencies is None:
+ raise InvalidPackage(package_name)
+ if not remove_unknown:
+ return package_dependencies
+ return [self._dependencies[dependency] for dependency in package_dependencies.dependencies
+ if self._dependencies.get(dependency)]
+
+
+def get_pkgbuild_variable(pkgbuild, variable, is_array=False):
+ if is_array:
+ array_string = '[@]'
+ else:
+ array_string = ''
+ with subprocess.Popen(
+ 'source %s && echo ${%s%s}' % (pkgbuild, variable, array_string),
+ shell=True, stdout=subprocess.PIPE) as shell_process:
+ if is_array:
+ return shell_process.stdout.readline().decode().split()
+ else:
+ return shell_process.stdout.readline().decode().strip()
+
+
+def get_pkgbuild_output_file(pkgbuild):
+ with subprocess.Popen(
+ 'source %s && echo ${pkgname}-${pkgver}-${pkgrel}-${HOSTTYPE}.pkg.tar.xz' % (pkgbuild),
+ shell=True, stdout=subprocess.PIPE) as shell_process:
+ return shell_process.stdout.readline().decode().strip()
+
+
+def get_dependencies(pkgbuild):
+ return get_pkgbuild_variable(pkgbuild, 'depends', is_array=True)
+
+
+def get_package_name(pkgbuild):
+ return get_pkgbuild_variable(pkgbuild, 'pkgname')
+
+
+def generate_makefile(cache):
+ makefile = """
+all: %s
+""" % ' '.join(['%s/%s' % (package.directory_name, package.output_file)
+ for package in cache.get_packages()])
+
+ for package in cache.get_package_names():
+ dependency_string = ' '.join(['%s/%s' % (dependency.directory_name, dependency.output_file)
+ for dependency in cache.get_dependencies(package)])
+ makefile += MAKEFILE_TARGET % {'package': cache.get_package_directory_name(package),
+ 'output_file': cache.get_package(package).output_file,
+ 'dependency_string': dependency_string}
+ return makefile
+
+
+def main():
+ if len(sys.argv) < 2:
+ print('Usage: %s <AUR package>*' % sys.argv[0])
+ return 1
+
+ dependency_cache = DependencyCache()
+ for arg in sys.argv[1:]:
+ dependency_cache.add_package_directory(arg)
+
+ print(generate_makefile(dependency_cache))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/get_stack_dependencies.py b/get_stack_dependencies.py
new file mode 100755
index 000000000000..8ad5b2fad816
--- /dev/null
+++ b/get_stack_dependencies.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+# Copyright (c) 2012, Lorenz Moesenlechner <moesenle@in.tum.de>
+# 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 the Intelligent Autonomous Systems Group/
+# Technische Universitaet Muenchen 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.
+
+import xml.dom.minidom as minidom
+import sys
+
+
+def main():
+ if len(sys.argv) < 2:
+ print('Usage: %s <stack.xml>' % sys.argv[0])
+ return 1
+
+ top_level = minidom.parse(sys.argv[1])
+ if len(top_level.childNodes) != 1 or top_level.childNodes[0].nodeName != 'stack':
+ print('Invalid stack.xml. No <stack> node found on toplevel.')
+ return 1
+ stack = top_level.childNodes[0]
+ legacy_dependency_nodes = [n for n in stack.childNodes if n.nodeName == 'depend']
+ if legacy_dependency_nodes:
+ print(*[n.getAttribute('stack') for n in legacy_dependency_nodes],
+ sep=' ', end='')
+ else:
+ dependencies = [n.firstChild.wholeText for n in stack.childNodes
+ if n.nodeName == 'depends']
+ print(*dependencies, sep=' ', end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/import_catkin_packages.py b/import_catkin_packages.py
new file mode 100755
index 000000000000..e0a15f3d4f71
--- /dev/null
+++ b/import_catkin_packages.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python2
+
+
+from __future__ import print_function
+
+import catkin_pkg.package
+from optparse import OptionParser
+import os
+import os.path
+import subprocess
+import urllib2
+import urlparse
+import yaml
+
+
+class PackageBase(object):
+
+ def __init__(self, distro, repository_url, name, version):
+ self.packages = []
+ self.distro = distro
+ self.repository_url = repository_url
+ package = self._parse_package_file(
+ self._get_package_xml_url(repository_url, name, version))
+ self.name = package.name
+ self.version = package.version
+ self.licenses = package.licenses
+ self.description = package.description
+ self.dependencies = [self._ensure_python2_dependency(dependency.name)
+ for dependency in package.build_depends + package.run_depends]
+
+ def _parse_package_file(self, url):
+ """
+ Parses the package.xml file specified by `url`.
+
+ Arguments:
+ - `url`: Valid URL pointing to a package.xml file.
+ """
+ return catkin_pkg.package.parse_package_string(
+ urllib2.urlopen(url).read())
+
+ def _get_ros_dependencies(self):
+ known_packages = self.distro.package_names(expand_metapackages=True)
+ return list(set(
+ [self._rosify_package_name(
+ 'ros-%s-' % self.distro.name + dependency)
+ for dependency in self.dependencies if dependency in known_packages]))
+
+ def _get_non_ros_dependencies(self):
+ known_packages = self.distro.package_names(expand_metapackages=True)
+ return list(set([dependency for dependency in self.dependencies
+ if dependency not in known_packages]))
+
+ def _rosify_package_name(self, name):
+ return name.replace('_', '-')
+
+ def _ensure_python2_dependency(self, dependency):
+ return dependency.replace('python-', 'python2-')
+
+ def _get_package_xml_url(self, url, name, version):
+ if url.find('github'):
+ return github_raw_url(url, 'package.xml', 'release/%s/%s' % (name, version))
+ else:
+ raise 'Unable to generate url for package.xml'
+
+ def generate(self, exclude_dependencies=[]):
+ raise '`generate` not implemented.'
+
+
+class Package(PackageBase):
+ BUILD_TEMPLATE = """
+pkgdesc="%(description)s"
+url='http://www.ros.org/'
+
+pkgname='ros-%(distro)s-%(arch_package_name)s'
+pkgver='%(package_version)s'
+arch=('i686' 'x86_64')
+pkgrel=1
+license=('%(license)s')
+makedepends=('ros-build-tools')
+
+ros_depends=(%(ros_package_dependencies)s)
+depends=(${ros_depends[@]}
+ %(other_dependencies)s)
+
+source=()
+md5sums=()
+
+build() {
+ [ -f /opt/ros/%(distro)s/setup.bash ] && source /opt/ros/%(distro)s/setup.bash
+ if [ -d ${srcdir}/%(package_name)s ]; then
+ cd ${srcdir}/%(package_name)s
+ git fetch origin --tags
+ git reset --hard release/%(package_name)s/${pkgver}
+ else
+ git clone -b release/%(package_name)s/${pkgver} %(package_url)s ${srcdir}/%(package_name)s
+ fi
+ [ -d ${srcdir}/build ] || mkdir ${srcdir}/build
+ cd ${srcdir}/build
+ /usr/share/ros-build-tools/fix-python-scripts.sh ${srcdir}/%(package_name)s
+ cmake ${srcdir}/%(package_name)s -DCATKIN_BUILD_BINARY_PACKAGE=ON -DCMAKE_INSTALL_PREFIX=/opt/ros/%(distro)s -DPYTHON_EXECUTABLE=/usr/bin/python2 -DPYTHON_INCLUDE_DIR=/usr/include/python2.7 -DPYTHON_LIBRARY=/usr/lib/libpython2.7.so -DSETUPTOOLS_DEB_LAYOUT=OFF
+ make
+}
+
+package() {
+ cd "${srcdir}/build"
+ make DESTDIR="${pkgdir}/" install
+}
+"""
+
+ def generate(self, exclude_dependencies=[]):
+ ros_dependencies = [dependency for dependency in self._get_ros_dependencies()
+ if dependency not in exclude_dependencies]
+ other_dependencies = [dependency for dependency in self._get_non_ros_dependencies()
+ if dependency not in exclude_dependencies]
+ return self.BUILD_TEMPLATE % {
+ 'distro': self.distro.name,
+ 'arch_package_name': self._rosify_package_name(self.name),
+ 'package_name': self.name,
+ 'package_version': self.version,
+ 'package_url': self.repository_url,
+ 'license': ', '.join(self.licenses),
+ 'description': self.description.replace('"', '\\"').replace('`', '\`'),
+ 'ros_package_dependencies': '\n '.join(ros_dependencies),
+ 'other_dependencies': '\n '.join(other_dependencies)
+ }
+
+
+class MetaPackage(PackageBase):
+ BUILD_TEMPLATE = """
+pkgdesc="%(description)s"
+url='http://www.ros.org/'
+
+pkgname='ros-%(distro)s-%(arch_package_name)s'
+pkgver='%(package_version)s'
+arch=('i686' 'x86_64')
+pkgrel=1
+license=('%(license)s')
+makedepends=('ros-build-tools')
+
+ros_depends=(%(ros_package_dependencies)s)
+depends=(${ros_depends[@]}
+ %(other_dependencies)s)
+
+source=()
+md5sums=()
+
+"""
+
+ def __init__(self, distro, repository_url, name, version):
+ super(MetaPackage, self).__init__(distro, repository_url, name, version)
+ self.packages = [Package(distro, repository_url, child_name, version)
+ for child_name in distro.meta_package_package_names(name)]
+
+ def generate(self, exclude_dependencies=[]):
+ ros_dependencies = [dependency for dependency in self._get_ros_dependencies()
+ if dependency not in exclude_dependencies]
+ other_dependencies = [dependency for dependency in self._get_non_ros_dependencies()
+ if dependency not in exclude_dependencies]
+ return self.BUILD_TEMPLATE % {
+ 'distro': self.distro.name,
+ 'arch_package_name': self._rosify_package_name(self.name),
+ 'package_name': self.name,
+ 'package_version': self.version,
+ 'license': ', '.join(self.licenses),
+ 'description': self.description.replace('"', '\"'),
+ 'ros_package_dependencies': '\n '.join(ros_dependencies),
+ 'other_dependencies': '\n '.join(other_dependencies)
+ }
+
+
+class DistroDescription(object):
+
+ def __init__(self, name, url):
+ stream = urllib2.urlopen(url)
+ self.name = name
+ self._distro = yaml.load(stream)
+ self._package_cache = {}
+ if self.name != self._distro['release-name']:
+ raise 'ROS distro names do not match (%s != %s)' % (self.name, self._distro['release-name'])
+
+ def package_names(self, expand_metapackages=False):
+ packages = [name for name in self._distro['repositories'].keys()]
+ if expand_metapackages:
+ return sum([([name] + self.meta_package_package_names(name)) if self._is_meta_package(name) else [name]
+ for name in packages],
+ [])
+ else:
+ return packages
+
+ def is_package(self, name):
+ return self._get_package_data(name) != None
+
+ def package(self, name):
+ package_data = self._get_package_data(name)
+ if not package_data:
+ raise 'Unable to find package `%s`' % name
+ if self._package_cache.get(name):
+ return self._package_cache[name]
+ url = package_data['url']
+ version = package_data['version'].split('-')[0]
+ if self._is_meta_package(name):
+ package = MetaPackage(self, url, name, version)
+ else:
+ package = Package(self, url, name, version)
+ self._package_cache[name] = package
+ return package
+
+ def meta_package_package_names(self, name):
+ return self._distro['repositories'][name]['packages'].keys()
+
+ def _is_meta_package(self, name):
+ if self._distro['repositories'].get(name):
+ return (self._distro['repositories'][name].get('packages') != None)
+
+ def _get_package_data(self, name):
+ """Searches for `name` in all known packages and metapackages."""
+ if self._distro['repositories'].get(name):
+ return self._distro['repositories'][name]
+ else:
+ for package in self.package_names():
+ if (self._is_meta_package(package)
+ and name in self._distro['repositories'][package]['packages']):
+ return self._distro['repositories'][package]
+
+
+def list_packages(distro_description):
+ print(*distro_description.package_names(), sep='\n')
+
+
+### From http://code.activestate.com/recipes/577058/ (r2)
+def query_yes_no(question, default="yes"):
+ """Ask a yes/no question via raw_input() and return their answer.
+
+ "question" is a string that is presented to the user.
+ "default" is the presumed answer if the user just hits <Enter>.
+ It must be "yes" (the default), "no" or None (meaning
+ an answer is required of the user).
+
+ The "answer" return value is one of "yes" or "no".
+ """
+ valid = {"yes":"yes", "y":"yes", "ye":"yes",
+ "no":"no", "n":"no"}
+ if default == None:
+ prompt = " [y/n] "
+ elif default == "yes":
+ prompt = " [Y/n] "
+ elif default == "no":
+ prompt = " [y/N] "
+ else:
+ raise ValueError("invalid default answer: '%s'" % default)
+ while True:
+ print(question + prompt)
+ choice = raw_input().lower()
+ if default is not None and choice == '':
+ return default
+ elif choice in valid.keys():
+ return valid[choice]
+ else:
+ print("Please respond with 'yes' or 'no' (or 'y' or 'n').")
+
+
+def github_raw_url(repo_url, path, commitish):
+ """
+ Returns the URL of the file blob corresponding to `path` in the
+ github repository `repo_url` in branch, commit or tag `commitish`.
+ """
+ url = urlparse.urlsplit(repo_url)
+ return 'https://raw.%(host)s%(repo_path)s/%(branch)s/%(path)s' % {
+ 'host': url.hostname,
+ 'repo_path': url.path.replace('.git', ''),
+ 'branch': commitish,
+ 'path': path
+ }
+
+
+def generate_pkgbuild(distro, package, directory, force=False,
+ no_overwrite=False, recursive=False, exclude_dependencies=[],
+ generated=None):
+ if generated is None:
+ generated = []
+ elif package.name in generated:
+ return
+ generated.append(package.name)
+ if package.packages:
+ for child_package in package.packages:
+ generate_pkgbuild(distro, child_package, directory,
+ force=force, exclude_dependencies=exclude_dependencies,
+ no_overwrite=no_overwrite, recursive=recursive,
+ generated=generated)
+ if recursive:
+ for dependency in package.dependencies:
+ if distro.is_package(dependency):
+ generate_pkgbuild(distro, distro.package(dependency), directory,
+ force=force, no_overwrite=no_overwrite, recursive=recursive,
+ exclude_dependencies=exclude_dependencies,
+ generated=generated)
+ output_directory = os.path.join(directory, package.name)
+ if not os.path.exists(output_directory):
+ os.mkdir(output_directory)
+ if os.path.exists(os.path.join(output_directory, 'PKGBUILD')):
+ if no_overwrite:
+ return
+ if not force and not query_yes_no(
+ "Directory '%s' already contains a PKGBUILD file. Overwrite?" % (
+ output_directory)):
+ return
+ print('Generating PKGBUILD for package %s.' % package.name)
+ with open(os.path.join(output_directory, 'PKGBUILD'), 'w') as pkgbuild:
+ pkgbuild.write(package.generate(exclude_dependencies))
+
+
+def main():
+ parser = OptionParser(usage='usage: %prog [options] PACKAGE...')
+ parser.add_option('--distro', default='groovy', metavar='distro',
+ help='Select the ROS distro to use.')
+ parser.add_option('--list-packages', dest='list_packages', action='store_true',
+ default=False, help='Lists all available packages.')
+ parser.add_option('--output-directory', metavar='output_directory', default='.',
+ help='The output directory. Packages are put into <output-directory>/<name>')
+ parser.add_option(
+ '--distro-url', metavar='distro_url',
+ default='https://raw.github.com/ros/rosdistro/master/releases/%s.yaml',
+ help='The URL of the distro description. %s is replaced by the actual distro name')
+ parser.add_option(
+ '--exclude-dependencies', metavar='exclude_dependencies',
+ default='python2-catkin-pkg,python2-rospkg,python2-rosdep',
+ help='Comma-separated list of (source) package dependencies to exclude from the generated PKGBUILD file.')
+ parser.add_option('-f', '--force', dest='force', action='store_true', default=False,
+ help='Always overwrite exiting PKGBUILD files.')
+ parser.add_option('-n', '--no-overwrite', dest='no_overwrite', action='store_true', default=False,
+ help='Do not overwrite PKGBUILD files.')
+ parser.add_option('--recursive', dest='recursive', action='store_true', default=False,
+ help='Recursively import dependencies')
+ options, args = parser.parse_args()
+
+ distro = DistroDescription(
+ options.distro, url=options.distro_url % options.distro)
+ if options.list_packages:
+ list_packages(distro)
+ return
+ elif args:
+ for package in args:
+ generate_pkgbuild(distro, distro.package(package),
+ os.path.abspath(options.output_directory),
+ exclude_dependencies=options.exclude_dependencies.split(','),
+ force=options.force, no_overwrite=options.no_overwrite,
+ recursive=options.recursive)
+ else:
+ parser.error('No packages specified.')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/stack-install-tools.sh b/stack-install-tools.sh
new file mode 100644
index 000000000000..1bbb4212f4d6
--- /dev/null
+++ b/stack-install-tools.sh
@@ -0,0 +1,56 @@
+# Copyright (c) 2012, Lorenz Moesenlechner <moesenle@in.tum.de>
+# 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 the Intelligent Autonomous Systems Group/
+# Technische Universitaet Muenchen 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.
+
+install_ros_stack() {
+ if [ -z "$1" ] || [ -z "$2" ]; then
+ echo "Usage: install_ros_stack <src-dir> <ros-dir>"
+ exit 1
+ fi
+
+ mkdir -p $pkgdir/$2
+ cp -r $1/* $pkgdir/$2
+ find $pkgdir/$2 -name manifest.xml -printf '%h/build\n' | xargs rm -rf
+ fix_rpaths $1 $2
+}
+
+fix_rpaths() {
+ if [ -z "$1" ] || [ -z "$2" ]; then
+ echo "Usage: fix_rpaths <src-dir> <ros-dir>"
+ exit 1
+ fi
+
+ executables=$(find $pkgdir/$2 -type f -executable)
+ for file in $executables; do
+ rpath_output=$(chrpath -l $file 2>/dev/null || echo "")
+ if [ -n "$rpath_output" ] && echo $rpath_output | grep RPATH; then
+ fixed_rpath=$(echo $rpath_output | sed 's/.*RPATH=//g' | sed "s?$1?$2?g")
+ chrpath -r $fixed_rpath $file
+ fi
+ done
+}
+