303 lines
9.8 KiB
Python
303 lines
9.8 KiB
Python
|
#! /usr/bin/env python
|
||
|
# encoding: utf-8
|
||
|
|
||
|
import shutil,re,os
|
||
|
import TaskGen,Node,Task,Utils,Build,Constants
|
||
|
from TaskGen import feature,taskgen,after,before
|
||
|
from Logs import debug
|
||
|
def copy_func(tsk):
|
||
|
env=tsk.env
|
||
|
infile=tsk.inputs[0].abspath(env)
|
||
|
outfile=tsk.outputs[0].abspath(env)
|
||
|
try:
|
||
|
shutil.copy2(infile,outfile)
|
||
|
except(OSError,IOError):
|
||
|
return 1
|
||
|
else:
|
||
|
if tsk.chmod:os.chmod(outfile,tsk.chmod)
|
||
|
return 0
|
||
|
def action_process_file_func(tsk):
|
||
|
if not tsk.fun:raise Utils.WafError('task must have a function attached to it for copy_func to work!')
|
||
|
return tsk.fun(tsk)
|
||
|
class cmd_taskgen(TaskGen.task_gen):
|
||
|
def __init__(self,*k,**kw):
|
||
|
TaskGen.task_gen.__init__(self,*k,**kw)
|
||
|
def apply_cmd(self):
|
||
|
if not self.fun:raise Utils.WafError('cmdobj needs a function!')
|
||
|
tsk=Task.TaskBase()
|
||
|
tsk.fun=self.fun
|
||
|
tsk.env=self.env
|
||
|
self.tasks.append(tsk)
|
||
|
tsk.install_path=self.install_path
|
||
|
class copy_taskgen(TaskGen.task_gen):
|
||
|
def __init__(self,*k,**kw):
|
||
|
TaskGen.task_gen.__init__(self,*k,**kw)
|
||
|
def apply_copy(self):
|
||
|
Utils.def_attrs(self,fun=copy_func)
|
||
|
self.default_install_path=0
|
||
|
lst=self.to_list(self.source)
|
||
|
self.meths.remove('apply_core')
|
||
|
for filename in lst:
|
||
|
node=self.path.find_resource(filename)
|
||
|
if not node:raise Utils.WafError('cannot find input file %s for processing'%filename)
|
||
|
target=self.target
|
||
|
if not target or len(lst)>1:target=node.name
|
||
|
newnode=self.path.find_or_declare(target)
|
||
|
tsk=self.create_task('copy',node,newnode)
|
||
|
tsk.fun=self.fun
|
||
|
tsk.chmod=self.chmod
|
||
|
tsk.install_path=self.install_path
|
||
|
if not tsk.env:
|
||
|
tsk.debug()
|
||
|
raise Utils.WafError('task without an environment')
|
||
|
def subst_func(tsk):
|
||
|
m4_re=re.compile('@(\w+)@',re.M)
|
||
|
env=tsk.env
|
||
|
infile=tsk.inputs[0].abspath(env)
|
||
|
outfile=tsk.outputs[0].abspath(env)
|
||
|
code=Utils.readf(infile)
|
||
|
code=code.replace('%','%%')
|
||
|
s=m4_re.sub(r'%(\1)s',code)
|
||
|
di=tsk.dict or{}
|
||
|
if not di:
|
||
|
names=m4_re.findall(code)
|
||
|
for i in names:
|
||
|
di[i]=env.get_flat(i)or env.get_flat(i.upper())
|
||
|
file=open(outfile,'w')
|
||
|
file.write(s%di)
|
||
|
file.close()
|
||
|
if tsk.chmod:os.chmod(outfile,tsk.chmod)
|
||
|
class subst_taskgen(TaskGen.task_gen):
|
||
|
def __init__(self,*k,**kw):
|
||
|
TaskGen.task_gen.__init__(self,*k,**kw)
|
||
|
def apply_subst(self):
|
||
|
Utils.def_attrs(self,fun=subst_func)
|
||
|
self.default_install_path=0
|
||
|
lst=self.to_list(self.source)
|
||
|
self.meths.remove('apply_core')
|
||
|
self.dict=getattr(self,'dict',{})
|
||
|
for filename in lst:
|
||
|
node=self.path.find_resource(filename)
|
||
|
if not node:raise Utils.WafError('cannot find input file %s for processing'%filename)
|
||
|
if self.target:
|
||
|
newnode=self.path.find_or_declare(self.target)
|
||
|
else:
|
||
|
newnode=node.change_ext('')
|
||
|
try:
|
||
|
self.dict=self.dict.get_merged_dict()
|
||
|
except AttributeError:
|
||
|
pass
|
||
|
if self.dict and not self.env['DICT_HASH']:
|
||
|
self.env=self.env.copy()
|
||
|
keys=list(self.dict.keys())
|
||
|
keys.sort()
|
||
|
lst=[self.dict[x]for x in keys]
|
||
|
self.env['DICT_HASH']=str(Utils.h_list(lst))
|
||
|
tsk=self.create_task('copy',node,newnode)
|
||
|
tsk.fun=self.fun
|
||
|
tsk.dict=self.dict
|
||
|
tsk.dep_vars=['DICT_HASH']
|
||
|
tsk.install_path=self.install_path
|
||
|
tsk.chmod=self.chmod
|
||
|
if not tsk.env:
|
||
|
tsk.debug()
|
||
|
raise Utils.WafError('task without an environment')
|
||
|
class cmd_arg(object):
|
||
|
def __init__(self,name,template='%s'):
|
||
|
self.name=name
|
||
|
self.template=template
|
||
|
self.node=None
|
||
|
class input_file(cmd_arg):
|
||
|
def find_node(self,base_path):
|
||
|
assert isinstance(base_path,Node.Node)
|
||
|
self.node=base_path.find_resource(self.name)
|
||
|
if self.node is None:
|
||
|
raise Utils.WafError("Input file %s not found in "%(self.name,base_path))
|
||
|
def get_path(self,env,absolute):
|
||
|
if absolute:
|
||
|
return self.template%self.node.abspath(env)
|
||
|
else:
|
||
|
return self.template%self.node.srcpath(env)
|
||
|
class output_file(cmd_arg):
|
||
|
def find_node(self,base_path):
|
||
|
assert isinstance(base_path,Node.Node)
|
||
|
self.node=base_path.find_or_declare(self.name)
|
||
|
if self.node is None:
|
||
|
raise Utils.WafError("Output file %s not found in "%(self.name,base_path))
|
||
|
def get_path(self,env,absolute):
|
||
|
if absolute:
|
||
|
return self.template%self.node.abspath(env)
|
||
|
else:
|
||
|
return self.template%self.node.bldpath(env)
|
||
|
class cmd_dir_arg(cmd_arg):
|
||
|
def find_node(self,base_path):
|
||
|
assert isinstance(base_path,Node.Node)
|
||
|
self.node=base_path.find_dir(self.name)
|
||
|
if self.node is None:
|
||
|
raise Utils.WafError("Directory %s not found in "%(self.name,base_path))
|
||
|
class input_dir(cmd_dir_arg):
|
||
|
def get_path(self,dummy_env,dummy_absolute):
|
||
|
return self.template%self.node.abspath()
|
||
|
class output_dir(cmd_dir_arg):
|
||
|
def get_path(self,env,dummy_absolute):
|
||
|
return self.template%self.node.abspath(env)
|
||
|
class command_output(Task.Task):
|
||
|
color="BLUE"
|
||
|
def __init__(self,env,command,command_node,command_args,stdin,stdout,cwd,os_env,stderr):
|
||
|
Task.Task.__init__(self,env,normal=1)
|
||
|
assert isinstance(command,(str,Node.Node))
|
||
|
self.command=command
|
||
|
self.command_args=command_args
|
||
|
self.stdin=stdin
|
||
|
self.stdout=stdout
|
||
|
self.cwd=cwd
|
||
|
self.os_env=os_env
|
||
|
self.stderr=stderr
|
||
|
if command_node is not None:self.dep_nodes=[command_node]
|
||
|
self.dep_vars=[]
|
||
|
def run(self):
|
||
|
task=self
|
||
|
def input_path(node,template):
|
||
|
if task.cwd is None:
|
||
|
return template%node.bldpath(task.env)
|
||
|
else:
|
||
|
return template%node.abspath()
|
||
|
def output_path(node,template):
|
||
|
fun=node.abspath
|
||
|
if task.cwd is None:fun=node.bldpath
|
||
|
return template%fun(task.env)
|
||
|
if isinstance(task.command,Node.Node):
|
||
|
argv=[input_path(task.command,'%s')]
|
||
|
else:
|
||
|
argv=[task.command]
|
||
|
for arg in task.command_args:
|
||
|
if isinstance(arg,str):
|
||
|
argv.append(arg)
|
||
|
else:
|
||
|
assert isinstance(arg,cmd_arg)
|
||
|
argv.append(arg.get_path(task.env,(task.cwd is not None)))
|
||
|
if task.stdin:
|
||
|
stdin=open(input_path(task.stdin,'%s'))
|
||
|
else:
|
||
|
stdin=None
|
||
|
if task.stdout:
|
||
|
stdout=open(output_path(task.stdout,'%s'),"w")
|
||
|
else:
|
||
|
stdout=None
|
||
|
if task.stderr:
|
||
|
stderr=open(output_path(task.stderr,'%s'),"w")
|
||
|
else:
|
||
|
stderr=None
|
||
|
if task.cwd is None:
|
||
|
cwd=('None (actually %r)'%os.getcwd())
|
||
|
else:
|
||
|
cwd=repr(task.cwd)
|
||
|
debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r"%(cwd,stdin,stdout,argv))
|
||
|
if task.os_env is None:
|
||
|
os_env=os.environ
|
||
|
else:
|
||
|
os_env=task.os_env
|
||
|
command=Utils.pproc.Popen(argv,stdin=stdin,stdout=stdout,stderr=stderr,cwd=task.cwd,env=os_env)
|
||
|
return command.wait()
|
||
|
class cmd_output_taskgen(TaskGen.task_gen):
|
||
|
def __init__(self,*k,**kw):
|
||
|
TaskGen.task_gen.__init__(self,*k,**kw)
|
||
|
def init_cmd_output(self):
|
||
|
Utils.def_attrs(self,stdin=None,stdout=None,stderr=None,command=None,command_is_external=False,argv=[],dependencies=[],dep_vars=[],hidden_inputs=[],hidden_outputs=[],cwd=None,os_env=None)
|
||
|
def apply_cmd_output(self):
|
||
|
if self.command is None:
|
||
|
raise Utils.WafError("command-output missing command")
|
||
|
if self.command_is_external:
|
||
|
cmd=self.command
|
||
|
cmd_node=None
|
||
|
else:
|
||
|
cmd_node=self.path.find_resource(self.command)
|
||
|
assert cmd_node is not None,('''Could not find command '%s' in source tree.
|
||
|
Hint: if this is an external command,
|
||
|
use command_is_external=True''')%(self.command,)
|
||
|
cmd=cmd_node
|
||
|
if self.cwd is None:
|
||
|
cwd=None
|
||
|
else:
|
||
|
assert isinstance(cwd,CmdDirArg)
|
||
|
self.cwd.find_node(self.path)
|
||
|
args=[]
|
||
|
inputs=[]
|
||
|
outputs=[]
|
||
|
for arg in self.argv:
|
||
|
if isinstance(arg,cmd_arg):
|
||
|
arg.find_node(self.path)
|
||
|
if isinstance(arg,input_file):
|
||
|
inputs.append(arg.node)
|
||
|
if isinstance(arg,output_file):
|
||
|
outputs.append(arg.node)
|
||
|
if self.stdout is None:
|
||
|
stdout=None
|
||
|
else:
|
||
|
assert isinstance(self.stdout,str)
|
||
|
stdout=self.path.find_or_declare(self.stdout)
|
||
|
if stdout is None:
|
||
|
raise Utils.WafError("File %s not found"%(self.stdout,))
|
||
|
outputs.append(stdout)
|
||
|
if self.stderr is None:
|
||
|
stderr=None
|
||
|
else:
|
||
|
assert isinstance(self.stderr,str)
|
||
|
stderr=self.path.find_or_declare(self.stderr)
|
||
|
if stderr is None:
|
||
|
raise Utils.WafError("File %s not found"%(self.stderr,))
|
||
|
outputs.append(stderr)
|
||
|
if self.stdin is None:
|
||
|
stdin=None
|
||
|
else:
|
||
|
assert isinstance(self.stdin,str)
|
||
|
stdin=self.path.find_resource(self.stdin)
|
||
|
if stdin is None:
|
||
|
raise Utils.WafError("File %s not found"%(self.stdin,))
|
||
|
inputs.append(stdin)
|
||
|
for hidden_input in self.to_list(self.hidden_inputs):
|
||
|
node=self.path.find_resource(hidden_input)
|
||
|
if node is None:
|
||
|
raise Utils.WafError("File %s not found in dir %s"%(hidden_input,self.path))
|
||
|
inputs.append(node)
|
||
|
for hidden_output in self.to_list(self.hidden_outputs):
|
||
|
node=self.path.find_or_declare(hidden_output)
|
||
|
if node is None:
|
||
|
raise Utils.WafError("File %s not found in dir %s"%(hidden_output,self.path))
|
||
|
outputs.append(node)
|
||
|
if not(inputs or getattr(self,'no_inputs',None)):
|
||
|
raise Utils.WafError('command-output objects must have at least one input file or give self.no_inputs')
|
||
|
if not(outputs or getattr(self,'no_outputs',None)):
|
||
|
raise Utils.WafError('command-output objects must have at least one output file or give self.no_outputs')
|
||
|
task=command_output(self.env,cmd,cmd_node,self.argv,stdin,stdout,cwd,self.os_env,stderr)
|
||
|
Utils.copy_attrs(self,task,'before after ext_in ext_out',only_if_set=True)
|
||
|
self.tasks.append(task)
|
||
|
task.inputs=inputs
|
||
|
task.outputs=outputs
|
||
|
task.dep_vars=self.to_list(self.dep_vars)
|
||
|
for dep in self.dependencies:
|
||
|
assert dep is not self
|
||
|
dep.post()
|
||
|
for dep_task in dep.tasks:
|
||
|
task.set_run_after(dep_task)
|
||
|
if not task.inputs:
|
||
|
task.runnable_status=type(Task.TaskBase.run)(runnable_status,task,task.__class__)
|
||
|
task.post_run=type(Task.TaskBase.run)(post_run,task,task.__class__)
|
||
|
def post_run(self):
|
||
|
for x in self.outputs:
|
||
|
h=Utils.h_file(x.abspath(self.env))
|
||
|
self.generator.bld.node_sigs[self.env.variant()][x.id]=h
|
||
|
def runnable_status(self):
|
||
|
return Constants.RUN_ME
|
||
|
Task.task_type_from_func('copy',vars=[],func=action_process_file_func)
|
||
|
TaskGen.task_gen.classes['command-output']=cmd_output_taskgen
|
||
|
|
||
|
feature('cmd')(apply_cmd)
|
||
|
feature('copy')(apply_copy)
|
||
|
before('apply_core')(apply_copy)
|
||
|
feature('subst')(apply_subst)
|
||
|
before('apply_core')(apply_subst)
|
||
|
feature('command-output')(init_cmd_output)
|
||
|
feature('command-output')(apply_cmd_output)
|
||
|
after('init_cmd_output')(apply_cmd_output)
|