Here is a simple guide on the steps involved in building and deploying a QT application statically on a target device. This guide is done with the assumption that the host machine runs Ubuntu and the target device is iMX6. But the steps involved are more or less the same for any device.

Why static ?  –  Usually in dynamically linking, the shared QT libraries( .so files) are required to be available in the target device when you run the application. In addition the plugins have to placed in the correct location in your target so that the application is able to find them during run time. But with static linking these dependencies with the libraries and plugins can eliminated which makes it easier to deploy applications in your target device. Static linking has its own advantages and disadvantages. A statically linked application size is bigger than a dynamically linked application size. But the overall size is reduced because not all functions from your shared libraries are built into your exe but just the required ones.

Important Note: Make yourself some time to read the license agreement before building QT statically. Don’t get yourself into legal problem by not understanding the license terms clearly. 

Step 1 – Building QT source:-

  1. Downloading the QT source:
    • You can download the opensource version from any of the official qt releases or download an enterprise pack if you own a commercial QT license by logging into your QT account. Make sure to download the right package based on your host machine’s operating system.
  2. Configuring the QT source:
    • Once downloaded, extract the source package to a specific directory.
    • Navigate to your source directory. cd <QT src directory>
    • Now its time to configure the QT source.
    • Before configuring we can export some variables that will come handy during our build and install steps. Export the following variables from your source directory path.
      • export SYSROOT_BASE=/opt/imx6toolchain/sysroots – This is the base sysroot directory.
      • export TARGET_DEVICE=linux-imx6-g++ – This is your target device which is from mkspec. In our example it is imx6.
      • export SYSROOT_TARGET=cortexa9hf-neon-poky-linux-gnueabi– This is the target directory inside your SYSROOT_BASE.
      • export CROSSCOMPILE_PREFIX=x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-– This is the path and the prefix of your cross compiler.
      • export HOST_PREFIX=~/build/qt5imx6– This is the path where the host binaries like qmake and moc will be installed.
    • Now we can configure our source. There are multiple options that can be passed while configuring. You can view the entire list of options that can be passed to the configure command from the help list. Run ./configure -h to view the list.
      • Here is a sample configuration in which QT is configured for opensource with static and for a release build. Look how the variables that we exported are passed to the prefix and device options. Also we can choose to exclude some modules or features from the build by using the -skip <module> and -no <feature> options.
      ./configure -verbose -opensource -release -static -prefix /opt/imx6_qt5 -hostprefix $HOST_PREFIX -device $TARGET_DEVICE -device-option CROSS_COMPILE=$SYSROOT_BASE/$CROSSCOMPILE_PREFIX -sysroot $SYSROOT_BASE/$SYSROOT_TARGET -mysql_config $SYSROOT_BASE/$SYSROOT_TARGET/usr/bin/mysql_config -psql_config /dev/null no-xcb -opengl es2 -eglfs -nomake tests -nomake examples -skip qtwebengine -skip qtwebglplugin
    • If you have a commercial license, use -commercial option instead of -opensource in the above command. If your configuration is successful you will see a summary of your configuration at the end showing a list of all the features and modules that are enabled/disabled.
  3. Building the QT source:

    • Once the configuration is successful, we can build it using the make command. Run make -j4 in your terminal to start the build.
    • This will take a considerable amount of time based on your CPU speed. The -j<number> denotes the number of jobs that you want to run in parallel. Usually this number is set equal to the number of cores available in your CPU.
    • Once the make is completed, you have to install the binaries. Run make -j4 install from your terminal. This will install the binaries to the path specified by HOST_PREFIX and SYSROOT_BASE variables.

Step 2 – Building QT Application:-

  1. Kit Creation in QT Creator:
    • Open your QT creator and go the Kit creation. In the “QT versions” tab, choose the qmake that has been generated in the HOST_PREFIX path and also set your gcc and g++ compilers for your target.
  2. Configure and Building QT project:
    • Include the CONFIG += static option in your .pro file to build your application statically.
    • You should also include the plugins and point the path to the libraries.
  3. Include Plugins as a part of your build:
    • It is required to build your plugins also as a part of your exe so that you don’t have to move them to your target when you run your application. In case if you don’t build your application along with the plugins, you will may see errors like this.
    •  qrc:/qml/main.qml:4 module "QtQuick2" is not installed
       qrc:/qml/main.qml:4 module "Window" is not installed
    • These errors can be avoided by explicitly mentioning the plugins in your project’s .pro file and specifying the libraries path using the QTPLUGIN and LIBS variables as shown below.
    • // file
      QTPLUGIN += windowplugin
      QTPLUGIN += qtquick2plugin
      LIBS += -L/<path to the plugin>/ -lqtquick2plugin
      LIBS += -L/<path to the plugin>/ -lwindowplugin
    • Also include the QT plugin header file and import the plugins inside your .cpp file and perform a clean build of your project.
//your main.cpp
#include <QtPlugin>

Step 3 – Deploying the application in target:-

Now your static application is ready to be deployed. Note that we have only eliminated the need for QT libraries for your application which means you don’t need the QT related .so files in your target device.  But the application may still need some external non QT libraries to run. These dependent libraries can be viewed by using objdump -x <your application> or by using the ldd command. Once you have listed and moved these libraries to your target, you can copy your QT application to your target device and run it.