3
# WARNING! Do not edit! http://waf.googlecode.com/svn/docs/wafbook/single.html#_obtaining_the_waf_file
5
import os,sys,errno,re,shutil
7
except:import pickle as cPickle
8
from waflib import Runner,TaskGen,Utils,ConfigSet,Task,Logs,Options,Context,Errors
11
CACHE_SUFFIX='_cache.py'
14
SAVED_ATTRS='root node_deps raw_deps task_sigs'.split()
19
class BuildContext(Context.Context):
20
'''executes the build'''
23
def __init__(self,**kw):
24
super(BuildContext,self).__init__(**kw)
26
self.top_dir=kw.get('top_dir',Context.top_dir)
27
self.run_dir=kw.get('run_dir',Context.run_dir)
28
self.post_mode=POST_AT_ONCE
29
self.out_dir=kw.get('out_dir',Context.out_dir)
30
self.cache_dir=kw.get('cache_dir',None)
31
if not self.cache_dir:
32
self.cache_dir=self.out_dir+os.sep+CACHE_DIR
37
self.cache_dir_contents={}
38
self.task_gen_cache_names={}
39
self.launch_dir=Context.launch_dir
40
self.jobs=Options.options.jobs
41
self.targets=Options.options.targets
42
self.keep=Options.options.keep
43
self.cache_global=Options.cache_global
44
self.nocache=Options.options.nocache
45
self.progress_bar=Options.options.progress_bar
46
self.deps_man=Utils.defaultdict(list)
50
def get_variant_dir(self):
53
return os.path.join(self.out_dir,self.variant)
54
variant_dir=property(get_variant_dir,None)
55
def __call__(self,*k,**kw):
57
ret=TaskGen.task_gen(*k,**kw)
58
self.task_gen_cache_names={}
59
self.add_to_group(ret,group=kw.get('group',None))
62
raise Errors.WafError('build contexts are not supposed to be copied')
63
def install_files(self,*k,**kw):
65
def install_as(self,*k,**kw):
67
def symlink_as(self,*k,**kw):
71
lst=Utils.listdir(self.cache_dir)
73
if e.errno==errno.ENOENT:
74
raise Errors.WafError('The project was not configured: run "waf configure" first!')
78
raise Errors.WafError('The cache directory is empty: reconfigure the project')
80
if fname.endswith(CACHE_SUFFIX):
81
env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,fname))
82
name=fname[:-len(CACHE_SUFFIX)]
83
self.all_envs[name]=env
84
for f in env[CFG_FILES]:
85
newnode=self.root.find_resource(f)
87
h=Utils.h_file(newnode.abspath())
88
except(IOError,AttributeError):
89
Logs.error('cannot find %r'%f)
93
if not(os.path.isabs(self.top_dir)and os.path.isabs(self.out_dir)):
94
raise Errors.WafError('The project was not configured: run "waf configure" first!')
95
self.path=self.srcnode=self.root.find_dir(self.top_dir)
96
self.bldnode=self.root.make_node(self.variant_dir)
100
if not self.all_envs:
103
def execute_build(self):
104
Logs.info("Waf: Entering directory `%s'"%self.variant_dir)
105
self.recurse([self.run_dir])
107
self.timer=Utils.Timer()
108
if self.progress_bar:
109
sys.stderr.write(Logs.colors.cursor_off)
113
if self.progress_bar==1:
114
c=len(self.returned_tasks)or 1
115
self.to_log(self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL))
118
sys.stderr.write(Logs.colors.cursor_on)
119
Logs.info("Waf: Leaving directory `%s'"%self.variant_dir)
123
env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,'build.config.py'))
124
except(IOError,OSError):
127
if env['version']<Context.HEXVERSION:
128
raise Errors.WafError('Version mismatch! reconfigure the project')
129
for t in env['tools']:
134
f=open(os.path.join(self.variant_dir,Context.DBFILE),'rb')
135
except(IOError,EOFError):
136
Logs.debug('build: could not load the build cache (missing)')
139
waflib.Node.pickle_lock.acquire()
140
waflib.Node.Nod3=self.node_class
144
Logs.debug('build: could not load the build cache %r'%e)
146
for x in SAVED_ATTRS:
147
setattr(self,x,data[x])
149
waflib.Node.pickle_lock.release()
156
for x in SAVED_ATTRS:
157
data[x]=getattr(self,x)
158
db=os.path.join(self.variant_dir,Context.DBFILE)
160
waflib.Node.pickle_lock.acquire()
161
waflib.Node.Nod3=self.node_class
164
f=open(db+'.tmp','wb')
170
waflib.Node.pickle_lock.release()
174
if not Utils.is_win32:
175
os.chown(db+'.tmp',st.st_uid,st.st_gid)
176
except(AttributeError,OSError):
178
os.rename(db+'.tmp',db)
180
Logs.debug('build: compile()')
181
self.producer=Runner.Parallel(self,self.jobs)
182
self.producer.biter=self.get_build_iterator()
183
self.returned_tasks=[]
185
self.producer.start()
186
except KeyboardInterrupt:
190
if self.producer.dirty:
192
if self.producer.error:
193
raise Errors.BuildError(self.producer.error)
194
def setup(self,tool,tooldir=None,funs=None):
195
if isinstance(tool,list):
196
for i in tool:self.setup(i,tooldir)
198
module=Context.load_tool(tool,tooldir)
199
if hasattr(module,"setup"):module.setup(self)
202
return self.all_envs[self.variant]
204
return self.all_envs['']
205
def set_env(self,val):
206
self.all_envs[self.variant]=val
207
env=property(get_env,set_env)
208
def add_manual_dependency(self,path,value):
209
if isinstance(path,waflib.Node.Node):
211
elif os.path.isabs(path):
212
node=self.root.find_resource(path)
214
node=self.path.find_resource(path)
215
self.deps_man[id(node)].append(value)
216
def launch_node(self):
219
except AttributeError:
220
self.p_ln=self.root.find_dir(self.launch_dir)
222
def hash_env_vars(self,env,vars_lst):
227
idx=str(id(env))+str(vars_lst)
230
except AttributeError:
231
cache=self.cache_env={}
234
return self.cache_env[idx]
237
lst=[env[a]for a in vars_lst]
238
ret=Utils.h_list(lst)
239
Logs.debug('envhash: %r %r',ret,lst)
242
def get_tgen_by_name(self,name):
243
cache=self.task_gen_cache_names
245
for g in self.groups:
249
except AttributeError:
254
raise Errors.WafError('Could not find a task generator for the name %r'%name)
255
def progress_line(self,state,total,col1,col2):
258
ind=Utils.rot_chr[Utils.rot_idx%4]
259
pc=(100.*state)/total
261
fs="[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s]["%(n,n,ind)
262
left=fs%(state,total,col1,pc,col2)
263
right='][%s%s%s]'%(col1,eta,col2)
264
cols=Logs.get_term_cols()-len(left)-len(right)+2*len(col1)+2*len(col2)
266
ratio=((cols*state)//total)-1
267
bar=('='*ratio+'>').ljust(cols)
268
msg=Utils.indicator%(left,bar,right)
270
def declare_chain(self,*k,**kw):
271
return TaskGen.declare_chain(*k,**kw)
273
for m in getattr(self,'pre_funs',[]):
275
def post_build(self):
276
for m in getattr(self,'post_funs',[]):
278
def add_pre_fun(self,meth):
280
self.pre_funs.append(meth)
281
except AttributeError:
283
def add_post_fun(self,meth):
285
self.post_funs.append(meth)
286
except AttributeError:
287
self.post_funs=[meth]
288
def get_group(self,x):
292
return self.groups[self.current_group]
293
if x in self.group_names:
294
return self.group_names[x]
295
return self.groups[x]
296
def add_to_group(self,tgen,group=None):
297
assert(isinstance(tgen,TaskGen.task_gen)or isinstance(tgen,Task.TaskBase))
299
self.get_group(group).append(tgen)
300
def get_group_name(self,g):
301
if not isinstance(g,list):
303
for x in self.group_names:
304
if id(self.group_names[x])==id(g):
307
def get_group_idx(self,tg):
309
for i in range(len(self.groups)):
310
for t in self.groups[i]:
314
def add_group(self,name=None,move=True):
315
if name and name in self.group_names:
316
Logs.error('add_group: name %s already present'%name)
318
self.group_names[name]=g
319
self.groups.append(g)
321
self.current_group=len(self.groups)-1
322
def set_group(self,idx):
323
if isinstance(idx,str):
324
g=self.group_names[idx]
325
for i in range(len(self.groups)):
326
if id(g)==id(self.groups[i]):
329
self.current_group=idx
332
for group in self.groups:
336
except AttributeError:
339
def get_targets(self):
342
for name in self.targets.split(','):
343
tg=self.get_tgen_by_name(name)
345
raise Errors.WafError('target %r does not exist'%name)
346
m=self.get_group_idx(tg)
352
return(min_grp,to_post)
353
def post_group(self):
354
if self.targets=='*':
355
for tg in self.groups[self.cur]:
358
except AttributeError:
363
if self.cur<self._min_grp:
364
for tg in self.groups[self.cur]:
367
except AttributeError:
372
for tg in self._exact_tg:
375
ln=self.launch_node()
376
for tg in self.groups[self.cur]:
379
except AttributeError:
382
if tg.path.is_child_of(ln):
384
def get_tasks_group(self,idx):
386
for tg in self.groups[idx]:
387
if isinstance(tg,Task.TaskBase):
390
tasks.extend(tg.tasks)
392
def get_build_iterator(self):
394
if self.targets and self.targets!='*':
395
(self._min_grp,self._exact_tg)=self.get_targets()
397
if self.post_mode!=POST_LAZY:
398
while self.cur<len(self.groups):
402
while self.cur<len(self.groups):
403
if self.post_mode!=POST_AT_ONCE:
405
tasks=self.get_tasks_group(self.cur)
406
Task.set_file_constraints(tasks)
407
Task.set_precedence_constraints(tasks)
415
class inst(Task.Task):
419
for x in self.source:
420
if isinstance(x,waflib.Node.Node):
423
y=self.path.find_resource(x)
425
idx=self.generator.bld.get_group_idx(self)
426
for tg in self.generator.bld.groups[idx]:
427
if not isinstance(tg,inst)and id(tg)!=id(self):
429
y=self.path.find_resource(x)
433
raise Errors.WafError('could not find %r in %r'%(x,self.path))
436
def runnable_status(self):
437
ret=super(inst,self).runnable_status()
438
if ret==Task.SKIP_ME:
444
return self.generator.exec_task()
445
def get_install_path(self,destdir=True):
446
dest=Utils.subst_vars(self.dest,self.env)
447
dest=dest.replace('/',os.sep)
448
if destdir and Options.options.destdir:
449
dest=os.path.join(Options.options.destdir,os.path.splitdrive(dest)[1].lstrip(os.sep))
451
def exec_install_files(self):
452
destpath=self.get_install_path()
454
raise Errors.WafError('unknown installation path %r'%self.generator)
455
for x,y in zip(self.source,self.inputs):
456
if self.relative_trick:
457
destfile=os.path.join(destpath,y.path_from(self.path))
458
Utils.check_dir(os.path.dirname(destfile))
460
destfile=os.path.join(destpath,y.name)
461
self.generator.bld.do_install(y.abspath(),destfile,self.chmod)
462
def exec_install_as(self):
463
destfile=self.get_install_path()
464
self.generator.bld.do_install(self.inputs[0].abspath(),destfile,self.chmod)
465
def exec_symlink_as(self):
466
destfile=self.get_install_path()
467
self.generator.bld.do_link(self.link,destfile)
468
class InstallContext(BuildContext):
469
'''installs the targets on the system'''
471
def __init__(self,**kw):
472
super(InstallContext,self).__init__(**kw)
474
self.is_install=INSTALL
475
def do_install(self,src,tgt,chmod=Utils.O644):
476
d,_=os.path.split(tgt)
478
raise Errors.WafError('Invalid installation given %r->%r'%(src,tgt))
480
srclbl=src.replace(self.srcnode.abspath()+os.sep,'')
481
if not Options.options.force:
488
if st1.st_mtime+2>=st2.st_mtime and st1.st_size==st2.st_size:
489
if not self.progress_bar:
490
Logs.info('- install %s (from %s)'%(tgt,srclbl))
492
if not self.progress_bar:
493
Logs.info('+ install %s (from %s)'%(tgt,srclbl))
499
shutil.copy2(src,tgt)
504
except(OSError,IOError):
505
Logs.error('File %r does not exist'%src)
506
raise Errors.WafError('Could not install the file %r'%tgt)
507
def do_link(self,src,tgt):
508
d,_=os.path.split(tgt)
511
if not os.path.islink(tgt):
513
elif os.readlink(tgt)!=src:
518
if not self.progress_bar:
519
Logs.info('+ symlink %s (to %s)'%(tgt,src))
522
if not self.progress_bar:
523
Logs.info('- symlink %s (to %s)'%(tgt,src))
524
def run_task_now(self,tsk,postpone):
527
if tsk.runnable_status()==Task.ASK_LATER:
528
raise self.WafError('cannot post the task %r'%tsk)
530
def install_files(self,dest,files,env=None,chmod=Utils.O644,relative_trick=False,cwd=None,add=True,postpone=True):
531
tsk=inst(env=env or self.env)
533
tsk.path=cwd or self.path
535
if isinstance(files,waflib.Node.Node):
538
tsk.source=Utils.to_list(files)
540
tsk.exec_task=tsk.exec_install_files
541
tsk.relative_trick=relative_trick
542
if add:self.add_to_group(tsk)
543
self.run_task_now(tsk,postpone)
545
def install_as(self,dest,srcfile,env=None,chmod=Utils.O644,cwd=None,add=True,postpone=True):
546
tsk=inst(env=env or self.env)
548
tsk.path=cwd or self.path
552
tsk.exec_task=tsk.exec_install_as
553
if add:self.add_to_group(tsk)
554
self.run_task_now(tsk,postpone)
556
def symlink_as(self,dest,src,env=None,cwd=None,add=True,postpone=True):
559
tsk=inst(env=env or self.env)
562
tsk.path=cwd or self.path
565
tsk.exec_task=tsk.exec_symlink_as
566
if add:self.add_to_group(tsk)
567
self.run_task_now(tsk,postpone)
569
class UninstallContext(InstallContext):
570
'''removes the targets installed'''
572
def __init__(self,**kw):
573
super(UninstallContext,self).__init__(**kw)
574
self.is_install=UNINSTALL
575
def do_install(self,src,tgt,chmod=Utils.O644):
576
if not self.progress_bar:
577
Logs.info('- remove %s'%tgt)
578
self.uninstall.append(tgt)
582
if e.errno!=errno.ENOENT:
583
if not getattr(self,'uninstall_error',None):
584
self.uninstall_error=True
585
Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)')
587
Logs.warn('could not remove %s (error code %r)'%(e.filename,e.errno))
589
tgt=os.path.dirname(tgt)
594
def do_link(self,src,tgt):
596
if not self.progress_bar:
597
Logs.info('- unlink %s'%tgt)
602
tgt=os.path.dirname(tgt)
609
def runnable_status(self):
611
setattr(Task.Task,'runnable_status_back',Task.Task.runnable_status)
612
setattr(Task.Task,'runnable_status',runnable_status)
613
super(UninstallContext,self).execute()
615
setattr(Task.Task,'runnable_status',Task.Task.runnable_status_back)
616
class CleanContext(BuildContext):
617
'''cleans the project'''
621
if not self.all_envs:
623
self.recurse([self.run_dir])
629
Logs.debug('build: clean called')
630
if self.bldnode!=self.srcnode:
631
lst=[self.root.find_or_declare(f)for f in self.env[CFG_FILES]]
632
for n in self.bldnode.ant_glob('**/*',excl='lock* *conf_check_*/** config.log c4che/*'):
636
self.root.children={}
637
for v in'node_deps task_sigs raw_deps'.split():
639
class ListContext(BuildContext):
640
'''lists the targets to execute'''
644
if not self.all_envs:
646
self.recurse([self.run_dir])
648
self.timer=Utils.Timer()
649
for g in self.groups:
653
except AttributeError:
658
self.get_tgen_by_name('')
661
lst=list(self.task_gen_cache_names.keys())
664
Logs.pprint('GREEN',k)
665
class StepContext(BuildContext):
666
'''executes tasks in a step-by-step fashion, for debugging'''
668
def __init__(self,**kw):
669
super(StepContext,self).__init__(**kw)
670
self.files=Options.options.files
673
Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"')
674
BuildContext.compile(self)
676
for g in self.groups:
680
except AttributeError:
684
for pat in self.files.split(','):
685
matcher=self.get_matcher(pat)
686
for g in self.groups:
688
if isinstance(tg,Task.TaskBase):
694
for node in getattr(tsk,'inputs',[]):
695
if matcher(node,output=False):
698
for node in getattr(tsk,'outputs',[]):
699
if matcher(node,output=True):
704
Logs.info('%s -> %r'%(str(tsk),ret))
705
def get_matcher(self,pat):
708
if pat.startswith('in:'):
710
pat=pat.replace('in:','')
711
elif pat.startswith('out:'):
713
pat=pat.replace('out:','')
714
anode=self.root.find_node(pat)
717
if not pat.startswith('^'):
719
if not pat.endswith('$'):
721
pattern=re.compile(pat)
722
def match(node,output):
723
if output==True and not out:
725
if output==False and not inn:
730
return pattern.match(node.abspath())
732
BuildContext.store=Utils.nogc(BuildContext.store)
733
BuildContext.restore=Utils.nogc(BuildContext.restore)