1#! /usr/bin/env python 2# encoding: utf-8 3# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file 4 5import os,shlex,shutil,traceback,errno,sys,stat 6from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node 7build_dir_override=None 8no_climb_commands=['configure'] 9default_cmd="build" 10def waf_entry_point(current_directory,version,wafdir): 11 Logs.init_log() 12 if Context.WAFVERSION!=version: 13 Logs.error('Waf script %r and library %r do not match (directory %r)',version,Context.WAFVERSION,wafdir) 14 sys.exit(1) 15 if'--version'in sys.argv: 16 Context.run_dir=current_directory 17 ctx=Context.create_context('options') 18 ctx.curdir=current_directory 19 ctx.parse_args() 20 sys.exit(0) 21 if len(sys.argv)>1: 22 potential_wscript=os.path.join(current_directory,sys.argv[1]) 23 if os.path.basename(potential_wscript)=='wscript'and os.path.isfile(potential_wscript): 24 current_directory=os.path.normpath(os.path.dirname(potential_wscript)) 25 sys.argv.pop(1) 26 Context.waf_dir=wafdir 27 Context.launch_dir=current_directory 28 no_climb=os.environ.get('NOCLIMB') 29 if not no_climb: 30 for k in no_climb_commands: 31 for y in sys.argv: 32 if y.startswith(k): 33 no_climb=True 34 break 35 for i,x in enumerate(sys.argv): 36 if x.startswith('--top='): 37 Context.run_dir=Context.top_dir=Utils.sane_path(x[6:]) 38 sys.argv[i]='--top='+Context.run_dir 39 if x.startswith('--out='): 40 Context.out_dir=Utils.sane_path(x[6:]) 41 sys.argv[i]='--out='+Context.out_dir 42 cur=current_directory 43 while cur and not Context.top_dir: 44 try: 45 lst=os.listdir(cur) 46 except OSError: 47 lst=[] 48 Logs.error('Directory %r is unreadable!',cur) 49 if Options.lockfile in lst: 50 env=ConfigSet.ConfigSet() 51 try: 52 env.load(os.path.join(cur,Options.lockfile)) 53 ino=os.stat(cur)[stat.ST_INO] 54 except EnvironmentError: 55 pass 56 else: 57 for x in(env.run_dir,env.top_dir,env.out_dir): 58 if Utils.is_win32: 59 if cur==x: 60 load=True 61 break 62 else: 63 try: 64 ino2=os.stat(x)[stat.ST_INO] 65 except OSError: 66 pass 67 else: 68 if ino==ino2: 69 load=True 70 break 71 else: 72 Logs.warn('invalid lock file in %s',cur) 73 load=False 74 if load: 75 Context.run_dir=env.run_dir 76 Context.top_dir=env.top_dir 77 Context.out_dir=env.out_dir 78 break 79 if not Context.run_dir: 80 if Context.WSCRIPT_FILE in lst: 81 Context.run_dir=cur 82 next=os.path.dirname(cur) 83 if next==cur: 84 break 85 cur=next 86 if no_climb: 87 break 88 if not Context.run_dir: 89 if'-h'in sys.argv or'--help'in sys.argv: 90 Logs.warn('No wscript file found: the help message may be incomplete') 91 Context.run_dir=current_directory 92 ctx=Context.create_context('options') 93 ctx.curdir=current_directory 94 ctx.parse_args() 95 sys.exit(0) 96 Logs.error('Waf: Run from a directory containing a file named %r',Context.WSCRIPT_FILE) 97 sys.exit(1) 98 try: 99 os.chdir(Context.run_dir) 100 except OSError: 101 Logs.error('Waf: The folder %r is unreadable',Context.run_dir) 102 sys.exit(1) 103 try: 104 set_main_module(os.path.normpath(os.path.join(Context.run_dir,Context.WSCRIPT_FILE))) 105 except Errors.WafError as e: 106 Logs.pprint('RED',e.verbose_msg) 107 Logs.error(str(e)) 108 sys.exit(1) 109 except Exception as e: 110 Logs.error('Waf: The wscript in %r is unreadable',Context.run_dir) 111 traceback.print_exc(file=sys.stdout) 112 sys.exit(2) 113 if'--profile'in sys.argv: 114 import cProfile,pstats 115 cProfile.runctx('from waflib import Scripting; Scripting.run_commands()',{},{},'profi.txt') 116 p=pstats.Stats('profi.txt') 117 p.sort_stats('time').print_stats(75) 118 else: 119 try: 120 run_commands() 121 except Errors.WafError as e: 122 if Logs.verbose>1: 123 Logs.pprint('RED',e.verbose_msg) 124 Logs.error(e.msg) 125 sys.exit(1) 126 except SystemExit: 127 raise 128 except Exception as e: 129 traceback.print_exc(file=sys.stdout) 130 sys.exit(2) 131 except KeyboardInterrupt: 132 Logs.pprint('RED','Interrupted') 133 sys.exit(68) 134def set_main_module(file_path): 135 Context.g_module=Context.load_module(file_path) 136 Context.g_module.root_path=file_path 137 def set_def(obj): 138 name=obj.__name__ 139 if not name in Context.g_module.__dict__: 140 setattr(Context.g_module,name,obj) 141 for k in(dist,distclean,distcheck): 142 set_def(k) 143 if not'init'in Context.g_module.__dict__: 144 Context.g_module.init=Utils.nada 145 if not'shutdown'in Context.g_module.__dict__: 146 Context.g_module.shutdown=Utils.nada 147 if not'options'in Context.g_module.__dict__: 148 Context.g_module.options=Utils.nada 149def parse_options(): 150 Context.create_context('options').execute() 151 for var in Options.envvars: 152 (name,value)=var.split('=',1) 153 os.environ[name.strip()]=value 154 if not Options.commands: 155 Options.commands=[default_cmd] 156 Options.commands=[x for x in Options.commands if x!='options'] 157 Logs.verbose=Options.options.verbose 158 if Options.options.zones: 159 Logs.zones=Options.options.zones.split(',') 160 if not Logs.verbose: 161 Logs.verbose=1 162 elif Logs.verbose>0: 163 Logs.zones=['runner'] 164 if Logs.verbose>2: 165 Logs.zones=['*'] 166def run_command(cmd_name): 167 ctx=Context.create_context(cmd_name) 168 ctx.log_timer=Utils.Timer() 169 ctx.options=Options.options 170 ctx.cmd=cmd_name 171 try: 172 ctx.execute() 173 finally: 174 ctx.finalize() 175 return ctx 176def run_commands(): 177 parse_options() 178 run_command('init') 179 while Options.commands: 180 cmd_name=Options.commands.pop(0) 181 ctx=run_command(cmd_name) 182 Logs.info('%r finished successfully (%s)',cmd_name,ctx.log_timer) 183 run_command('shutdown') 184def distclean_dir(dirname): 185 for(root,dirs,files)in os.walk(dirname): 186 for f in files: 187 if f.endswith(('.o','.moc','.exe')): 188 fname=os.path.join(root,f) 189 try: 190 os.remove(fname) 191 except OSError: 192 Logs.warn('Could not remove %r',fname) 193 for x in(Context.DBFILE,'config.log'): 194 try: 195 os.remove(x) 196 except OSError: 197 pass 198 try: 199 shutil.rmtree('c4che') 200 except OSError: 201 pass 202def distclean(ctx): 203 '''removes the build directory''' 204 lst=os.listdir('.') 205 for f in lst: 206 if f==Options.lockfile: 207 try: 208 proj=ConfigSet.ConfigSet(f) 209 except IOError: 210 Logs.warn('Could not read %r',f) 211 continue 212 if proj['out_dir']!=proj['top_dir']: 213 try: 214 shutil.rmtree(proj['out_dir']) 215 except EnvironmentError as e: 216 if e.errno!=errno.ENOENT: 217 Logs.warn('Could not remove %r',proj['out_dir']) 218 else: 219 distclean_dir(proj['out_dir']) 220 for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']): 221 p=os.path.join(k,Options.lockfile) 222 try: 223 os.remove(p) 224 except OSError as e: 225 if e.errno!=errno.ENOENT: 226 Logs.warn('Could not remove %r',p) 227 if not Options.commands: 228 for x in'.waf-1. waf-1. .waf3-1. waf3-1.'.split(): 229 if f.startswith(x): 230 shutil.rmtree(f,ignore_errors=True) 231class Dist(Context.Context): 232 '''creates an archive containing the project source code''' 233 cmd='dist' 234 fun='dist' 235 algo='tar.bz2' 236 ext_algo={} 237 def execute(self): 238 self.recurse([os.path.dirname(Context.g_module.root_path)]) 239 self.archive() 240 def archive(self): 241 import tarfile 242 arch_name=self.get_arch_name() 243 try: 244 self.base_path 245 except AttributeError: 246 self.base_path=self.path 247 node=self.base_path.make_node(arch_name) 248 try: 249 node.delete() 250 except OSError: 251 pass 252 files=self.get_files() 253 if self.algo.startswith('tar.'): 254 tar=tarfile.open(arch_name,'w:'+self.algo.replace('tar.','')) 255 for x in files: 256 self.add_tar_file(x,tar) 257 tar.close() 258 elif self.algo=='zip': 259 import zipfile 260 zip=zipfile.ZipFile(arch_name,'w',compression=zipfile.ZIP_DEFLATED) 261 for x in files: 262 archive_name=self.get_base_name()+'/'+x.path_from(self.base_path) 263 zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED) 264 zip.close() 265 else: 266 self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') 267 try: 268 from hashlib import sha1 269 except ImportError: 270 digest='' 271 else: 272 digest=' (sha=%r)'%sha1(node.read(flags='rb')).hexdigest() 273 Logs.info('New archive created: %s%s',self.arch_name,digest) 274 def get_tar_path(self,node): 275 return node.abspath() 276 def add_tar_file(self,x,tar): 277 p=self.get_tar_path(x) 278 tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path)) 279 tinfo.uid=0 280 tinfo.gid=0 281 tinfo.uname='root' 282 tinfo.gname='root' 283 if os.path.isfile(p): 284 fu=open(p,'rb') 285 try: 286 tar.addfile(tinfo,fileobj=fu) 287 finally: 288 fu.close() 289 else: 290 tar.addfile(tinfo) 291 def get_tar_prefix(self): 292 try: 293 return self.tar_prefix 294 except AttributeError: 295 return self.get_base_name() 296 def get_arch_name(self): 297 try: 298 self.arch_name 299 except AttributeError: 300 self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo) 301 return self.arch_name 302 def get_base_name(self): 303 try: 304 self.base_name 305 except AttributeError: 306 appname=getattr(Context.g_module,Context.APPNAME,'noname') 307 version=getattr(Context.g_module,Context.VERSION,'1.0') 308 self.base_name=appname+'-'+version 309 return self.base_name 310 def get_excl(self): 311 try: 312 return self.excl 313 except AttributeError: 314 self.excl=Node.exclude_regs+' **/waf-1.8.* **/.waf-1.8* **/waf3-1.8.* **/.waf3-1.8* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' 315 if Context.out_dir: 316 nd=self.root.find_node(Context.out_dir) 317 if nd: 318 self.excl+=' '+nd.path_from(self.base_path) 319 return self.excl 320 def get_files(self): 321 try: 322 files=self.files 323 except AttributeError: 324 files=self.base_path.ant_glob('**/*',excl=self.get_excl()) 325 return files 326def dist(ctx): 327 '''makes a tarball for redistributing the sources''' 328 pass 329class DistCheck(Dist): 330 fun='distcheck' 331 cmd='distcheck' 332 def execute(self): 333 self.recurse([os.path.dirname(Context.g_module.root_path)]) 334 self.archive() 335 self.check() 336 def check(self): 337 import tempfile,tarfile 338 try: 339 t=tarfile.open(self.get_arch_name()) 340 for x in t: 341 t.extract(x) 342 finally: 343 t.close() 344 cfg=[] 345 if Options.options.distcheck_args: 346 cfg=shlex.split(Options.options.distcheck_args) 347 else: 348 cfg=[x for x in sys.argv if x.startswith('-')] 349 instdir=tempfile.mkdtemp('.inst',self.get_base_name()) 350 ret=Utils.subprocess.Popen([sys.executable,sys.argv[0],'configure','install','uninstall','--destdir='+instdir]+cfg,cwd=self.get_base_name()).wait() 351 if ret: 352 raise Errors.WafError('distcheck failed with code %r'%ret) 353 if os.path.exists(instdir): 354 raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir) 355 shutil.rmtree(self.get_base_name()) 356def distcheck(ctx): 357 '''checks if the project compiles (tarball from 'dist')''' 358 pass 359def autoconfigure(execute_method): 360 def execute(self): 361 if not Configure.autoconfig: 362 return execute_method(self) 363 env=ConfigSet.ConfigSet() 364 do_config=False 365 try: 366 env.load(os.path.join(Context.top_dir,Options.lockfile)) 367 except EnvironmentError: 368 Logs.warn('Configuring the project') 369 do_config=True 370 else: 371 if env.run_dir!=Context.run_dir: 372 do_config=True 373 else: 374 h=0 375 for f in env.files: 376 try: 377 h=Utils.h_list((h,Utils.readf(f,'rb'))) 378 except EnvironmentError: 379 do_config=True 380 break 381 else: 382 do_config=h!=env.hash 383 if do_config: 384 cmd=env.config_cmd or'configure' 385 if Configure.autoconfig=='clobber': 386 tmp=Options.options.__dict__ 387 Options.options.__dict__=env.options 388 try: 389 run_command(cmd) 390 finally: 391 Options.options.__dict__=tmp 392 else: 393 run_command(cmd) 394 run_command(self.cmd) 395 else: 396 return execute_method(self) 397 return execute 398Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute) 399