1
2
3
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
43
57
59
60 tree = Build.bld
61 parn = self.parent
62 node = self.inputs[0]
63
64
65 try:
66 self.signature()
67 except:
68 print "TODO"
69 else:
70
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
84 if d in mocfiles:
85 error("paranoia owns")
86 continue
87
88 mocfiles.append(d)
89
90
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
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
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
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
126 tmp_lst = tree.raw_deps[self.unique_id()] = mocfiles
127
128
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)])
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
144 self.run_after = moctasks
145 self.moc_done = 1
146
147 run = Task.TaskBase.classes['cxx'].__dict__['run']
148
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
162 self.buf = []
163 self.files = []
165 if name == 'file':
166 self.buf = []
168 if name == 'file':
169 self.files.append(''.join(self.buf))
171 self.buf.append(cars)
172
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
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
214 "hook for uic tasks"
215 uictask = self.create_task('ui4')
216 uictask.inputs = [node]
217 uictask.outputs = [node.change_ext('.h')]
218
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):
265
267 "the .ts files are added to self.lang"
268 lst=[]
269 excludes = self.to_list(excludes)
270
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