90cae7e0ae5550066780750aa6ae803aca912af8
[bbaumbach/samba-autobuild/.git] / third_party / waf / waflib / extras / qt4.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy, 2006-2010 (ita)
4
5 """
6
7 Tool Description
8 ================
9
10 This tool helps with finding Qt4 tools and libraries,
11 and also provides syntactic sugar for using Qt4 tools.
12
13 The following snippet illustrates the tool usage::
14
15         def options(opt):
16                 opt.load('compiler_cxx qt4')
17
18         def configure(conf):
19                 conf.load('compiler_cxx qt4')
20
21         def build(bld):
22                 bld(
23                         features = 'qt4 cxx cxxprogram',
24                         uselib   = 'QTCORE QTGUI QTOPENGL QTSVG',
25                         source   = 'main.cpp textures.qrc aboutDialog.ui',
26                         target   = 'window',
27                 )
28
29 Here, the UI description and resource files will be processed
30 to generate code.
31
32 Usage
33 =====
34
35 Load the "qt4" tool.
36
37 You also need to edit your sources accordingly:
38
39 - the normal way of doing things is to have your C++ files
40   include the .moc file.
41   This is regarded as the best practice (and provides much faster
42   compilations).
43   It also implies that the include paths have beenset properly.
44
45 - to have the include paths added automatically, use the following::
46
47      from waflib.TaskGen import feature, before_method, after_method
48      @feature('cxx')
49      @after_method('process_source')
50      @before_method('apply_incpaths')
51      def add_includes_paths(self):
52         incs = set(self.to_list(getattr(self, 'includes', '')))
53         for x in self.compiled_tasks:
54             incs.add(x.inputs[0].parent.path_from(self.path))
55         self.includes = sorted(incs)
56
57 Note: another tool provides Qt processing that does not require
58 .moc includes, see 'playground/slow_qt/'.
59
60 A few options (--qt{dir,bin,...}) and environment variables
61 (QT4_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool,
62 tool path selection, etc; please read the source for more info.
63
64 """
65
66 try:
67         from xml.sax import make_parser
68         from xml.sax.handler import ContentHandler
69 except ImportError:
70         has_xml = False
71         ContentHandler = object
72 else:
73         has_xml = True
74
75 import os, sys
76 from waflib.Tools import cxx
77 from waflib import Task, Utils, Options, Errors, Context
78 from waflib.TaskGen import feature, after_method, extension
79 from waflib.Configure import conf
80 from waflib import Logs
81
82 MOC_H = ['.h', '.hpp', '.hxx', '.hh']
83 """
84 File extensions associated to the .moc files
85 """
86
87 EXT_RCC = ['.qrc']
88 """
89 File extension for the resource (.qrc) files
90 """
91
92 EXT_UI  = ['.ui']
93 """
94 File extension for the user interface (.ui) files
95 """
96
97 EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C']
98 """
99 File extensions of C++ files that may require a .moc processing
100 """
101
102 QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative QtDesigner"
103
104 class qxx(Task.classes['cxx']):
105         """
106         Each C++ file can have zero or several .moc files to create.
107         They are known only when the files are scanned (preprocessor)
108         To avoid scanning the c++ files each time (parsing C/C++), the results
109         are retrieved from the task cache (bld.node_deps/bld.raw_deps).
110         The moc tasks are also created *dynamically* during the build.
111         """
112
113         def __init__(self, *k, **kw):
114                 Task.Task.__init__(self, *k, **kw)
115                 self.moc_done = 0
116
117         def runnable_status(self):
118                 """
119                 Compute the task signature to make sure the scanner was executed. Create the
120                 moc tasks by using :py:meth:`waflib.Tools.qt4.qxx.add_moc_tasks` (if necessary),
121                 then postpone the task execution (there is no need to recompute the task signature).
122                 """
123                 if self.moc_done:
124                         return Task.Task.runnable_status(self)
125                 else:
126                         for t in self.run_after:
127                                 if not t.hasrun:
128                                         return Task.ASK_LATER
129                         self.add_moc_tasks()
130                         return Task.Task.runnable_status(self)
131
132         def create_moc_task(self, h_node, m_node):
133                 """
134                 If several libraries use the same classes, it is possible that moc will run several times (Issue 1318)
135                 It is not possible to change the file names, but we can assume that the moc transformation will be identical,
136                 and the moc tasks can be shared in a global cache.
137
138                 The defines passed to moc will then depend on task generator order. If this is not acceptable, then
139                 use the tool slow_qt4 instead (and enjoy the slow builds... :-( )
140                 """
141                 try:
142                         moc_cache = self.generator.bld.moc_cache
143                 except AttributeError:
144                         moc_cache = self.generator.bld.moc_cache = {}
145
146                 try:
147                         return moc_cache[h_node]
148                 except KeyError:
149                         tsk = moc_cache[h_node] = Task.classes['moc'](env=self.env, generator=self.generator)
150                         tsk.set_inputs(h_node)
151                         tsk.set_outputs(m_node)
152
153                         if self.generator:
154                                 self.generator.tasks.append(tsk)
155
156                         # direct injection in the build phase (safe because called from the main thread)
157                         gen = self.generator.bld.producer
158                         gen.outstanding.append(tsk)
159                         gen.total += 1
160
161                         return tsk
162
163         def moc_h_ext(self):
164                 ext = []
165                 try:
166                         ext = Options.options.qt_header_ext.split()
167                 except AttributeError:
168                         pass
169                 if not ext:
170                         ext = MOC_H
171                 return ext
172
173         def add_moc_tasks(self):
174                 """
175                 Create the moc tasks by looking in ``bld.raw_deps[self.uid()]``
176                 """
177                 node = self.inputs[0]
178                 bld = self.generator.bld
179
180                 try:
181                         # compute the signature once to know if there is a moc file to create
182                         self.signature()
183                 except KeyError:
184                         # the moc file may be referenced somewhere else
185                         pass
186                 else:
187                         # remove the signature, it must be recomputed with the moc task
188                         delattr(self, 'cache_sig')
189
190                 include_nodes = [node.parent] + self.generator.includes_nodes
191
192                 moctasks = []
193                 mocfiles = set()
194                 for d in bld.raw_deps.get(self.uid(), []):
195                         if not d.endswith('.moc'):
196                                 continue
197
198                         # process that base.moc only once
199                         if d in mocfiles:
200                                 continue
201                         mocfiles.add(d)
202
203                         # find the source associated with the moc file
204                         h_node = None
205
206                         base2 = d[:-4]
207                         for x in include_nodes:
208                                 for e in self.moc_h_ext():
209                                         h_node = x.find_node(base2 + e)
210                                         if h_node:
211                                                 break
212                                 if h_node:
213                                         m_node = h_node.change_ext('.moc')
214                                         break
215                         else:
216                                 # foo.cpp -> foo.cpp.moc
217                                 for k in EXT_QT4:
218                                         if base2.endswith(k):
219                                                 for x in include_nodes:
220                                                         h_node = x.find_node(base2)
221                                                         if h_node:
222                                                                 break
223                                                 if h_node:
224                                                         m_node = h_node.change_ext(k + '.moc')
225                                                         break
226
227                         if not h_node:
228                                 raise Errors.WafError('No source found for %r which is a moc file' % d)
229
230                         # create the moc task
231                         task = self.create_moc_task(h_node, m_node)
232                         moctasks.append(task)
233
234                 # simple scheduler dependency: run the moc task before others
235                 self.run_after.update(set(moctasks))
236                 self.moc_done = 1
237
238 class trans_update(Task.Task):
239         """Update a .ts files from a list of C++ files"""
240         run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}'
241         color   = 'BLUE'
242
243 class XMLHandler(ContentHandler):
244         """
245         Parser for *.qrc* files
246         """
247         def __init__(self):
248                 self.buf = []
249                 self.files = []
250         def startElement(self, name, attrs):
251                 if name == 'file':
252                         self.buf = []
253         def endElement(self, name):
254                 if name == 'file':
255                         self.files.append(str(''.join(self.buf)))
256         def characters(self, cars):
257                 self.buf.append(cars)
258
259 @extension(*EXT_RCC)
260 def create_rcc_task(self, node):
261         "Create rcc and cxx tasks for *.qrc* files"
262         rcnode = node.change_ext('_rc.cpp')
263         self.create_task('rcc', node, rcnode)
264         cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o'))
265         try:
266                 self.compiled_tasks.append(cpptask)
267         except AttributeError:
268                 self.compiled_tasks = [cpptask]
269         return cpptask
270
271 @extension(*EXT_UI)
272 def create_uic_task(self, node):
273         "hook for uic tasks"
274         uictask = self.create_task('ui4', node)
275         uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])]
276
277 @extension('.ts')
278 def add_lang(self, node):
279         """add all the .ts file into self.lang"""
280         self.lang = self.to_list(getattr(self, 'lang', [])) + [node]
281
282 @feature('qt4')
283 @after_method('apply_link')
284 def apply_qt4(self):
285         """
286         Add MOC_FLAGS which may be necessary for moc::
287
288                 def build(bld):
289                         bld.program(features='qt4', source='main.cpp', target='app', use='QTCORE')
290
291         The additional parameters are:
292
293         :param lang: list of translation files (\*.ts) to process
294         :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension
295         :param update: whether to process the C++ files to update the \*.ts files (use **waf --translate**)
296         :type update: bool
297         :param langname: if given, transform the \*.ts files into a .qrc files to include in the binary file
298         :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension
299         """
300         if getattr(self, 'lang', None):
301                 qmtasks = []
302                 for x in self.to_list(self.lang):
303                         if isinstance(x, str):
304                                 x = self.path.find_resource(x + '.ts')
305                         qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm')))
306
307                 if getattr(self, 'update', None) and Options.options.trans_qt4:
308                         cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [
309                                 a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')]
310                         for x in qmtasks:
311                                 self.create_task('trans_update', cxxnodes, x.inputs)
312
313                 if getattr(self, 'langname', None):
314                         qmnodes = [x.outputs[0] for x in qmtasks]
315                         rcnode = self.langname
316                         if isinstance(rcnode, str):
317                                 rcnode = self.path.find_or_declare(rcnode + '.qrc')
318                         t = self.create_task('qm2rcc', qmnodes, rcnode)
319                         k = create_rcc_task(self, t.outputs[0])
320                         self.link_task.inputs.append(k.outputs[0])
321
322         lst = []
323         for flag in self.to_list(self.env['CXXFLAGS']):
324                 if len(flag) < 2:
325                         continue
326                 f = flag[0:2]
327                 if f in ('-D', '-I', '/D', '/I'):
328                         if (f[0] == '/'):
329                                 lst.append('-' + flag[1:])
330                         else:
331                                 lst.append(flag)
332         self.env.append_value('MOC_FLAGS', lst)
333
334 @extension(*EXT_QT4)
335 def cxx_hook(self, node):
336         """
337         Re-map C++ file extensions to the :py:class:`waflib.Tools.qt4.qxx` task.
338         """
339         return self.create_compiled_task('qxx', node)
340
341 class rcc(Task.Task):
342         """
343         Process *.qrc* files
344         """
345         color   = 'BLUE'
346         run_str = '${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}'
347         ext_out = ['.h']
348
349         def rcname(self):
350                 return os.path.splitext(self.inputs[0].name)[0]
351
352         def scan(self):
353                 """Parse the *.qrc* files"""
354                 if not has_xml:
355                         Logs.error('no xml support was found, the rcc dependencies will be incomplete!')
356                         return ([], [])
357
358                 parser = make_parser()
359                 curHandler = XMLHandler()
360                 parser.setContentHandler(curHandler)
361                 fi = open(self.inputs[0].abspath(), 'r')
362                 try:
363                         parser.parse(fi)
364                 finally:
365                         fi.close()
366
367                 nodes = []
368                 names = []
369                 root = self.inputs[0].parent
370                 for x in curHandler.files:
371                         nd = root.find_resource(x)
372                         if nd:
373                                 nodes.append(nd)
374                         else:
375                                 names.append(x)
376                 return (nodes, names)
377
378 class moc(Task.Task):
379         """
380         Create *.moc* files
381         """
382         color   = 'BLUE'
383         run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}'
384         def keyword(self):
385                 return "Creating"
386         def __str__(self):
387                 return self.outputs[0].path_from(self.generator.bld.launch_node())
388
389 class ui4(Task.Task):
390         """
391         Process *.ui* files
392         """
393         color   = 'BLUE'
394         run_str = '${QT_UIC} ${SRC} -o ${TGT}'
395         ext_out = ['.h']
396
397 class ts2qm(Task.Task):
398         """
399         Create *.qm* files from *.ts* files
400         """
401         color   = 'BLUE'
402         run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}'
403
404 class qm2rcc(Task.Task):
405         """
406         Transform *.qm* files into *.rc* files
407         """
408         color = 'BLUE'
409         after = 'ts2qm'
410
411         def run(self):
412                 """Create a qrc file including the inputs"""
413                 txt = '\n'.join(['<file>%s</file>' % k.path_from(self.outputs[0].parent) for k in self.inputs])
414                 code = '<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n%s\n</qresource>\n</RCC>' % txt
415                 self.outputs[0].write(code)
416
417 def configure(self):
418         """
419         Besides the configuration options, the environment variable QT4_ROOT may be used
420         to give the location of the qt4 libraries (absolute path).
421
422         The detection will use the program *pkg-config* through :py:func:`waflib.Tools.config_c.check_cfg`
423         """
424         self.find_qt4_binaries()
425         self.set_qt4_libs_to_check()
426         self.set_qt4_defines()
427         self.find_qt4_libraries()
428         self.add_qt4_rpath()
429         self.simplify_qt4_libs()
430
431 @conf
432 def find_qt4_binaries(self):
433         env = self.env
434         opt = Options.options
435
436         qtdir = getattr(opt, 'qtdir', '')
437         qtbin = getattr(opt, 'qtbin', '')
438
439         paths = []
440
441         if qtdir:
442                 qtbin = os.path.join(qtdir, 'bin')
443
444         # the qt directory has been given from QT4_ROOT - deduce the qt binary path
445         if not qtdir:
446                 qtdir = os.environ.get('QT4_ROOT', '')
447                 qtbin = os.environ.get('QT4_BIN') or os.path.join(qtdir, 'bin')
448
449         if qtbin:
450                 paths = [qtbin]
451
452         # no qtdir, look in the path and in /usr/local/Trolltech
453         if not qtdir:
454                 paths = os.environ.get('PATH', '').split(os.pathsep)
455                 paths.append('/usr/share/qt4/bin/')
456                 try:
457                         lst = Utils.listdir('/usr/local/Trolltech/')
458                 except OSError:
459                         pass
460                 else:
461                         if lst:
462                                 lst.sort()
463                                 lst.reverse()
464
465                                 # keep the highest version
466                                 qtdir = '/usr/local/Trolltech/%s/' % lst[0]
467                                 qtbin = os.path.join(qtdir, 'bin')
468                                 paths.append(qtbin)
469
470         # at the end, try to find qmake in the paths given
471         # keep the one with the highest version
472         cand = None
473         prev_ver = ['4', '0', '0']
474         for qmk in ('qmake-qt4', 'qmake4', 'qmake'):
475                 try:
476                         qmake = self.find_program(qmk, path_list=paths)
477                 except self.errors.ConfigurationError:
478                         pass
479                 else:
480                         try:
481                                 version = self.cmd_and_log(qmake + ['-query', 'QT_VERSION']).strip()
482                         except self.errors.WafError:
483                                 pass
484                         else:
485                                 if version:
486                                         new_ver = version.split('.')
487                                         if new_ver > prev_ver:
488                                                 cand = qmake
489                                                 prev_ver = new_ver
490         if cand:
491                 self.env.QMAKE = cand
492         else:
493                 self.fatal('Could not find qmake for qt4')
494
495         qtbin = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_BINS']).strip() + os.sep
496
497         def find_bin(lst, var):
498                 if var in env:
499                         return
500                 for f in lst:
501                         try:
502                                 ret = self.find_program(f, path_list=paths)
503                         except self.errors.ConfigurationError:
504                                 pass
505                         else:
506                                 env[var]=ret
507                                 break
508
509         find_bin(['uic-qt3', 'uic3'], 'QT_UIC3')
510         find_bin(['uic-qt4', 'uic'], 'QT_UIC')
511         if not env.QT_UIC:
512                 self.fatal('cannot find the uic compiler for qt4')
513
514         self.start_msg('Checking for uic version')
515         uicver = self.cmd_and_log(env.QT_UIC + ["-version"], output=Context.BOTH)
516         uicver = ''.join(uicver).strip()
517         uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '')
518         self.end_msg(uicver)
519         if uicver.find(' 3.') != -1:
520                 self.fatal('this uic compiler is for qt3, add uic for qt4 to your path')
521
522         find_bin(['moc-qt4', 'moc'], 'QT_MOC')
523         find_bin(['rcc-qt4', 'rcc'], 'QT_RCC')
524         find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE')
525         find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE')
526
527         env['UIC3_ST']= '%s -o %s'
528         env['UIC_ST'] = '%s -o %s'
529         env['MOC_ST'] = '-o'
530         env['ui_PATTERN'] = 'ui_%s.h'
531         env['QT_LRELEASE_FLAGS'] = ['-silent']
532         env.MOCCPPPATH_ST = '-I%s'
533         env.MOCDEFINES_ST = '-D%s'
534
535 @conf
536 def find_qt4_libraries(self):
537         qtlibs = getattr(Options.options, 'qtlibs', None) or os.environ.get("QT4_LIBDIR")
538         if not qtlibs:
539                 try:
540                         qtlibs = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_LIBS']).strip()
541                 except Errors.WafError:
542                         qtdir = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() + os.sep
543                         qtlibs = os.path.join(qtdir, 'lib')
544         self.msg('Found the Qt4 libraries in', qtlibs)
545
546         qtincludes =  os.environ.get("QT4_INCLUDES") or self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_HEADERS']).strip()
547         env = self.env
548         if not 'PKG_CONFIG_PATH' in os.environ:
549                 os.environ['PKG_CONFIG_PATH'] = '%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib' % (qtlibs, qtlibs)
550
551         try:
552                 if os.environ.get("QT4_XCOMPILE"):
553                         raise self.errors.ConfigurationError()
554                 self.check_cfg(atleast_pkgconfig_version='0.1')
555         except self.errors.ConfigurationError:
556                 for i in self.qt4_vars:
557                         uselib = i.upper()
558                         if Utils.unversioned_sys_platform() == "darwin":
559                                 # Since at least qt 4.7.3 each library locates in separate directory
560                                 frameworkName = i + ".framework"
561                                 qtDynamicLib = os.path.join(qtlibs, frameworkName, i)
562                                 if os.path.exists(qtDynamicLib):
563                                         env.append_unique('FRAMEWORK_' + uselib, i)
564                                         self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN')
565                                 else:
566                                         self.msg('Checking for %s' % i, False, 'YELLOW')
567                                 env.append_unique('INCLUDES_' + uselib, os.path.join(qtlibs, frameworkName, 'Headers'))
568                         elif env.DEST_OS != "win32":
569                                 qtDynamicLib = os.path.join(qtlibs, "lib" + i + ".so")
570                                 qtStaticLib = os.path.join(qtlibs, "lib" + i + ".a")
571                                 if os.path.exists(qtDynamicLib):
572                                         env.append_unique('LIB_' + uselib, i)
573                                         self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN')
574                                 elif os.path.exists(qtStaticLib):
575                                         env.append_unique('LIB_' + uselib, i)
576                                         self.msg('Checking for %s' % i, qtStaticLib, 'GREEN')
577                                 else:
578                                         self.msg('Checking for %s' % i, False, 'YELLOW')
579
580                                 env.append_unique('LIBPATH_' + uselib, qtlibs)
581                                 env.append_unique('INCLUDES_' + uselib, qtincludes)
582                                 env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i))
583                         else:
584                                 # Release library names are like QtCore4
585                                 for k in ("lib%s.a", "lib%s4.a", "%s.lib", "%s4.lib"):
586                                         lib = os.path.join(qtlibs, k % i)
587                                         if os.path.exists(lib):
588                                                 env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')])
589                                                 self.msg('Checking for %s' % i, lib, 'GREEN')
590                                                 break
591                                 else:
592                                         self.msg('Checking for %s' % i, False, 'YELLOW')
593
594                                 env.append_unique('LIBPATH_' + uselib, qtlibs)
595                                 env.append_unique('INCLUDES_' + uselib, qtincludes)
596                                 env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i))
597
598                                 # Debug library names are like QtCore4d
599                                 uselib = i.upper() + "_debug"
600                                 for k in ("lib%sd.a", "lib%sd4.a", "%sd.lib", "%sd4.lib"):
601                                         lib = os.path.join(qtlibs, k % i)
602                                         if os.path.exists(lib):
603                                                 env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')])
604                                                 self.msg('Checking for %s' % i, lib, 'GREEN')
605                                                 break
606                                 else:
607                                         self.msg('Checking for %s' % i, False, 'YELLOW')
608
609                                 env.append_unique('LIBPATH_' + uselib, qtlibs)
610                                 env.append_unique('INCLUDES_' + uselib, qtincludes)
611                                 env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i))
612         else:
613                 for i in self.qt4_vars_debug + self.qt4_vars:
614                         self.check_cfg(package=i, args='--cflags --libs', mandatory=False)
615
616 @conf
617 def simplify_qt4_libs(self):
618         # the libpaths make really long command-lines
619         # remove the qtcore ones from qtgui, etc
620         env = self.env
621         def process_lib(vars_, coreval):
622                 for d in vars_:
623                         var = d.upper()
624                         if var == 'QTCORE':
625                                 continue
626
627                         value = env['LIBPATH_'+var]
628                         if value:
629                                 core = env[coreval]
630                                 accu = []
631                                 for lib in value:
632                                         if lib in core:
633                                                 continue
634                                         accu.append(lib)
635                                 env['LIBPATH_'+var] = accu
636
637         process_lib(self.qt4_vars,       'LIBPATH_QTCORE')
638         process_lib(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG')
639
640 @conf
641 def add_qt4_rpath(self):
642         # rpath if wanted
643         env = self.env
644         if getattr(Options.options, 'want_rpath', False):
645                 def process_rpath(vars_, coreval):
646                         for d in vars_:
647                                 var = d.upper()
648                                 value = env['LIBPATH_'+var]
649                                 if value:
650                                         core = env[coreval]
651                                         accu = []
652                                         for lib in value:
653                                                 if var != 'QTCORE':
654                                                         if lib in core:
655                                                                 continue
656                                                 accu.append('-Wl,--rpath='+lib)
657                                         env['RPATH_'+var] = accu
658                 process_rpath(self.qt4_vars,       'LIBPATH_QTCORE')
659                 process_rpath(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG')
660
661 @conf
662 def set_qt4_libs_to_check(self):
663         if not hasattr(self, 'qt4_vars'):
664                 self.qt4_vars = QT4_LIBS
665         self.qt4_vars = Utils.to_list(self.qt4_vars)
666         if not hasattr(self, 'qt4_vars_debug'):
667                 self.qt4_vars_debug = [a + '_debug' for a in self.qt4_vars]
668         self.qt4_vars_debug = Utils.to_list(self.qt4_vars_debug)
669
670 @conf
671 def set_qt4_defines(self):
672         if sys.platform != 'win32':
673                 return
674         for x in self.qt4_vars:
675                 y = x[2:].upper()
676                 self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y)
677                 self.env.append_unique('DEFINES_%s_DEBUG' % x.upper(), 'QT_%s_LIB' % y)
678
679 def options(opt):
680         """
681         Command-line options
682         """
683         opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries')
684
685         opt.add_option('--header-ext',
686                 type='string',
687                 default='',
688                 help='header extension for moc files',
689                 dest='qt_header_ext')
690
691         for i in 'qtdir qtbin qtlibs'.split():
692                 opt.add_option('--'+i, type='string', default='', dest=i)
693
694         opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False)
695