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. http://fpm.readthedocs.io/en/latest/ grade: devel confinement: devmode

apps: fpm: environment: RUBYLIB: $SNAP/usr/lib/ruby/2.3.0:$SNAP/usr/lib/x86_64-linux-gnu/ruby/2.3.0 GEM_HOME: $SNAP/gems GEM_PATH: $SNAP command: ruby $SNAP/bin/fpm

parts: fpm: source: . plugin: nil build-packages: - build-essential - ruby-dev - rubygems-integration - libreadline-dev - libssl-dev - libtinfo-dev stage-packages: - 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 /snap/fpm/x1/gems/childprocess-0.9.0/lib/childprocess/unix/fork_exec_process.rb:58:in `launch_process’: No such file or directory - gem (ChildProcess::LaunchError) 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 directory)

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:

mangle-shebang: 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 ( Bug #1829564 “snapcraft clean crashes on snapcraft.yaml with bad...” : Bugs : Snapcraft ), 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”, “–install-dir”, “/tmp/package-gem-staging-ff4c376ab3c9eeb7cc09896e1f3b01d4b1fc53d65b936d66071803b50833/snap/fpm/x1/gems”, “–ignore-dependencies”, “-E”, “–bindir”, “/tmp/package-gem-staging-ff4c376ab3c9eeb7cc09896e1f3b01d4b1fc53d65b936d66071803b50833/snap/fpm/x1/gems/bin”, “/tmp/package-gem-build-e5dfcee45d3490656ae048e5b29336eaed8b46425bdc677d30e28abd6ebe/json/json-2.2.0.gem”] {:level=>:error}

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 … /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `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 (LoadError) $ 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