<tdalign="right"valign="center"><imgsrc="logo32.png"align="right"width="64"height="32"border="0"></td></tr></table><palign="right">[<ahref="qmake-manual-5.html">Prev: qmake Concepts</a>] [<ahref="qmake-manual.html">Home</a>] [<ahref="qmake-manual-7.html">Next: Using Precompiled Headers</a>]</p>
<h2align="center">qmake's Advanced Concepts</h2>
<h3><aname="1"></a>qmake's Advanced Concepts</h3>
<p>The <em>qmake</em> project files we've seen up to now have been very simple, just a list of <em>name = value</em> and <em>name += value</em> lines. <em>qmake</em> provides a lot more power, for example you can use a single project file to produce makefiles for multiple platforms.</p>
<h3><aname="2"></a>Operators</h3>
<p>So far, you have seen the <em>=</em> operator and <em>+=</em> 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.</p>
<h4><aname="2-1"></a>The '=' operator</h4>
<p>This operator simply assigns a value to a variable, it is used like this:</p>
<pre>
TARGET = myapp
</pre>
<p>This sets the TARGET variable to <em>myapp</em>. This will remove any previously set TARGET.</p>
<h4><aname="2-2"></a>The '+=' operator</h4>
<p>This operator appends a value to the list of values in a variable. It is used like this:</p>
<pre>
DEFINES += QT_DLL
</pre>
<p>This appends QT_DLL to the list of pre-processor defines to be put in the makefile.</p>
<h4><aname="2-3"></a>The '-=' operator</h4>
<p>This operator removes a value from the list of values in a variable. It is used like this:</p>
<pre>
DEFINES -= QT_DLL
</pre>
<p>This removes QT_DLL from the list of pre-processor defines to be put in the makefile.</p>
<h4><aname="2-4"></a>The '*=' operator</h4>
<p>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:</p>
<pre>
DEFINES *= QT_DLL
</pre>
<p>QT_DLL will only be added to the list of pre-processor defines if it is not already defined.</p>
<h4><aname="2-5"></a>The '~=' operator</h4>
<p>This operator replaces any values that match the regexp with the specified value. It is used like this:</p>
<pre>
DEFINES ~= s/QT_[DT].+/QT
</pre>
<p>This removes any values in the list that start with QT_D or QT_T with QT.</p>
<h3><aname="3"></a>Scopes</h3>
<p>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:</p>
<pre>
win32 {
DEFINES += QT_DLL
}
</pre>
<p>The above code will add the QT_DLL define to the makefile if <em>qmake</em> is used on a Windows platform. If <em>qmake</em> 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:</p>
<pre>
win32:DEFINES += QT_DLL
</pre>
<p>For example, suppose we want to process something on all platforms <em>except</em> for Windows. We can achieve this by negating the scope like this:</p>
<pre>
!win32 {
DEFINES += QT_DLL
}
</pre>
<p>Any entry on the CONFIG line is also a scope. For example, if you write this:</p>
<pre>
CONFIG += warn_on
</pre>
<p>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:</p>
<pre>
CONFIG += qt warn_on debug
debug {
TARGET = myappdebug
}
release {
TARGET = myapp
}
</pre>
<p>In the above code, two scopes are created which depend on what is put on the CONFIG line. In the example, <em>debug</em> is on the config line, so the TARGET variable is set to <em>myappdebug</em>. If <em>release</em> was on the config line, then the TARGET variable would be set to <em>myapp</em>.</p>
<p>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:</p>
<p>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:</p>
<p>The variables that we have encountered so far are system variables, such as <em>DEFINES</em>, <em>SOURCES</em> and <em>HEADERS</em>. 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:</p>
<pre>
MY_VARIABLE = value
</pre>
<p>There are no restricitions on what you do to your own variables, as <em>qmake</em> will just ignore them unless it needs to look at them for a scope.</p>
<p>You can also assign the value of a current variable to another variable by prefixing $$ to the variable name. For example:</p>
<pre>
MY_DEFINES = $$DEFINES
</pre>
<p>Now the MY_DEFINES variable contains what is in the DEFINES variable at this point in the project file. This is also equivalent to:</p>
<p>The second notation allows you to adjoin the variable expansion to another value without separating by space. <em>qmake</em> 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:</p>
<p>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:</p>
<h4><aname="4-1"></a>join( variablename, glue, before, after )</h4>
<p>This will join the value of <em>variablename</em> with glue. If this value is non-empty it will prefix the value with <em>before</em> and suffix it with <em>after</em>. <em>variablename</em> is the only required field, the others will default to empty strings. If you need to encode spaces in <em>glue</em>, <em>before</em>, or <em>after</em> you must quote them.</p>
<p>This will place the value in <em>variablename</em> in position <em>position</em> of the list. If the value of <em>variablename</em> is not long this will return an empty string. <em>variablename</em> is the only required field, if not specified position will default to the first value in the list (0).</p>
<p>This will place all the values in <em>variablename</em> that match <em>substr</em>. <em>substr</em> may be a regular expression as well, and will be matched accordingly.</p>
<pre>
MY_VAR = one two three four
MY_VAR2 = $$join(MY_VAR, " -L", -L) -Lfive
MY_VAR3 = $$member(MY_VAR, 2) $$find(MY_VAR, t.*)
</pre>
<p>MY_VAR2 will contain '-Lone -Ltwo -Lthree -Lfour -Lfive', and MYVAR3 will contains 'three two three'.</p>
<p>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.</p>
<pre>
UNAME = $$system(uname -s)
contains( UNAME, [lL]inux ):message( This looks like Linux ($$UNAME) to me )
</pre>
<h3><aname="5"></a>Test Functions</h3>
<p><em>qmake</em> 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.</p>
<h4><aname="5-1"></a>contains( variablename, value )</h4>
<p>If <em>value</em> is in the list of values stored in the variable called <em>variablename</em>, then the settings inside the scope will be processed. For example:</p>
<p>If <em>thread</em> is in the list of values for the <em>CONFIG</em> variable, then TQT_THREAD_SUPPORT will be added to the list of values in the <em>DEFINES</em> variable.</p>
<h4><aname="5-2"></a>count( variablename, number )</h4>
<p>If <em>number</em> matches the number of values stored in the variable called <em>variablename</em>, then the settings inside the scope will be processed. For example:</p>
<pre>
count( DEFINES, 5 ) {
CONFIG += debug
}
</pre>
<h4><aname="5-3"></a>error( string )</h4>
<p>This function outputs the string given and then makes <em>qmake</em> exit. For example:</p>
<pre>
error( "An error has occured" )
</pre>
<p>The text "An error has occured" will be displayed on the console and <em>qmake</em> will exit.</p>
<h4><aname="5-4"></a>exists( filename )</h4>
<p>If the specified file exists, then the settings inside the scope will be processed. For example:</p>
<pre>
exists( /local/qt/qmake/main.cpp ) {
SOURCES += main.cpp
}
</pre>
<p>If <em>/local/qt/qmake/main.cpp</em> exists then main.cpp is added to the list of source files.</p>
<p>Note that "/" can be used as a directory separator regardless of the platform.</p>
<h4><aname="5-5"></a>equals( variable, value )</h4>
<p>If the specified variable is equal to the value passed the scope will be processed. For example:</p>
<pre>
NUMBERS = 1 2 3
equals( NUMBERS, 3 4 5 ) {
message("The numbers are equal")
}
</pre>
<p>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).</p>
<h4><aname="5-6"></a>include( filename )</h4>
<p>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:</p>
<pre>
include( myotherapp.pro )
</pre>
<p>Any settings in the <em>myotherapp.pro</em> project file are now processed.</p>
<h4><aname="5-7"></a>isEmpty( variablename )</h4>
<p>This is the equivalent of using count( variablename, 0 ). If the variable called <em>variablename</em> has no elements, then the settings inside the scope will be processed. An example of this is:</p>
<pre>
isEmpty( CONFIG ) {
CONFIG += qt warn_on debug
}
</pre>
<h4><aname="5-8"></a>message( string )</h4>
<p>This function simply outputs a message on the console.</p>
<pre>
message( "This is a message" )
</pre>
<p>The text "This is a message" is output to the console and processing of the project file carries on.</p>
<h4><aname="5-9"></a>system( command )</h4>
<p>The specified command is performed and if it returns an exit code of 1, the settings inside the scope are processed. For example:</p>
<pre>
system( ls /bin ) {
SOURCES += bin/main.cpp
HEADERS += bin/main.h
}
</pre>
<p>So if the command <em>ls /bin</em> returns 1 then <em>bin/main.cpp</em> is added to the list of sources and <em>bin/main.h</em> is added to the list of headers.</p>
<h4><aname="5-10"></a>infile( filename, var, val )</h4>
<p>This function will succeed if the file <em>filename</em> (when parsed by qmake itself) contains the variable <em>var</em> with a value of <em>val</em>. You may also not pass in a third argument (<em>val</em>) and the function will only test if <em>var</em> has been assigned to in the file.</p>
<!-- eof -->
<palign="right">[<ahref="qmake-manual-5.html">Prev: qmake Concepts</a>] [<ahref="qmake-manual.html">Home</a>] [<ahref="qmake-manual-7.html">Next: Using Precompiled Headers</a>]</p>