I’ve created a couple of classic snaps of Electron applications, text editors. I’ve found that some of the libraries bundled via stage-packages: are not being found by the application.
This came to light on Ubuntu GNOME 17.04 which doesn’t ship gconf2 by default. Electron applications require gconf2 and the classic snaps fail to find libgconf-2.so.4, although it is included in the snap.
What is the correct technique to ensure classic snaps can find all their bundled libraries? Here is an example snapcraft.yaml for the Atom snap I am publishing so you can see how things are currently setup. As you can see my attempts to coerce LD_LIBRARY_PATH aren’t working.
name: atom
version: 1.18.0
summary: A hackable text editor for the 21st Century.
description: |
Atom is a free and open source text editor that is modern,
approachable, and hackable to the core.
grade: stable
confinement: classic
parts:
atom:
plugin: dump
source: https://github.com/atom/atom/releases/download/v1.18.0/atom-amd64.deb
source-type: deb
# Correct path to icon.
prepare: |
sed -i 's|Icon=atom|Icon=/usr/share/pixmaps/atom\.png|g' usr/share/applications/atom.desktop
after:
- desktop-gtk2
stage-packages:
- gconf2
- libasound2
- libnotify4
- libnspr4
- libnss3
- libpulse0
- libxss1
- libxtst6
apps:
atom:
# Correct the TMPDIR path for Chromium Framework/Electron to
# ensure libappindicator has readable resources.
# Coerce LD_LIBRARY_PATH so libgconf-2.so.4 can be found in the snap.
command: env TMPDIR=$XDG_RUNTIME_DIR LD_LIBARY_PATH=$SNAP/usr/lib/x86_64-gnu-linux/usr/lib ${SNAP}/bin/desktop-launch ${SNAP}/usr/share/atom/atom
desktop: usr/share/applications/atom.desktop
Note that while the application may require libgconf to be present to run, the security policy won’t allow the application to talk to gconf (it can load the library of course since it is an antiquated settings technology that isn’t required on modern desktop systems (it can load the library of course). This is almost always a harmless denial with the applications trying various compat settings schemes and they happily move along (eg, to gsettings).
Ahhh, I didn’t read the commit carefully. I misunderstood that to be something snapcraft would do when creating a classic snap. Understand now, thanks. I’ll update my snaps accordingly.
well, perhaps a fix to snapd/snap-confine might be possible to seed the var by default when classic snaps are executed, i’ll leave it to @niemeyer and @zyga-snapd to decide that
snapd won’t fiddle with the environment in that way, but it’s trivial to do that without a wrapper by just adding an environment variable in snapcraft.yaml.
Maybe a remote part with a desktop-launch that works on classic?
I don’t think it’s easy to add all the environment variables required in the snapcraft.yaml.
since this just came up again from a solus bug that @ikey pointed to https://dev.solus-project.com/T4390 i actually took a look at the launcher inside the atom snap …
#!/bin/sh
if test "$1" = "classic"; then
shift
case $SNAP_ARCH in
amd64)
TRIPLET="x86_64-linux-gnu"
;;
armhf)
TRIPLET="arm-linux-gnueabihf"
;;
arm64)
TRIPLET="aarch64-linux-gnu"
;;
*)
TRIPLET="$(uname -p)-linux-gnu"
;;
esac
export LD_LIBRARY_PATH=$SNAP/usr/lib:$SNAP/usr/lib/$TRIPLET
fi
# Correct the TMPDIR path for Chromium Framework/Electron to ensure
# libappindicator has readable resources.
export TMPDIR=$XDG_RUNTIME_DIR
exec ${SNAP}/bin/desktop-launch $@
the snap ships many libs in $SNAP/lib and $SNAP/lib/$TRIPLET but neither is added to LD_LIBRARY_PATH
If the trend is to continue, it would be beneficial to at least build the electron runtime in a snap with confinement: classic to have a proper runtime, heck, maybe this could be shared through a content plug/slot interface to reduce the size of snaps.
FWIW, I’ve been thinking about doing something similar for python.
why would the electron runtime have anythig to do with it, the libs in the snap are simply not found because $SNAP/lib and friends are not in LD_LIBRARY_PATH …
those two paths: $SNAP/lib and $SNAP/lib/$TRIPLET should be added by snapcraft to the LD_LIBRARY_PATH by placing them into the $SNAP/command-$SNAP.wrapper which is what actually gets launched first
The only line that I influenced by declarations in the snapcraft.yaml is the exec line. IIRC if you add an environment: declaration it will add those variables in this script before the exec, too.
Well, the current wrapper in the atom snap definitely doesnt have it.
I created https://github.com/snapcrafters/atom/pull/3 that should help … if you want to experiment with “environment:” instead. feel free
No no no. I am suggesting that if you intend to snap up an electron or python app with classic confinement you should compile the runtime to have the appropriate dynamic linker loader and rpaths setup.
To ease that, I suggested created prebuilts for people to replace or consume from (through the content interface).
No worries, that is not what I suggested. The current approach is fine for when the execution environment doesn’t change, that is everything != classic confined.