waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

qt4.py (20306B)


      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