~ubuntu-branches/ubuntu/wily/radare/wily

« back to all changes in this revision

Viewing changes to wafadmin/Build.py

  • Committer: Package Import Robot
  • Author(s): Sebastian Reichel
  • Date: 2012-03-28 03:05:57 UTC
  • mfrom: (2.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120328030557-f8ceougppsgihb8g
Tags: 1:1.5.2-6
fix glib includes for glib 2.32+ (Closes: #665604) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
# encoding: utf-8
 
3
import sys
 
4
if sys.hexversion < 0x020400f0: from sets import Set as set
 
5
import os,sys,cPickle,types,imp,errno,re,glob,gc,time,shutil
 
6
import Runner,TaskGen,Node,Scripting,Utils,Environment,Task,Logs,Options
 
7
from Logs import debug,error,info
 
8
from Constants import*
 
9
SAVED_ATTRS='root srcnode bldnode node_sigs node_deps raw_deps task_sigs id_nodes'.split()
 
10
g_modcache={}
 
11
bld=None
 
12
class BuildError(Utils.WafError):
 
13
        def __init__(self,b=None,t=[]):
 
14
                self.bld=b
 
15
                self.tasks=t
 
16
                self.ret=1
 
17
                Utils.WafError.__init__(self,self.format_error())
 
18
        def format_error(self):
 
19
                lst=['Build failed']
 
20
                for tsk in self.tasks:
 
21
                        txt=tsk.format_error()
 
22
                        if txt:lst.append(txt)
 
23
                return'\n'.join(lst)
 
24
class BuildContext(object):
 
25
        def __init__(self):
 
26
                global bld
 
27
                bld=self
 
28
                self.task_manager=Task.TaskManager()
 
29
                self.id_nodes=0
 
30
                self.all_envs={}
 
31
                self.bdir=''
 
32
                self.path=None
 
33
                self.cache_node_abspath={}
 
34
                self.cache_scanned_folders={}
 
35
                self.uninstall=[]
 
36
                for v in'cache_node_abspath task_sigs node_deps raw_deps node_sigs'.split():
 
37
                        var={}
 
38
                        setattr(self,v,var)
 
39
                self.cache_dir_contents={}
 
40
                self.all_task_gen=[]
 
41
                self.task_gen_cache_names={}
 
42
                self.cache_sig_vars={}
 
43
                self.log=None
 
44
                self.root=None
 
45
                self.srcnode=None
 
46
                self.bldnode=None
 
47
        def load(self):
 
48
                code=''
 
49
                try:
 
50
                        file=open(os.path.join(self.cachedir,'build.config.py'),'r')
 
51
                        code=file.read()
 
52
                        file.close()
 
53
                except(IOError,OSError):
 
54
                        pass
 
55
                else:
 
56
                        re_imp=re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$',re.M)
 
57
                        for m in re_imp.finditer(code):
 
58
                                g=m.group
 
59
                                if g(2)=='version':
 
60
                                        if eval(g(3))<HEXVERSION:
 
61
                                                raise Utils.WafError('Version mismatch! reconfigure the project')
 
62
                                elif g(2)=='tools':
 
63
                                        lst=eval(g(3))
 
64
                                        for t in lst:
 
65
                                                self.setup(**t)
 
66
                gc.disable()
 
67
                try:
 
68
                        file=open(os.path.join(self.bdir,DBFILE),'rb')
 
69
                        data=cPickle.load(file)
 
70
                        file.close()
 
71
                except(IOError,EOFError):
 
72
                        debug('build: Build cache loading failed')
 
73
                else:
 
74
                        for x in SAVED_ATTRS:setattr(self,x,data[x])
 
75
                gc.enable()
 
76
        def save(self):
 
77
                gc.disable()
 
78
                file=open(os.path.join(self.bdir,DBFILE),'wb')
 
79
                data={}
 
80
                for x in SAVED_ATTRS:data[x]=getattr(self,x)
 
81
                cPickle.dump(data,file,-1)
 
82
                file.close()
 
83
                gc.enable()
 
84
        def clean(self):
 
85
                debug('build: clean called')
 
86
                def clean_rec(node):
 
87
                        for x in node.childs.keys():
 
88
                                nd=node.childs[x]
 
89
                                tp=nd.id&3
 
90
                                if tp==Node.DIR:
 
91
                                        clean_rec(nd)
 
92
                                elif tp==Node.BUILD:
 
93
                                        for env in self.all_envs.values():
 
94
                                                pt=nd.abspath(env)
 
95
                                                if pt in env['waf_config_files']:continue
 
96
                                                try:os.remove(pt)
 
97
                                                except OSError:pass
 
98
                                        node.childs.__delitem__(x)
 
99
                node=self.launch_node()or self.srcnode
 
100
                clean_rec(node)
 
101
                if node==self.srcnode:
 
102
                        for v in'node_sigs node_deps task_sigs raw_deps cache_node_abspath'.split():
 
103
                                var={}
 
104
                                setattr(self,v,var)
 
105
        def compile(self):
 
106
                debug('build: compile called')
 
107
                os.chdir(self.bdir)
 
108
                self.flush()
 
109
                self.generator=Runner.Parallel(self,Options.options.jobs)
 
110
                def dw(on=True):
 
111
                        if Options.options.progress_bar:
 
112
                                if on:sys.stdout.write(Logs.colors.cursor_on)
 
113
                                else:sys.stdout.write(Logs.colors.cursor_off)
 
114
                debug('build: executor starting')
 
115
                try:
 
116
                        dw(on=False)
 
117
                        self.generator.start()
 
118
                except KeyboardInterrupt:
 
119
                        dw()
 
120
                        os.chdir(self.srcnode.abspath())
 
121
                        self.save()
 
122
                        Utils.pprint('RED','Build interrupted')
 
123
                        if Logs.verbose>1:raise
 
124
                        else:sys.exit(68)
 
125
                except Exception:
 
126
                        dw()
 
127
                        raise
 
128
                else:
 
129
                        dw()
 
130
                        self.save()
 
131
                if self.generator.error:
 
132
                        os.chdir(self.srcnode.abspath())
 
133
                        raise BuildError(self,self.task_manager.tasks_done)
 
134
                os.chdir(self.srcnode.abspath())
 
135
        def install(self):
 
136
                debug('build: install called')
 
137
                self.flush()
 
138
                if Options.commands['uninstall']:
 
139
                        lst=[]
 
140
                        for x in self.uninstall:
 
141
                                dir=os.path.dirname(x)
 
142
                                if not dir in lst:lst.append(dir)
 
143
                        lst.sort()
 
144
                        lst.reverse()
 
145
                        nlst=[]
 
146
                        for y in lst:
 
147
                                x=y
 
148
                                while len(x)>4:
 
149
                                        if not x in nlst:nlst.append(x)
 
150
                                        x=os.path.dirname(x)
 
151
                        nlst.sort()
 
152
                        nlst.reverse()
 
153
                        for x in nlst:
 
154
                                try:os.rmdir(x)
 
155
                                except OSError:pass
 
156
        def add_subdirs(self,dirs):
 
157
                for dir in Utils.to_list(dirs):
 
158
                        if dir:Scripting.add_subdir(dir,self)
 
159
        def new_task_gen(self,*k,**kw):
 
160
                if len(k)==0:return TaskGen.task_gen()
 
161
                cls_name=k[0]
 
162
                try:cls=TaskGen.task_gen.classes[cls_name]
 
163
                except KeyError:raise Utils.WscriptError('%s is not a valid task generator -> %s'%(cls_name,[x for x in TaskGen.task_gen.classes]))
 
164
                else:return cls(*k,**kw)
 
165
        def load_envs(self):
 
166
                try:
 
167
                        lst=Utils.listdir(self.cachedir)
 
168
                except OSError,e:
 
169
                        if e.errno==errno.ENOENT:
 
170
                                raise Utils.WafError('The project was not configured: run "waf configure" first!')
 
171
                        else:
 
172
                                raise
 
173
                if not lst:
 
174
                        raise Utils.WafError('The cache directory is empty: reconfigure the project')
 
175
                for file in lst:
 
176
                        if file.endswith(CACHE_SUFFIX):
 
177
                                env=Environment.Environment()
 
178
                                env.load(os.path.join(self.cachedir,file))
 
179
                                name=file.split('.')[0]
 
180
                                self.all_envs[name]=env
 
181
                self.init_variants()
 
182
                for env in self.all_envs.values():
 
183
                        for f in env['dep_files']:
 
184
                                newnode=self.srcnode.find_or_declare(f)
 
185
                                try:
 
186
                                        hash=Utils.h_file(newnode.abspath(env))
 
187
                                except(IOError,AttributeError):
 
188
                                        error("cannot find "+f)
 
189
                                        hash=SIG_NIL
 
190
                                self.node_sigs[env.variant()][newnode.id]=hash
 
191
        def setup(self,tool,tooldir=None,funs=None):
 
192
                if type(tool)is types.ListType:
 
193
                        for i in tool:self.setup(i,tooldir)
 
194
                        return
 
195
                if not tooldir:tooldir=Options.tooldir
 
196
                file=None
 
197
                key=str((tool,tooldir))
 
198
                module=g_modcache.get(key,None)
 
199
                if not module:
 
200
                        file,name,desc=imp.find_module(tool,tooldir)
 
201
                        module=imp.load_module(tool,file,name,desc)
 
202
                        g_modcache[key]=module
 
203
                if hasattr(module,"setup"):module.setup(self)
 
204
                if file:file.close()
 
205
        def init_variants(self):
 
206
                debug('build: init variants')
 
207
                lstvariants=[]
 
208
                for env in self.all_envs.values():
 
209
                        if not env.variant()in lstvariants:
 
210
                                lstvariants.append(env.variant())
 
211
                self._variants=lstvariants
 
212
                debug('build: list of variants is %s'%str(lstvariants))
 
213
                for name in lstvariants+[0]:
 
214
                        for v in'node_sigs cache_node_abspath'.split():
 
215
                                var=getattr(self,v)
 
216
                                if not name in var:
 
217
                                        var[name]={}
 
218
        def load_dirs(self,srcdir,blddir):
 
219
                assert(os.path.isabs(srcdir))
 
220
                assert(os.path.isabs(blddir))
 
221
                self.cachedir=os.path.join(blddir,CACHE_DIR)
 
222
                if srcdir==blddir:
 
223
                        raise Utils.WafError("build dir must be different from srcdir: %s <-> %s "%(srcdir,blddir))
 
224
                self.bdir=blddir
 
225
                self.load()
 
226
                if not self.root:
 
227
                        self.root=Node.Node('',None,Node.DIR)
 
228
                if not self.srcnode:
 
229
                        self.srcnode=self.root.ensure_dir_node_from_path(srcdir)
 
230
                debug('build: srcnode is %s and srcdir %s'%(str(self.srcnode.name),srcdir))
 
231
                self.path=self.srcnode
 
232
                try:os.makedirs(blddir)
 
233
                except OSError:pass
 
234
                if not self.bldnode:
 
235
                        self.bldnode=self.root.ensure_dir_node_from_path(blddir)
 
236
                self.init_variants()
 
237
        def rescan(self,src_dir_node):
 
238
                if self.cache_scanned_folders.get(src_dir_node.id,None):return
 
239
                self.cache_scanned_folders[src_dir_node.id]=1
 
240
                if hasattr(self,'repository'):self.repository(src_dir_node)
 
241
                if sys.platform=="win32"and not src_dir_node.name:
 
242
                        return
 
243
                self.listdir_src(src_dir_node,src_dir_node.abspath())
 
244
                h1=self.srcnode.height()
 
245
                h2=src_dir_node.height()
 
246
                lst=[]
 
247
                child=src_dir_node
 
248
                while h2>h1:
 
249
                        lst.append(child.name)
 
250
                        child=child.parent
 
251
                        h2-=1
 
252
                lst.reverse()
 
253
                for variant in self._variants:
 
254
                        sub_path=os.path.join(self.bldnode.abspath(),variant,*lst)
 
255
                        try:
 
256
                                self.listdir_bld(src_dir_node,sub_path,variant)
 
257
                        except OSError:
 
258
                                dict=self.node_sigs[variant]
 
259
                                for node in src_dir_node.childs.values():
 
260
                                        if node.id in dict:
 
261
                                                dict.__delitem__(node.id)
 
262
                                        if node.id!=self.bldnode.id:
 
263
                                                src_dir_node.childs.__delitem__(node.name)
 
264
                                os.makedirs(sub_path)
 
265
        def listdir_src(self,parent_node,path):
 
266
                listed_files=set(Utils.listdir(path))
 
267
                self.cache_dir_contents[parent_node.id]=listed_files
 
268
                debug('build: folder contents '+str(listed_files))
 
269
                node_names=set([x.name for x in parent_node.childs.values()if x.id&3==Node.FILE])
 
270
                cache=self.node_sigs[0]
 
271
                to_keep=listed_files&node_names
 
272
                for x in to_keep:
 
273
                        node=parent_node.childs[x]
 
274
                        try:
 
275
                                cache[node.id]=Utils.h_file(path+os.sep+node.name)
 
276
                        except IOError:
 
277
                                raise Utils.WafError("The file %s is not readable or has become a dir"%node.abspath())
 
278
                to_remove=node_names-listed_files
 
279
                if to_remove:
 
280
                        cache=self.node_sigs[0]
 
281
                        for name in to_remove:
 
282
                                nd=parent_node.childs[name]
 
283
                                if nd.id in cache:
 
284
                                        cache.__delitem__(nd.id)
 
285
                                parent_node.childs.__delitem__(name)
 
286
        def listdir_bld(self,parent_node,path,variant):
 
287
                i_existing_nodes=[x for x in parent_node.childs.values()if x.id&3==Node.BUILD]
 
288
                listed_files=set(Utils.listdir(path))
 
289
                node_names=set([x.name for x in i_existing_nodes])
 
290
                remove_names=node_names-listed_files
 
291
                ids_to_remove=[x.id for x in i_existing_nodes if x.name in remove_names]
 
292
                cache=self.node_sigs[variant]
 
293
                for nid in ids_to_remove:
 
294
                        if nid in cache:
 
295
                                cache.__delitem__(nid)
 
296
        def get_env(self):
 
297
                return self.env_of_name('default')
 
298
        def set_env(self,name,val):
 
299
                self.all_envs[name]=val
 
300
        env=property(get_env,set_env)
 
301
        def add_manual_dependency(self,path,value):
 
302
                h=getattr(self,'deps_man',{})
 
303
                if os.path.isabs(path):
 
304
                        node=self.root.find_resource(path)
 
305
                else:
 
306
                        node=self.path.find_resource(path)
 
307
                h[node]=value
 
308
                self.deps_man=h
 
309
        def launch_node(self):
 
310
                try:
 
311
                        return self.p_ln
 
312
                except AttributeError:
 
313
                        self.p_ln=self.root.find_dir(Options.launch_dir)
 
314
                        return self.p_ln
 
315
        def glob(self,pattern,relative=True):
 
316
                path=self.path.abspath()
 
317
                files=[self.root.find_resource(x)for x in glob.glob(path+os.sep+pattern)]
 
318
                if relative:
 
319
                        files=[x.path_to_parent(self.path)for x in files if x]
 
320
                else:
 
321
                        files=[x.abspath()for x in files if x]
 
322
                return files
 
323
        def add_group(self):
 
324
                self.flush(all=0)
 
325
                self.task_manager.add_group()
 
326
        def hash_env_vars(self,env,vars_lst):
 
327
                idx=str(id(env))+str(vars_lst)
 
328
                try:return self.cache_sig_vars[idx]
 
329
                except KeyError:pass
 
330
                lst=[env.get_flat(a)for a in vars_lst]
 
331
                ret=Utils.h_list(lst)
 
332
                debug("envhash: %s %s"%(ret.encode('hex'),str(lst)))
 
333
                self.cache_sig_vars[idx]=ret
 
334
                return ret
 
335
        def name_to_obj(self,name):
 
336
                cache=self.task_gen_cache_names
 
337
                if not cache:
 
338
                        for x in self.all_task_gen:
 
339
                                if x.name:
 
340
                                        cache[x.name]=x
 
341
                                elif not self.task_gen_cache_names.get(x,''):
 
342
                                        cache[x.target]=x
 
343
                return cache.get(name,None)
 
344
        def flush(self,all=1):
 
345
                self.ini=time.time()
 
346
                self.task_gen_cache_names={}
 
347
                self.name_to_obj('')
 
348
                debug('build: delayed operation TaskGen.flush() called')
 
349
                if Options.options.compile_targets:
 
350
                        debug('task_gen: posting objects listed in compile_targets')
 
351
                        targets_objects={}
 
352
                        for target_name in Options.options.compile_targets.split(','):
 
353
                                target_name=target_name.strip()
 
354
                                targets_objects[target_name]=self.name_to_obj(target_name)
 
355
                                if all and not targets_objects[target_name]:raise Utils.WafError("target '%s' does not exist"%target_name)
 
356
                        for target_obj in targets_objects.values():
 
357
                                if target_obj:
 
358
                                        target_obj.post()
 
359
                else:
 
360
                        debug('task_gen: posting objects (normal)')
 
361
                        ln=self.launch_node()
 
362
                        if ln.is_child_of(self.bldnode)or not ln.is_child_of(self.srcnode):
 
363
                                ln=self.srcnode
 
364
                        for obj in self.all_task_gen:
 
365
                                if not obj.path.is_child_of(ln):continue
 
366
                                obj.post()
 
367
        def env_of_name(self,name):
 
368
                if not name:
 
369
                        error('env_of_name called with no name!')
 
370
                        return None
 
371
                try:
 
372
                        return self.all_envs[name]
 
373
                except KeyError:
 
374
                        error('no such environment: '+name)
 
375
                        return None
 
376
        def progress_line(self,state,total,col1,col2):
 
377
                n=len(str(total))
 
378
                Utils.rot_idx+=1
 
379
                ind=Utils.rot_chr[Utils.rot_idx%4]
 
380
                ini=self.ini
 
381
                pc=(100.*state)/total
 
382
                eta=time.strftime('%H:%M:%S',time.gmtime(time.time()-ini))
 
383
                fs="[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s]["%(n,n,ind)
 
384
                left=fs%(state,total,col1,pc,col2)
 
385
                right='][%s%s%s]'%(col1,eta,col2)
 
386
                cols=Utils.get_term_cols()-len(left)-len(right)+2*len(col1)+2*len(col2)
 
387
                if cols<7:cols=7
 
388
                ratio=int((cols*state)/total)-1
 
389
                bar=('='*ratio+'>').ljust(cols)
 
390
                msg=Utils.indicator%(left,bar,right)
 
391
                return msg
 
392
        def do_install(self,src,tgt,chmod=0644):
 
393
                if Options.commands['install']:
 
394
                        if not Options.options.force:
 
395
                                try:
 
396
                                        t1=os.stat(tgt).st_mtime
 
397
                                        t2=os.stat(src).st_mtime
 
398
                                except OSError:
 
399
                                        pass
 
400
                                else:
 
401
                                        if t1>=t2:
 
402
                                                return False
 
403
                        srclbl=src.replace(self.srcnode.abspath(None)+os.sep,'')
 
404
                        info("* installing %s as %s"%(srclbl,tgt))
 
405
                        try:os.remove(tgt)
 
406
                        except OSError:pass
 
407
                        try:
 
408
                                shutil.copy2(src,tgt)
 
409
                                os.chmod(tgt,chmod)
 
410
                        except IOError:
 
411
                                try:
 
412
                                        os.stat(src)
 
413
                                except IOError:
 
414
                                        error('File %r does not exist'%src)
 
415
                                raise Utils.WafError('Could not install the file %r'%tgt)
 
416
                        return True
 
417
                elif Options.commands['uninstall']:
 
418
                        info("* uninstalling %s"%tgt)
 
419
                        self.uninstall.append(tgt)
 
420
                        try:os.remove(tgt)
 
421
                        except OSError:pass
 
422
                        return True
 
423
        def get_install_path(self,path,env=None):
 
424
                if not env:env=self.env
 
425
                destdir=env.get_destdir()
 
426
                destpath=Utils.subst_vars(path,env)
 
427
                if destdir:
 
428
                        destpath=os.path.join(destdir,destpath.lstrip(os.sep))
 
429
                return destpath
 
430
        def install_files(self,path,files,env=None,chmod=0644,relative_trick=False):
 
431
                if not Options.is_install:return[]
 
432
                if not path:return[]
 
433
                node=self.path
 
434
                if type(files)is types.StringType and'*'in files:
 
435
                        gl=node.abspath()+os.sep+files
 
436
                        lst=glob.glob(gl)
 
437
                else:
 
438
                        lst=Utils.to_list(files)
 
439
                env=env or self.env
 
440
                destpath=self.get_install_path(path,env)
 
441
                Utils.check_dir(destpath)
 
442
                installed_files=[]
 
443
                for filename in lst:
 
444
                        if not os.path.isabs(filename):
 
445
                                nd=node.find_resource(filename)
 
446
                                if not nd:
 
447
                                        raise Utils.WafError("Unable to install the file `%s': not found in %s"%(filename,node))
 
448
                                if relative_trick:
 
449
                                        destfile=os.path.join(destpath,filename)
 
450
                                        Utils.check_dir(os.path.dirname(destfile))
 
451
                                else:
 
452
                                        destfile=os.path.join(destpath,nd.name)
 
453
                                filename=nd.abspath(env)
 
454
                        else:
 
455
                                alst=Utils.split_path(filename)
 
456
                                destfile=os.path.join(destpath,alst[-1])
 
457
                        if self.do_install(filename,destfile,chmod):
 
458
                                installed_files.append(destfile)
 
459
                return installed_files
 
460
        def install_as(self,path,srcfile,env=None,chmod=0644):
 
461
                if not Options.is_install:return False
 
462
                if not path:return False
 
463
                if not env:env=self.env
 
464
                node=self.path
 
465
                destpath=self.get_install_path(path,env)
 
466
                dir,name=os.path.split(destpath)
 
467
                Utils.check_dir(dir)
 
468
                if not os.path.isabs(srcfile):
 
469
                        filenode=node.find_resource(srcfile)
 
470
                        src=filenode.abspath(env)
 
471
                else:
 
472
                        src=srcfile
 
473
                return self.do_install(src,destpath,chmod)
 
474
        def symlink_as(self,path,src,env=None):
 
475
                if not Options.is_install:return
 
476
                if not path:return
 
477
                tgt=self.get_install_path(path,env)
 
478
                dir,name=os.path.split(tgt)
 
479
                Utils.check_dir(dir)
 
480
                if Options.commands['install']:
 
481
                        try:
 
482
                                if not os.path.islink(tgt)or os.readlink(tgt)!=src:
 
483
                                        info("* symlink %s (-> %s)"%(tgt,src))
 
484
                                        os.symlink(src,tgt)
 
485
                                return 0
 
486
                        except OSError:
 
487
                                return 1
 
488
                elif Options.commands['uninstall']:
 
489
                        try:
 
490
                                info("* removing %s"%(tgt))
 
491
                                os.remove(tgt)
 
492
                                return 0
 
493
                        except OSError:
 
494
                                return 1
 
495