[ fromfile: qmake.xml id: qmake ]
C++ applications are generally composed of many source files, header files, and external libraries. During the normal course of project development, source files and libraries get added, changed, or removed. To build an executable that reflects the current state of the project, all such changes require compilation and the resulting object files must all be properly linked. This changing-rebuilding process typically happens many times.
Keeping track of all of the parts of such a project requires a mechanism that precisely specifies the input files involved, the tools needed to build, the intermediate targets and their dependencies, and the final executable target.
The most widely used utility for handling the job of building a project is make [6].
make reads the details of the project specifications and the instructions for the compiler from a Makefile,
which resembles a shell script but contains (at a minimum):
Rules for building certain kinds of files (e.g., to get a
.o file from a .cpp file, we must run gcc -c on the .cpp file)
Sources and Headers lists that contain the names of all source and header files needed by the project
Targets that specify which executables (or libraries) must be built
Dependencies that list which targets need to be rebuilt when certain files get changed
The make command by default loads the file named Makefile from your current working directory and performs the specified build steps (compiling and linking).
The immediate benefit of using make is that it recompiles only the files that have changed or are affected by any changes, rather than blindly recompiling every source file every time.
Figure 1.1 is a diagram which shows the steps involved in building a Qt application.
With Qt, it is not necessary to write Makefiles.
Qt provides a tool called qmake to generate Makefiles for you.
It is still necessary to somehow run make and understand its output.
Most IDEs run make (or something similar) under the covers and either display or filter its output.
In order to create a Makefile, qmake requires a project file.
A project file describes the project by listing all of the other files, as well as all of the options and file locations that are needed to build the project.
It is much simpler than a Makefile and can easily be created by the user.
Fortunately, qmake can also create a simple project file with the command:
qmake -project
When this command is issued, qmake lists all source files (*.cpp) in the current working directory as SOURCES and all header files (*.h) in that directory as HEADERS. The resulting project file will be given the name that follows the optional -o switch. If that switch and its argument are not present, qmake uses the name of the current working directory to name the project file and also, eventually, the executable file.
After the project file has been created, the command:
qmake
will create a Makefile based on the project file.
The command:
make
will attempt to build an executable by following the instructions in the Makefile. The name of the executable is specified by the TARGET variable. It defaults to the name of the project.
Let's use qmake to build the same little program that we discussed, compiled, and ran in Example 1.1.
The transcript below shows which files get created at each step of the build process.
src/early-examples/example0> ls fac.cpp src/early-examples/example0> qmake -project src/early-examples/example0> ls example0.pro fac.cpp src/early-examples/example0> cat example0.pro ###################################################################### # Automatically generated by qmake (2.01a) Tue Jul 28 21:52:05 2009 ###################################################################### TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . # Input SOURCES += fac.cpp src/early-examples/example0> qmake src/early-examples/example0> ls example0.pro fac.cpp Makefile src/early-examples/example0> make g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o fac.o fac.cpp g++ -o example0 fac.o -L/usr/lib -lQtGui -lQtCore -lpthread src/early-examples/example0> ls example0 example0.pro fac.cpp fac.o Makefile src/early-examples/example0>
Notice that we can see the arguments passed to the compiler when we run make.
If any errors are encountered, we will see them too.
Now we can run this app.
src/early-examples/example0> ./example0 Factorial of: 10 The Factorial of 10 is: 3628800 src/early-examples/example0> ./example0 Factorial of: -3 No negative values, please! Factorial of: 0 The Factorial of 0 is: 1 src/early-examples/example0>
Instead of running the command line compiler directly, we will henceforth use qmake and make
which greatly simplify the build process - especially when a project involves multiple source and header files and libraries.
We discuss the make command and Makefiles in a bit more detail in Section C.1.
The project file can be thought of as a map of our project, containing references to all files and locations required for building our application or library.
Like other source code files, this is both human-readable and machine-readable.
The .pro file is the first place to look when we encounter “not found” or “undefined” messages during the build process (especially at link time).
For further details we recommend that you read Trolltech's guide to qmake.
As we add more source-code, header, or library modules to our project, we must edit the .pro file and add the new items to the appropriate SOURCES, HEADERS, and LIBS lists.
The same documentation standards that apply to C++ source code should be applied to project files (where comments begin with #).
[6] Depending on your development environment, you may find variants of make, such as mingw32-make, gmake, or unsermake. In MS Dev Studio, you'll find nmake
| Generated: $Date: 2009-09-08 12:15:32 -0400 (Tue, 08 Sep 2009) $ | © 2009 Alan Ezust and Paul Ezust. |