Creating a snap
This tutorial will demonstrate how to use Snapcraft to create a new snap, and how to use it.
First, let us install Snapcraft.
$ sudo snap install --classic snapcraft
(Note that the snapcraft Debian package from the apt repositories is largely deprecated. One should use the snap package.)
Snapcraft has built-in support for Catkin. In order for it to know which project components to include, you must ensure that your projects have install rules.
For our example, we will use roscpp_tutorials from the ros_tutorials.
Initialize a new Snapcraft project here:
$ mkdir ~/roscpp_tutorials_snap $ cd ~/roscpp_tutorials_snap $ snapcraft init
This will create a file in a subdirectory snap/snapcraft.yaml
The snapcraft file
Open that snap/snapcraft.yaml file and copy over the following:
name: ros-talker-listener version: '0.1' summary: ROS Talker/Listener Example description: | This example launches a ROS talker and listener. confinement: devmode base: core18 parts: ros-tutorials: plugin: catkin source: https://github.com/ros/ros_tutorials.git source-branch: melodic-devel source-space: roscpp_tutorials/ apps: ros-talker-listener: command: roslaunch roscpp_tutorials talker_listener.launch
Don't worry, we will break it down together.
name: ros-talker-listener version: '0.1' summary: ROS Talker/Listener Example description: | This example launches a ROS talker and listener.
This is the basic metadata that all snaps require. These fields are fairly self-explanatory but note that the name must be globally unique across all snaps.
The base keyword defines a special kind of snap that provides a run-time environment with a minimal set of libraries that are common to most applications. Core18 is the current standard base for snap building and is based on Ubuntu 18.04 LTS. It is, therefore, the base used for Melodic.
3. Security model
parts: ros-tutorials: plugin: catkin source: https://github.com/ros/ros_tutorials.git source-branch: melodic-devel source-space: roscpp_tutorials/
Parts define how to build your app. In this case, we have one: ros-tutorials. Parts can point to local directories, remote git repositories, or tarballs. Here, we specify our source as a GitHub repository at a specific branch. We also specifically tell Catkin to build the roscpp_tutorials subdirectory. For more information about the plugin and it options, please refer to the online documentation. The Catkin packages you’re building must have install rules, or the snapcraft CLI won’t know which components to place into the snap. Make sure you install binaries, libraries, header files, launch files, etc.
apps: ros-talker-listener: command: roslaunch roscpp_tutorials talker_listener.launch
Apps are the commands exposed to end users. Each key under apps is the command name that should be made available on users’ systems. The command keyword specifies the command to be run as its name suggests.
Building the snap
Now that we are all set up, let’s build the snap:
$ cd ~/roscpp_tutorials_snap $ snapcraft *EXPERIMENTAL* extensions enabled. Launching a VM. Launched: snapcraft-ros-talker-listener [...] Snapped ros-talker-listener_0.1_amd64.snap
That will take a few minutes. From the logs, and among other things, you will see Snapcraft using rosdep to pull the dependencies of your package but also Catkin building your application. That is because internally, Snapcraft relies on the familiar ROS tool.
Testing the snap
This snap is completely standalone: it includes ROS and your application, meaning that you don’t even need to install ROS on your system. Let's test it out:
$ sudo snap install ros-talker-listener_0.1_amd64.snap --devmode
Note that we use --devmode here because the snap is devmode confinement. The moment of truth, will it run?
[ INFO] [1497643945.491444894]: hello world 0 [ INFO] [1497643945.495444894]: I heard: [hello world 0] [ INFO] [1497643945.591430533]: hello world 1 [ INFO] [1497643945.595430533]: I heard: [hello world 1] [ INFO] [1497643945.691426519]: hello world 2 [ INFO] [1497643945.695426519]: I heard: [hello world 2] [ INFO] [1497643945.791444793]: hello world 3 [ INFO] [1497643945.795444793]: I heard: [hello world 3]
It does! We see the expected output!