1#!/usr/bin/env python
2# encoding: utf-8
3# Thomas Nagy, 2006-2010 (ita)
4
5"""
6
7Tool Description
8================
9
10This tool helps with finding Qt4 tools and libraries,
11and also provides syntactic sugar for using Qt4 tools.
12
13The 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
29Here, the UI description and resource files will be processed
30to generate code.
31
32Usage
33=====
34
35Load the "qt4" tool.
36
37You 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
57Note: another tool provides Qt processing that does not require
58.moc includes, see 'playground/slow_qt/'.
59
60A few options (--qt{dir,bin,...}) and environment variables
61(QT4_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool,
62tool path selection, etc; please read the source for more info.
63
64"""
65
66try:
67	from xml.sax import make_parser
68	from xml.sax.handler import ContentHandler
69except ImportError:
70	has_xml = False
71	ContentHandler = object
72else:
73	has_xml = True
74
75import os, sys
76from waflib.Tools import cxx
77from waflib import Task, Utils, Options, Errors, Context
78from waflib.TaskGen import feature, after_method, extension
79from waflib.Configure import conf
80from waflib import Logs
81
82MOC_H = ['.h', '.hpp', '.hxx', '.hh']
83"""
84File extensions associated to the .moc files
85"""
86
87EXT_RCC = ['.qrc']
88"""
89File extension for the resource (.qrc) files
90"""
91
92EXT_UI  = ['.ui']
93"""
94File extension for the user interface (.ui) files
95"""
96
97EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C']
98"""
99File extensions of C++ files that may require a .moc processing
100"""
101
102QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative QtDesigner"
103
104class 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
238class 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
243class 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)
260def 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)
272def 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')
278def 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')
284def 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)
335def 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
341class 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
378class 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
389class 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
397class 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
404class 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
417def 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
432def 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
536def 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
617def 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
641def 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
662def 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
671def 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
679def 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
696