Compile Static Qt Build in Ubuntu Optimized for Small Size With AppImage Support!
Qt is a static build-ready framework but it published as Shared Library due to license requirements. As you are reading this you should already know what is the requirement to build a static build and what is the benefits.
For me, it makes my life easy to distribute my final product with one single binary file for all Qt libraries and less dependency on system library and no need to worry about other system libs which could be missing in other computers and systems, as either, I also build my app against static system libs to get one absolute file or just package few systems shared libs.
For windows, there is a qt static build in Msys2 Repo but I could not find any ready static build for Linux with the last releases.
Looking around a with many trial and error I got the correct build configuration for my environment which may help you too.
My Build Env.
OS | Ubuntu 20.04 Lts |
Device Vendor | Lenovo x240 |
CPU | Intel® Core™ i5-4300U CPU @ 1.90GHz × 4 |
RAM | 7.7 GiB |
Graphics | Intel® HD Graphics 4400 (HSW GT2) |
Qt Source Version | 5.14.2 |
Build Tools | GCC 9.3 |
Time Spent | 4 hours |
Set-Up the build Env. in Ubuntu
- Install build requiremnet in Ubuntu
sudo apt-get build-dep qt5-default sudo apt install build-essential libclang-dev libssl-dev python-is-python2 libfontconfig1-dev libfreetype6-dev
- Download Qt Source from Qt Download Page
- Set the Build Directory strcutre tree to be like this :
/home/foxoman/Qt5static // My Build Dir under the name Qt5static └── 5.14.2 ├── build // Build Prefix ├── src // extract the Qt source here └── static // final install folder
Configure the build
Now open the terminal and apply this one command, if you apply same build structure then you do not need to change anything otherwise change accordingly
cd ~/Qt5static/5.14.2/build; ~/Qt5static/5.14.2/src/configure -v -static -release -ltcg -optimize-size -no-pch -prefix ~/Qt5static/5.14.2/ -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -qt-xcb -qt-harfbuzz -make libs -nomake tools -nomake examples -nomake tests -opensource -confirm-license -skip qtwebengine -dbus-linked -no-rpath -openssl-linked -opengl desktop -sysconfdir "/etc/xdg" -no-qml-debug -feature-freetype -fontconfig -feature-relocatable -strip
To Understand what each setting do or to get more options
cd ~/Qt5static/5.14.2/build; ~/Qt5static/5.14.2/src/configure -h
Here are some the configuration options i used
-static -release | Build a static release no debug |
-ltcg -optimize-size | Reduce the build size but will increase the compile time |
-qt-* | Use those Lib from Qt not from the system |
-nomake tools, examples, tests | Do not build the qt tools like QtCreator and the examples and the tests |
-dbus-linked -openssl-linked | Dynamic link to openssl and dbus Libs and to relink when needed |
-feature-freetype -fontconfig | Enable fontconfig to read system fonts otherwise you have to ship your app with the fonts |
Build and Install
To Build and install the static final build in static folder run the bellow commands
make -j $(grep -c ^processor /proc/cpuinfo)
make install
Configure QtCreator to Use the Static Kit
You Will have to Add the Qt Version from the static build and New Qt Kit to use!
Creating New Project you Can Activate the New Static Build
Optimize for smaller size
Due to our build configuration, the build size will be smaller than the normal static build size and we can make it smaller using:
- Strip linux command
strip -s /appDir/app
- UPX compress tool to almost half of its size.
./upx -9 /appDir/app
Build An AppImage
AppImage format is the portable format in Linux and by building your app as a static app then it so easy to package it and distribute your app for Linux.
We will do it manually in an easy way.
- Install appimagetool
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
sudo chmod +x /usr/local/bin/appimagetool
- Build the AppDir Dir Structure to be a simple as bellow
/home/foxoman/app.AppDir
├── app.desktop
├── app.png
├── AppRun
└── usr
├── bin
│ └── app
└── share
├── applications
│ └── app.desktop
└── icons
└── hicolor
└── 256x256
└── apps
└── app.png
8 directories, 6 files
In Case you wanted to add few System Libs or Qt Plug-In which you can not build statically needed to be shipped with your app add it in /usr/lib/ folder and activate the export to the lib folder in AppRun file as explained later!
Make a folder Called app.AppDir and create the sub dir as per the above structure
You Will only need 4 files to care about, your App Binary should be in
/bin/
folder and the app icon in two places and the desktop file also in two places plus the AppRun bash file to run the app, And/lib/
Folder for shared system libs.
#!/bin/sh
HERE="$(dirname "$(readlink -f "${0}")")"
## If you gonna add more libs inside the appimage uncomment this line and change the url as needed
#export LD_LIBRARY_PATH=${HERE}/usr/lib/foobar:$LD_LIBRARY_PATH
# uncomment for GUI App
#exec "${HERE}/usr/bin/app" "$@"
# uncomment for console app
x-terminal-emulator -e "${HERE}/usr/bin/app" "$@"
- now run this command to build the appimage
appimagetool '/home/foxoman/app.AppDir'
Finding the missing Libs
Few System Libs still needed if it's not linked statically to your bin like the GCC libs and so on.
To find out what libs is needed:
objdump -p /bin/app
It will tell you something like this:
Dynamic Section:
NEEDED libc.so.6
NEEDED libdouble-conversion.so.3
NEEDED libicui18n.so.66
NEEDED libicuuc.so.66
NEEDED libglib-2.0.so.0
NEEDED libpthread.so.0
NEEDED libstdc++.so.6
NEEDED libm.so.6
NEEDED libgcc_s.so.1
NEEDED ld-linux-x86-64.so.2
And you could use this command to find where those required libs is located:
ldd -v /bin/app
Result like this:
linux-vdso.so.1 (0x00007ffed2df0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fedae872000)
libdouble-conversion.so.3 => /lib/x86_64-linux-gnu/libdouble-conversion.so.3 (0x00007fedae85c000)
libicui18n.so.66 => /lib/x86_64-linux-gnu/libicui18n.so.66 (0x00007fedae55d000)
libicuuc.so.66 => /lib/x86_64-linux-gnu/libicuuc.so.66 (0x00007fedae377000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fedae24e000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fedae22b000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fedae048000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fedadef9000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fedadede000)
/lib64/ld-linux-x86-64.so.2 (0x00007fedaec54000)
libicudata.so.66 => /lib/x86_64-linux-gnu/libicudata.so.66 (0x00007fedac41d000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fedac417000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fedac3a4000)
You will need to ship them with your app image then you finally able to complete all requirements or just build and link it statically with your app as bellow if you have static system libs available or you build it your self statically.
To Make Automatic AppImage Build you could use AppImage Builder.
Static link all System Libs at once!
To make life easier for you, you may need to compile your app statically with all required system static libraries, to do that add this Line to your app qmake file in QtCreator or to the command line.
QMAKE_LFLAGS += -static -s -Os
This will also strip out your binary file and you will not need to use strip command!
Final Result
Using Static Qt Build and strip with UPX tool and package it as AppImage I am able to get a completely High Performance, Small Size portable format solution to publish my apps in all Linux distros. While the size looks high for console app but for a full GUI app with an approximate of 10 - 20 MB only is a big success.
I have created a small console app as an example.
Optimized Static App Size | 38 mb |
after strip size | 35.5 mb |
after upx size | 11.6 mb |
AppImage Size | 11.3 mb |
The test app is a full console app String to Binary Converter!
Download and test it and let me know!
Please let me know how it works and your comment and share for this article down in comment section.