Package wafadmin :: Package Tools :: Module qt4
[hide private]
[frames] | no frames]

Source Code for Module wafadmin.Tools.qt4

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3  # Thomas Nagy, 2006 (ita) 
  4   
  5  """ 
  6  Qt4 support 
  7   
  8  If QT4_ROOT is given (absolute path), the configuration will look in it first 
  9   
 10  This module also demonstrates how to add tasks dynamically (when the build has started) 
 11  """ 
 12   
 13  try: 
 14          from xml.sax import make_parser 
 15          from xml.sax.handler import ContentHandler 
 16  except ImportError: 
 17          has_xml = False 
 18          ContentHandler = object 
 19  else: 
 20          has_xml = True 
 21   
 22  import os, sys 
 23  import ccroot, cxx 
 24  import TaskGen, Task, Utils, Runner, Options, Build 
 25  from TaskGen import taskgen, feature, after, extension 
 26  from Logs import error 
 27  from Constants import * 
 28   
 29  MOC_H = ['.h', '.hpp', '.hxx', '.hh'] 
 30  EXT_RCC = ['.qrc'] 
 31  EXT_UI  = ['.ui'] 
 32  EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] 
33 34 -class MTask(Task.Task):
35 "A cpp task that may create a moc task dynamically" 36 37 scan = ccroot.scan 38
39 - def __init__(self, parent):
40 Task.Task.__init__(self, parent.env) 41 self.moc_done = 0 42 self.parent = parent
43
44 - def runnable_status(self):
45 if self.moc_done: 46 # if there is a moc task, delay the computation of the file signature 47 for t in self.run_after: 48 if not t.hasrun: 49 return ASK_LATER 50 # the moc file enters in the dependency calculation 51 # so we need to recompute the signature when the moc file is present 52 self.signature() 53 return Task.Task.runnable_status(self) 54 else: 55 self.add_moc_tasks() 56 return ASK_LATER
57
58 - def add_moc_tasks(self):
59 60 tree = Build.bld 61 parn = self.parent 62 node = self.inputs[0] 63 64 # to know if there is a moc file to create 65 try: 66 self.signature() 67 except: 68 print "TODO" 69 else: 70 # remove the signature, it must be recomputed 71 delattr(self, 'sign_all') 72 73 moctasks=[] 74 mocfiles=[] 75 variant = node.variant(parn.env) 76 try: 77 tmp_lst = tree.raw_deps[self.unique_id()] 78 tree.raw_deps[self.unique_id()] = [] 79 except KeyError: 80 tmp_lst = [] 81 for d in tmp_lst: 82 if not d.endswith('.moc'): continue 83 # paranoid check 84 if d in mocfiles: 85 error("paranoia owns") 86 continue 87 # process that base.moc only once 88 mocfiles.append(d) 89 90 # find the extension - this search is done only once 91 ext = '' 92 try: ext = Options.options.qt_header_ext 93 except AttributeError: pass 94 95 if not ext: 96 base2 = d[:-4] 97 path = node.parent.srcpath(parn.env) 98 for i in MOC_H: 99 try: 100 # TODO we could use find_resource 101 os.stat(os.path.join(path, base2+i)) 102 except OSError: 103 pass 104 else: 105 ext = i 106 break 107 if not ext: raise Utils.WafError("no header found for %s which is a moc file" % str(d)) 108 109 # next time we will not search for the extension (look at the 'for' loop below) 110 h_node = node.parent.find_resource(base2+i) 111 m_node = h_node.change_ext('.moc') 112 tree.node_deps[(self.unique_id(), m_node.name)] = h_node 113 114 # create the task 115 task = Task.TaskBase.classes['moc'](parn.env, normal=0) 116 task.set_inputs(h_node) 117 task.set_outputs(m_node) 118 119 generator = Build.bld.generator 120 generator.outstanding.insert(0, task) 121 generator.total += 1 122 123 moctasks.append(task) 124 125 # remove raw deps except the moc files to save space (optimization) 126 tmp_lst = tree.raw_deps[self.unique_id()] = mocfiles 127 128 # look at the file inputs, it is set right above 129 lst = tree.node_deps.get(self.unique_id(), ()) 130 for d in lst: 131 name = d.name 132 if name.endswith('.moc'): 133 task = Task.TaskBase.classes['moc'](parn.env, normal=0) 134 task.set_inputs(tree.node_deps[(self.unique_id(), name)]) # 1st element in a tuple 135 task.set_outputs(d) 136 137 generator = Build.bld.generator 138 generator.outstanding.insert(0, task) 139 generator.total += 1 140 141 moctasks.append(task) 142 143 # simple scheduler dependency: run the moc task before others 144 self.run_after = moctasks 145 self.moc_done = 1
146 147 run = Task.TaskBase.classes['cxx'].__dict__['run']
148
149 -def translation_update(task):
150 outs = [a.abspath(task.env) for a in task.outputs] 151 outs = " ".join(outs) 152 lupdate = task.env['QT_LUPDATE'] 153 154 for x in task.inputs: 155 file = x.abspath(task.env) 156 cmd = "%s %s -ts %s" % (lupdate, file, outs) 157 Utils.pprint('BLUE', cmd) 158 Runner.exec_command(cmd)
159
160 -class XMLHandler(ContentHandler):
161 - def __init__(self):
162 self.buf = [] 163 self.files = []
164 - def startElement(self, name, attrs):
165 if name == 'file': 166 self.buf = []
167 - def endElement(self, name):
168 if name == 'file': 169 self.files.append(''.join(self.buf))
170 - def characters(self, cars):
171 self.buf.append(cars)
172
173 -def scan(self):
174 "add the dependency on the files referenced in the qrc" 175 node = self.inputs[0] 176 parser = make_parser() 177 curHandler = XMLHandler() 178 parser.setContentHandler(curHandler) 179 fi = open(self.inputs[0].abspath(self.env)) 180 parser.parse(fi) 181 fi.close() 182 183 nodes = [] 184 names = [] 185 root = self.inputs[0].parent 186 for x in curHandler.files: 187 x = x.encode('utf8') 188 nd = root.find_resource(x) 189 if nd: nodes.append(nd) 190 else: names.append(x) 191 192 return (nodes, names)
193
194 @extension(EXT_RCC) 195 -def create_rcc_task(self, node):
196 "hook for rcc files" 197 198 rcnode = node.change_ext('_rc.cpp') 199 200 rcctask = self.create_task('rcc') 201 rcctask.inputs = [node] 202 rcctask.outputs = [rcnode] 203 204 cpptask = self.create_task('cxx') 205 cpptask.inputs = [rcnode] 206 cpptask.outputs = [rcnode.change_ext('.o')] 207 cpptask.defines = self.scanner_defines 208 self.compiled_tasks.append(cpptask) 209 210 return cpptask
211
212 @extension(EXT_UI) 213 -def create_uic_task(self, node):
214 "hook for uic tasks" 215 uictask = self.create_task('ui4') 216 uictask.inputs = [node] 217 uictask.outputs = [node.change_ext('.h')]
218
219 -class qt4_taskgen(cxx.cxx_taskgen):
220 - def __init__(self, *kw):
221 cxx.cxx_taskgen.__init__(self, *kw) 222 self.link_task = None 223 self.lang = '' 224 self.langname = '' 225 self.update = 0 226 self.features.append('qt4')
227
228 @taskgen 229 @feature('qt4') 230 @after('apply_link') 231 -def apply_qt4(self):
232 if self.lang: 233 lst=[] 234 trans=[] 235 for l in self.to_list(self.lang): 236 t = Task.TaskBase.classes['ts2qm'](self.env) 237 t.set_inputs(self.path.find_resource(l+'.ts')) 238 t.set_outputs(t.inputs[0].change_ext('.qm')) 239 lst.append(t.outputs[0]) 240 241 if self.update: 242 trans.append(t.inputs[0]) 243 244 if self.update and Options.options.trans_qt4: 245 # we need the cpp files given, except the rcc task we create after 246 # FIXME may be broken 247 u = Task.TaskCmd(translation_update, self.env, 2) 248 u.inputs = [a.inputs[0] for a in self.compiled_tasks] 249 u.outputs = trans 250 251 if self.langname: 252 t = Task.TaskBase.classes['qm2rcc'](self.env) 253 t.set_inputs(lst) 254 t.set_outputs(self.path.find_or_declare(self.langname+'.qrc')) 255 t.path = self.path 256 k = create_rcc_task(self, t.outputs[0]) 257 self.link_task.inputs.append(k.outputs[0]) 258 259 lst = [] 260 for flag in self.to_list(self.env['CXXFLAGS']): 261 if len(flag) < 2: continue 262 if flag[0:2] == '-D' or flag[0:2] == '-I': 263 lst.append(flag) 264 self.env['MOC_FLAGS'] = lst
265
266 -def find_sources_in_dirs(self, dirnames, excludes=[], exts=[]):
267 "the .ts files are added to self.lang" 268 lst=[] 269 excludes = self.to_list(excludes) 270 #make sure dirnames is a list helps with dirnames with spaces 271 dirnames = self.to_list(dirnames) 272 273 ext_lst = exts or self.mappings.keys() + TaskGen.task_gen.mappings.keys() 274 275 for name in dirnames: 276 anode = self.path.find_dir(name) 277 Build.bld.rescan(anode) 278 279 for name in Build.bld.cache_dir_contents[anode.id]: 280 (base, ext) = os.path.splitext(name) 281 if ext in ext_lst: 282 if not name in lst: 283 if name in excludes: continue 284 lst.append((anode.path_to_parent(self.path) or '.') + '/' + name) 285 elif ext == '.ts': 286 self.lang += ' '+base 287 288 lst.sort() 289 self.source = self.source+' '+(" ".join(lst))
290 setattr(qt4_taskgen