|
|
|
\chapter qmake's Advanced Concepts
|
|
|
|
|
|
|
|
\section1 qmake's Advanced Concepts
|
|
|
|
|
|
|
|
The \e qmake project files we've seen up to now have been very simple,
|
|
|
|
just a list of \e{name = value} and \e{name += value} lines. \e qmake
|
|
|
|
provides a lot more power, for example you can use a single project
|
|
|
|
file to produce makefiles for multiple platforms.
|
|
|
|
|
|
|
|
\section1 Operators
|
|
|
|
|
|
|
|
So far, you have seen the \e = operator and \e += operator being used
|
|
|
|
in a project file. There are more operators available for use; but
|
|
|
|
some of these should be used carefully as they may change more than
|
|
|
|
you expect them to.
|
|
|
|
|
|
|
|
\section2 The '=' operator
|
|
|
|
|
|
|
|
This operator simply assigns a value to a variable, it is used like
|
|
|
|
this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
TARGET = myapp
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This sets the TARGET variable to \e myapp. This will remove any
|
|
|
|
previously set TARGET.
|
|
|
|
|
|
|
|
\section2 The '+=' operator
|
|
|
|
|
|
|
|
This operator appends a value to the list of values in a variable. It
|
|
|
|
is used like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
DEFINES += QT_DLL
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This appends QT_DLL to the list of pre-processor defines to be put in the
|
|
|
|
makefile.
|
|
|
|
|
|
|
|
\section2 The '-=' operator
|
|
|
|
|
|
|
|
This operator removes a value from the list of values in a variable.
|
|
|
|
It is used like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
DEFINES -= QT_DLL
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This removes QT_DLL from the list of pre-processor defines to be put
|
|
|
|
in the makefile.
|
|
|
|
|
|
|
|
\section2 The '*=' operator
|
|
|
|
|
|
|
|
This operator only adds a value to the list of values in a variable if
|
|
|
|
it doesn't already exist. It is used like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
DEFINES *= QT_DLL
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
QT_DLL will only be added to the list of pre-processor defines if it
|
|
|
|
is not already defined.
|
|
|
|
|
|
|
|
\section2 The '~=' operator
|
|
|
|
|
|
|
|
This operator replaces any values that match the regexp with the
|
|
|
|
specified value. It is used like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
DEFINES ~= s/QT_[DT].+/QT
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This removes any values in the list that start with QT_D or QT_T with
|
|
|
|
QT.
|
|
|
|
|
|
|
|
\section1 Scopes
|
|
|
|
|
|
|
|
A scope are similar to 'if' statements, if a certain condition is
|
|
|
|
true, the settings inside the scope are processed. A scope is written
|
|
|
|
like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
win32 {
|
|
|
|
DEFINES += QT_DLL
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The above code will add the QT_DLL define to the makefile if \e qmake
|
|
|
|
is used on a Windows platform. If \e qmake is used on a different
|
|
|
|
platform than Windows, the define will be ignored. You may also perform
|
|
|
|
single line conditionals/assignments with qmake like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
win32:DEFINES += QT_DLL
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
For example, suppose we want to process something on all platforms
|
|
|
|
\e except for Windows. We can achieve this by negating the scope like
|
|
|
|
this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
!win32 {
|
|
|
|
DEFINES += QT_DLL
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Any entry on the CONFIG line is also a scope. For example, if you
|
|
|
|
write this:
|
|
|
|
\code
|
|
|
|
CONFIG += warn_on
|
|
|
|
\endcode
|
|
|
|
you will have a scope called 'warn_on'. This makes it easy to change
|
|
|
|
the configuration for a project without losing all the custom settings
|
|
|
|
that might be needed for a specific configuration. Since it is
|
|
|
|
possible to put your own values on the CONFIG line, this provides you
|
|
|
|
with a very powerful configuration tool for your makefiles. For
|
|
|
|
example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
CONFIG += qt warn_on debug
|
|
|
|
debug {
|
|
|
|
TARGET = myappdebug
|
|
|
|
}
|
|
|
|
release {
|
|
|
|
TARGET = myapp
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
In the above code, two scopes are created which depend on what
|
|
|
|
is put on the CONFIG line. In the example, \e debug is on the config
|
|
|
|
line, so the TARGET variable is set to \e myappdebug. If \e release
|
|
|
|
was on the config line, then the TARGET variable would be set to \e
|
|
|
|
myapp.
|
|
|
|
|
|
|
|
It is also possible to check for two things before processing some
|
|
|
|
settings. For instance, if you want to check if the platform is
|
|
|
|
Windows and that the thread configuration is set, you would write
|
|
|
|
this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
win32 {
|
|
|
|
thread {
|
|
|
|
DEFINES += QT_THREAD_SUPPORT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
To save writing many nested scopes, you can nest scopes using a colon
|
|
|
|
like this:
|
|
|
|
|
|
|
|
\code
|
|
|
|
win32:thread {
|
|
|
|
DEFINES += QT_THREAD_SUPPORT
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Once a test has been performed you may also do else/elseif operations. With
|
|
|
|
this you may easily write complicated tests. This can be done with the
|
|
|
|
special 'else' scope, it can be combined with other scopes (separated by
|
|
|
|
colons as above) for example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
win32:thread {
|
|
|
|
DEFINES += QT_THREAD_SUPPORT
|
|
|
|
} else:debug {
|
|
|
|
DEFINES += QT_NOTHREAD_DEBUG
|
|
|
|
} else {
|
|
|
|
message("Unknown configuration")
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\section1 Variables
|
|
|
|
|
|
|
|
The variables that we have encountered so far are system variables,
|
|
|
|
such as \e DEFINES, \e SOURCES and \e HEADERS. It is possible for you
|
|
|
|
to create your own variables so that you use them in scopes. It's
|
|
|
|
easy to create your own variable; just name it and assign something to
|
|
|
|
it. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
MY_VARIABLE = value
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
There are no restricitions on what you do to your own variables, as \e
|
|
|
|
qmake will just ignore them unless it needs to look at them for a
|
|
|
|
scope.
|
|
|
|
|
|
|
|
You can also assign the value of a current variable to another
|
|
|
|
variable by prefixing $$ to the variable name. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
MY_DEFINES = $$DEFINES
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Now the MY_DEFINES variable contains what is in the DEFINES variable at
|
|
|
|
this point in the project file. This is also equivalent to:
|
|
|
|
|
|
|
|
\code
|
|
|
|
MY_DEFINES = $${DEFINES}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The second notation allows you to adjoin the variable expansion to another
|
|
|
|
value without separating by space. \e qmake will allow a variable to
|
|
|
|
contain anything (including $(VALUE), which will be placed directly into
|
|
|
|
the Makefile, and allow it to expand as appropriate, usually an environment
|
|
|
|
variable). However, if you require an environment variable to be replaced
|
|
|
|
immediately then you may use the $$() notation. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
MY_DEFINES = $$(ENV_DEFINES)
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This will set MY_DEFINES to the value of the evironment variable
|
|
|
|
ENV_DEFINES as it parses the .pro file. Additionally you may call built-in
|
|
|
|
functions in variable replacing. These functions (not to be confused with
|
|
|
|
Test Functions as enumerated in the next section) are listed below:
|
|
|
|
|
|
|
|
\section2 join( variablename, glue, before, after )
|
|
|
|
|
|
|
|
This will join the value of \e variablename with glue. If this value is
|
|
|
|
non-empty it will prefix the value with \e before and suffix it with \e
|
|
|
|
after. \e variablename is the only required field, the others will default
|
|
|
|
to empty strings. If you need to encode spaces in \e glue, \e before, or \e
|
|
|
|
after you must quote them.
|
|
|
|
|
|
|
|
\section2 prompt( question )
|
|
|
|
|
|
|
|
This will display \e question, and read from stdin as a return value.
|
|
|
|
|
|
|
|
\section2 member( variablename, position )
|
|
|
|
|
|
|
|
This will place the value in \e variablename in position \e position of the
|
|
|
|
list. If the value of \e variablename is not long this will return an empty
|
|
|
|
string. \e variablename is the only required field, if not specified
|
|
|
|
position will default to the first value in the list (0).
|
|
|
|
|
|
|
|
\section2 find( variablename, substr )
|
|
|
|
|
|
|
|
This will place all the values in \e variablename that match \e substr. \e
|
|
|
|
substr may be a regular expression as well, and will be matched
|
|
|
|
accordingly.
|
|
|
|
|
|
|
|
\code
|
|
|
|
MY_VAR = one two three four
|
|
|
|
MY_VAR2 = $$join(MY_VAR, " -L", -L) -Lfive
|
|
|
|
MY_VAR3 = $$member(MY_VAR, 2) $$find(MY_VAR, t.*)
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
MY_VAR2 will contain '-Lone -Ltwo -Lthree -Lfour -Lfive', and MYVAR3 will
|
|
|
|
contains 'three two three'.
|
|
|
|
|
|
|
|
\section2 system( program_and_args )
|
|
|
|
|
|
|
|
This will return the stdout/stderr of the program executed, and parse it as
|
|
|
|
normally expected. You can use this to interrogate information about the
|
|
|
|
platform for example.
|
|
|
|
|
|
|
|
\code
|
|
|
|
UNAME = $$system(uname -s)
|
|
|
|
contains( UNAME, [lL]inux ):message( This looks like Linux ($$UNAME) to me )
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\section1 Test Functions
|
|
|
|
|
|
|
|
\e qmake provides built-in functions that perform simple, yet powerful
|
|
|
|
tests. These tests may be used in place of scopes (as described above), in
|
|
|
|
some cases it is more usefull to use the test function by itself ignoring
|
|
|
|
its test value.
|
|
|
|
|
|
|
|
\section2 contains( variablename, value )
|
|
|
|
|
|
|
|
If \e value is in the list of values stored in the variable called \e
|
|
|
|
variablename, then the settings inside the scope will be processed.
|
|
|
|
For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
contains( CONFIG, thread ) {
|
|
|
|
DEFINES += QT_THREAD_SUPPORT
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
If \e thread is in the list of values for the \e CONFIG variable, then
|
|
|
|
QT_THREAD_SUPPORT will be added to the list of values in the \e
|
|
|
|
DEFINES variable.
|
|
|
|
|
|
|
|
\section2 count( variablename, number )
|
|
|
|
|
|
|
|
If \e number matches the number of values stored in the variable
|
|
|
|
called \e variablename, then the settings inside the scope will be
|
|
|
|
processed. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
count( DEFINES, 5 ) {
|
|
|
|
CONFIG += debug
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\section2 error( string )
|
|
|
|
|
|
|
|
This function outputs the string given and then makes \e qmake exit.
|
|
|
|
For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
error( "An error has occured" )
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The text "An error has occured" will be displayed on the console and
|
|
|
|
\e qmake will exit.
|
|
|
|
|
|
|
|
\section2 exists( filename )
|
|
|
|
|
|
|
|
If the specified file exists, then the settings inside the scope will
|
|
|
|
be processed. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
exists( /local/qt/qmake/main.cpp ) {
|
|
|
|
SOURCES += main.cpp
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
If \e /local/qt/qmake/main.cpp exists then main.cpp is added to the
|
|
|
|
list of source files.
|
|
|
|
|
|
|
|
Note that "/" can be used as a directory separator regardless of the
|
|
|
|
platform.
|
|
|
|
|
|
|
|
|
|
|
|
\section2 equals( variable, value )
|
|
|
|
|
|
|
|
If the specified variable is equal to the value passed the scope will
|
|
|
|
be processed. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
NUMBERS = 1 2 3
|
|
|
|
equals( NUMBERS, 3 4 5 ) {
|
|
|
|
message("The numbers are equal")
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The message will not be displayed because "1 2 3" does not equal "1 2
|
|
|
|
3". As with all functions you can pass an expanded variable as the
|
|
|
|
value argument (ie, $$NUMBERS).
|
|
|
|
|
|
|
|
\section2 include( filename )
|
|
|
|
|
|
|
|
The contents of filename are included at this point in the project
|
|
|
|
file, so any settings in the specified file will be processed. An
|
|
|
|
example of this is:
|
|
|
|
|
|
|
|
\code
|
|
|
|
include( myotherapp.pro )
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Any settings in the \e myotherapp.pro project file are now processed.
|
|
|
|
|
|
|
|
\section2 isEmpty( variablename )
|
|
|
|
|
|
|
|
This is the equivalent of using count( variablename, 0 ). If the
|
|
|
|
variable called \e variablename has no elements, then the settings
|
|
|
|
inside the scope will be processed. An example of this is:
|
|
|
|
|
|
|
|
\code
|
|
|
|
isEmpty( CONFIG ) {
|
|
|
|
CONFIG += qt warn_on debug
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\section2 message( string )
|
|
|
|
|
|
|
|
This function simply outputs a message on the console.
|
|
|
|
|
|
|
|
\code
|
|
|
|
message( "This is a message" )
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
The text "This is a message" is output to the console and
|
|
|
|
processing of the project file carries on.
|
|
|
|
|
|
|
|
\section2 system( command )
|
|
|
|
|
|
|
|
The specified command is performed and if it returns an exit code of
|
|
|
|
1, the settings inside the scope are processed. For example:
|
|
|
|
|
|
|
|
\code
|
|
|
|
system( ls /bin ) {
|
|
|
|
SOURCES += bin/main.cpp
|
|
|
|
HEADERS += bin/main.h
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
So if the command \e {ls /bin} returns 1 then \e bin/main.cpp is added
|
|
|
|
to the list of sources and \e bin/main.h is added to the list of
|
|
|
|
headers.
|
|
|
|
|
|
|
|
\section2 infile( filename, var, val )
|
|
|
|
|
|
|
|
This function will succeed if the file \e filename (when parsed
|
|
|
|
by qmake itself) contains the variable \e var with a value of
|
|
|
|
\e val. You may also not pass in a third argument (\e val) and the
|
|
|
|
function will only test if \e var has been assigned to in the file.
|