Link to index:clem's Qt/Embedded, Opie, iPAQ and security resources
Tux with a linux handheld


On this page, we explain how to download, configure, install or build Qt/Embedded and Opie on a Linux, Intel (x86) architecture, for both x86 and ARM (hp/Compaq iPAQ Pocket PC) target architectures.

We designed this page to centralize everything we need to do to get a valid development environment, without giving too much details. If you want more detailed, high level information (but that will be more scattered too), please look at this page's references.
Note: these instructions are heavily tested on a Linux Debian / unstable (aka 'sid') configuration, but I am trying to make them valid for most linux distributions. See for example this note if you are not using Debian (but Red Hat, Mandrake, Suse, Gentoo or any other Linux distribution).

Table of Contents

Before we start

If the OS you are using is not a Debian unstable, please note this:
Typographic convention: lines that start with a path followed by a percent sign `%' (/here/is/an/example%) are commands you must type as a normal user; lines that start with a path, but followed by a hash sign `#' (/here/is/another/example#) are commands you must type as root.
If it's the first time you read this page, you may skip the News section and jump directly to our how-to!

News about this page

November 20, 2004

Added -gif option to the ./configure part of Building Qt paragraph, since the corresponding patent has expired. Thanks for pointing that out, Lewis Jardine!

October 17, 2004

Notes added about speeding up Opie builds (or opie-based applications) with ccache and distcc.

September 29, 2004

Backup link added to the crosscompiler installation part, since OpenZaurus toolchain directory has disappeared :-/

September 24, 2004

Note added in Building Opie on how your DEBUG options must be the same in your build environment and in the packages you are using.

September 17, 2004

July 12, 2004

Fixed another typo in the Qt build environment setup (/arm/ path missing in the right column). Thanks, Ralf Staudemeyer!

April 25, 2004

Added a new link in the link list at the end, to a new guide for Zaurus developers, and fixed a typo in the alien and tar based ARM libraries extraction part: the wrong libpng version was written, so my one-line extracting command would not work.

January 18, 2004 (happy new year!)

Updated the Qt environment setup part so we make sure we will not use a Qt3 version of UIC, if present. Thanks to Christoph Dwertmann for his feedback!

December 12, 2003

Updated zlib1g and libpng available versions in ARM libraries installation part.

October 02, 2003

Now there is a patch for Qt2.3.7 in Opie qt/ directory, whose application is simpler than the Qt2.3.5 previous patch. Simplified the patching part of Qt installation then. By the way, Opie 1.0 and 1.0.1 still have Qt2.3.5 in their feeds, so in some circumstances you may prefer to configure your dev. environment with Qt2.3.5 rather than with Qt2.3.7. More details soon.

September 28, 2003 guys seem to prefer the .3 version of their 2.95 compiler to its .4 version, which was moved recently in an unsupported subdirectory. Altough I use the .4 version without any problem, I've prefered to put the .3 version in the cross-compiler installation part.

September 23, 2003

I know use libpng version 1.2 (aka libpng3) instead of libpng version 1.0 (aka libpng2) to compile Qt and Opie. Indeed, Opie 1.0 and newer depend (through libqte2) on libpng3, and only libpng3. x86 libraries installation and ARM libraries installation parts have therefore been updated.

September 03, 2003

The cross-compiler I recommend (GCC2.95-based, from Open Zaurus team) makes valid binaries for XScale processors, at least for the PXA-250 used in h3900 iPAQ series, on which I work (along with h3600 and h3800). I've not tested it yet on h2200 or h5400 series though. I removed the corresponding item in my Todo list, even if I'd like to hear how compilation for new iPAQ series is going.

August 12, 2003

Qt/Embedded 2.3.7 is out, download link updated.

August 09, 2003

New section about what to do as soon as Opie is compiled (using qmake, qvfb and more generally how to develop Opie applications).

August 05, 2003

Added the exact conversion and extraction commands non-Debian users have to type to get ARM libraries and headers, thanks to Franz Regensburger feedback.

July 23, 2003

opie-login can be compiled again! I took the files from libpam0g-dev we need from my qt/include and qt/lib, put them into a tar.gz with the same architecture as the original Debian package, and put the archive on my servers (see at the end of the ARM packages URL list below).

July 22, 2003

Unfortunately, I don't propose anymore a way to cross-compile opie-login since the appropriate debian package for libpam0g, which was the testing one until recently, has been upgraded to GLIBC2.3 (more details below).

July 14, 2003

Added a introduction to the document, where I explain how this page is still useful if you don't use the same Linux distribution (Debian) or Debian flavor (unstable) as me.

July 3, 2003

The cross-compiler (ARM target) section has been greatly simplified:
Many fixes and explanations were added here and there.
Finally, everything has been successfully tested up to and including Opie compilation, for both architectures. I did not perform runtime tests on x86 (through qvfb) and on different iPAQs configurations yet...

Recipe for a valid Qt/Opie development environment

Different things to do for both target architectures
Todo list for x86 target Todo list for ARM target

Downloading Opie latest sources through CVS

Note: we will explain how to install Qt and Opie in your /opt directory, but this is an unimportant choice, and you may as well choose a path like ~/dev/opie-and-qt or anything else.
% cd /opt
/opt% touch ~/.cvspass
If you are connecting to Opie CVS for the first time, you must log in as an anonymous user (and give 'anoncvs' as the password).
/opt% cvs login
Then you can checkout the Opie code:
/opt% cvs -z6 checkout opie
And repeat this in the directory you will use for cross-compilation:
/opt% mkdir arm; cd arm/
/opt/arm% cvs -z6 checkout opie
Note: you can put -r BRANCH_1_0 between checkout and opie, in the previous lines, to checkout the stable branch of Opie, Opie 1.0, instead of the development version.

Installing UIC binary and downloading Qt/Embedded sources

You can install the UIC through a Debian package:
/opt# apt-get install libqte2-dev || apt-get install uic
But if you are not using Debian, you can simply download a (big) uic binary statically linked:
/opt# wget -O /usr/local/bin/uic then make it executable of course: chmod +x /usr/local/bin/uic
You can then download and extract the latest Qt/Embedded 2 sources:
/opt% wget
Decompress the sources in two directories (one for each architecture):
/opt% tar xvjf qt-embedded-2.3.8.tar.bz2
/opt% cp -a qt-2.3.8 arm/

Installing the cross-compiler (GCC2.95-based, from Open Zaurus team)

% cd /tmp
First we download and extract the latest GCC2.95-based toolchain (definition of a toolchain):
/tmp% wget
If the link above is still broken (it was around Sep 29, 2004), you can try this one from archive.
/tmp% tar xvjf cross-2.95.3.tar.bz2
Then we install it into /usr/local/arm directory, and we tell our environment to look here for binaries:
/tmp# mkdir /usr/local/arm; cp -a 2.95.3 /usr/local/arm
/tmp% export PATH=/usr/local/arm/2.95.3/bin:$PATH

Installing x86 libraries needed by Qt and Opie

# apt-get install libfreetype6-dev libjpeg62-dev libpam0g-dev libpng12-dev zlib1g-dev libbluetooth1-dev libpcsclite-dev pkg-config
You can also install libpcap-dev (useful if you want to build libopie2net)

Installing ARM libraries needed by Qt and Opie

Downloading ARM headers and libraries from Debian package pool

Extracting these packages, Debian way

/tmp% mkdir libjpeg62 && dpkg-deb -x libjpeg62_6b-5_arm.deb libjpeg62 && dpkg-deb -x libjpeg62-dev_6b-5_arm.deb libjpeg62 && mkdir libfreetype6 && dpkg-deb -x libfreetype6_2.0.9-1_arm.deb libfreetype6 && dpkg-deb -x libfreetype6-dev_2.0.9-1_arm.deb libfreetype6 && mkdir zlib1g && dpkg-deb -x zlib1g_1.1.4-1.0woody0_arm.deb zlib1g && dpkg-deb -x zlib1g-dev_1.1.4-1.0woody0_arm.deb zlib1g && mkdir libpcap0.7 && dpkg-deb -x libpcap0.7_0.7.2-7_arm.deb libpcap0.7 && dpkg-deb -x libpcap0.7-dev_0.7.2-7_arm.deb libpcap0.7 && mkdir libpng3 && dpkg-deb -x libpng3_1.2.1-1.1.woody.9_arm.deb libpng3 && dpkg-deb -x libpng-dev_1.2.1-1.1.woody.9_arm.deb libpng3 && mkdir libbluetooth1 && dpkg-deb -x libbluetooth1_2.11-1_arm.deb libbluetooth1 && dpkg-deb -x libbluetooth1-dev_2.11-1_arm.deb libbluetooth1 && mkdir libgcc1 && dpkg-deb -x libgcc1_3.0.4-7_arm.deb libgcc1 && mkdir libpcsclite1 && dpkg-deb -x libpcsclite1_1.2.9-beta6-1_arm.deb libpcsclite1 && dpkg-deb -x libpcsclite-dev_1.2.9-beta6-1_arm.deb libpcsclite1 && mkdir flex && dpkg-deb -x flex_2.5.4a-24_arm.deb flex && tar xzf libpam0g-dev_0.76-9_arm_for_Opie.tgz

Alternative to last paragraph: Extracting these packages, Alien way (if you are using another Linux distribution)

Since we run the following command as a normal user, alien will complain the permissions won't be right. Don't pay attention to this message, since the permissions will be right enough to compile Opie :-)
/tmp% alien --to-tgz *.deb
Now we have .tgz packages, which we can extract with tar:
/tmp% mkdir libjpeg62 && tar Cxzf libjpeg62 libjpeg62-6b.tgz && tar Cxzf libjpeg62 libjpeg62-dev-6b.tgz && mkdir libfreetype6 && tar Cxzf libfreetype6 libfreetype6-2.0.9.tgz && tar Cxzf libfreetype6 libfreetype6-dev-2.0.9.tgz && mkdir zlib1g && tar Cxzf zlib1g zlib1g-1.1.4.tgz && tar Cxzf zlib1g zlib1g-dev-1.1.4.tgz && mkdir libpcap0.7 && tar Cxzf libpcap0.7 libpcap0.7-0.7.2.tgz && tar Cxzf libpcap0.7 libpcap0.7-dev-0.7.2.tgz && mkdir libpng3 && tar Cxzf libpng3 libpng3-1.2.1.tgz && tar Cxzf libpng3 libpng-dev-1.2.1.tgz && mkdir libbluetooth1 && tar Cxzf libbluetooth1 libbluetooth1-2.11.tgz && tar Cxzf libbluetooth1 libbluetooth1-dev-2.11.tgz && mkdir libgcc1 && tar Cxzf libgcc1 libgcc1-3.0.4.tgz && mkdir libpcsclite1 && tar Cxzf libpcsclite1 libpcsclite1-1.2.9-beta6.tgz && tar Cxzf libpcsclite1 libpcsclite-dev-1.2.9-beta6.tgz && mkdir flex && tar Cxzf flex flex-2.5.4a.tgz && tar xzf libpam0g-dev_0.76-9_arm_for_Opie.tgz

Installing headers and libraries into the right directories

/tmp# find libjpeg62 libfreetype6 zlib1g libpcap0.7 libpng3 libbluetooth1 libgcc1 libpcsclite1 flex -path '*/include/*' -maxdepth 3 -exec cp -R {} /usr/local/arm/2.95.3/arm-linux/include \;
/tmp# find libjpeg62 libfreetype6 zlib1g libpcap0.7 libpng3 libbluetooth1 libgcc1 libpcsclite1 flex -path '*/lib/*' -maxdepth 3 -exec cp -R --no-dereference {} /usr/local/arm/2.95.3/arm-linux/lib \;

Setting up the environment and patching Qt (x86 target)

% export QTDIR=/opt/qt-2.3.8
% cd $QTDIR/
/opt/qt-2.3.8% export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH
/opt/qt-2.3.8% mkdir -p bin

Setting up the environment and patching Qt (ARM target)

% export QTDIR=/opt/arm/qt-2.3.8
% cd $QTDIR/
/opt/arm/qt-2.3.8% mkdir -p bin
In the following line, we link to the Qt2 version of the UIC to compile Qt/Embedded. Depending on the option you've chosen in the UIC installation step, its binary name is /usr/share/qte2/bin/uic on Debian unstable and testing, uic on Debian stable, uic2 on Redhat, or uic if you prefered to install a statically linked uic in /usr/local/bin! So adapt the path in the following line, and link your binary to $QTDIR/bin like this:
/opt/qt-2.3.8% ln -s /path/to/your/qt2/uic bin/uic
/opt/qt-2.3.8% export OPIEDIR=/opt/opie
/opt/qt-2.3.8% ln -s $OPIEDIR/qt/qconfig*.h src/tools/

/opt/qt-2.3.8% ls $OPIEDIR/qt
Try to guess which patches concern you amongst the output files; but if you are compiling for iPAQ and with qt-2.3.8, you'll probably have to apply only one patch (add-macosx after -all if you are using MacOS X):
/opt/qt-2.3.8% patch -p1 < $OPIEDIR/qt/qt-2.3.8.patch/qte238-all.patch patch command output
/opt/qt-2.3.8% ln -s /path/to/your/qt2/uic bin/uic
/opt/arm/qt-2.3.8% export OPIEDIR=/opt/arm/opie
/opt/arm/qt-2.3.8% ln -s $OPIEDIR/qt/qconfig*.h src/tools/
/opt/arm/qt-2.3.8% ls $OPIEDIR/qt
Try to guess which patches concern you amongst the output files; but if you are compiling for iPAQ and with qt-2.3.8, you'll probably have to apply only one patch (add-macosx after -all if you are using MacOS X):
/opt/arm/qt-2.3.8% patch -p1 < $OPIEDIR/qt/qt-2.3.8.patch/qte238-all.patch patch command output

Building Qt for Opie (x86 target)

/opt/qt-2.3.8% make make command output

Building Qt for Opie (ARM target)

/opt/arm/qt-2.3.8% ./configure -qconfig qpe -depths 4,16,24 -xplatform linux-ipaq-g++ -no-qvfb -system-jpeg -system-libpng -gif -system-zlib -vnc -no-xft configure command output
Note: if you are crosscompiling for a Sharp Zaurus and not an iPAQ, replace linux-ipaq-g++ in the previous line by linux-sharp-g++. You will also need to extract this Sharp kernel headers RPM package (or its .tar.gz counterpart here) somewhere on your disk (by default /opt/Embedix/tools/arm-linux), set $KERNEL_PATH to point to it, and append -I$KERNEL_PATH/include to the ./configure line above.
/opt/arm/qt-2.3.8% make make command output

Building Opie (x86 target)


Building Opie (ARM target)

Notes on tools to speed up compilation:
  • If you think you will compile Opie more than once (it happens e.g. when you run make clean then make again), you can cache the results of each compilation item with ccache, a useful tool to speed up compilations. The simplest way to do that before building Opie is to set the CCACHE environment variable like this once ccache is installed:
    % export CCACHE=ccache
  • If you have several (preferably Linux or MacOS X) computers around you, you can speed up any compilation with distcc, another useful compilation speeding tool to distribute compilation on several machines. Let's say distcc is now installed on two of your machines plus the one you are building Opie on (you can have of course a local team share its ressources there), whose IP addresses are and Now all you have to do is to set up two variables, the first one always used by distcc, the second one used by Opie build scripts, and to tell make to use twice as many parallel processes:
    % export DISTCC_HOSTS=" localhost"
    % export DISTCC=distcc
    % alias make="make -j 6"
    Note: you can get more information about this kind of setting up on distcc and ccache web pages, in their man pages, and on this Opie wiki page on ccache and distcc usage.
/opt/opie% make menuconfig resulting .config file ; note: you may have to install flex if it fails.
/opt/arm/opie% make menuconfig resulting .config file ; note: you may have to install flex if it fails.
Notes on setting options in the menuconfig build interface:
  • If you plan to compile and put libraries (or plugins) on your iPAQ where most packages come from the official Opie feed, check that Enable debug builds (CONFIG_DEBUG) is unset in Build Parameters. Indeed, especially if you use the odebug, owarn marcros, libraries compiled in a CONFIG_DEBUG=y must be loaded by applications compiled with CONFIG_DEBUG=y, and vice-versa; and Opie official feeds are compiled with CONFIG_DEBUG unset so you must unset it on your ARM build environment if you are just building plugins.
Before quitting, check that Intel x86 is selected in Build Parameters / Target Machine.
Then you can run:
/opt/opie% make oldconfig
and finally:
/opt/opie% make make output
Before quitting, check that iPAQ (or the appropriate Zaurus, Simpad, Yopy... target if your target device is not exactly an iPAQ) is selected in Build Parameters / Target Machine.
To speed up application launching times, you may want to select, in the same menu, Enable Quick Launch.
Then you can run:
/opt/arm/opie% make oldconfig
and finally:
/opt/arm/opie% make make output

What to do from here

Don't forget to use qmake!

Since you must have compiled Opie at least for one architecture, x86 or ARM, you have now a valid qmake binary, for x86 (don't forget you develop on x86, whether you develop for x86 or ARM), at this address: $OPIEDIR/qmake/qmake. This tool, included and used by Opie, is in fact a backport from Trolltech's useful tool from Qt3, and is designed to create Makefiles easily, from .pro files, whatever your target architecture is. Trolltech has a good qmake manual here.

Hello, world! for Opie

You can now start to develop applications for Opie, whereas you run them on your x86 desktop through qvfb (how to getqvfb), or on you iPAQ. For example, you can now read the Hello, World! wiki page on! Among other things, it will teach you to write a .pro file and to build the corresponding Makefile, or to let Opie know there's a new .pro file, so its main Makefile will call qmake for all the applications you decided to compile, including yours.
Finally, you can find guidelines for Opie programming on another web site, which features a big Opie development handbook, for HP/Compaq iPAQ and Sharp Zaurus.

How to get qvfb (here is a qvfb short description by Qt)

Install the qt3-dev-tools-embedded package under Debian unstable or testing, libqt3-dev under Debian stable, or compile a recent Qt for X11 (qvfb runs on X, not on iPAQs Qt/Embedded) like this one: There should be RPM or other binaries packages availabe for your linux distribution to avoid the compilation step (see for example this Qtopia FTP directory to get an RPM that should contain qvfb).

Miscellaneous notes

Other cross-compiling related stuff

How to cross-compile OpenSSL for ARM

In a nutshell:
/opt/arm% wget && tar xvzf openssl-0.9.7d.tar.gz && cd openssl-0.9.7d
/opt/arm/openssl-0.9.7d% ./Configure linux-elf-arm --prefix=/usr
Then set your environment so a gcc 3.3-based ARM crosscompiler (OpenZaurus 3.3.1 in /usr/local/arm/3.3 will be fine) is in your $PATH, and patch your Makefile to use this cross-compiler (the patch also contains a linking instruction to libdl, needed to get the openssl binary):
/opt/arm/openssl-0.9.7d% export PATH=/usr/local/arm/3.3/bin:$PATH
/opt/arm/openssl-0.9.7d% wget -N && patch -p1 < opensslForARM.Makefile.patch
You can compile it now! (after setting DISTCC to /usr/bin/distcc, DISTCC_HOSTS to your distcc hosts, and using make -j DISTCC_HOSTS*2, for example, instead of make to distribute compiling if you want and can):
/opt/arm/openssl-0.9.7d% make && make build-shared
You can do the following if you want (that way /opt/arm/openssl will be your local OpenSSL dir, its includes will be in include and its libs in lib):
/opt/arm/openssl-0.9.7d% mkdir lib && cd lib && ln -s ../libcrypto* ../libssl* . && cd ../.. && ln -s openssl-0.9.7d openssl


Other links

Questions or comments? Contact the author! (Clément Séveillac (personal email) - PGP key / fingerprint)