About This Manual
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:
- MS/Windows - 95, 98, NT, and 2000
- Unix/X11 - Linux, Sun Solaris, HP-UX, Tru64, IBM AIX, SGI IRIX and a wide range of others
- Embedded - Linux platforms
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:
- Unpack the Qt archive, configure and build.
- The 'qmake' executable will then be located in the 'bin' subdirectory.
After qmake is built:
- Set the QMAKESPEC environment variable to point to a directory containing a description of your platform and compiler (see below)
- Add the 'qmake' executable to your PATH
Here are some examples:
- Unix Bourne shell:
· QMAKESPEC=/usr/local/qt/mkspecs/linux-g++
· PATH=$PATH:/local/qmake/bin
· export QMAKESPEC PATH
- Unix C shell:
· setenv QMAKESPEC /usr/local/qt/mkspecs/linux-g++
· setenv PATH $PATH:/local/qmake/bin
- Microsoft Windows:
· 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:
- borland make makefiles
- unix-style makefiles, i.e. suitable for gmake, etc.
- msdev nmake makefiles
- msdev dsp project files
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).
Project Templates
qmake understands several kinds of 'templates' which tell qmake what kind of project it is building. The supported values are:
- app - Creates a makefile for building applications (the default)
- lib - Creates a makefile for building libraries
- subdirs - Creates a makefile for building targets in subdirectories
A project 'template' is specified using the TEMPLATE system variable. If no TEMPLATE is specified, 'app' is assumed.
The Application Template
The application template, 'app', lets you generate makefiles to compile and link executable programs.
This template recognizes several system variables
- HEADERS - Header files
- SOURCES - Source files
- LEXSOURCES - qmake will generate a makefile to process the listed files with lex, and then compile it
- YACCSOURCES - qmake will generate a makefile to process the listed files with yacc, and then compile it
- TARGET - Name of executable (adds .exe if on Windows).
- DESTDIR - Where to put the TARGET
- DEFINES - Tell compiler to define C preprocessor macros (-D option)
- INCLUDEPATH - Sets the include file search path for the compiler (-I option).
- DEPENDPATH - Sets the dependency search path for the compiler
- FORMS - Specify .ui files for addition to the build
- DEF_FILE - Win32 only: Link with a .def file
- RC_FILE - Win32 only: Use a .rc file (compile to temporary .res)
- RES_FILE - Win32 only: Link with a .res file
The Library Template
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:
- VERSION - the version number of the target library, e.g. 1.40. The version is important for shared libraries.
The Subdirs Template
The 'subdirs' template lets you generate makefiles to invoke qmake within subdirectories.
This template recognizes the following system variables:
- SUBDIRS - contains the name of all subdirectories to be processed
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.
Special Templates for Microsoft Visual C++
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:
- vcapp - Creates an application project file
- vclib - Creates a library project file
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:
- release - Compile with optimization enabled, ignored if "debug" is specified
- debug - Compile with debug options enabled
- warn_on - The compiler should emit more warnings than normally, ignored if "warn_off" is specified
- warn_off - The compiler should emit as few warnings as possible, preferably none at all.
These options define the application/library type:
- qt - The target is a Qt application/library and requires Qt header files/library.
- opengl - The target requires the OpenGL (or Mesa) headers/libraries.
- thread - The target is a multi-threaded application or library.
- x11 - The target is a X11 application or library.
- windows - The target is a Win32 window application (app only).
- console - The target is a console application (app only).
- dll - The target is a shared object/DLL.
- staticlib - The target is a static library (lib only).
- plugin - The target is a plugin (lib only). This enables dll as well.
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:
- Parse the QMAKESPEC config file (qmake.conf)
- Parse the cache file, if available (.qmake.cache)
- Parse and command line options
- Parse the project file
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.
Syntax
A qmake project file has a very simple syntax.
The # character begins a comment which lasts until the end of the line.
Variables
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":
- It appears in the CONFIG variable (see the CONFIG section)
- If qmake is in an OS mode (see the -unix/-win32 option in the command reference) you may use the OS dependent scope (unix/win32)
- Function testing (see the function tests section)
- If a given compiler is used as specified by the QMAKESPEC (see the QMAKESPEC section).
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.
Cache file
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:
- CONFIG - This will tell qmake what CONFIG's are in scope
- QMAKESPEC - This will tell qmake what configuration should be used to create Makefiles. Strictly speaking this isn't necesary since the QMAKESPEC environment variable can be used instead, but placing it here will remove the necessity for the environment variable.
- OBJ_DIR UI_DIR MOC_DIR - If you want all your files to go to a directory (project-wide) then specifying them in the .qmake.cache file will help.
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:
- this is a win32 build, in which case the win32 block would have set it
- if the QMAKESPEC/qmake.conf variable defined it (not likely)
- if the .qmake.cache file specified it (in your configure script?)
- on the command line to qmake.
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).