Skip to content

Commit

Permalink
Merge pull request #152 from kyrofa/catkin_support_roslaunch
Browse files Browse the repository at this point in the history
Catkin plugin: Add support for ROS tools.
  • Loading branch information
come-maiz committed Dec 7, 2015
2 parents bd115ad + edd1367 commit fc51421
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 28 deletions.
4 changes: 2 additions & 2 deletions examples/ros/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ description: A really small ROS example

binaries:
listener:
exec: opt/ros/indigo/beginner_tutorials/lib/beginner_tutorials/listener
exec: rosrun beginner_tutorials listener
talker:
exec: opt/ros/indigo/beginner_tutorials/lib/beginner_tutorials/talker
exec: rosrun beginner_tutorials talker

services:
rosmaster:
Expand Down
11 changes: 6 additions & 5 deletions examples/ros/src/beginner_tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# %Tag(FULLTEXT)%
cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

Expand All @@ -25,7 +24,6 @@ add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})

## Build service client and server
# %Tag(SRVCLIENT)%
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)
Expand All @@ -34,6 +32,9 @@ add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)

# %EndTag(SRVCLIENT)%

# %EndTag(FULLTEXT)%
## Mark executables for installation
install(TARGETS talker listener add_two_ints_server add_two_ints_client
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
49 changes: 29 additions & 20 deletions snapcraft/plugins/catkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import tempfile
import logging
import shutil
import re

import snapcraft
from snapcraft import repo
Expand Down Expand Up @@ -91,7 +92,6 @@ def env(self, root):
'lib',
self.python_version,
'dist-packages')),
'DESTDIR={0}'.format(self.installdir),
# ROS needs it but doesn't set it :-/
'CPPFLAGS="-std=c++11 $CPPFLAGS -I{0} -I{1}"'.format(
os.path.join(root, 'usr', 'include', 'c++', self.gcc_version),
Expand All @@ -105,6 +105,10 @@ def env(self, root):
root,
self.options.rosversion),
'ROS_MASTER_URI=http://localhost:11311',

# Various ROS tools (e.g. rospack) keep a cache, and they determine
# where the cache goes using $ROS_HOME.
'ROS_HOME=$SNAP_APP_USER_DATA_PATH/.ros',
'_CATKIN_SETUP_DIR={}'.format(os.path.join(
root, 'opt', 'ros', self.options.rosversion)),
'echo FOO=BAR\nif `test -e {0}` ; then\n. {0} ;\nfi\n'.format(
Expand Down Expand Up @@ -239,20 +243,19 @@ def build(self):
self._find_package_deps()
self._build_packages_deps()

# the hacks
findcmd = ['find', self.installdir, '-name', '*.cmake', '-delete']
self.run(findcmd)

self.run(
['rm', '-f',
'opt/ros/' + self.options.rosversion + '/.catkin',
'opt/ros/' + self.options.rosversion + '/.rosinstall',
'opt/ros/' + self.options.rosversion + '/setup.sh',
'opt/ros/' + self.options.rosversion + '/_setup_util.py'],
cwd=self.installdir)

# FIXME: Removing this here since it'll clash with the one from
# roscore. Remove this line once the roscore plugin is gone.
os.remove(os.path.join(self.installdir, 'usr/bin/xml2-config'))

# Fix the shebang in _setup_util.py to be portable
with open('{}/opt/ros/{}/_setup_util.py'.format(
self.installdir, self.options.rosversion), 'r+') as f:
pattern = re.compile(r'#!.*python')
replaced = pattern.sub(r'#!/usr/bin/env python', f.read())
f.seek(0)
f.truncate()
f.write(replaced)

def _build_packages_deps(self):
# Ugly dependency resolution, just loop through until we can
# find something to build. When we do, build it. Loop until we
Expand All @@ -276,26 +279,32 @@ def _build_packages_deps(self):
def _handle_package(self, pkg):
catkincmd = ['catkin_make_isolated']

# Install the package
catkincmd.append('--install')

# Specify the package to be built
catkincmd.append('--pkg')
catkincmd.append(pkg)

# Define the location
# Don't clutter the real ROS workspace-- use the Snapcraft build
# directory
catkincmd.extend(['--directory', self.builddir])

# Specify that the package should be installed along with the rest of
# the ROS distro.
catkincmd.extend(['--install-space', self.rosdir])

# Start the CMake Commands
catkincmd.append('--cmake-args')

# CMake directories
catkincmd.append('-DCATKIN_DEVEL_PREFIX={}'.format(self.rosdir))
catkincmd.append('-DCMAKE_INSTALL_PREFIX={}'.format(self.installdir))

# Dep CMake files
# Make sure all ROS dependencies can be found, even without the
# workspace setup
for dep in self.dependencies:
catkincmd.append('-D{0}_DIR={1}'.format(
dep.replace('-', '_'),
os.path.join(self.rosdir, 'share', dep, 'cmake')))

# Compiler fun
# Make sure we're using the compilers included in this .snap
catkincmd.extend([
'-DCMAKE_C_FLAGS="$CFLAGS"',
'-DCMAKE_CXX_FLAGS="$CPPFLAGS"',
Expand Down
76 changes: 75 additions & 1 deletion snapcraft/tests/test_plugin_catkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,90 @@ class _IOError(IOError):
errno = os.errno.EACCES


class CatkinTestCase(tests.TestCase):
class CatkinPluginTestCase(tests.TestCase):

def setUp(self):
super().setUp()

class props:
rosversion = 'foo'
catkin_packages = ['my_package']

self.properties = props()

patcher = mock.patch('snapcraft.repo.Ubuntu')
self.ubuntu_mock = patcher.start()
self.addCleanup(patcher.stop)

def test_pull_debian_dependencies(self):
plugin = catkin.CatkinPlugin('test-part', self.properties)

tmpdir = tempfile.TemporaryDirectory()
self.addCleanup(tmpdir.cleanup)
plugin.sourcedir = tmpdir.name

# Create ROS package directory
os.mkdir(os.path.join(plugin.sourcedir, "my_package"))

# Now create my_package's package.xml:
with open(os.path.join(plugin.sourcedir, "my_package",
"package.xml"), 'w') as f:
f.write("""<?xml version="1.0"?>
<package>
<buildtool_depend>buildtool_depend</buildtool_depend>
<build_depend>build_depend</build_depend>
<run_depend>run_depend</run_depend>
</package>""")

plugin.pull()

self.ubuntu_mock.assert_has_calls([
mock.call().get([
'ros-foo-buildtool-depend',
'ros-foo-build-depend',
'ros-foo-run-depend']),
mock.call().unpack(plugin.installdir)])

def test_pull_local_dependencies(self):
self.properties.catkin_packages.append('package_2')

plugin = catkin.CatkinPlugin('test-part', self.properties)

tmpdir = tempfile.TemporaryDirectory()
self.addCleanup(tmpdir.cleanup)
plugin.sourcedir = tmpdir.name

# Create ROS package directory for both packages
os.mkdir(os.path.join(plugin.sourcedir, "my_package"))
os.mkdir(os.path.join(plugin.sourcedir, "package_2"))

# Now create my_package's package.xml, specifying that is depends upon
# package_2:
with open(os.path.join(plugin.sourcedir, "my_package",
"package.xml"), 'w') as f:
f.write("""<?xml version="1.0"?>
<package>
<build_depend>package_2</build_depend>
</package>""")

# Finally, create package_2's package.xml, specifying that is has no
# dependencies:
with open(os.path.join(plugin.sourcedir, "package_2",
"package.xml"), 'w') as f:
f.write("""<?xml version="1.0"?>
<package>
</package>""")

plugin.pull()

self.assertTrue('my_package' in plugin.package_local_deps,
'Expected "my_package" to be in the dependencies')
self.assertEqual(plugin.package_local_deps['my_package'],
{'package_2'},
'Expected "my_package" to depend upon "package_2"')
self.assertFalse(self.ubuntu_mock.called,
"Ubuntu packages were unexpectedly pulled down")

def test_log_warning_when_unable_to_find_a_catkin_package(self):
fake_logger = fixtures.FakeLogger()
self.useFixture(fake_logger)
Expand Down

0 comments on commit fc51421

Please sign in to comment.