Home · All Classes · Annotated · Functions

Build System User Guide

This document is designed for anyone working with the Qtopia build system. It is used in conjunction with the Build System Reference which describes individual items in more detail and the Build system Internals document that provides additional developer-oriented information.

Terminology

TermDescription
Qt
  • The name of Trolltech's GUI toolkit for desktop systems.
  • This is also referred to as Qt (host) and qtopiacore (host).
Qtopia Core
  • The name given to Qt when it is run on embedded Linux systems.
  • Features additional functionality not present in the desktop version.
  • It does not run under an existing windowing system.
  • This was previously known as Qt/Embedded.
  • This is also referred to as Qt (target) and qtopiacore (target).
source tree
  • Where source code is located. This can be the same as the build tree.
build tree
  • Where build files are located. This can be the same as the source tree.
project root
  • The Qtopia source tree is split into a number of areas called project roots.
  • Generally, files are found relative to a project root.
project
  • A project is a directory that contains a .pro file.
  • Typically represents an application, library or plug-in to be built.
internal project
  • This is a project inside the Qtopia tree.
external project
  • This is a project outside the Qtopia tree.

Note: Qt and Qtopia Core share the same sources but must be built as two separate products, even when building for the desktop.

Overview

What has Changed?

If you have used earlier Qtopia releases there are some significant changes to how the build system works as follows:

What is the Build System?

For definition purposes, the build system comprises the following files:

FileDescription
configureThe initial entry point into the build system used to set up the build tree.
bin/qtopiamakeCalled by configure and doubles as the the initial entry point for external projects.
bin/*.pmSupport modules for the perl scripts that comprise the build system.
MakefileSecond entry point into the build system. Makefiles are created by qtopiamake.
Makefile.targetFile created by qmake for each project. It should not be called directly.
*.proFile read by qmake when it makes Makefile.target. There is one of these files for each project.
*.prfFeatures files that can be loaded explicitly but are typically loaded implicitly.
*.priThese are miscellaneous build system files included from .pro or .prf files.

Platform Support

Qtopia builds on Linux using GNU make. It should not be difficult to build on other Unix-like systems, though non-GNU make utilities might be a problem and due to assumptions made in the build system, building under Cygwin may prove difficult. Building without a make tool that is, qmake's XCode/Visual Studio project generation is not possible as parts of the the build system functionality are based on running Makefiles.

Depot Hopping

When editing source files and shadow building (that is, build tree != source tree) you may be interested in depot hopping. Simply set QPEDIR to the location of your build tree and the Makefiles that qtopiamake puts in the source tree will call through to those in the build tree. For example:

    cd /path/to/build
    export QPEDIR=$PWD
    cd /path/to/source/examples/application
    $QPEDIR/bin/qtopiamake # sets up shadow build to $QPEDIR/examples/application
    make # build in $QPEDIR/examples/application

Features

Dependencies

The Qtopia build system has dependency information embedded into the .pro files. This makes it possible to build everything in the most efficient way as well as providing flexibility. For example, a library can be renamed with a single change in a single file whereas without the dependency system, many files would need to be changed. The dependency information also provides the ability to graph interdependencies between projects as well as dependencies on external libraries.

Note: Do not put LIBS+= or INCLUDEPATH+= lines in your .pro files, use depends() instead. This applies even if you need to depend on something that isn't built (ie. part of the system). Simply create a stub project with dep() commands. This keeps dependencies clearly defined.

If your application can handle a missing dependency you should do something like this:

    contains(PROJECTS,mydep):CONFIG+=enable_mydep
    enable_mydep:depends(mydep)
    else:DEFINES+=QTOPIA_NO_MYDEP

Use the presence or absence of enable_mydep in the .pro file. For example, disable whole files that use the dependency. Use the presence or absence of QTOPIA_NO_MYDEP to handle code that interfaces with the dependency.

For information about how to use the dependency system please refer to the dep(), idep() and depends() functions.

Applications

Qtopia applications can be built in one of four ways:

  1. quicklaunch
  2. non-quicklaunch
  3. singleexec (quicklaunch)
  4. singleexec (non-quicklaunch)

To facilitate switching between build modes, Qtopia provides two macros which are used as follows:

    #include "myheader.h"
    #include <QtopiaApplication>

    QTOPIA_ADD_APPLICATION(QTOPIA_TARGET, MyMainClass)
    QTOPIA_MAIN

The first argument to QTOPIA_ADD_APPLICATION() must be a literal string that matches the binary name that is, the value of TARGET from the .pro file. The build system defines QTOPIA_TARGET with the value of TARGET and it is recommended to use this macro.

The second argument to QTOPIA_ADD_APPLICATION() should be the name of your class. If you use the wrong value you will get a compile failure.

Building for either quicklaunch or singleexec (quicklaunch) requires these macros but the build system cannot easily determine if you have used them and the penalty for a wrong guess could be disastrous. Therefore you must use the qtopia_main CONFIG value if you use these macros or the build system will assume your application is not quicklaunch-compatible. If your application does not handle quicklaunch or is singleexec you can use the no_quicklaunch or no_singleexec CONFIG values.

For example, games do not need the speed benefits of quicklauncher (and there is a size penalty for using quicklauncher) but they do work with singleexec. So use CONFIG+=qtopia_main no_quicklaunch to indicate this.

Some applications, such as those using a custom application class, cannot use the macros. Tis prevents the use of quicklauncher but you can still work with singleexec if you make some changes to your code. You need to use the singleexec_main CONFIG value and have a main.cpp similar to the following:

    #include "myheader.h"
    #include <QtopiaApplication>

    #ifdef SINGLE_EXEC
    QTOPIA_ADD_APPLICATION(QTOPIA_TARGET, MyMainClass)
    #define MAIN_FUNC main_MyMainClass
    #else
    #define MAIN_FUNC main
    #endif

    int MAIN_FUNC( int argc, char **argv )
    {
        MyApplication a( argc, argv );
        MyWidget w;
        w.show();
        return a.exec();
    }

Libraries

Library projects .pro files require extra code to make them usable by other projects, for example:

    qtopia_project(lib)
    TARGET=mylib

    PREFIX=MYLIB
    MYLIB_FORMS=foobase.ui
    MYLIB_HEADERS=foo.h
    MYLIB_PRIVATE_HEADERS=foo_p.h
    MYLIB_SOURCES=foo.cpp

    resolve_include()

    mylib_headers.files=$$MYLIB_HEADERS
    mylib_headers.path=/include/qtopia/mylib
    mylib_headers.hint=headers
    INSTALLS+=mylib_headers

    mylib_private_headers.files=$$MYLIB_PRIVATE_HEADERS
    mylib_private_headers.path=/include/qtopia/mylib/private
    mylib_private_headers.hint=headers
    INSTALLS+=mylib_private_headers

    idep(LIBS+=-l$$TARGET)
    qt_inc($$TARGET)

This project is a library project called mylib. The use of PREFIX, MYLIB_* and resolve_include() is not strictly required but will help if the library needs to be extended later.

There are some install rules created and qt_inc() is used to setup the headers. See Setting Up Headers for details.

The use of idep() ensures that dependent projects will be linked to this library.

Plug-ins

External plug-ins will need to set the plugin_type variable so that the build system knows what type of plug-in they are.

subdirs

A project that uses the keyword subdirs to qtopia_project() will cause other directories to be built. The project at the top of each project root specifies a value for subdirs, however there are many projects that do not and subdirs projects that are inside a project root will cause part of the tree to be built. It is also possible to build all directories (instead of those listed in PROJECTS) by using the build_all_dirs CONFIG value. This is superior to using recursive subdirs as it allows dependencies to be processed.

Install Helpers

To simplify the code required in each .pro file and to aid installation, common functionality has been moved into the build system. This is mostly visible through the use of Install Hints and is assisted by the use of the EXTRA_TS_FILES variable.

Packages

Qtopia projects are automatically setup to be built into packages, and by default these are single packages. Non-qtopia projects must add packages to their CONFIG to be built into packages. The package contents are the result of running make install. To configure the default package you should use the pkg structure, for example:

    pkg.name=myapp
    pkg.desc=My Great App
    pkg.version=1.0

You can create other structures and assign them to the PACKAGES variable to create more than one package though this is not well tested. The structure of a packaging structure is as follows:

    # struct package {
    #     name       # eg. $name.ipk
    #     desc       # one line summary
    #     domain     # SXE security domains
    #     deps       # packages that this ipk depends on
    #     multi      # additional projects that should be included in this package
    #     version    # package version
    #     license    # package license
    #     maintainer # package maintainer
    #     targets    # targets to run (ie. install stuff)
    # }

The use of pkg structure is suppressed by adding the no_pkg CONFIG value. This is useful for multi-project packages, for exmaple, several network-related projects are put into one package. To improve maintainability, you should indicate which project is responsible for packaging if you do this, for example:

    # Packaged by settings/network
    CONFIG+=no_pkg

Internationalization

The build system has a variable named TRANSLATABLES that is used to facilitate a single set of translations across a number of products and configurations. Conditional source should be added to the TRANSLATABLES variable even if the condition is false.

Non-code Translatables

Non-code Translatables are processed with bin/nct_lupdate which extracts data from the following formats:

FormatDescription
zone.tabA special case used to extract city names from the time zone database
QSettingsFormat for Qtopia configuration files that deal with translated values.

The following is an example of a translatable settings file:

    [Translation]
    File=QtopiaApplications
    Context=Calendar
    Comment[Desktop Entry/Name]=Use soft hyphen (char U00AD) to indicate hyphenation
    [Desktop Entry]
    Comment[]=A Calendar and Scheduling Program
    Exec=datebook
    Icon=datebook/DateBook
    Type=Application
    Name[]=Cal\xad\x65n\xad\x64\x61r
    MimeType=text/x-vcalendar

In the above datebook.desktop example,the important parts are the [Translation] section and the Var[]=Value lines.

Code LineDescription
File=QtopiaApplicationsInstructs the build system to store the translations in a file called QtopiaApplications.ts. The files in Qtopia are generally stored in global .ts files but third-party applications need to use their own files.
Context=CalendarSpecifies the context to use for the translations. When QObject::tr() is called an implicit context is used, however, QApplication::translate() allows the context to be set. This must be somewhat unique so that translators do not have to deal with unrelated strings when translating content.
Comment[Desktop Entry/Name]=Use soft hyphen (char U00AD) to indicate hyphenationPlaces a comment in the .ts file for translators. In this case, the value Name in the [Desktop Entry] section is given a comment.
Name[]=Cal\xad\x65n\xad\x64\x61rWhen Qtopia reads this value, it will try to translate it.

Tasks

Setting Up Headers

The header setup process is a little complicated. The following is a step-by-step process:

  1. configure runs and
  2. The headers install rules setup classic headers (Qtopia 2 style) based on the .path value and Qt 4 style headers to keep old source working. Note: Their use is deprecated and they will be removed in a future version.
  3. The Qt 4 style headers are installed into a directory named after TARGET.
  4. Libraries should use the qt_inc() function so that their dependents have this directory added to the INCLUDEPATH automatically.

Note: It is possible to use idep(INCLUDEPATH+=$$PWD) but this is not recommended as you cannot limit the files accessible when this method is used. You also cannot keep private headers separated from public headers.

Setting up a Global Condition

Place the following code in the optvar section of configure:

    set_optvar( "myopt", +{
        "set" => [ "%", "Enable myopt." ],
        "unset" => [ "no-%", "Disable myopt." ],
        "default" => 1,
        "visible" => $qtopia_visref,
        "autodep" => $qtopia_autoref,
    });

Place the following code in the config_pri section of configure:

    if ( opt("myopt") ) {
        print CONFIG_PRI "CONFIG+=enable_myopt\n";
    }

Place the following code in src/build/qtopia.prf:

    # positive define (preferred)
    enable_myopt:DEFINES+=QTOPIA_MYOPT
    # negative define (to match the QT_NO_ style)
    !enable_myopt:DEFINES+=QTOPIA_NO_MYOPT

Note: The use of a positively-worded option. It is much easier to determine what code does when the options are positively worded.

Deciding What To Build

The file projects.pri includes other files to setup the PROJECTS and THEMES variables which control what is built.

The following files are included from src in the source tree:

FileDescription
general.priProjects and themes that are in all Qtopia source packages.
commercial.priProjects and themes that are only in commercial Qtopia source packages.
custom.priOverrides/additions for Qtopia.
desktop.priProjects that are in Qtopia Desktop.
custom_qd.priOverrides/additions for Qtopia Desktop.

The following files are included from src in the build tree:

FileDescription
local.priOverrides/additions specific to a build.
local_qd.priOverrides/additions for Qtopia Desktop specific to a build.

It is not recommended to modify general.pri and commercial.pri, instead you should use custom.pri and local.pri. The intent is for organization changes (that is, changes that will be part of a redistributed source package) to go into custom.pri and changes for individual developers to go into local.pri.

When adding projects, it is recommended to use *= to avoid the possibility of duplicate entries as duplicate entries can cause problems when you try to build. For example:

    PROJECTS+=myproj
    PROJECTS*=myproj # no duplicate
    PROJECTS+=myproj # duplicate

A project can be removed using -= as follows:

    PROJECTS-=myproj

Note: qmake does not consider it an error to remove a non-existent value so check for spelling errors if a removed project is still building.

CONFIG values that are set based on edition and configuration can be used when adding projects, for example, a PDA-specific application could be added with:

    pda:PROJECTS*=myproj

In the situation where You might want to enable a project only if another project is enabled, you can check for the presence of a project with the qmake contains function as follows:

    contains(PROJECTS,applications/mygreatapp):PROJECTS*=plugins/mygreatapp/time

Common Makefile Targets

The following targets should work everywhere and will descend into subdirectories unless otherwise noted:

TargetDescription
allBuild the target.
firstSame as all. Provided for compatibility with Qt (which uses all to mean both debug and release versions).
installRun the install rules.
install_targetInstall the target only (eg. the application binary).
cleaninstallRemove the image (and dimage) directories before installing. (Only useful when used from the top of the tree).
lupdateUpdate .ts files.
syncqtopia
packagesMake installable packages. See Packages for details.
sdkRun the SDK rules.
devsdkRun the DevSDK rules.
regenerateRebuild the Makefile for this project. Do not descend into subdirectories.
qmakeSame as regenerate but descends into subdirectories.
qmake-debugSame as regenerate but turns on qmake debugging.
cleanRemove intermediate files (not everything).
discleanRemove the target and Makefile.target.
remove_targetRemove the target so that make will cause it to be re-linked.
relinkRuns make remove_target and make so that all targets are re-linked.

Device Configuration Profiles

Device Configuration Profiles simplify the task of configuring Qtopia for a device. A single directory contains all of the configuration information required to build for the device. The profiles are located in the devices directory in the source tree and are activated by running:

    configure -device foo

For a tutorial on the process of implementing a plug-in for a new device see : Tutorial: Implementing a Device Plug-in

The following sections describe how to customize the profiles:

Features

Each feature of the Device Configuration Profiles is identified by the file that implements it.

configure

Each device configuration profile can have a file named configure that specifies all the arguments required to configure for the new device. This simplifies the process as generally many configuration arguments are required.

When configure ... -device foo ... is run, configure checks for $QTOPIA_DEPOT_PATH/devices/device/configure and if it is found, configure re-launches itself with -device device replaced by the contents of the file.

The following is a sample configure file:

    -edition phone -xplatform mydev -arch arm -no-qvfb
    -release -displaysize 240x320 -quicklaunch
    -defaultbuttons phone
    -extra-qtopiacore-config -plugin-kbd-mydev
    -extra-qtopiacore-config -plugin-mouse-mydev
    -prefix /opt/Qtopia

Note:

  1. Whitespace is interpreted by the shell so the newlines are not relevant.
  2. The ordering of arguments is significant. Anything specified before -device can be overridden by the device profile while anything after -device can override the device profile.

For example, the sample file above specifies -release. Here is what would happen -debug is passed before and after -device foo:

environment

The environment script (if it exists) is sourced before re-running configure and before Makefile calls Makefile.target. The suggested use is to set up paths to an appropriate compiler with the DEVICE_CONFIG_PATH variable set to the path of the device configuration profile so that files inside the device directory can be located.

mkspecs

A typical behavior of the configure file is to set -xplatform so it is useful to have a platform specification for the device. Profiles can contain a mkspecs directory that is used to determine -platform and -xplatform speciification files. This allows a device to be built without having to modify the Qt depot (although it is possible to move a specification file to Qt without having to modify the configure line).

For example, the mydev specification files are in its configuration directory as follows:

    devices/mydev/mkspecs/qws/linux-mydev-g++/qmake.conf
    devices/mydev/mkspecs/qws/linux-mydev-g++/qplatformdefs.h

There are mkspecs that ship with Qtopia Core located in qtopiacore/qt/mkspecs/qws. You should copy one that is similar to your device, for example, linux-arm-g++, and modify it to suit your device. Be sure to check the compiler name and the compiler flags (especially optimization flags). You may also want the mkspec to specify a define to be used to enable device-specific code in Qtopia Core and Qtopia.

custom.h/custom.cpp

These files are device-specific and it is useful for them to be included in the Device Configuration Profile. If they are not present, configure will look in the traditional location, $QTOPIA_DEPOT_PATH/src/libraries/qtopia/custom-$xplatform.(h|cpp). See Hardware Configuration for information about custom.h.

defaultbuttons.conf

Every device needs a suitable defaultbuttons.conf, However, use of this file only occurs if -defaultbuttons is not passed to configure. Refer to: Keypad Button Behavior for a description of defaultbuttons.conf.

config.pri

Configuration tweaks can be done here. This is read just after the configure-generated config.pri, before each .pro file is read. A modified config.pri file is used to customize configuration. This file is read after the the config.pri file generated by configure and before each .pro file. Adding <content> to a config.pri file is equivalent to running the following:

    configure -config <content>

projects.pri

The projects.pri file is used to enable and disable projects for a device. It is processed after general.pri and commercial.pri but before custom.pri and local.pri so that the user can still override the projects.

src

If the src directory exists, it is added as a project root that is:

        configure -build $QTOPIA_DEPOT_PATH/devices/foo/src}

It is recommended to mimic the Qtopia source tree layout for ease of reference.

qconfig.h

This file overrides the use of qconfig-qpe.h. It can define all new items or can include and override settings by using:

        #include "qconfig-qpe.h"

Note: Beware of dependencies when including and overriding.

Limitations

Profiles do not currently with the following:


Copyright © 2006 Trolltech Trademarks
Qtopia 4.1.7