How to change the embedded rpath of shared library (.so)?
-
We have libqtforandroid.so here, right?
\qtbase\src\plugins\platforms\androidIn this shared library, it has a rpath embedded as below:
$ aarch64-linux-android-readelf.exe -d libqtforandroid.so Dynamic section at offset 0x102df8 contains 37 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libjnigraphics.so] 0x0000000000000001 (NEEDED) Shared library: [libandroid.so] 0x0000000000000001 (NEEDED) Shared library: [libc++_shared.so] 0x0000000000000001 (NEEDED) Shared library: [liblog.so] 0x0000000000000001 (NEEDED) Shared library: [libz.so] 0x0000000000000001 (NEEDED) Shared library: [libm.so] 0x0000000000000001 (NEEDED) Shared library: [libdl.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so] 0x0000000000000001 (NEEDED) Shared library: [libEGL.so] 0x0000000000000001 (NEEDED) Shared library: [libQt5Gui.so] 0x0000000000000001 (NEEDED) Shared library: [libQt5Core.so] 0x0000000000000001 (NEEDED) Shared library: [libGLESv2.so] 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so] 0x000000000000000e (SONAME) Library soname: [libqtforandroid.so] 0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../../../lib]
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../../../lib]
I traced to the Makefile, which is generated by qmake.
LFLAGS = --sysroot=D:/android/android-ndk-r16b/platforms/android-27/arch-arm64/ -Wl,--no-undefined -Wl,-z,origin -Wl,-rpath=\$$ORIGIN/../../../lib -Wl,--no-undefined -Wl,-z,noexecstack -shared -Wl,-soname,libqtforandroid.so
My question is where and how "../../../lib" is determined? What do I do if I want to change it? Thank you.
-
Paths are embeded into .so files, that's just how Qt works, even though it is a pain in the rear end.
You can use qt.conf to get around it. And/ or use standard Qt directory layout, just like windeployqt, androiddeployqt, macdeployqt and linuxdeployqt are using.
Why do you need to change it?
-
@sierdzio
I am having strange UnsatisfiedLinkError error when loading libqtforandroid.so.The logs look like:
01-01 05:33:19.616 4412 4412 D QtJAVA : Try to load /vendor/app/MyQtApp/plugins/platforms/android/libqtforandroid.so 01-01 05:33:19.624 4412 4412 E QtJAVA : UnsatisfiedLinkError '/vendor/app/MyQtApp/plugins/platforms/android/libqtforandroid.so' 01-01 05:33:19.624 4412 4412 E QtJAVA : java.lang.UnsatisfiedLinkError: dlopen failed: library "libQt5Gui.so" not found
The libQt5Gui.so locates at /vendor/app/MyQtApp/lib/arm64.
libqtforandroid.so depends on libQt5Gui.so. It is understandable that linker tries to load libQt5Gui.so.
It seems that linker doesn't append 'arm64' on the rpath. I am not sure about that, so I want try setting rpath to $ORIGIN/../../../lib/arm64.There is another mystery. Why does linker try to load libQt5Gui.so again when libQt5Gui.so has been loaded in the same function (qt\qtbase\src\android\jar\src\org\qtproject\qt5\android\QNative.loadQtLibraries())?
The loading events just happen in the same for loop. -
In qcoreapplication.cpp, I see this comment:
The return value of this function may change when a QCoreApplication is created. It is not recommended to call it before creating a QCoreApplication. The directory of the application executable (\b not the working directory) is part of the list if it is known. In order to make it known a QCoreApplication has to be constructed as it will use \c {argv[0]} to find it. Qt provides default library paths, but they can also be set using a \l{Using qt.conf}{qt.conf} file. Paths specified in this file will override default values. Note that if the qt.conf file is in the directory of the application executable, it may not be found until a QCoreApplication is created. If it is not found when calling this function, the default library paths will be used.
Unfortunately, for an Android application, the QtLoader in Java level loads libraries before the QCoreApplication is created.
I doubt that qt.conf would help on this matter.