~ubuntu-branches/ubuntu/saucy/xmms2/saucy-proposed

« back to all changes in this revision

Viewing changes to wafadmin/Tools/misc.py

  • Committer: Bazaar Package Importer
  • Author(s): Benjamin Drung
  • Date: 2011-10-22 23:53:00 UTC
  • mto: (38.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 43.
  • Revision ID: james.westby@ubuntu.com-20111022235300-u50pdo3g341jvk7q
ImportĀ upstreamĀ versionĀ 0.8+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# encoding: utf-8
3
 
# Thomas Nagy, 2006 (ita)
4
 
 
5
 
"""
6
 
Custom objects:
7
 
 - execute a function everytime
8
 
 - copy a file somewhere else
9
 
"""
10
 
 
11
 
import shutil, re, os
12
 
import TaskGen, Node, Task, Utils, Build, Constants
13
 
from TaskGen import feature, taskgen, after, before
14
 
from Logs import debug
15
 
 
16
 
def copy_func(tsk):
17
 
        "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)"
18
 
        env = tsk.env
19
 
        infile = tsk.inputs[0].abspath(env)
20
 
        outfile = tsk.outputs[0].abspath(env)
21
 
        try:
22
 
                shutil.copy2(infile, outfile)
23
 
        except (OSError, IOError):
24
 
                return 1
25
 
        else:
26
 
                if tsk.chmod: os.chmod(outfile, tsk.chmod)
27
 
                return 0
28
 
 
29
 
def action_process_file_func(tsk):
30
 
        "Ask the function attached to the task to process it"
31
 
        if not tsk.fun: raise Utils.WafError('task must have a function attached to it for copy_func to work!')
32
 
        return tsk.fun(tsk)
33
 
 
34
 
class cmd_taskgen(TaskGen.task_gen):
35
 
        def __init__(self, *k, **kw):
36
 
                TaskGen.task_gen.__init__(self, *k, **kw)
37
 
 
38
 
@feature('cmd')
39
 
def apply_cmd(self):
40
 
        "call a command everytime"
41
 
        if not self.fun: raise Utils.WafError('cmdobj needs a function!')
42
 
        tsk = Task.TaskBase()
43
 
        tsk.fun = self.fun
44
 
        tsk.env = self.env
45
 
        self.tasks.append(tsk)
46
 
        tsk.install_path = self.install_path
47
 
 
48
 
class copy_taskgen(TaskGen.task_gen):
49
 
        "By default, make a file copy, if fun is provided, fun will make the copy (or call a compiler, etc)"
50
 
        def __init__(self, *k, **kw):
51
 
                TaskGen.task_gen.__init__(self, *k, **kw)
52
 
 
53
 
@feature('copy')
54
 
@before('apply_core')
55
 
def apply_copy(self):
56
 
        Utils.def_attrs(self, fun=copy_func)
57
 
        self.default_install_path = 0
58
 
 
59
 
        lst = self.to_list(self.source)
60
 
        self.meths.remove('apply_core')
61
 
 
62
 
        for filename in lst:
63
 
                node = self.path.find_resource(filename)
64
 
                if not node: raise Utils.WafError('cannot find input file %s for processing' % filename)
65
 
 
66
 
                target = self.target
67
 
                if not target or len(lst)>1: target = node.name
68
 
 
69
 
                # TODO the file path may be incorrect
70
 
                newnode = self.path.find_or_declare(target)
71
 
 
72
 
                tsk = self.create_task('copy', node, newnode)
73
 
                tsk.fun = self.fun
74
 
                tsk.chmod = self.chmod
75
 
 
76
 
                if not tsk.env:
77
 
                        tsk.debug()
78
 
                        raise Utils.WafError('task without an environment')
79
 
 
80
 
def subst_func(tsk):
81
 
        "Substitutes variables in a .in file"
82
 
 
83
 
        m4_re = re.compile('@(\w+)@', re.M)
84
 
 
85
 
        env = tsk.env
86
 
        infile = tsk.inputs[0].abspath(env)
87
 
        outfile = tsk.outputs[0].abspath(env)
88
 
 
89
 
        code = Utils.readf(infile)
90
 
 
91
 
        # replace all % by %% to prevent errors by % signs in the input file while string formatting
92
 
        code = code.replace('%', '%%')
93
 
 
94
 
        s = m4_re.sub(r'%(\1)s', code)
95
 
 
96
 
        di = tsk.dict or {}
97
 
        if not di:
98
 
                names = m4_re.findall(code)
99
 
                for i in names:
100
 
                        di[i] = env.get_flat(i) or env.get_flat(i.upper())
101
 
 
102
 
        file = open(outfile, 'w')
103
 
        file.write(s % di)
104
 
        file.close()
105
 
        if tsk.chmod: os.chmod(outfile, tsk.chmod)
106
 
 
107
 
class subst_taskgen(TaskGen.task_gen):
108
 
        def __init__(self, *k, **kw):
109
 
                TaskGen.task_gen.__init__(self, *k, **kw)
110
 
 
111
 
@feature('subst')
112
 
@before('apply_core')
113
 
def apply_subst(self):
114
 
        Utils.def_attrs(self, fun=subst_func)
115
 
        self.default_install_path = 0
116
 
        lst = self.to_list(self.source)
117
 
        self.meths.remove('apply_core')
118
 
 
119
 
        self.dict = getattr(self, 'dict', {})
120
 
 
121
 
        for filename in lst:
122
 
                node = self.path.find_resource(filename)
123
 
                if not node: raise Utils.WafError('cannot find input file %s for processing' % filename)
124
 
 
125
 
                if self.target:
126
 
                        newnode = self.path.find_or_declare(self.target)
127
 
                else:
128
 
                        newnode = node.change_ext('')
129
 
 
130
 
                try:
131
 
                        self.dict = self.dict.get_merged_dict()
132
 
                except AttributeError:
133
 
                        pass
134
 
 
135
 
                if self.dict and not self.env['DICT_HASH']:
136
 
                        self.env = self.env.copy()
137
 
                        keys = list(self.dict.keys())
138
 
                        keys.sort()
139
 
                        lst = [self.dict[x] for x in keys]
140
 
                        self.env['DICT_HASH'] = str(Utils.h_list(lst))
141
 
 
142
 
                tsk = self.create_task('copy', node, newnode)
143
 
                tsk.fun = self.fun
144
 
                tsk.dict = self.dict
145
 
                tsk.dep_vars = ['DICT_HASH']
146
 
                tsk.install_path = self.install_path
147
 
                tsk.chmod = self.chmod
148
 
 
149
 
                if not tsk.env:
150
 
                        tsk.debug()
151
 
                        raise Utils.WafError('task without an environment')
152
 
 
153
 
####################
154
 
## command-output ####
155
 
####################
156
 
 
157
 
class cmd_arg(object):
158
 
        """command-output arguments for representing files or folders"""
159
 
        def __init__(self, name, template='%s'):
160
 
                self.name = name
161
 
                self.template = template
162
 
                self.node = None
163
 
 
164
 
class input_file(cmd_arg):
165
 
        def find_node(self, base_path):
166
 
                assert isinstance(base_path, Node.Node)
167
 
                self.node = base_path.find_resource(self.name)
168
 
                if self.node is None:
169
 
                        raise Utils.WafError("Input file %s not found in " % (self.name, base_path))
170
 
 
171
 
        def get_path(self, env, absolute):
172
 
                if absolute:
173
 
                        return self.template % self.node.abspath(env)
174
 
                else:
175
 
                        return self.template % self.node.srcpath(env)
176
 
 
177
 
class output_file(cmd_arg):
178
 
        def find_node(self, base_path):
179
 
                assert isinstance(base_path, Node.Node)
180
 
                self.node = base_path.find_or_declare(self.name)
181
 
                if self.node is None:
182
 
                        raise Utils.WafError("Output file %s not found in " % (self.name, base_path))
183
 
 
184
 
        def get_path(self, env, absolute):
185
 
                if absolute:
186
 
                        return self.template % self.node.abspath(env)
187
 
                else:
188
 
                        return self.template % self.node.bldpath(env)
189
 
 
190
 
class cmd_dir_arg(cmd_arg):
191
 
        def find_node(self, base_path):
192
 
                assert isinstance(base_path, Node.Node)
193
 
                self.node = base_path.find_dir(self.name)
194
 
                if self.node is None:
195
 
                        raise Utils.WafError("Directory %s not found in " % (self.name, base_path))
196
 
 
197
 
class input_dir(cmd_dir_arg):
198
 
        def get_path(self, dummy_env, dummy_absolute):
199
 
                return self.template % self.node.abspath()
200
 
 
201
 
class output_dir(cmd_dir_arg):
202
 
        def get_path(self, env, dummy_absolute):
203
 
                return self.template % self.node.abspath(env)
204
 
 
205
 
 
206
 
class command_output(Task.Task):
207
 
        color = "BLUE"
208
 
        def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr):
209
 
                Task.Task.__init__(self, env, normal=1)
210
 
                assert isinstance(command, (str, Node.Node))
211
 
                self.command = command
212
 
                self.command_args = command_args
213
 
                self.stdin = stdin
214
 
                self.stdout = stdout
215
 
                self.cwd = cwd
216
 
                self.os_env = os_env
217
 
                self.stderr = stderr
218
 
 
219
 
                if command_node is not None: self.dep_nodes = [command_node]
220
 
                self.dep_vars = [] # additional environment variables to look
221
 
 
222
 
        def run(self):
223
 
                task = self
224
 
                #assert len(task.inputs) > 0
225
 
 
226
 
                def input_path(node, template):
227
 
                        if task.cwd is None:
228
 
                                return template % node.bldpath(task.env)
229
 
                        else:
230
 
                                return template % node.abspath()
231
 
                def output_path(node, template):
232
 
                        fun = node.abspath
233
 
                        if task.cwd is None: fun = node.bldpath
234
 
                        return template % fun(task.env)
235
 
 
236
 
                if isinstance(task.command, Node.Node):
237
 
                        argv = [input_path(task.command, '%s')]
238
 
                else:
239
 
                        argv = [task.command]
240
 
 
241
 
                for arg in task.command_args:
242
 
                        if isinstance(arg, str):
243
 
                                argv.append(arg)
244
 
                        else:
245
 
                                assert isinstance(arg, cmd_arg)
246
 
                                argv.append(arg.get_path(task.env, (task.cwd is not None)))
247
 
 
248
 
                if task.stdin:
249
 
                        stdin = open(input_path(task.stdin, '%s'))
250
 
                else:
251
 
                        stdin = None
252
 
 
253
 
                if task.stdout:
254
 
                        stdout = open(output_path(task.stdout, '%s'), "w")
255
 
                else:
256
 
                        stdout = None
257
 
 
258
 
                if task.stderr:
259
 
                        stderr = open(output_path(task.stderr, '%s'), "w")
260
 
                else:
261
 
                        stderr = None
262
 
 
263
 
                if task.cwd is None:
264
 
                        cwd = ('None (actually %r)' % os.getcwd())
265
 
                else:
266
 
                        cwd = repr(task.cwd)
267
 
                debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" %
268
 
                             (cwd, stdin, stdout, argv))
269
 
 
270
 
                if task.os_env is None:
271
 
                        os_env = os.environ
272
 
                else:
273
 
                        os_env = task.os_env
274
 
                command = Utils.pproc.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env)
275
 
                return command.wait()
276
 
 
277
 
class cmd_output_taskgen(TaskGen.task_gen):
278
 
        def __init__(self, *k, **kw):
279
 
                TaskGen.task_gen.__init__(self, *k, **kw)
280
 
 
281
 
@feature('command-output')
282
 
def init_cmd_output(self):
283
 
        Utils.def_attrs(self,
284
 
                stdin = None,
285
 
                stdout = None,
286
 
                stderr = None,
287
 
                # the command to execute
288
 
                command = None,
289
 
 
290
 
                # whether it is an external command; otherwise it is assumed
291
 
                # to be an executable binary or script that lives in the
292
 
                # source or build tree.
293
 
                command_is_external = False,
294
 
 
295
 
                # extra parameters (argv) to pass to the command (excluding
296
 
                # the command itself)
297
 
                argv = [],
298
 
 
299
 
                # dependencies to other objects -> this is probably not what you want (ita)
300
 
                # values must be 'task_gen' instances (not names!)
301
 
                dependencies = [],
302
 
 
303
 
                # dependencies on env variable contents
304
 
                dep_vars = [],
305
 
 
306
 
                # input files that are implicit, i.e. they are not
307
 
                # stdin, nor are they mentioned explicitly in argv
308
 
                hidden_inputs = [],
309
 
 
310
 
                # output files that are implicit, i.e. they are not
311
 
                # stdout, nor are they mentioned explicitly in argv
312
 
                hidden_outputs = [],
313
 
 
314
 
                # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here)
315
 
                cwd = None,
316
 
 
317
 
                # OS environment variables to pass to the subprocess
318
 
                # if None, use the default environment variables unchanged
319
 
                os_env = None)
320
 
 
321
 
@feature('command-output')
322
 
@after('init_cmd_output')
323
 
def apply_cmd_output(self):
324
 
        if self.command is None:
325
 
                raise Utils.WafError("command-output missing command")
326
 
        if self.command_is_external:
327
 
                cmd = self.command
328
 
                cmd_node = None
329
 
        else:
330
 
                cmd_node = self.path.find_resource(self.command)
331
 
                assert cmd_node is not None, ('''Could not find command '%s' in source tree.
332
 
Hint: if this is an external command,
333
 
use command_is_external=True''') % (self.command,)
334
 
                cmd = cmd_node
335
 
 
336
 
        if self.cwd is None:
337
 
                cwd = None
338
 
        else:
339
 
                assert isinstance(cwd, CmdDirArg)
340
 
                self.cwd.find_node(self.path)
341
 
 
342
 
        args = []
343
 
        inputs = []
344
 
        outputs = []
345
 
 
346
 
        for arg in self.argv:
347
 
                if isinstance(arg, cmd_arg):
348
 
                        arg.find_node(self.path)
349
 
                        if isinstance(arg, input_file):
350
 
                                inputs.append(arg.node)
351
 
                        if isinstance(arg, output_file):
352
 
                                outputs.append(arg.node)
353
 
 
354
 
        if self.stdout is None:
355
 
                stdout = None
356
 
        else:
357
 
                assert isinstance(self.stdout, str)
358
 
                stdout = self.path.find_or_declare(self.stdout)
359
 
                if stdout is None:
360
 
                        raise Utils.WafError("File %s not found" % (self.stdout,))
361
 
                outputs.append(stdout)
362
 
 
363
 
        if self.stderr is None:
364
 
                stderr = None
365
 
        else:
366
 
                assert isinstance(self.stderr, str)
367
 
                stderr = self.path.find_or_declare(self.stderr)
368
 
                if stderr is None:
369
 
                        raise Utils.WafError("File %s not found" % (self.stderr,))
370
 
                outputs.append(stderr)
371
 
 
372
 
        if self.stdin is None:
373
 
                stdin = None
374
 
        else:
375
 
                assert isinstance(self.stdin, str)
376
 
                stdin = self.path.find_resource(self.stdin)
377
 
                if stdin is None:
378
 
                        raise Utils.WafError("File %s not found" % (self.stdin,))
379
 
                inputs.append(stdin)
380
 
 
381
 
        for hidden_input in self.to_list(self.hidden_inputs):
382
 
                node = self.path.find_resource(hidden_input)
383
 
                if node is None:
384
 
                        raise Utils.WafError("File %s not found in dir %s" % (hidden_input, self.path))
385
 
                inputs.append(node)
386
 
 
387
 
        for hidden_output in self.to_list(self.hidden_outputs):
388
 
                node = self.path.find_or_declare(hidden_output)
389
 
                if node is None:
390
 
                        raise Utils.WafError("File %s not found in dir %s" % (hidden_output, self.path))
391
 
                outputs.append(node)
392
 
 
393
 
        if not (inputs or getattr(self, 'no_inputs', None)):
394
 
                raise Utils.WafError('command-output objects must have at least one input file or give self.no_inputs')
395
 
        if not (outputs or getattr(self, 'no_outputs', None)):
396
 
                raise Utils.WafError('command-output objects must have at least one output file or give self.no_outputs')
397
 
 
398
 
        task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr)
399
 
        Utils.copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True)
400
 
        self.tasks.append(task)
401
 
 
402
 
        task.inputs = inputs
403
 
        task.outputs = outputs
404
 
        task.dep_vars = self.to_list(self.dep_vars)
405
 
 
406
 
        for dep in self.dependencies:
407
 
                assert dep is not self
408
 
                dep.post()
409
 
                for dep_task in dep.tasks:
410
 
                        task.set_run_after(dep_task)
411
 
 
412
 
        if not task.inputs:
413
 
                # the case for svnversion, always run, and update the output nodes
414
 
                task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run
415
 
                task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__)
416
 
 
417
 
        # TODO the case with no outputs?
418
 
 
419
 
def post_run(self):
420
 
        for x in self.outputs:
421
 
                h = Utils.h_file(x.abspath(self.env))
422
 
                self.generator.bld.node_sigs[self.env.variant()][x.id] = h
423
 
 
424
 
def runnable_status(self):
425
 
        return Constants.RUN_ME
426
 
 
427
 
Task.task_type_from_func('copy', vars=[], func=action_process_file_func)
428
 
TaskGen.task_gen.classes['command-output'] = cmd_output_taskgen
429