4
if sys.hexversion < 0x020400f0: from sets import Set as set
5
import os,traceback,copy
6
import Build,Task,Utils,Logs,Options
7
from Logs import debug,error,warn
9
typos={'sources':'source','targets':'target','include':'includes','define':'defines','importpath':'importpaths','install_var':'install_path','install_subdir':'install_path','inst_var':'install_path','inst_dir':'install_path','feature':'features',}
10
class register_obj(type):
11
def __init__(cls,name,bases,dict):
12
super(register_obj,cls).__init__(name,bases,dict)
15
if name.endswith(suffix):
16
task_gen.classes[name.replace(suffix,'')]=cls
17
class task_gen(object):
18
__metaclass__=register_obj
21
prec=Utils.DefaultDict(list)
22
traits=Utils.DefaultDict(set)
24
def __init__(self,*kw,**kwargs):
25
self.prec=Utils.DefaultDict(list)
30
self.features=list(kw)
32
self.default_chmod=O644
33
self.default_install_path=None
35
self.bld=kwargs.get('bld',Build.bld)
36
self.env=self.bld.env.copy()
37
self.path=self.bld.path
39
self.idx=self.bld.idx[self.path.id]=self.bld.idx.get(self.path.id,0)+1
40
for key,val in kwargs.iteritems():
42
self.bld.task_manager.add_task_gen(self)
43
self.bld.all_task_gen.append(self)
45
return("<task_gen '%s' of type %s defined in %s>"%(self.name or self.target,self.__class__.__name__,str(self.path)))
46
def __setattr__(self,name,attr):
47
real=typos.get(name,name)
49
warn('typo %s -> %s'%(name,real))
51
traceback.print_stack()
52
object.__setattr__(self,real,attr)
53
def to_list(self,value):
54
if isinstance(value,str):return value.split()
58
self.features=Utils.to_list(self.features)
59
for x in self.features+['*']:
62
warn('feature %r does not exist - bind at least one method to it'%x)
65
prec_tbl=self.prec or task_gen.prec
71
for x in prec.values():
78
if e in keys:out.append(e)
91
if prec:raise Utils.WafError("graph has a cycle %s"%str(prec))
94
debug('task_gen: posting %s %d',self,id(self))
98
except AttributeError:
99
raise Utils.WafError("tried to retrieve %s which is not a valid method"%x)
100
debug('task_gen: -> %s (%d)',x,id(self))
104
if isinstance(self.target,list):
105
self.name=' '.join(self.target)
107
self.name=self.target
108
if getattr(self,'posted',None):
111
debug('task_gen: posted %s',self.name)
113
def get_hook(self,ext):
114
try:return self.mappings[ext]
116
try:return task_gen.mappings[ext]
117
except KeyError:return None
118
def create_task(self,name,src=None,tgt=None,env=None):
120
task=Task.TaskBase.classes[name](env.copy(),generator=self)
124
task.set_outputs(tgt)
125
self.tasks.append(task)
127
def name_to_obj(self,name):
128
return self.bld.name_to_obj(name,self.env)
129
def find_sources_in_dirs(self,dirnames,excludes=[],exts=[]):
130
err_msg="'%s' attribute must be a list"
131
if not isinstance(excludes,list):
132
raise Utils.WscriptError(err_msg%'excludes')
133
if not isinstance(exts,list):
134
raise Utils.WscriptError(err_msg%'exts')
136
dirnames=self.to_list(dirnames)
137
ext_lst=exts or list(self.mappings.keys())+list(task_gen.mappings.keys())
138
for name in dirnames:
139
anode=self.path.find_dir(name)
140
if not anode or not anode.is_child_of(self.bld.srcnode):
141
raise Utils.WscriptError("Unable to use '%s' - either because it's not a relative path"", or it's not child of '%s'."%(name,self.bld.srcnode))
142
self.bld.rescan(anode)
143
for name in self.bld.cache_dir_contents[anode.id]:
144
if name.startswith('.'):
146
(base,ext)=os.path.splitext(name)
147
if ext in ext_lst and not name in lst and not name in excludes:
148
lst.append((anode.relpath_gen(self.path)or'.')+os.path.sep+name)
150
self.source=self.to_list(self.source)
151
if not self.source:self.source=lst
152
else:self.source+=lst
154
newobj=task_gen(bld=self.bld)
155
for x in self.__dict__:
156
if x in['env','bld']:
158
elif x in["path","features"]:
159
setattr(newobj,x,getattr(self,x))
161
setattr(newobj,x,copy.copy(getattr(self,x)))
162
newobj.__class__=self.__class__
163
if isinstance(env,str):
164
newobj.env=self.bld.all_envs[env].copy()
166
newobj.env=env.copy()
168
def get_inst_path(self):
169
return getattr(self,'_install_path',getattr(self,'default_install_path',''))
170
def set_inst_path(self,val):
171
self._install_path=val
172
install_path=property(get_inst_path,set_inst_path)
174
return getattr(self,'_chmod',getattr(self,'default_chmod',O644))
175
def set_chmod(self,val):
177
chmod=property(get_chmod,set_chmod)
178
def declare_extension(var,func):
180
for x in Utils.to_list(var):
181
task_gen.mappings[x]=func
183
raise Utils.WscriptError('declare_extension takes either a list or a string %r'%var)
184
task_gen.mapped[func.__name__]=func
185
def declare_order(*k):
191
if not f1 in task_gen.prec[f2]:
192
task_gen.prec[f2].append(f1)
193
def declare_chain(name='',action='',ext_in='',ext_out='',reentrant=True,color='BLUE',install=0,before=[],after=[],decider=None,rule=None,scan=None):
194
action=action or rule
195
if isinstance(action,str):
196
act=Task.simple_task_type(name,action,color=color)
198
act=Task.task_type_from_func(name,action,color=color)
199
act.ext_in=tuple(Utils.to_list(ext_in))
200
act.ext_out=tuple(Utils.to_list(ext_out))
201
act.before=Utils.to_list(before)
202
act.after=Utils.to_list(after)
204
def x_file(self,node):
206
ext=decider(self,node)
209
if isinstance(ext,str):
210
out_source=node.change_ext(ext)
212
self.allnodes.append(out_source)
213
elif isinstance(ext,list):
214
out_source=[node.change_ext(x)for x in ext]
216
for i in xrange((reentrant is True)and len(out_source)or reentrant):
217
self.allnodes.append(out_source[i])
219
raise Utils.WafError("do not know how to process %s"%str(ext))
220
tsk=self.create_task(name,node,out_source)
221
if node.__class__.bld.is_install:
223
declare_extension(act.ext_in,x_file)
224
def bind_feature(name,methods):
225
lst=Utils.to_list(methods)
226
task_gen.traits[name].update(lst)
228
setattr(task_gen,func.__name__,func)
232
setattr(task_gen,func.__name__,func)
234
task_gen.traits[name].update([func.__name__])
239
setattr(task_gen,func.__name__,func)
241
if not func.__name__ in task_gen.prec[fun_name]:
242
task_gen.prec[fun_name].append(func.__name__)
247
setattr(task_gen,func.__name__,func)
249
if not fun_name in task_gen.prec[func.__name__]:
250
task_gen.prec[func.__name__].append(fun_name)
255
setattr(task_gen,func.__name__,func)
257
for x in Utils.to_list(var):
258
task_gen.mappings[x]=func
260
raise Utils.WafError('extension takes either a list or a string %r'%var)
261
task_gen.mapped[func.__name__]=func
264
def apply_core(self):
265
find_resource=self.path.find_resource
266
for filename in self.to_list(self.source):
267
x=self.get_hook(filename)
271
node=find_resource(filename)
272
if not node:raise Utils.WafError("source not found: '%s' in '%s'"%(filename,str(self.path)))
273
self.allnodes.append(node)
274
for node in self.allnodes:
275
x=self.get_hook(node.suffix())
277
raise Utils.WafError("Cannot guess how to process %s (got mappings %r in %r) -> try conf.check_tool(..)?"%(str(node),self.__class__.mappings.keys(),self.__class__))
279
feature('*')(apply_core)
281
if not getattr(self,'rule',None):
284
self.meths.remove('apply_core')
289
if isinstance(func,str):
290
(func,vars2)=Task.compile_fun('',self.rule,shell=getattr(self,'shell',True))
292
vars=getattr(self,'vars',vars2)
294
if isinstance(self.rule,str):
297
vars=Utils.h_fun(self.rule)
298
name=getattr(self,'name',None)or self.target or self.rule
299
if not isinstance(name,str):
301
cls=Task.task_type_from_func(name,func,vars)
302
tsk=self.create_task(name)
303
if getattr(self,'target',None):
305
tsk.outputs=[self.path.find_or_declare(x)for x in self.to_list(self.target)]
306
if getattr(self,'source',None):
309
for x in self.to_list(self.source):
310
y=self.path.find_resource(x)
312
raise Utils.WafError('input file %r could not be found (%r)'%(x,self.path.abspath()))
315
tsk.inputs.extend(self.allnodes)
316
if getattr(self,'scan',None):
318
if getattr(self,'install_path',None):
319
tsk.install_path=self.install_path
320
if getattr(self,'cwd',None):
322
if getattr(self,'on_results',None):
323
Task.update_outputs(cls)
324
if getattr(self,'always',None):
326
for x in['after','before','ext_in','ext_out']:
327
setattr(cls,x,getattr(self,x,[]))
328
feature('*')(exec_rule)
329
before('apply_core')(exec_rule)
330
def sequence_order(self):
331
if self.meths and self.meths[-1]!='sequence_order':
332
self.meths.append('sequence_order')
334
if getattr(self,'seq_start',None):
336
if getattr(self.bld,'prev',None):
338
for x in self.bld.prev.tasks:
342
feature('seq')(sequence_order)