- Building Qt Applications
- Using qmake
- Using Third-Party Build Tools
Using Third-Party Build Tools
Many build tools are available, both open source and commercial, that can be used to build Qt applications. Such tools fall into two broad categories: tools that generate makefiles (or IDE project files) and rely on the standard build system, and tools that are build systems in their own right, with no external build tools necessary.
In this section, we will review three tools, all chosen because they have support for Qt built-in or easily available. The first, CMake, generates makefiles, and the other two, Boost.Build and SCons, are build systems in their own right. In each case, we will see how to build the Spreadsheet application developed in Chapters 3 and 4. Evaluating any new build tool or build system requires some reading up and some experimentation on real applications, but we hope that this brief review of build tools will be illustrative.
CMake: Cross-Platform Make
The CMake tool, available from http://www.cmake.org/, is an open source cross-platform makefile generator with support for Qt 4 development built-in. To use CMake, we must create a CMakeLists.txt file to describe the project, much like a qmake .pro file. Here is the CMakeLists.txt file for the Spreadsheet application:
project(spreadsheet) cmake_minimum_required(VERSION 2.4.0) find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) set(spreadsheet_SRCS cell.cpp finddialog.cpp gotocelldialog.cpp main.cpp mainwindow.cpp sortdialog.cpp spreadsheet.cpp ) set(spreadsheet_MOC_SRCS finddialog.h gotocelldialog.h mainwindow.h sortdialog.h spreadsheet.h ) set(spreadsheet_UIS gotocelldialog.ui sortdialog.ui ) set(spreadsheet_RCCS spreadsheet.qrc ) qt4_wrap_cpp(spreadsheet_MOCS ${spreadsheet_MOC_SRCS}) qt4_wrap_ui(spreadsheet_UIS_H ${spreadsheet_UIS}) qt4_wrap_cpp(spreadsheet_MOC_UI ${spreadsheet_UIS_H}) qt4_add_resources(spreadsheet_RCC_SRCS ${spreadsheet_RCCS}) add_definitions(-DQT_NO_DEBUG) add_executable(spreadsheet ${spreadsheet_SRCS} ${spreadsheet_MOCS} ${spreadsheet_MOC_UI} ${spreadsheet_RCC_SRCS}) target_link_libraries(spreadsheet ${QT_LIBRARIES} pthread)
Most of the file is simply boilerplate. The only application-specific items we must put in are the application's name (in the first line), the list of .cpp source files, the list of .ui files, and the list of .qrc files. For header files, CMake is smart enough to figure out the dependencies for itself, so we don't need to specify them. However, .h files that define Q_OBJECT classes must be processed by moc, so we have listed these.
The first few lines set the application name and pull in CMake's support for Qt 4. Then we set up some variables to hold the file names. The qt4_wrap_cpp() command runs moc on the given files, and similarly qt4_wrap_ui() runs uic and qt4_add_resources() runs rcc. To create the executable, we specify all the required .cpp files, including those generated by moc and rcc. Finally, we must specify the libraries to link with the executable, in this case the standard Qt 4 libraries and the threading library.
Once the CMakeLists.txt file is completed, we can generate a makefile using the following command:
cmake .
This tells CMake to read the CMakeLists.txt file in the current directory and to generate a file called Makefile. We can then use make (or nmake) to build the application, and make clean if we want a fresh start.
Boost.Build (bjam)
The Boost C++ class libraries include their own build tool, called Boost.Build or bjam, available freely and documented at http://www.boost.org/tools/build/v2/. Version 2 of this tool has built-in support for Qt 4 applications but assumes that there is an environment variable called QTDIR that gives the path to the Qt 4 installation. Some installations of Boost.Build have Qt support disabled by default; for these, we must edit the file user-config.jam and add the line
using qt ;
Instead of relying on QTDIR, we can specify the path where Qt is installed by changing the preceding line to something like this:
using qt : /home/kathy/opt/qt432 ;
Every application built with Boost.Build requires two files: boost-build.jam and Jamroot. In fact, only one copy of boost-build.jam is required for any number of applications, as long as it is in a directory that includes all the applications' directories as subdirectories (no matter how deeply nested). The boost-build.jam file needs to contain only a single line, to specify the path to the build system's installation directory. For example:
boost-build /home/kathy/opt/boost-build ;
The Jamroot file needed to build the Spreadsheet application looks like this:
using qt : /home/kathy/opt/qt432 ; exe spreadsheet : cell.cpp finddialog.cpp finddialog.h gotocelldialog.cpp gotocelldialog.h gotocelldialog.ui main.cpp mainwindow.cpp mainwindow.h sortdialog.cpp sortdialog.h sortdialog.ui spreadsheet.cpp spreadsheet.h spreadsheet.qrc /qt//QtGui /qt//QtCore ;
The first line pulls in the Qt 4 support, and we must provide the Qt 4 installation path. Next, we specify that we want to build an executable called spreadsheet and that it depends on the files listed. For header files, Boost.Build is smart enough to figure out the dependencies for itself, so normally we don't need to list them. However, .h files that define Q_OBJECT classes must be processed by moc, so we must include them in the list. The last two lines specify the Qt libraries we want to use.
Assuming that the bjam executable is in the path, we can build the application using the following command:
bjam release
This tells Boost.Build to build the application specified in the current directory's Jamroot file using a release build. (If you installed only Qt's debug libraries, this will produce errors; run bjam debug in that case.) The moc, uic, and rcc tools will be run as necessary. To clean up, run bjam clean release.
SCons: Software Construction Tool
The SCons tool, available at http://www.scons.org/, is an open source Python-based build tool that is meant to replace make. It has built-in support for Qt 3, and an add-on to support Qt 4 is available from David García Garzón at http://www.iua.upf.edu/~dgarcia/Codders/sconstools.html. There is one file to download from that site, qt4.py, and this should be put in the same directory as the application. This extension is expected to be included in the official SCons release in due course.
Once qt4.py is in place, we can create an SConstruct file where we specify our build:
#!/usr/bin/env python import os QT4_PY_PATH = "." QTDIR = "/home/kathy/opt/qt432" pkgpath = os.environ.get("PKG_CONFIG_PATH", "") pkgpath += ":%s/lib/pkgconfig" % QTDIR os.environ["PKG_CONFIG_PATH"] = pkgpath os.environ["QTDIR"] = QTDIR env = Environment(tools=["default", "qt4"], toolpath=[QT4_PY_PATH]) env["CXXFILESUFFIX"] = ".cpp" env.EnableQt4Modules(["QtGui", "QtCore"]) rccs = [env.Qrc("spreadsheet.qrc", QT4_QRCFLAGS="-name spreadsheet")] uis = [env.Uic4(ui) for ui in ["gotocelldialog.ui", "sortdialog.ui"]] sources = [ "cell.cpp", "finddialog.cpp", "gotocelldialog.cpp", "main.cpp", "mainwindow.cpp", "sortdialog.cpp", "spreadsheet.cpp"] env.Program(target="spreadsheet", source=[rccs, sources])
This file is written in Python, so we have access to all the features and libraries available in the Python language.
Most of the file is boilerplate, with just a few application-specific items needed. We begin by setting the paths to qt4.py and to Qt 4's installation directory. We could avoid copying qt4.py into every application's directory by putting it in a standard location and setting the path to it accordingly. We must explicitly enable the Qt modules we are using, in this case QtCore and QtGui, and we must specify the files that need to be processed by rcc or uic. Finally, we list the source files, and set the program's name as well as the source and resource files it depends on. We do not have to specify the .h files; the Qt 4 support is smart enough to run moc correctly as necessary, by inspecting the .cpp files.
Now we can build the application using the scons command:
scons
This builds the application specified in the SConstruct file in the current directory. We can clean up using scons -c.