probonopd / linuxdeployqt

Makes Linux applications self-contained by copying in the libraries and plugins that the application uses, and optionally generates an AppImage. Can be used for Qt and other applications
Other
2.22k stars 414 forks source link

linuxdeployqt doesn't set the RPATH of QML plugins #618

Open a12e opened 2 months ago

a12e commented 2 months ago

AppImages fail to start because libworkerscriptplugin.so have no RPATH set, and thus tries to load its backing library libQt6QmlWorkerScript.so.6 on the host system instead of the AppImage.

Cannot load library /tmp/.mount_XXXL4O6JB/usr/qml/QtQml/WorkerScript/libworkerscriptplugin.so: /tmp/.mount_XXXL4O6JB/usr/bin/../lib/libQt6Qml.so.6: version `Qt_6.7.2_PRIVATE_API' not found (required by /lib64/libQt6QmlWorkerScript.so.6)

No QML plugin (stored in /tmp/.mount_XXXL4O6JB/usr/qml/) has its RPATH set.

Non-working QML plugin .so:

$ LANG=en readelf -d /tmp/.mount_XXXL4O6JB/usr/qml/QtQml/WorkerScript/libworkerscriptplugin.so

Dynamic section at offset 0x3d98 contains 30 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libQt6QmlWorkerScript.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Qml.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x2000
 0x000000000000000d (FINI)               0x25c4
 0x0000000000000019 (INIT_ARRAY)         0x4c90
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x4c98
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x370
 0x0000000000000005 (STRTAB)             0x720
 0x0000000000000006 (SYMTAB)             0x3a8
 0x000000000000000a (STRSZ)              1323 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x5000
 0x0000000000000002 (PLTRELSZ)           312 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x1198
 0x0000000000000007 (RELA)               0xdd8
 0x0000000000000008 (RELASZ)             960 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffc (VERDEF)             0xc98
 0x000000006ffffffd (VERDEFNUM)          4
 0x000000006ffffffe (VERNEED)            0xd08
 0x000000006fffffff (VERNEEDNUM)         5
 0x000000006ffffff0 (VERSYM)             0xc4c
 0x000000006ffffff9 (RELACOUNT)          22
 0x0000000000000000 (NULL)               0x0

Working backing library .so (note RUNPATH):

$ LANG=en readelf -d /tmp/.mount_XXXL4O6JB/usr/lib/libQt6QmlWorkerScript.so.6

Dynamic section at offset 0x142a0 contains 32 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Qml.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Network.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6Core.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libQt6QmlWorkerScript.so.6]
 0x000000000000000c (INIT)               0x6000
 0x000000000000000d (FINI)               0xe0d4
 0x0000000000000019 (INIT_ARRAY)         0x12720
 0x000000000000001b (INIT_ARRAYSZ)       24 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x12738
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2f0
 0x0000000000000005 (STRTAB)             0x144f0
 0x0000000000000006 (SYMTAB)             0x3e8
 0x000000000000000a (STRSZ)              7518 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000003 (PLTGOT)             0x13000
 0x0000000000000002 (PLTRELSZ)           3336 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x4aa0
 0x0000000000000007 (RELA)               0x3768
 0x0000000000000008 (RELASZ)             4920 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffc (VERDEF)             0x35f8
 0x000000006ffffffd (VERDEFNUM)          4
 0x000000006ffffffe (VERNEED)            0x3668
 0x000000006fffffff (VERNEEDNUM)         5
 0x000000006ffffff0 (VERSYM)             0x345e
 0x000000006ffffff9 (RELACOUNT)          132
 0x0000000000000000 (NULL)               0x0

The problem is that with "modern Qt with CMake" the QML plugins are already copied in appdir/usr/qml during cmake --install. When linuxdeployqt steps on this existing directory (https://github.com/probonopd/linuxdeployqt/blob/ff74b85e0352d65053207fd884aacc31aaaae09b/tools/linuxdeployqt/shared.cpp#L1771-L1776), it does nothing because the target QML directory already exists.

A workaround is to rm -rf appdir/usr/qml before invoking linuxdeployqt.

probonopd commented 2 months ago

Thanks for analyzing this @a12e, and for the workaround.

Maybe we should simply not skip already deployed imports? This might significantly increase the time the program needs to run. The proper thing to do would probably be to check if it had been deployed and rpath patched properly before...

Reference: