I’m trying to understand best practice for setting LD_LIBRARY_PATH
in apps.foobar.environment
. From my testing I was surprised to learn that expansion syntax like the following does not work the way I expected as it seems to remove some of the default paths that are generally set for apps.
apps:
foobar:
command: ...
environment:
LD_LIBRARY_PATH: $SNAP/usr/my-lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
The following demonstrates this:
name: test-snap
base: core24
version: '1.0.0'
summary: Test snap
description: |
LD_LIBRARY_PATH test
grade: devel
confinement: strict
apps:
print-path:
command: usr/bin/print-path
parts:
print-path:
plugin: dump
source: bin/
organize:
print-path: usr/bin/print-path
where print-path
is a simple script:
#!/bin/bash
echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}"
This results in:
$ test-snap.print-path
LD_LIBRARY_PATH: /var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void
As you can see, there are some default directories added for an app, and I assume it’s important that these be preserved even if a user wants to update LD_LIBRARY_PATH
(more on that later…). Note that if you stage a package (e.g. libcurl4
) you end up with even more defaults:
$ test-snap.print-path
LD_LIBRARY_PATH: /var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void:/snap/test-snap/x12/usr/lib:/snap/test-snap/x12/usr/lib/x86_64-linux-gnu
So LD_LIBRARY_PATH
is automatically updated to find the libs from stage-packages
, which is a nice feature.
Now if I adjust the LD_LIBRARY_PATH
from the apps.print-path.environment
section using the suggested method from the snapcraft documentation:
apps:
print-path:
command: usr/bin/print-path
environment:
LD_LIBRARY_PATH: $SNAP/foo/bar:${LD_LIBRARY_PATH}
This produces the expected result:
$ test-snap.print-path
LD_LIBRARY_PATH: /snap/test-snap/x13/foo/bar:/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void:/snap/test-snap/x13/usr/lib:/snap/test-snap/x13/usr/lib/x86_64-linux-gnu
However, if I try using the :+
parameter, which I see used frequently in snap definitions and is suggested as being important for avoiding unbound variable definitions (albeit for build-environment
in this particular link), I get an unexpected result:
apps:
print-path:
command: usr/bin/print-path
environment:
LD_LIBRARY_PATH: $SNAP/foo/bar${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
$ test-snap.print-path
LD_LIBRARY_PATH: /snap/test-snap/x14/foo/bar
So the defaults that are generally set are removed, and as a result your app can no longer find libs from stage-packages
installed in $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR
. And perhaps there may be other issues from other directories (/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void
) being removed?
Is this expected?
I understand that LD_LIBRARY_PATH: $SNAP/foo/bar:$LD_LIBRARY_PATH
will work (and that’s what is suggested in the snapcraft docs), but I’ve also seen security concerns raised over using this approach. cc @lucyllewy
I’m curious what others think and consider best practice. Thanks!
Side note: my tests used snapcraft version 8.9.4 and snapd version 2.68.4.