1 <?xml version="1.0" encoding="UTF-8"?>
4 Copyright (c) 2001-2010 The SCons Foundation
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
18 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
19 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
27 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
29 <title>The SCons qt4 tool</title>
33 <surname>Dirk Baechle</surname>
36 <pubdate>2010-12-06</pubdate>
42 <para>This tool can be used to compile Qt projects, designed for versions
43 4.x.y and higher. It is not usable for Qt3 and older versions, since some
44 of the helper tools (<literal>moc</literal>, <literal>uic</literal>)
45 behave different.</para>
47 <section id="install">
48 <title>Install</title>
50 <para>Installing it, requires you to copy (or, even better: checkout)
51 the contents of the package's <literal>qt4</literal> folder to</para>
55 <para><quote><literal>/path_to_your_project/site_scons/site_tools/qt4</literal></quote>,
56 if you need the Qt4 Tool in one project only, or</para>
60 <para><quote><literal>~/.scons/site_scons/site_tools/qt4</literal></quote>,
61 for a system-wide installation under your current login.</para>
65 <para>For more infos about this, please refer to</para>
69 <para>the SCons User's Guide, chap. 17.7 "Where to put your custom
70 Builders and Tools" and</para>
74 <para>the SCons Tools Wiki page at <ulink
75 url="https://github.com/SCons/scons/wiki/ToolsIndex">https://github.com/SCons/scons/wiki/ToolsIndex</ulink>.</para>
80 <section id="activation">
81 <title>How to activate</title>
83 <para>For activating the tool "qt4", you have to add its name to the
84 Environment constructor, like this</para>
86 <screen>env = Environment(tools=['default','qt4'])
89 <para>On its startup, the Qt4 tool tries to read the variable
90 <literal>QT4DIR</literal> from the current Environment and
91 <literal>os.environ</literal>. If it is not set, the value of
92 <literal>QTDIR</literal> (in Environment/<literal>os.environ</literal>)
93 is used as a fallback.</para>
95 <para>So, you either have to explicitly give the path of your Qt4
96 installation to the Environment with</para>
98 <screen>env['QT4DIR'] = '/usr/local/Trolltech/Qt-4.2.3'
101 <para>or set the <literal>QT4DIR</literal> as environment variable in
105 <section id="requirements">
106 <title>Requirements</title>
108 <para>Under Linux, "qt4" uses the system tool
109 <literal>pkg-config</literal> for automatically setting the required
110 compile and link flags of the single Qt4 modules (like QtCore,
111 QtGui,...). This means that</para>
115 <para>you should have <literal>pkg-config</literal> installed,
120 <para>you additionally have to set
121 <literal>PKG_CONFIG_PATH</literal> in your shell environment, such
122 that it points to $<literal>QT4DIR/lib/pkgconfig</literal> (or
123 $<literal>QT4DIR/lib</literal> for some older versions).</para>
127 <para>Based on these two environment variables
128 (<literal>QT4DIR</literal> and <literal>PKG_CONFIG_PATH</literal>), the
129 "qt4" tool initializes all <literal>QT4_*</literal> construction
130 variables listed in the Reference manual. This happens when the tool is
131 "detected" during Environment construction. As a consequence, the setup
132 of the tool gets a two-stage process, if you want to override the values
133 provided by your current shell settings:</para>
135 <screen># Stage 1: create plain environment
136 qtEnv = Environment()
138 qtEnv['QT4DIR'] = '/usr/local/Trolltech/Qt-4.2.3
139 qtEnv['ENV']['PKG_CONFIG_PATH'] = '/usr/local/Trolltech/Qt-4.2.3/lib/pkgconfig'
140 # Stage 2: add qt4 tool
146 <section id="boilerplate">
147 <title>Suggested boilerplate</title>
149 <para>Based on the requirements above, we suggest a simple ready-to-go
150 setup as follows:</para>
152 <para>SConstruct</para>
154 <screen># Detect Qt version
155 qtdir = detectLatestQtDir()
157 # Create base environment
158 baseEnv = Environment()
159 #...further customization of base env
161 # Clone Qt environment
162 qtEnv = baseEnv.Clone()
163 # Set QT4DIR and PKG_CONFIG_PATH
164 qtEnv['ENV']['PKG_CONFIG_PATH'] = os.path.join(qtdir, 'lib/pkgconfig')
165 qtEnv['QT4DIR'] = qtdir
168 #...further customization of qt env
170 # Export environments
171 Export('baseEnv qtEnv')
173 # Your other stuff...
174 # ...including the call to your SConscripts
177 <para>In a SConscript</para>
179 <screen># Get the Qt4 environment
184 env.Append(CCFLAGS=['-m32']) # or whatever
186 env.StaticLibrary('foo', Glob('*.cpp'))
189 <para>The detection of the Qt directory could be as simple as directly
190 assigning a fixed path</para>
192 <screen>def detectLatestQtDir():
193 return "/usr/local/qt4.3.2"
196 <para>or a little more sophisticated</para>
198 <screen># Tries to detect the path to the installation of Qt with
199 # the highest version number
200 def detectLatestQtDir():
201 if sys.platform.startswith("linux"):
202 # Simple check: inspect only '/usr/local/Trolltech'
203 paths = glob.glob('/usr/local/Trolltech/*')
210 # Simple check: inspect only 'C:\Qt'
211 paths = glob.glob('C:\\Qt\\*')
216 return os.environ.get("QTDIR","")
220 <section id="firstproject">
221 <title>A first project</title>
223 <para>The following SConscript is for a simple project with some cxx
224 files, using the QtCore, QtGui and QtNetwork modules:</para>
226 <screen>Import('qtEnv')
228 env.EnableQt4Modules([
233 # Add your CCFLAGS and CPPPATHs to env here...
235 env.Program('foo', Glob('*.cpp'))
240 <title>MOC it up</title>
242 <para>For the basic support of automocing, nothing needs to be done by the
243 user. The tool usually detects the <literal>Q_OBJECT</literal> macro and
244 calls the <quote><literal>moc</literal></quote> executable
247 <para>If you don't want this, you can switch off the automocing by
250 <screen>env['QT4_AUTOSCAN'] = 0
253 <para>in your SConscript file. Then, you have to moc your files
254 explicitly, using the Moc4 builder.</para>
256 <para>You can also switch to an extended automoc strategy with</para>
258 <screen>env['QT4_AUTOSCAN_STRATEGY'] = 1
261 <para>Please read the description of the
262 <literal>QT4_AUTOSCAN_STRATEGY</literal> variable in the Reference manual
265 <para>For debugging purposes, you can set the variable
266 <literal>QT4_DEBUG</literal> with</para>
268 <screen>env['QT4_DEBUG'] = 1
271 <para>which outputs a lot of messages during automocing.</para>
275 <title>Forms (.ui)</title>
277 <para>The header files with setup code for your GUI classes, are not
278 compiled automatically from your <literal>.ui</literal> files. You always
279 have to call the Uic4 builder explicitly like</para>
281 <screen>env.Uic4(Glob('*.ui'))
282 env.Program('foo', Glob('*.cpp'))
286 <section id="resources">
287 <title>Resource files (.qrc)</title>
289 <para>Resource files are not built automatically, you always have to add
290 the names of the <literal>.qrc</literal> files to the source list for your
291 program or library:</para>
293 <screen>env.Program('foo', Glob('*.cpp')+Glob('*.qrc'))
296 <para>For each of the Resource input files, its prefix defines the name of
297 the resulting resource. An appropriate
298 <quote><literal>-name</literal></quote> option is added to the call of the
299 <literal>rcc</literal> executable by default.</para>
301 <para>You can also call the Qrc4 builder explicitly as</para>
303 <screen>qrccc = env.Qrc4('foo') # ['foo.qrc'] -> ['qrc_foo.cc']
306 <para>or (overriding the default suffix)</para>
308 <screen>qrccc = env.Qrc4('myprefix_foo.cxx','foo.qrc') # -> ['qrc_myprefix_foo.cxx']
311 <para>and then add the resulting cxx file to the sources of your
312 Program/Library:</para>
314 <screen>env.Program('foo', Glob('*.cpp') + qrccc)
318 <section id="translation">
319 <title>Translation files</title>
321 <para>The update of the <literal>.ts</literal> files and the conversion to
322 binary <literal>.qm</literal> files is not done automatically. You have to
323 call the corresponding builders on your own.</para>
325 <para>Example for updating a translation file:</para>
327 <screen>env.Ts4('foo.ts','.') # -> ['foo.ts']
330 <para>By default, the <literal>.ts</literal> files are treated as
331 <emphasis>precious</emphasis> targets. This means that they are not
332 removed prior to a rebuild, but simply get updated. Additionally, they do
333 not get cleaned on a <quote><literal>scons -c</literal></quote>. If you
334 want to delete the translation files on the
335 <quote><literal>-c</literal></quote> SCons command, you can set the
336 variable <quote><literal>QT4_CLEAN_TS</literal></quote> like this</para>
338 <screen>env['QT4_CLEAN_TS']=1
341 <para>Example for releasing a translation file, i.e. compiling it to a
342 <literal>.qm</literal> binary file:</para>
344 <screen>env.Qm4('foo') # ['foo.ts'] -> ['foo.qm']
347 <para>or (overriding the output prefix)</para>
349 <screen>env.Qm4('myprefix','foo') # ['foo.ts'] -> ['myprefix.qm']
352 <para>As an extension both, the Ts4() and Qm4 builder, support the
353 definition of multiple targets. So, calling</para>
355 <screen>env.Ts4(['app_en','app_de'], Glob('*.cpp'))
360 <screen>env.Qm4(['app','copy'], Glob('*.ts'))
363 <para>should work fine.</para>
365 <para>Finally, two short notes about the support of directories for the
366 Ts4() builder. You can pass an arbitrary mix of cxx files and subdirs to
369 <screen>env.Ts4('app_en',['sub1','appwindow.cpp','main.cpp']))
372 <para>where <literal>sub1</literal> is a folder that gets scanned
373 recursively for cxx files by <literal>lupdate</literal>. But like this,
374 you lose all dependency information for the subdir, i.e. if a file inside
375 the folder changes, the .ts file is not updated automatically! In this
376 case you should tell SCons to always update the target:</para>
378 <screen>ts = env.Ts4('app_en',['sub1','appwindow.cpp','main.cpp'])
382 <para>Last note: specifying the current folder
383 <quote><literal>.</literal></quote> as input to Ts4() and storing the
384 resulting .ts file in the same directory, leads to a dependency cycle! You
385 then have to store the .ts and .qm files outside of the current folder, or
386 use <literal>Glob('*.cpp'))</literal> instead.</para>