Qt Packaging: harfbuzz missing symbol on Fedora

When running the MiniZinc snap on Fedora 28 trying to open the IDE using minizinc.ide on the command line will return the following error:

/var/lib/snapd/snap/minizinc/20/bin/MiniZincIDE: symbol lookup error: /lib64/libharfbuzz.so.0: undefined symbol: FT_Get_Var_Blend_Coordinates

The snap works on Ubuntu based distributions.

The error seems to suggest that a library is missing; however, the Qt packages for the IDE are gathered using the AppImage tool linuxdeployqt (which should include all libraries used), and both using the raw files and in the AppImage the IDE works fine on Fedora.

Is there anything that I might have forgot to take into account when building the MiniZinc snap? Maybe regarding something like libharfbuzz, libfreetype, or Qt in general?

The snap is in classic confinement, this means that the snap has access to the host libraries which will not likely to be compatible with the libraries provided by the snap and the core snap(in this case it is the Harfbuzz library). Proper care must be done to LD_LIBRARY_PATHs to ensure only in-snap libraries are called by in-snap programs (and vice versa)

Would you be able to explain how the “core” snap is actually involved in this classic confinement? Because I understand that the harfbuzz library is loaded from the local machine, but this is expected behaviour. (It is described here as the fix to a Qt packaging problem) Loading the local library works both when just using the packaged raw files or the AppImage; however when this package is snapped, it doesn’t work for some reason.

In all run the same script is used to start the IDE which set the LD_LIBRARY_PATH:

DIR=$(dirname $(readlink -f "$0"))
[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p $XDG_RUNTIME_DIR -m 700
export QT_PLUGIN_PATH=$DIR/plugins
exec $DIR/bin/MiniZincIDE $@

I don’t have a definitive answer yet, but found the following article to be related: https://gitlab.com/probono/platformissues#harfbuzz

I’ve seen this, the way this is currently circumvented is by not packaging FreeType and using the system version.

It seems that in the snap a different version of FreeType is used than when I use the system version. Can it be that the snap in classic version still uses the FreeType library from the core snap even though I’m using a classic confinement?

The core snap’s content is accessible at /snap/core/current, you may ensure it by searching in the directories.

It seems FreeType is included in the core snap on /snap/core/current/usr/lib/x86_64-linux-gnu/libfreetype.so.6. This might mean that this version is being used, I will investigate this further soon, but this might require some work. Just outputting the LD_LIBRARY_PATH in the script will require me to make a new version of the snap (which takes a while).

I’d suggest using snap try to hunt this sort of thing down.

Although it seems the issue was indeed that libfreefont was loaded from the core snap:

	libfreetype.so.6 => /snap/core/current/usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f51352c8000)

Although I have found the problem, I don’t see a way around the problem. The location of the library seems to be hard coded in the binary within the snapping process. So changing the LD_LIBRARY_PATH does not seem to be succesful. I’ve also tried including the libharfbuzz package in the snap, this seems to work, but then an error occurs for libqxcb.so. This package is giving an error because a core package has a libc version is incompatible:

/snap/core/current/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /lib64/libICE.so.6)

It seems a bit much to have to include glibc in my snap as well.

All these issues seem to just be caused by the snapping process forcing the use of libraries within the “core” snap. This then causes a mix of incompatible libraries that seems very unnecessary Is there any way around this? Can I snap my package in a way that it doesn’t rewrite library dependencies to the core snap?

when building a classic-confinement snap you must ensure that you do not load libraries from the host system. You must load all libraries from your snap or if supplied in the base snap from there. The base snap core includes libc, so you do not need to ship that inside your own snap. If your snap is loading libraries from the host system then you must work to stop that from happening, because it will fail randomly on the disparate systems that snaps can run on.