3 # Thomas Nagy, 2006-2010 (ita)
6 This tool is totally deprecated
9 .pc.in files for .pc files
10 the feature intltool_in - see demos/intltool
15 from waflib import Node, Task, Utils, Errors
16 from waflib.TaskGen import feature, after_method, before_method
17 from waflib.Logs import debug
19 def copy_attrs(orig, dest, names, only_if_set=False):
21 copy class attributes from an object to another
23 for a in Utils.to_list(names):
24 u = getattr(orig, a, ())
25 if u or not only_if_set:
29 "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)"
30 infile = tsk.inputs[0].abspath()
31 outfile = tsk.outputs[0].abspath()
33 shutil.copy2(infile, outfile)
34 except EnvironmentError:
37 if tsk.chmod: os.chmod(outfile, tsk.chmod)
40 def action_process_file_func(tsk):
41 "Ask the function attached to the task to process it"
42 if not tsk.fun: raise Errors.WafError('task must have a function attached to it for copy_func to work!')
47 "call a command everytime"
48 if not self.fun: raise Errors.WafError('cmdobj needs a function!')
52 self.tasks.append(tsk)
53 tsk.install_path = self.install_path
56 @before_method('process_source')
58 Utils.def_attrs(self, fun=copy_func)
59 self.default_install_path = 0
61 lst = self.to_list(self.source)
62 self.meths.remove('process_source')
65 node = self.path.find_resource(filename)
66 if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
69 if not target or len(lst)>1: target = node.name
71 # TODO the file path may be incorrect
72 newnode = self.path.find_or_declare(target)
74 tsk = self.create_task('copy', node, newnode)
76 tsk.chmod = getattr(self, 'chmod', Utils.O644)
80 raise Errors.WafError('task without an environment')
83 "Substitutes variables in a .in file"
85 m4_re = re.compile('@(\w+)@', re.M)
87 code = tsk.inputs[0].read() #Utils.readf(infile)
89 # replace all % by %% to prevent errors by % signs in the input file while string formatting
90 code = code.replace('%', '%%')
92 s = m4_re.sub(r'%(\1)s', code)
95 di = getattr(tsk, 'dict', {}) or getattr(tsk.generator, 'dict', {})
97 names = m4_re.findall(code)
99 di[i] = env.get_flat(i) or env.get_flat(i.upper())
101 tsk.outputs[0].write(s % di)
104 @before_method('process_source')
105 def apply_subst(self):
106 Utils.def_attrs(self, fun=subst_func)
107 lst = self.to_list(self.source)
108 self.meths.remove('process_source')
110 self.dict = getattr(self, 'dict', {})
113 node = self.path.find_resource(filename)
114 if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
117 newnode = self.path.find_or_declare(self.target)
119 newnode = node.change_ext('')
122 self.dict = self.dict.get_merged_dict()
123 except AttributeError:
126 if self.dict and not self.env['DICT_HASH']:
127 self.env = self.env.derive()
128 keys = list(self.dict.keys())
130 lst = [self.dict[x] for x in keys]
131 self.env['DICT_HASH'] = str(Utils.h_list(lst))
133 tsk = self.create_task('copy', node, newnode)
136 tsk.dep_vars = ['DICT_HASH']
137 tsk.chmod = getattr(self, 'chmod', Utils.O644)
141 raise Errors.WafError('task without an environment')
144 ## command-output ####
147 class cmd_arg(object):
148 """command-output arguments for representing files or folders"""
149 def __init__(self, name, template='%s'):
151 self.template = template
154 class input_file(cmd_arg):
155 def find_node(self, base_path):
156 assert isinstance(base_path, Node.Node)
157 self.node = base_path.find_resource(self.name)
158 if self.node is None:
159 raise Errors.WafError("Input file %s not found in " % (self.name, base_path))
161 def get_path(self, env, absolute):
163 return self.template % self.node.abspath()
165 return self.template % self.node.srcpath()
167 class output_file(cmd_arg):
168 def find_node(self, base_path):
169 assert isinstance(base_path, Node.Node)
170 self.node = base_path.find_or_declare(self.name)
171 if self.node is None:
172 raise Errors.WafError("Output file %s not found in " % (self.name, base_path))
174 def get_path(self, env, absolute):
176 return self.template % self.node.abspath()
178 return self.template % self.node.bldpath()
180 class cmd_dir_arg(cmd_arg):
181 def find_node(self, base_path):
182 assert isinstance(base_path, Node.Node)
183 self.node = base_path.find_dir(self.name)
184 if self.node is None:
185 raise Errors.WafError("Directory %s not found in " % (self.name, base_path))
187 class input_dir(cmd_dir_arg):
188 def get_path(self, dummy_env, dummy_absolute):
189 return self.template % self.node.abspath()
191 class output_dir(cmd_dir_arg):
192 def get_path(self, env, dummy_absolute):
193 return self.template % self.node.abspath()
196 class command_output(Task.Task):
198 def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr):
199 Task.Task.__init__(self, env=env)
200 assert isinstance(command, (str, Node.Node))
201 self.command = command
202 self.command_args = command_args
209 if command_node is not None: self.dep_nodes = [command_node]
210 self.dep_vars = [] # additional environment variables to look
214 #assert len(task.inputs) > 0
216 def input_path(node, template):
218 return template % node.bldpath()
220 return template % node.abspath()
221 def output_path(node, template):
223 if task.cwd is None: fun = node.bldpath
224 return template % fun()
226 if isinstance(task.command, Node.Node):
227 argv = [input_path(task.command, '%s')]
229 argv = [task.command]
231 for arg in task.command_args:
232 if isinstance(arg, str):
235 assert isinstance(arg, cmd_arg)
236 argv.append(arg.get_path(task.env, (task.cwd is not None)))
239 stdin = open(input_path(task.stdin, '%s'))
244 stdout = open(output_path(task.stdout, '%s'), "w")
249 stderr = open(output_path(task.stderr, '%s'), "w")
254 cwd = ('None (actually %r)' % os.getcwd())
257 debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" %
258 (cwd, stdin, stdout, argv))
260 if task.os_env is None:
264 command = Utils.subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env)
265 return command.wait()
267 @feature('command-output')
268 def init_cmd_output(self):
269 Utils.def_attrs(self,
273 # the command to execute
276 # whether it is an external command; otherwise it is assumed
277 # to be an executable binary or script that lives in the
278 # source or build tree.
279 command_is_external = False,
281 # extra parameters (argv) to pass to the command (excluding
282 # the command itself)
285 # dependencies to other objects -> this is probably not what you want (ita)
286 # values must be 'task_gen' instances (not names!)
289 # dependencies on env variable contents
292 # input files that are implicit, i.e. they are not
293 # stdin, nor are they mentioned explicitly in argv
296 # output files that are implicit, i.e. they are not
297 # stdout, nor are they mentioned explicitly in argv
300 # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here)
303 # OS environment variables to pass to the subprocess
304 # if None, use the default environment variables unchanged
307 @feature('command-output')
308 @after_method('init_cmd_output')
309 def apply_cmd_output(self):
310 if self.command is None:
311 raise Errors.WafError("command-output missing command")
312 if self.command_is_external:
316 cmd_node = self.path.find_resource(self.command)
317 assert cmd_node is not None, ('''Could not find command '%s' in source tree.
318 Hint: if this is an external command,
319 use command_is_external=True''') % (self.command,)
328 for arg in self.argv:
329 if isinstance(arg, cmd_arg):
330 arg.find_node(self.path)
331 if isinstance(arg, input_file):
332 inputs.append(arg.node)
333 if isinstance(arg, output_file):
334 outputs.append(arg.node)
336 if self.stdout is None:
339 assert isinstance(self.stdout, str)
340 stdout = self.path.find_or_declare(self.stdout)
342 raise Errors.WafError("File %s not found" % (self.stdout,))
343 outputs.append(stdout)
345 if self.stderr is None:
348 assert isinstance(self.stderr, str)
349 stderr = self.path.find_or_declare(self.stderr)
351 raise Errors.WafError("File %s not found" % (self.stderr,))
352 outputs.append(stderr)
354 if self.stdin is None:
357 assert isinstance(self.stdin, str)
358 stdin = self.path.find_resource(self.stdin)
360 raise Errors.WafError("File %s not found" % (self.stdin,))
363 for hidden_input in self.to_list(self.hidden_inputs):
364 node = self.path.find_resource(hidden_input)
366 raise Errors.WafError("File %s not found in dir %s" % (hidden_input, self.path))
369 for hidden_output in self.to_list(self.hidden_outputs):
370 node = self.path.find_or_declare(hidden_output)
372 raise Errors.WafError("File %s not found in dir %s" % (hidden_output, self.path))
375 if not (inputs or getattr(self, 'no_inputs', None)):
376 raise Errors.WafError('command-output objects must have at least one input file or give self.no_inputs')
377 if not (outputs or getattr(self, 'no_outputs', None)):
378 raise Errors.WafError('command-output objects must have at least one output file or give self.no_outputs')
380 cwd = self.bld.variant_dir
381 task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr)
382 task.generator = self
383 copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True)
384 self.tasks.append(task)
387 task.outputs = outputs
388 task.dep_vars = self.to_list(self.dep_vars)
390 for dep in self.dependencies:
391 assert dep is not self
393 for dep_task in dep.tasks:
394 task.set_run_after(dep_task)
397 # the case for svnversion, always run, and update the output nodes
398 task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run
399 task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__)
401 # TODO the case with no outputs?
404 for x in self.outputs:
405 x.sig = Utils.h_file(x.abspath())
407 def runnable_status(self):
410 Task.task_factory('copy', vars=[], func=action_process_file_func)