This article will describe installing and building snap package.
Table of Contents
1 snap package
A snap package includes private root filesystem which has libraries required by package. This will protect dependency of libraries for each package but duplicated libraryes will make size of system be large.
For example, the private root filesystem of bluez is as below.
$ tree /snap/bluez/6/ /snap/bluez/6/ ├── command-bluetoothctl.wrapper ├── command-bluez.wrapper ├── command-obexctl.wrapper ├── command-obex.wrapper ├── meta │ ├── gui │ │ └── icon.png │ └── snap.yaml └── usr ├── bin │ ├── bluetoothctl │ └── obexctl ├── lib │ ├── bluetooth │ │ ├── bluetoothd │ │ └── obexd │ └── x86_64-linux-gnu │ ├── libical.so.1 -> libical.so.1.0.1 │ ├── libical.so.1.0.1 │ ├── libicalss.so.1 -> libicalss.so.1.0.1 │ ├── libicalss.so.1.0.1 │ ├── libicalvcal.so.1 -> libicalvcal.so.1.0.1 │ └── libicalvcal.so.1.0.1 └── share └── doc ├── bluez │ ├── copyright │ └── overview.md └── libical1a └── copyright
2 Install snapd
The snapd is a tool for installing snap package. This name may be changed from snappy to snapd.
$ sudo apt install -y snapd
2.1 snap command
The snap command for package operations is as below.
snap find | List avaiable packages |
snap find <pattern> | List avaiable packages with pattern |
snap list | List installed packages |
snap install <package> | Install package |
snap remove <package> | Uninstall package |
2.2 Available packages
Available packages on 2016/6/28 are as below.
ab alsa-utils apktool atom-cwayne audovia base beagleblack bluez canonical-dragon canonical-i386 canonical-pc canonical-pc-linux canonical-pi2 cassandra cla-check compass-straightedge drmips eeevil ejabberd filebot foobar21 freecad freechartgeany gdoc-html-cleaner ghex-udt gmailfilter gnuchess go-example-webserver hangups hello hello-huge hello-snap hello-world htop http jenkins john-the-ripper kale keepassx-elopio kpcli-elopio krita languagetool links littlewatcher minecraft-server-jdstrand miniterm-joc moon-buggy morse-converter-py nextcloud nikola nmap notes open-solitaire-classic openscad-plars owncloud pciutils pen roseapple-pi scummvm serial-vault shadowsocks shout simplenote-jamiebennett snapd-hacker-toolbelt snappy-debug snapstore-example speed-test spread sshtron stellarium-plars sudo systesterpro64 taskwarrior-plars teatime-unity telegram-sergiusens tic-tac-toe tio tor-middle-relay tpad tproxy ubuntu-calculator-app ubuntu-clock-app ubuntu-core ufw vaca vault-elopio vlc vtop webcam-webui-stylerrr webdm x11-apps xkcd-webserver xkcdpass-codersquid yacas yagy
For example, jenkins has a openjdk in private root filesystem.
3 snap package structure
snap package structure is following.
3.1 /var/lib/snapd/snaps/<package>.snap
This is a squashfs image for private root filesystem. This image will be mount to /snap/<package/<rev> but read only mount because of squashfs.
$ mount | grep snap /var/lib/snapd/snaps/ubuntu-core_122.snap on /snap/ubuntu-core/122 type squashfs (ro,relatime) /var/lib/snapd/snaps/jenkins_6.snap on /snap/jenkins/6 type squashfs (ro,relatime)
3.2 /etc/systemd/system/snap-<package>-<rev>.mount
This is a systemd script for mounting <package>.snap. This will be started before snap.<package>.<component>.service.
3.3 /etc/systemd/system/snap.<package>.<component>.service
This is a systemd script for running command-<component>.wrapper as service. SNAP_XXX variable like SNAP_DATA and SNAP_USER_DATA will be set in this scripts. This is started by snapd.frameworks.target.
3.4 /snap/bin/<component>
This is a command for running command-<componetn>.wrapper. SNAP_XXX variable like SNAP_DATA and SNAP_USER_DATA will be set in this scripts. /etc/profile.d/apps-bin-path.sh will add /snap/bin to PATH variable.
3.5 /snap/<package>/<rev>/command-<component>.wrapper
This is a wrapper script running by /snap/bin/<component> and snap.<package>.<component>.service. This will exchange SNAP_XXX variable to variable of real command and run real command. The real command is like /snap/bluez/6/usr/bin/bluetoothctl.
3.6 SNAP_DATA
SNAP_DATA in almost packages is set to /var/snap/<package>/<rev>. This is used to output data like logging and database.
I think that package configuration file like /etc/<package>.conf is in this directory but this is up to command-<component>.wrapper.
For example, /snap/jenkins/6/command-jenkins.wrapper only uses SNAP_DATA as JENKINS_HOME but not uses for setting JENKINS_PORT, jenkins snap package could not change TCP port.
3.7 SNAP_USER_DATA
SNAP_USER_DATA in almost packages is set to /<user>/snap/<package>/<rev>. Data for each user will be saved.
4 Install snapcraft
The snapcraft is a tool for building snap package.
$ sudo apt install -y snapcraft
4.1 snapcraft command
The snapcraft command for package operations is as below.
snapcraft | Build package |
snapcraft clean | Clean work directory |
4.2 snapcraft-examples
The snapcraft-examples are examples for snapcraft.
$ sudo apt install -y snapcraft-examples $ ls /usr/share/doc/snapcraft-examples/examples/git 96boards-kernel godd mosquitto ros webchat busybox gopaste opencv shout downloader-with-wiki-parts java-hello-world py2-project tomcat-maven-webapp git libpipeline py3-project webcam-webui
Check git example.
$ cp -a /usr/share/doc/snapcraft-examples/examples/git . $ cd git $ tree . ├── setup │ └── gui │ └── icon.png └── snapcraft.yaml
The snapcraft.yaml is configuration file for snapcraft. This snapcraft.yaml is very simple because of make plugin.
$ cat snapcraft.yaml name: git version: 2.8.0 summary: Git is a free and open source distributed version control system. description: This example is not really production quality confinement: strict apps: server: command: bin/git parts: git: plugin: make source: https://github.com/git/git source-type: git make-parameters: - prefix= build-packages: [gettext, libssl-dev, libcurl4-openssl-dev, libexpat1-dev]
The make plugin will run "make all" and "make install DESTDIR=xxx". When Makefile defines DESTDIR properly, snapcraft.yml only needs source code URL, type, and build-packages.
Plugins of snapcraft are as below.
$ snapcraft list-plugins ant catkin copy jdk kernel maven nodejs python3 tar-content autotools cmake go kbuild make nil python2 scons
Build git snap package.
$ snapcraft $ sudo snap install git_2.8.0_amd64.snap $ ls /snap/git current x1
5 Create original snap package
This article will use tetris source code which uses simple Makefile.
Building tetris source code without snapcraft is as below. This will create jni/src/ncurses command and jni/src/sdl command.
$ sudo apt install -y libsdl2-dev libsdl2-image-dev \ libsdl2-ttf-dev libncurses5-dev
$ git clone https://github.com/hiroom2/tetris-sdl-and-ncurses
$ cd tetris-sdl-and-ncurses $ make $ ./jni/src/ncurses # or ./jni/src/sdl
Create work directory and generate snapcraft.yml template with "snapcraft init".
$ mkdir tetris $ snapcraft init # Generate template snapcraft.yml
Change snapcraft.yml as below. /snap/bin/<package>.<component> and wrapper script will be created by apps directive.
$ cat snapcraft.yaml name: tetris version: 1.0 summary: tetris with ncurses or sdl2 description: https://github.com/hiroom2/tetris-sdl-and-ncurses confinement: strict # /snap/bin/<package>.<component> apps: sdl: command: bin/sdl ncurses: command: bin/ncurses # Build package parts: tetris: plugin: make source: https://github.com/hiroom2/tetris-sdl-and-ncurses source-type: git build-packages: [libsdl2-dev, libsdl2-image-dev, libsdl2-ttf-dev, libncurses5-dev]
Build snap package.
$ snapcraft Preparing to pull tetris Pulling tetris Cloning into '/home/hiroom2/tetris/parts/tetris/src'... remote: Counting objects: 26, done. remote: Compressing objects: 100% (24/24), done. remote: Total 26 (delta 1), reused 25 (delta 1), pack-reused 0 Unpacking objects: 100% (26/26), done. Checking connectivity... done. Preparing to build tetris Building tetris make -j1 make -C jni/src make[1]: Entering directory '/home/hiroom2/tetris/parts/tetris/build/jni/src' rm -rf sdl ncurses *.dSYM g++ -Wall -I. `sdl2-config --cflags` -o sdl Tetris.cpp TetrisSDL.cpp SDL.cpp -lpthread -lSDL2 -lSDL2_ttf g++ -Wall -I. -o ncurses Tetris.cpp TetrisNcurses.cpp ncurses.cpp -lpthread -lncurses make[1]: Leaving directory '/home/hiroom2/tetris/parts/tetris/build/jni/src' make install DESTDIR=/home/hiroom2/tetris/parts/tetris/install install -d -m755 /home/hiroom2/tetris/parts/tetris/install/bin/ install -m755 jni/src/sdl /home/hiroom2/tetris/parts/tetris/install/bin/ install -m755 jni/src/ncurses /home/hiroom2/tetris/parts/tetris/install/bin/ncurses Staging tetris Priming tetris Snapping 'tetris' - Snapped tetris_1.0_amd64.snap
Install snap package.
$ sudo snap install tetris_1.0_amd64.snap Name Version Rev Developer Notes tetris 1.0 x1 -
/snap/tetrisにsquashfs is mounted.
$ tree /snap/tetris/ /snap/tetris/ ├── current -> x1 └── x1 ├── bin │ ├── ncurses │ └── sdl ├── command-ncurses.wrapper ├── command-sdl.wrapper ├── meta │ └── snap.yaml └── usr └── lib └── x86_64-linux-gnu ├── libasound.so.2 ├── libasyncns.so.0 ├── libFLAC.so.8 ├── libogg.so.0 ├── libpulse.so.0 ├── libSDL2-2.0.so.0 ├── libSDL2_ttf-2.0.so.0 ├── libsndfile.so.1 ├── libsndio.so.6.1 ├── libvorbisenc.so.2 ├── libvorbis.so.0 ├── libwayland-client.so.0 ├── libwayland-cursor.so.0 ├── libwayland-egl.so.1 ├── libX11.so.6 ├── libXau.so.6 ├── libxcb.so.1 ├── libXcursor.so.1 ├── libXdmcp.so.6 ├── libXext.so.6 ├── libXfixes.so.3 ├── libXinerama.so.1 ├── libXi.so.6 ├── libxkbcommon.so.0 ├── libXrandr.so.2 ├── libXrender.so.1 ├── libXss.so.1 ├── libXxf86vm.so.1 └── pulseaudio └── libpulsecommon-8.0.so
/snap/bin/<package>.<component> is added.
$ ls /snap/bin/tetris.* /snap/bin/tetris.ncurses /snap/bin/tetris.sdl