![]() |
| ||
Classes - Annotated - Tree - Functions - Home - Structure |
See also the \e qmake Command Reference.
This manual describes qmake, a cross-platform utility for generating makefiles. qmake was written by Trolltech to provide a simple-to-use tool for supporting large and complex software builds across many platforms, including:
qmake is a standard part of the Qt library installation and will be built and installed properly when building the Qt library. To install qmake separately:
After qmake is built:
Here are some examples:
QMAKESPEC=/usr/local/qt/mkspecs/linux-g++ PATH=$PATH:/local/qmake/bin export QMAKESPEC PATH
setenv QMAKESPEC /usr/local/qt/mkspecs/linux-g++ setenv PATH $PATH:/local/qmake/bin
set QMAKESPEC=c:\qt\mkspecs\win32-msvc set PATH=%PATH%;c:\qmake\bin
qmake is now installed.
Let's assume you have a small Qt application consisting of one C++ header file and two source files.
First you need to create a qmake project file, e.g. hello.pro:
HEADERS = hello.h SOURCES = hello.cpp main.cpp TARGET = hello
This file contains information about the 'hello' project. To create a makefile for this project, invoke qmake as follows:
qmake hello.pro -o Makefile
This creates a makefile for the 'hello' project. To compile this project, type:
make
This builds the 'hello' program. Remember to set the QMAKESPEC environment variable properly before you run qmake.
qmake is a simple tool from Trolltech to create and maintain makefiles for software projects across multiple platforms. qmake provides all of the functionality involved in generating complex makefiles using a single 'project' specification. That 'project' can be targeted to create makefiles for different platforms. It can be a painful task to manage makefiles manually, especially if you develop for more than one platform or use more than one compiler. qmake automates and streamlines this process, allowing you to spend your valuable time writing code, not makefiles.
qmake can be used for any software project of any size, and also contains special features to support developing applications with Trolltech's Qt library.
qmake is a part of the Qt library and is licensed under several licenses, including the QPL, GPL and a commercial license. See the Qt LICENSE file for details.
qmake understands a simple language to describe a makefile, and in turn will generate a project description as appropriate for your target platform. qmake currently generates output for:
qmake requires a description of your platform so that a suitable makefile can be generated. These descriptions are kept in a 'makefile specification' file called qmake.conf. qmake needs this configuration file in order to generate appropriate makefiles for specific platform and compiler combinations. The QMAKESPEC environment variable must be set to the name of a directory which contains this configuration file. The qmake.conf file will contain such basic information as the compiler to use, the names of system libraries and the location of system headers.
On startup, qmake will attempt to locate the qmake.conf file for your platform by using the QMAKESPEC environment variable. Alternatively, it will load all of the default values. The QMAKESPEC environment variable can be used to tell qmake where to find this file, or a command line option can be given. qmake ships with many standard QMAKESPEC files for many platform-compiler combinations. See the \e qmake command reference for more information.
The QMAKESPEC environment variable should point to a directory which contains information about your platform and compiler. When invoked, qmake will use the QMAKESPEC environment variable to find your compiler specifications.
This configuration file contains compiler options and lists tools and libraries.
You can find many platform-compiler combination descriptions in the 'mkspecs' directory of your Qt installation.
Armed with your platform description from the appropriate QMAKESPEC file, qmake will then load any specified 'project files' which describe your software project and generate a makefile to build that project. A project file will typically contain a list of header and source files used by your project. For Qt-based projects, qmake will automatically generate dependencies for moc and uic, if they are needed by your project. The project file will also contain information about the type of project being created (for example, an application or a library), as well as configuration information (such as debug/release, project defines, and extra libraries used when linking).
qmake understands several kinds of 'templates' which tell qmake what kind of project it is building. The supported values are:
A project 'template' is specified using the TEMPLATE system variable. If no TEMPLATE is specified, 'app' is assumed.
The application template, 'app', lets you generate makefiles to compile and link executable programs.
This template recognizes several system variables
The library template, 'lib', lets you generate makefiles to compile and create static or shared libraries.
This template supports the same project variables as 'app' (see above), as well as the following sytem variables:
The 'subdirs' template lets you generate makefiles to invoke qmake within subdirectories.
This template recognizes the following system variables:
qmake assumes that each subdirectory contains additional project files to be processed. Each sub-project file must be named the same as the directory (ie in subdirectory display, you must have a display.pro which will be made by built by qmake, and finally make the project). See the qmake reference manual for details.
If you have Microsoft Visual C++ 5.0, 6.0 or higher, you can use two special templates to generate a MSVC++ IDE project (.dsp file). After you have generated e.g. hello.dsp, choose File|Open Workspace and select the hello.dsp file. Visual C++ will then create a workspace (.dsw file) for you. The additional templates for Microsoft Visual C++ are:
Run qmake to create a hello.dsp file (use -t to override the default template):
qmake -t vcapp -o hello.dsp hello.pro
The CONFIG system variable is recognized by qmake and specifies what compiler options to use and which extra libraries to link in. Anything may be assigned to this variable, however some values will be recognized internally by qmake and have special meaning as described below.
These options control the compilation flags:
These options define the application/library type:
For example, if the 'hello' application uses both Qt and the OpenGL libraries, and you want to compile it with debugging symbols, the hello.pro project file should contain a CONFIG line like the following:
CONFIG = qt opengl debug
The CONFIG system variable is also used when scoping variable assignments.
The most common qmake options and project variables are described here. See the qmake reference manual for details.
qmake project files (typically having a .pro extension) are parsed from top to bottom and consist of a series of user defined variables as well as operations on those variables. When qmake is finished parsing the file without error, a makefile is generated for the platform-compiler combination specified by the QMAKESPEC file. The order of execution for qmake is:
When parsing, there are two classes of variables understood by qmake: user-defined variables and internal system variables. Many internal system variables begin with 'QMAKE_' (user variables should of course use a different prefix), and there are a few common system variables with simpler names, such as PROJECT, CONFIG, SOURCES, HEADERS, etc (more on these project variables below). Below is an outline of the language features understood by qmake.
A qmake project file has a very simple syntax.
The # character begins a comment which lasts until the end of the line.
You may set project variables, append to project variables, and remove from project variables.
To set a project variable:
HEADERS = gui.h xml.h url.h
If you cannot fit everything on one line, use '\' to split it up:
HEADERS = gui.h \ xml.h \ url.h
A user variable name can be any string. The five operators (~=, *=, =, -=, and +=) can be used together to operate on those variables. Using $$ you can refer to another variable previously defined in qmake. There are several operators available to work on lists of values. For example:
PIG=oink moo #$$PIG contains oink and moo PIG-=moo #$$PIG now contains only oink OTHERPIG=$$PIG #$$OTHERPIG contains oink PIG+=snort #$$PIG now contains oink and snort OTHERPIG=eat #$$OTHERPIG now contains only eat
See the \e qmake command reference for more info.
Project variables contains lists of items (for system variables, these consist of things such as header files, compiler options etc.) and use whitespace to separate the items. This means that qmake cannot deal with items containing whitespace. The INCLUDEPATH variable is an exception. If INCLUDEPATH contains one or more semicolons (;), qmake uses the semicolon to separate the include directories, hence you can have include directories containing whitespace (this is quite common on Windows).
Here is an example:
INCLUDEPATH = C:\Program Files\DBLib\Include;C:\qt\include
qmake supports project variable expansion. Use $$ to expand any project variable:
ALLFILES = $$HEADERS $$SOURCES
Most often you assign values to a project variable, but you can also add to, remove from or replace parts of a project variable:
A = abc X = xyz A += abc def # A = abc def C = $$A # C = abc def C += ghi # C = abc def ghi B = $$A # B = abc def B -= abc # B = def B *= abc def # B = abc abc def A ~= s/ab[xc]/xyz/ # A = xyz def
You can also set variables from the command line when running the qmake program. For instance, if you want to generate a makefile with debug information:
qmake "CONFIG+=debug" hello.pro
You may use scopes to conditionally assign to variables. There are several ways to test for something being "in scope":
Scopes must be colon separated from their assignment for example:
SOURCES = common.cpp # common for all platforms unix:SOURCES += unix.cpp # additional sources for Unix win32:SOURCES += win32.cpp # additional sources for Windows unix:LIBS += -lm # on Unix we need the math lib
You may logically AND together scopes by separating multiple scopes with colons, similarly you may negate a scope with the '!' character. In some cases you may actually just want to execute the scope, and not do an assignment, this is perfectly legal in qmake - and the final colon is optional. For example:
win32:win32-msvc:USING_MSVC=1 #if this is win32, and the win32-msvc #compiler is to be used then set the variable unix:include(file.pri) #if this is unix, then substitute the contents #file.pri with this include line. !unix:debug:message(oh dear, unix should be debugged!):WEIRD=1
The syntax scope:assignment can get a little cumbersome when a test is performed multiple times. It also leads to a makefile becoming hard to understand without digging into it, so scopes may be blocked to attempt to modularize different tests. For example:
win32:dance { contains(dance, square_dance):CONFIG += howdown contains(dance, disco):CONFIG += nightfever ACTION += dancing }
Because the syntax for qmake is line based it makes the blocking syntax very strict, this means: You must have the { on the same line as the scope test (you may have 1 assignment after it if you wish). Then the following assignments must be one per line, and finally the block is terminated with a line containing only a '}' character. A second block style syntax is supported for one line blocks, e.g. For example:
test { VARIABLE = value } # which has the same effect as: test:VARIABLE = value
As we've seen in some of the examples above, functions may be used to do advanced tests. For the most part simply testing for platform or the value appearing in the CONFIG variable should be sufficent, but there are other built in functions which can be used. The functions used by qmake may not be extended externally, and this functionallity will probably not be added. See the \e qmake command reference for more info.
qmake can optionally use a 'cache' file to prevent mistaken misconfiguration. qmake will never generate a cache file on its own, it is the obligation of some outside program to do this. The syntax is identical to a normal .pro file. The cache file must be called .qmake.cache, and should be placed at the top directory of your project. qmake will later walk backwards in your project hierarchy to find it (ie starting at the your current working directory, then its parent, and so on until it reaches a .qmake.cache, or the root).
qmake does not require the use of a .qmake.cache - and if it does not exist qmake will not complain. If it does exist, and you want to override it, you may use the -nocache option. See the \e qmake command reference for more info.
With all the above you have enough to design a simple build structure with qmake. In practice there are several caveats to setting up such a project, and this tutorial will try to run through a project file and describe what the output will be. It will also try to give some helpful pointers on using qmake in a similar fashion as Trolltech.
So to start we will outline a simple build procedure. The first thing you meet in many projects is a configure script. If you are writing a project of any size you may want to do this by hand or even with autoconf. Once this script has been run you need to create some Makefiles, similarly you will probably want to create a .qmake.cache in your top level directory (probably where your configure script is). If you create this .qmake.cache each time the user runs configure you can guarantee that your whole tree will be built using the same config options. The most useful things to put in the .qmake.cache are:
After this has been done simply run qmake on the necesary .pro files and you are are set. That is all that we'll mention about configure scripts. If you are writing a small project (less than a couple .pro files) then you may not need to bother with a configure script.
How do we write project files for qmake to process? First you must decide what kind of output you want, for example, a library or an application. For demonstration purposes we will show an application:
TEMPLATE=app TARGET=hello_world SOURCES=main.cpp hello.cpp HEADERS=hello.h
Taken line by line:
TEMPLATE=app This will cause the output to be an application, it will be a fully resolved object and will be placed in DESTDIR, which in this case is not set, so will default to the current working directory.
TARGET=hello_world An application will be created called hello_world
SOURCES=main.cpp hello.cpp Both main.cpp and hello.cpp will be compiled and linked into the final output of hello_world. It will look through these files and parse them as a preprocessor and try to resolve all dependancies for the makefile.
HEADERS=hello.h This tells qmake to look at hello.h. It doesn't mean it will actually do anything in the Makefile, but instead qmake will try to decide if something *should* be done. This mostly means if the header file needs to be moc'd special rules will be added and it the new files will be added to the project.
In many cases this is enough. With all this you are set to build a hello_world project. But suppose your project was bigger and you had some platform specific code:
TEMPLATE=app TARGET=hello_world SOURCES=main.cpp hello.cpp HEADERS=hello.h unix:SOURCES+=hello_unix.cpp win32 { SOURCES += hello_win.cpp CONFIG += bye_world } bye_world:DEFINES += DO_GOODBYE data.path=$$target.path/data data.files = data/*.dat INSTALLS += data target.path=/usr/local/$$TARGET INSTALLS += target
Explaining these new lines:
unix:SOURCES+=hello_unix.cpp If the current target is unix then the file hello_unix.cpp will be included in SOURCES and used as above.
win32 { This starts a block, if win32 is the current target (then the above test will have failed) and the following statements will be applied, otherwise qmake will ignore them.
SOURCES += hello_win.cpp Similar to above hello_win.cpp will be added to the SOURCES, again this is only if win32 was the current target
CONFIG += bye_world This will modify the CONFIG variable and add bye_world to the list of active configurations.
} This terminates the block, after this everything will be processed as usual. It is safe to nest these conditionals (up to 32 deep), and qmake will only process the correct blocks.
bye_world:DEFINES += DO_GOODBYE If bye_world is in the CONFIG list, then DO_GOODBYE will be added to the list of DEFINES, as above this case will only happen if:
data.path=$$target.path/data data.files = data/*.dat INSTALLS += data
We'll look at these three lines together because they're related. First we fill in an object called data. Strictly speaking these aren't objects, as you are free to assign to anything in data (data.qmake for example). Note that only certain variables will be looked at by qmake (outlined in Install Targets). Then it adds the 'data' object to the list of INSTALLS, which will later be processed by qmake to create an install target. And then target.path=/usr/local/$$TARGET sets the target.path to /usr/local/hello_world
INSTALLS += target This is similar to the above, but shows that target is a special install object, that will use the .path member to decide where to put the things qmake creates (in this case just $$TARGET, but in a library more could be created).
Copyright © 2001 Trolltech | Trademarks | Qt version 3.0.0-beta2
|