I just want to snap a gem


Hi all!
I’m in dependency hell with ruby; doing ‘gem install fpm’ causes havoc
with a carefully curated
set of gems. So I figured I’d snap fpm to avoid that. It’s a bit
hard for a newbie,
and I’m recording the steps along the way. Still not working.

Starting with the (already outdated!) doc at
I put together a snapcraft.yaml that seems to build ok on ubuntu 16.04
with ‘snapcraft’
(or on ubuntu 19.04 with ‘snapcraft cleanbuild’), but doesn’t run.

– snip –
name: fpm
version: 1.1
summary: Effing Package Management
description: |
Build packages for multiple platforms (deb, rpm, etc) with great
ease and sanity.
grade: devel
confinement: devmode

RUBYLIB: $SNAP/usr/lib/ruby/2.3.0:$SNAP/usr/lib/x86_64-linux-gnu/ruby/2.3.0
command: ruby $SNAP/bin/fpm

source: .
plugin: nil
- build-essential
- ruby-dev
- rubygems-integration
- libreadline-dev
- libssl-dev
- libtinfo-dev
- ruby
- rubygems-integration
override-build: |
snapcraftctl build
gem install fpm -i $SNAPCRAFT_PART_INSTALL
– snip –

After installing the resulting snap with
$ sudo snap install .snap --devmode --dangerous
I tried it out, but it can’t find ‘gem’:
$ fpm -s gem -t deb json
`launch_process’: No such file or directory - gem
I looked at the failing syscall with
$ snap run --strace fpm -s gem -t deb json

[pid 27738] access("/snap/fpm/x1/usr/bin/gem", X_OK) = 0

[pid 27738] execve("/snap/fpm/x1/usr/bin/gem", [“gem”, “fetch”,
“json”], 0x1d7fe90 /
81 vars */) = -1 ENOENT (No such file or

Desperately searching for a clue, I tried running that file without
snap to see what would happen:

$ /snap/fpm/x1/usr/bin/gem
bash: /snap/fpm/x1/usr/bin/gem: /usr/bin/ruby2.3: bad interpreter: No
such file or directory

Well, shucks. Is my snapcraft.yaml supposed to fix up the shebang
line on the installed ruby scripts in its bin?
(I guess that’s what the ruby plugin would do. I was avoiding that
because it… builds… ruby. Every time I build.
I was hoping for a more lightweight build experience.)
OK, added a part for that:

plugin: nil
after: [fpm]
override-build: |
snapcraftctl build
sed -i ‘s/#!/usr/bin/ruby/#!/usr/bin/env ruby/’
$SNAPCRAFT_STAGE/usr/bin/gem2.3 $SNAPCRAFT_STAGE/usr/bin/rake

After pausing to file a bug report on poor typo handling (
https://bugs.launchpad.net/snapcraft/+bug/1829564 ), I ran again:

$ fpm -s gem -t deb json
Process failed: gem failed (exit code 1). Full command was:[“gem”,
“install”, “–quiet”, “–no-ri”, “–no-rdoc”, “–no-user-install”,
“–ignore-dependencies”, “-E”, “–bindir”,

Grubbing through strace again, I found my stage-packages was missing
ruby-dev and build-essential:
[pid 1726] stat("/snap/fpm/x1/usr/lib/ruby/include/ruby.h",
0x7ffeed577510) = -1 ENOENT (No such file or directory)
[pid 1726] write(2, "mkmf.rb can’t find header files "…, 84) = 84
[pid 1721] <… read resumed> "mkmf.rb can’t find header files "…, 8192) = 84

After adding those, next it failed cryptically because libjson-dev
wasn’t installed…
at which point a little light went on in my head: I need classic
confinement, not devmode,
if I want this to be a generally usable snap.
Added that and removed the stage-packages step and mangle-shebang part entirely.
Built and ran again:
$ sudo snapcraft
$ sudo snap remove fpm
$ sudo snap install --classic --dangerous fpm_1.1_amd64.snap
$ fpm -s gem -t deb json

`require’: libruby-2.3.so.2.3: cannot open shared object file: No such
file or directory - /snap/fpm/x1/gems/ffi-1.10.0/lib/ffi_c.so
$ file /snap/fpm/x1/gems/ffi-1.10.0/lib/ffi_c.so
/snap/fpm/x1/gems/ffi-1.10.0/lib/ffi_c.so: ELF 64-bit LSB shared
object, x86-64, version 1 (SYSV), dynamically linked,
BuildID[sha1]=b48ec412884dc24929f5fc4c852259b6150f88b2, with
debug_info, not stripped

Dunno why it claims the file doesn’t exist, but oh, shit, using
classic means I can’t assume ruby 2.3.
But the implicit base is ubuntu 16.04… um… I guess I need base:
core19, but that doesn’t exist, so core18?
Trying that now, but I have to run. Sending this email in case
somebody knows of a good
snap for fpm already :slight_smile:

  • Dan