~ubuntu-branches/ubuntu/trusty/ldb/trusty-proposed

« back to all changes in this revision

Viewing changes to buildtools/wafadmin/Tools/misc.py

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-02-07 16:04:26 UTC
  • mfrom: (1.3.11)
  • Revision ID: package-import@ubuntu.com-20120207160426-hz17vq8gs1epwkf2
Tags: 1:1.1.4+git20120206-1
* New upstream snapshot.
 + Extracts waf source code. Closes: #654482
 + Disable tdb2 support.

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