Using catkin plugin from external device

I’m trying to build my current ROS workspace from an armhf board with a tiny disk and I’m running out of space. In order to solve that, I thought that inserting an external device like an SD card and building the snap from there would be a good workaround, however, the next problem with rosdep is arising:

/media/sdcard/mmcblk1p1/snap$ snapcraft
Preparing to pull workspace                                                                                                                                                                                                                                                                                                                                                                                                                 
Pulling workspace 
Preparing to fetch compilers...
Fetching compilers...                                                                                                                                                                                                                                                                                                                                                                            
Installing compilers...
Preparing to fetch rosdep...
Fetching rosdep...                                                                                                                                                                                                                                                                                                                                                                              
Installing rosdep...
Initializing rosdep database...

/usr/bin/env: python: No such file or directory

Sorry, Snapcraft ran into an error when trying to running through its
lifecycle that generated the following traceback:
Traceback (most recent call last):
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/plugins/_ros/rosdep.py", line 88, in setup
    self._run(['init'])
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/plugins/_ros/rosdep.py", line 196, in _run
    env=env).decode('utf8').strip()
  File "/snap/snapcraft/1427/usr/lib/python3.5/subprocess.py", line 626, in check_output
    **kwargs).stdout
  File "/snap/snapcraft/1427/usr/lib/python3.5/subprocess.py", line 708, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['rosdep', 'init']' returned non-zero exit status 127

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/snap/snapcraft/1427/bin/snapcraft", line 11, in <module>
    load_entry_point('snapcraft==2.41', 'console_scripts', 'snapcraft')()
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 1043, in invoke
    return Command.invoke(self, ctx)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1427/usr/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 87, in augment_usage_errors
    yield
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/cli/_runner.py", line 79, in run
    ctx.forward(lifecyclecli.commands['snap'])
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 553, in forward
    return self.invoke(cmd, **kwargs)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1427/usr/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 87, in augment_usage_errors
    yield
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/cli/lifecycle.py", line 139, in snap
    project_options, directory=directory, output=output)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/lifecycle/_packer.py", line 46, in snap
    execute('prime', project_options)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/lifecycle/_runner.py", line 80, in execute
    _Executor(config, project_options).run(step, part_names)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/lifecycle/_runner.py", line 191, in run
    self._run_step(step, part, part_names)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/lifecycle/_runner.py", line 236, in _run_step
    getattr(part, step)()
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/__init__.py", line 354, in pull
    self._runner.pull()
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/_runner.py", line 81, in pull
    self._sourcedir)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/_runner.py", line 166, in _run_scriptlet
    scriptlet_name, function_call.strip())))
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/_runner.py", line 214, in _handle_builtin_function
    function(**function_args)
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/__init__.py", line 361, in _do_pull
    self.plugin.pull()
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/plugins/catkin.py", line 461, in pull
    rosdep.setup()
  File "/snap/snapcraft/1427/lib/python3.5/site-packages/snapcraft/plugins/_ros/rosdep.py", line 92, in setup
    'Error initializing rosdep database:\n{}'.format(output))
RuntimeError: Error initializing rosdep database:

The same snap works fine if I execute it from a non-external directory (I’m using the source-space tag to point where is the workspace, using an absolute path). In order to check that this functionality is supported by snapcraft, I tried to build the “hello-world” snap from the external media, thing that I could do without any problem. Is it doable what I am trying to do? Is there a better option? Any advice is appreciated!

I’m a little confused how you’ve got this setup, mind giving me some more clarity? So you have your snapcraft.yaml in /media/sdcard/mmcblk1p1/snap, but it’s pointing to a workspace not in the same directory? And you’re doing that with source-space? Any chance you can share your YAML, or a redacted version?

Sure thing! I am using this example instead of my real snapcraft.yaml for clarity.

name: publisher-subscriber
version: '0.1'
summary: ROS Example
description: |
  The ROS publisher/subscriber example packaged as a snap.

grade: stable
confinement: strict

parts:
  workspace:
    plugin: catkin
    rosdistro: indigo
    source-space: /home/ubuntu/Projects/catkin_ws/src
    catkin-packages: [beginner_tutorials]

apps:
  roscore:
    command: roscore
    plugs: [network, network-bind]

  talker:
    command: rosrun beginner_tutorials talker
    plugs: [network, network-bind]

  listener:
    command: rosrun beginner_tutorials listener
    plugs: [network, network-bind]

If I use this snap from “local” (/home/ubuntu/Projects/snap or any other folder like /var/snap_tests/snaps) it works. However, if I do it from /media/sdcard/mmcblk1p1/snap it doesn’t.

I am starting to think that might be related to the way the SD card is mounted in the system. I have a specific rule in /etc/udev/rules.d for it and maybe something is not as smooth as it should…

OK, found it. It wasn’t anything related to the snapcraft.yaml, neither to how the media was being mounted with my custom udev rule. it was because somehow the SD card file-system was FAT32. After changing it to ext4 it works as expected. Sorry for the noise!