Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Building Qt for Embedded Linux
[toc align_right="yes" depth="2"]
NOTE: This article is for Qt 4 only. For Qt 5, see http://doc.qt.io/qt-5/embedded-linux.html
Introduction
To get a reasonable Qt for Embedded Linux development environment setup it is necessary to build Qt twice:
- For the host system (your own workstation) where the development will be done. We will refer to this as the host build.
- For the target system (the embedded board) where we will deploy the applications. We will refer to this as the target build.
The host system configuration is not so very different from a standard Qt/X11 installation and uses your normal tool chain so we will describe this configuration first.
The target build configuration however is a little different. We must build in on the host machine but in such a way that the applications generated with it are able to execute on the embedded platform being targeted. This requires us to use our cross-compiling toolchain so a little more effort is required here - although not much so don't worry. :-)
Pre-requisites
Before we begin please make sure that you have a working cross-compiling toolchain. This will either be supplied with your device's SDK or you can build your own.
If you are using a commercial license then please also ensure that a valid license file is located at $HOME/.qt-license
The Host Build
Configuring the Host Build
Firstly you need the latest and greatest version of the Qt source, so go and download the Qt-everywhere package from the Nokia website (or from your customer portal if you are a commercial customer). Once you have the tarball, extract it somewhere convenient for your normal user e.g. $HOME/development/qt-4.7.2, say. Change into the Qt source directory and configure Qt for an embedded host build with something along the lines of:
<br />./configure -prefix /usr/local/qt-embedded-4.7.2 -embedded -qt-gfx-linuxfb -qt-gfx-qvfb -qt-gfx-vnc -no-largefile -exceptions -no-accessibility -no-qt3support -qt-zlib -no-gif -no-libtiff -qt-libpng -no-libmng -qt-libjpeg -openssl -no-nis -no-cups -depths 8,16,18,32 -qt-kbd-tty -qt-kbd-qvfb -qt-kbd-linuxinput -qt-mouse-linuxinput -qt-mouse-qvfb -qt-mouse-pc -commercial -confirm-license -silent<br />
The above configure line tells Qt to configure itself for an embedded build using your normal system tool chain. However, some of these options warrant further explanation.
prefix <path>The host build of Qt-Embedded will be installed under this prefix. Please make sure that this is something different than your system Qt install prefix so that we do not clobber anything from that!embeddedEnable support for the embedded options. This includes the QWS window system into the build and enables so other embedded related options.qt-gfx-linuxfbEnable the linux framebuffer driver so that the app can be tested full screen on the host (outside of X11)qt-gfx-qvfbEnable support for testing applications in the qvfb (virtual framebuffer application which is part of Qt/X11)qt-gfx-vncEnabled support for exporting application display over VNCdepths 8,16,18,32Include support for these colour depths. These are just some common options. Please refer to your board's documentation to see what it actually supports. Setting the same option here will allow you to see an accurate representation of your app even when running it on the host machine.qt-kdb-ttyEnable support for the tty keyboard driverqt-kbd-qvfbEnable keyboard support with qvfbqt-kbd-linuxinputEnable a keyboard linux input in the QtGui library.qt-mouse-linuxinputEnable a mouse linux input in the QtGui library.qt-mouse-qvfbEnable mouse support with qvfbconfirm-licenseLazy option to save agreeing to license agreement during configure process (you can go drink tea instead)
The other options should be fairly self-explanatory, but see ./configure —help for more detail. You can of course specify additional options to configure or remove some of the ones listed in the above example depending upon your requirements.
The configure process can take a few minutes as it must first compile the qmake application and some other supporting utilities.
The build itself
This bit is simple. Just issue the command make -j<no of parallel jobs>. The argument to give to the -j flag is down to personal choice. A good general guide is to use the number of available CPU cores + 1. So on a single core machine you might use:
make -j2<code>
or on a quad-core machine:
make j5
If you wish to leave some CPU cores free for other taks whilst building then reduce the number.
Depending upon the speed and load of your machine the build can take of the order of a few tens of minutes on a modern PC. This is a good time to get yourself a cup of tea and a biscuit or "do something else":http://developer.qt.nokia.com/forums/viewthread/3085/!
Once the build has completed it is time to install Qt. You may need to su to root to do this part depending upon what prefix you configured the build with above. As the appropriate user do:
make install<code>
<br />Congratulations you should now have a working Qt for Embedded Linux host build. We'll see how to use it shortly, but first we need to build a version of Qt for our target device.
<br />h1. The Target Build
<br />h2. Cleaning the Previous Build
<br />We already have a Qt build directory from the above Host System steps. We can re-use this for our target build. We just need to remove the previous configuration. As your normal user once more, cd into the Qt build directory and issue:
<br />
make confclean
This is a list of qmake variable assignments that tells qmake what flags to pass through to the compiler, which compiler to use etc.
This will remove all build files and the previous configuration.
h2. Preparing a mkspec
Before we can redo the configuration for the target system, we will need a new set of mkspecs that tells qmake which tool chain it should reference when it creates the makefiles. The contents of the mkspecs files will vary depending upon the architecture and other details of your target device. Qt ships with some example mkspecs that you can either use directly or as inspiration for your own. Take a look in the mkspecs/qws directory under your Qt source directory. If you are able to use one of these then great make a note of its name. If not then we need to roll our own custom mkspec.
If you need to make your own custom mkspec file then make a copy of the closest match from the existing mkspecs form the mkspec/qws sub-directory and name it something appropriate. In this example we will create a mkspec to go along with the cross-compiling toolchain that we made earlier.
The mkspec consists of 2 files:
# qmake.conf
# qplatformdefs.h - This is a header file with various platform-specific #includes and #defines. Often this just refers to an existing qplatformdefs.h file from another generic mkspec.
For our example we are using our 486-based toolchain. A typical qmake.conf file for this may looki like this:
<br />#<br /># qmake configuration for linux-g++ modified to use 486 compliant compiler<br />#
MAKEFILE_GENERATOR = UNIX<br />TEMPLATE = app<br />CONFIG ''= qt warn_on release link_prl<br />QT''= core gui network<br />QMAKE_INCREMENTAL_STYLE = sublib
QMAKE_CC = i486-pc-linux-gnu-gcc<br />QMAKE_LEX = flex<br />QMAKE_LEXFLAGS =<br />QMAKE_YACC = yacc<br />QMAKE_YACCFLAGS = -d<br />QMAKE_CFLAGS = -pipe<br />QMAKE_CFLAGS_WARN_ON = -Wall -W<br />QMAKE_CFLAGS_WARN_OFF =<br />QMAKE_CFLAGS_RELEASE = -O2<br />QMAKE_CFLAGS_DEBUG = -g<br />QMAKE_CFLAGS_SHLIB = -fPIC<br />QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses<br />QMAKE_CFLAGS_THREAD = -D_REENTRANT<br />QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CXX = i486-pc-linux-gnu-g++<br />QMAKE_CXXFLAGS = $$QMAKE_CFLAGS<br />QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON<br />QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF<br />QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE<br />QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG<br />QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB<br />QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC<br />QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD<br />QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
QMAKE_INCDIR = /usr/i486-pc-linux-gnu/usr/include<br />QMAKE_LIBDIR = /usr/i486-pc-linux-gnu/usr/lib<br />QMAKE_INCDIR_X11 =<br />QMAKE_LIBDIR_X11 =<br />QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS]<br />QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS]<br />QMAKE_INCDIR_OPENGL =<br />QMAKE_LIBDIR_OPENGL =<br />QMAKE_INCDIR_QTOPIA = $(QPEDIR)/include<br />QMAKE_LIBDIR_QTOPIA = $(QPEDIR)/lib
QMAKE_LINK = i486-pc-linux-gnu-g++<br />QMAKE_LINK_SHLIB = i486-pc-linux-gnu-g++<br />QMAKE_LFLAGS =<br />QMAKE_LFLAGS_RELEASE =<br />QMAKE_LFLAGS_DEBUG =<br />QMAKE_LFLAGS_SHLIB = -shared<br />QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB<br />QMAKE_LFLAGS_SONAME = -Wl,-soname,<br />QMAKE_LFLAGS_THREAD =<br />QMAKE_RPATH = -Wl,-rpath,
QMAKE_LIBS =<br />QMAKE_LIBS_DYNLOAD = -ldl<br />QMAKE_LIBS_X11 =<br />QMAKE_LIBS_X11SM =<br />QMAKE_LIBS_QT = -lqte<br />QMAKE_LIBS_QT_THREAD = -lqte-mt<br />QMAKE_LIBS_QT_OPENGL = -lqgl<br />QMAKE_LIBS_QTOPIA = -lqpe -lqtopia<br />QMAKE_LIBS_THREAD = -lpthread<br />QMAKE_LIBS_OPENGL =
QMAKE_MOC = $$[QT_INSTALL_BINS]/moc<br />QMAKE_UIC = $$[QT_INSTALL_BINS]/uic
QMAKE_AR = i486-pc-linux-gnu-ar cqs<br />QMAKE_RANLIB =
QMAKE_TAR = tar -cf<br />QMAKE_GZIP = gzip –9f
QMAKE_COPY = cp -f<br />QMAKE_MOVE = mv -f<br />QMAKE_DEL_FILE = rm -f<br />QMAKE_DEL_DIR = rmdir<br />QMAKE_CHK_DIR_EXISTS = test -d<br />QMAKE_MKDIR = mkdir -p<br />include(../../common/unix.conf)<br />load(qt_config)<br />
The corresponding qplatformdefs.h file is much simpler and just refers to an existing generic one:
<br />#include "../../linux-g+''/qplatformdefs.h&quot;<br />
To complete this custom mkspec, place the above files into a directory called linux-i486-g+ within the mkspecs/qws directory.
Configuring the target build
We are now ready to configure Qt to use our mkspec and hence use our cross-compiling toolchain. We do so with the following command:
<br /> ./configure -xplatform qws/linux-i486-g++ -embedded x86 -prefix /usr/i486-pc-linux-gnu/usr/local/qt-embedded -qt-gfx-linuxfb -qt-gfx-vnc -no-largefile -exceptions -no-accessibility -no-qt3support -no-sse2 -qt-zlib -no-gif -no-libtiff -qt-libpng -no-libmng -qt-libjpeg -openssl -no-nis -no-cups -depths 16 -qt-kbd-linuxinput -nomake demos -nomake examples -qt-mouse-linuxinput -qt-mouse-tslib -confirm-license<br />
We have some different options here now compared to the earlier host configuration. Notably all references to the qvfb support are gone. This is because the virtual framebuffer application is purely a development and testing tool. It is not designed with security in mind so you should never deploy it on the target.
Here is some information on the other new options that appear:
xplatform <mkspec files to use>Cross compile for the target platform using the environment specified in the mkspec filesembedded <target CPU architecture>The CPU architecture of the target platformprefix <path>The path to install the cross-compiled Qt to. This should be within your sysroot on your host machine to make things easier.qt-mouse-tslibEnable touch screen support via the generic tslib touch screen libraryI<path>Extra include directory to search (in this case for tslib headers)L<path>Extra library directory to search (in this case for tslib headers)
Building and installing
To build and then install the cross-compiled target version of Qt, you can follow the same instructions as for the host build. In short:
<br />make <s>j&lt;number of jobs&gt;<br />su</s> (if you need root access to be able to install)<br />make install<br />
And that's it! You now have everything needed to start writing, testing and running Qt applications for embedded devices on both your development machien and on the device itself (after a suitable deployment).
Summary
In this tutorial you have learned how to:
- Configure, build and install Qt for Embedded Linux as a host build
- Prepare custom mkspecs suitable for your target device