diff options
Diffstat (limited to 'waflib/Scripting.py')
-rw-r--r-- | waflib/Scripting.py | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/waflib/Scripting.py b/waflib/Scripting.py new file mode 100644 index 0000000..f7a3809 --- /dev/null +++ b/waflib/Scripting.py @@ -0,0 +1,403 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file + +from __future__ import with_statement +import os,shlex,shutil,traceback,errno,sys,stat +from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node +build_dir_override=None +no_climb_commands=['configure'] +default_cmd="build" +def waf_entry_point(current_directory,version,wafdir): + Logs.init_log() + if Context.WAFVERSION!=version: + Logs.error('Waf script %r and library %r do not match (directory %r)',version,Context.WAFVERSION,wafdir) + sys.exit(1) + Context.waf_dir=wafdir + Context.run_dir=Context.launch_dir=current_directory + start_dir=current_directory + no_climb=os.environ.get('NOCLIMB') + if len(sys.argv)>1: + potential_wscript=os.path.join(current_directory,sys.argv[1]) + if os.path.basename(potential_wscript)==Context.WSCRIPT_FILE and os.path.isfile(potential_wscript): + path=os.path.normpath(os.path.dirname(potential_wscript)) + start_dir=os.path.abspath(path) + no_climb=True + sys.argv.pop(1) + ctx=Context.create_context('options') + (options,commands,env)=ctx.parse_cmd_args(allow_unknown=True) + if options.top: + start_dir=Context.run_dir=Context.top_dir=options.top + no_climb=True + if options.out: + Context.out_dir=options.out + if not no_climb: + for k in no_climb_commands: + for y in commands: + if y.startswith(k): + no_climb=True + break + cur=start_dir + while cur: + try: + lst=os.listdir(cur) + except OSError: + lst=[] + Logs.error('Directory %r is unreadable!',cur) + if Options.lockfile in lst: + env=ConfigSet.ConfigSet() + try: + env.load(os.path.join(cur,Options.lockfile)) + ino=os.stat(cur)[stat.ST_INO] + except EnvironmentError: + pass + else: + for x in(env.run_dir,env.top_dir,env.out_dir): + if not x: + continue + if Utils.is_win32: + if cur==x: + load=True + break + else: + try: + ino2=os.stat(x)[stat.ST_INO] + except OSError: + pass + else: + if ino==ino2: + load=True + break + else: + Logs.warn('invalid lock file in %s',cur) + load=False + if load: + Context.run_dir=env.run_dir + Context.top_dir=env.top_dir + Context.out_dir=env.out_dir + break + if not Context.run_dir: + if Context.WSCRIPT_FILE in lst: + Context.run_dir=cur + next=os.path.dirname(cur) + if next==cur: + break + cur=next + if no_climb: + break + if not Context.run_dir: + if options.whelp: + Logs.warn('These are the generic options (no wscript/project found)') + ctx.parser.print_help() + sys.exit(0) + Logs.error('Waf: Run from a folder containing a %r file (or try -h for the generic options)',Context.WSCRIPT_FILE) + sys.exit(1) + try: + os.chdir(Context.run_dir) + except OSError: + Logs.error('Waf: The folder %r is unreadable',Context.run_dir) + sys.exit(1) + try: + set_main_module(os.path.normpath(os.path.join(Context.run_dir,Context.WSCRIPT_FILE))) + except Errors.WafError as e: + Logs.pprint('RED',e.verbose_msg) + Logs.error(str(e)) + sys.exit(1) + except Exception as e: + Logs.error('Waf: The wscript in %r is unreadable',Context.run_dir) + traceback.print_exc(file=sys.stdout) + sys.exit(2) + if options.profile: + import cProfile,pstats + cProfile.runctx('from waflib import Scripting; Scripting.run_commands()',{},{},'profi.txt') + p=pstats.Stats('profi.txt') + p.sort_stats('time').print_stats(75) + else: + try: + try: + run_commands() + except: + if options.pdb: + import pdb + type,value,tb=sys.exc_info() + traceback.print_exc() + pdb.post_mortem(tb) + else: + raise + except Errors.WafError as e: + if Logs.verbose>1: + Logs.pprint('RED',e.verbose_msg) + Logs.error(e.msg) + sys.exit(1) + except SystemExit: + raise + except Exception as e: + traceback.print_exc(file=sys.stdout) + sys.exit(2) + except KeyboardInterrupt: + Logs.pprint('RED','Interrupted') + sys.exit(68) +def set_main_module(file_path): + Context.g_module=Context.load_module(file_path) + Context.g_module.root_path=file_path + def set_def(obj): + name=obj.__name__ + if not name in Context.g_module.__dict__: + setattr(Context.g_module,name,obj) + for k in(dist,distclean,distcheck): + set_def(k) + if not'init'in Context.g_module.__dict__: + Context.g_module.init=Utils.nada + if not'shutdown'in Context.g_module.__dict__: + Context.g_module.shutdown=Utils.nada + if not'options'in Context.g_module.__dict__: + Context.g_module.options=Utils.nada +def parse_options(): + ctx=Context.create_context('options') + ctx.execute() + if not Options.commands: + Options.commands.append(default_cmd) + if Options.options.whelp: + ctx.parser.print_help() + sys.exit(0) +def run_command(cmd_name): + ctx=Context.create_context(cmd_name) + ctx.log_timer=Utils.Timer() + ctx.options=Options.options + ctx.cmd=cmd_name + try: + ctx.execute() + finally: + ctx.finalize() + return ctx +def run_commands(): + parse_options() + run_command('init') + while Options.commands: + cmd_name=Options.commands.pop(0) + ctx=run_command(cmd_name) + Logs.info('%r finished successfully (%s)',cmd_name,ctx.log_timer) + run_command('shutdown') +def distclean_dir(dirname): + for(root,dirs,files)in os.walk(dirname): + for f in files: + if f.endswith(('.o','.moc','.exe')): + fname=os.path.join(root,f) + try: + os.remove(fname) + except OSError: + Logs.warn('Could not remove %r',fname) + for x in(Context.DBFILE,'config.log'): + try: + os.remove(x) + except OSError: + pass + try: + shutil.rmtree('c4che') + except OSError: + pass +def distclean(ctx): + '''removes build folders and data''' + def remove_and_log(k,fun): + try: + fun(k) + except EnvironmentError as e: + if e.errno!=errno.ENOENT: + Logs.warn('Could not remove %r',k) + if not Options.commands: + for k in os.listdir('.'): + for x in'.waf-2 waf-2 .waf3-2 waf3-2'.split(): + if k.startswith(x): + remove_and_log(k,shutil.rmtree) + cur='.' + if ctx.options.no_lock_in_top: + cur=ctx.options.out + try: + lst=os.listdir(cur) + except OSError: + Logs.warn('Could not read %r',cur) + return + if Options.lockfile in lst: + f=os.path.join(cur,Options.lockfile) + try: + env=ConfigSet.ConfigSet(f) + except EnvironmentError: + Logs.warn('Could not read %r',f) + return + if not env.out_dir or not env.top_dir: + Logs.warn('Invalid lock file %r',f) + return + if env.out_dir==env.top_dir: + distclean_dir(env.out_dir) + else: + remove_and_log(env.out_dir,shutil.rmtree) + for k in(env.out_dir,env.top_dir,env.run_dir): + p=os.path.join(k,Options.lockfile) + remove_and_log(p,os.remove) +class Dist(Context.Context): + '''creates an archive containing the project source code''' + cmd='dist' + fun='dist' + algo='tar.bz2' + ext_algo={} + def execute(self): + self.recurse([os.path.dirname(Context.g_module.root_path)]) + self.archive() + def archive(self): + import tarfile + arch_name=self.get_arch_name() + try: + self.base_path + except AttributeError: + self.base_path=self.path + node=self.base_path.make_node(arch_name) + try: + node.delete() + except OSError: + pass + files=self.get_files() + if self.algo.startswith('tar.'): + tar=tarfile.open(node.abspath(),'w:'+self.algo.replace('tar.','')) + for x in files: + self.add_tar_file(x,tar) + tar.close() + elif self.algo=='zip': + import zipfile + zip=zipfile.ZipFile(node.abspath(),'w',compression=zipfile.ZIP_DEFLATED) + for x in files: + archive_name=self.get_base_name()+'/'+x.path_from(self.base_path) + zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED) + zip.close() + else: + self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') + try: + from hashlib import sha256 + except ImportError: + digest='' + else: + digest=' (sha256=%r)'%sha256(node.read(flags='rb')).hexdigest() + Logs.info('New archive created: %s%s',self.arch_name,digest) + def get_tar_path(self,node): + return node.abspath() + def add_tar_file(self,x,tar): + p=self.get_tar_path(x) + tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path)) + tinfo.uid=0 + tinfo.gid=0 + tinfo.uname='root' + tinfo.gname='root' + if os.path.isfile(p): + with open(p,'rb')as f: + tar.addfile(tinfo,fileobj=f) + else: + tar.addfile(tinfo) + def get_tar_prefix(self): + try: + return self.tar_prefix + except AttributeError: + return self.get_base_name() + def get_arch_name(self): + try: + self.arch_name + except AttributeError: + self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo) + return self.arch_name + def get_base_name(self): + try: + self.base_name + except AttributeError: + appname=getattr(Context.g_module,Context.APPNAME,'noname') + version=getattr(Context.g_module,Context.VERSION,'1.0') + self.base_name=appname+'-'+version + return self.base_name + def get_excl(self): + try: + return self.excl + except AttributeError: + self.excl=Node.exclude_regs+' **/waf-2.* **/.waf-2.* **/waf3-2.* **/.waf3-2.* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' + if Context.out_dir: + nd=self.root.find_node(Context.out_dir) + if nd: + self.excl+=' '+nd.path_from(self.base_path) + return self.excl + def get_files(self): + try: + files=self.files + except AttributeError: + files=self.base_path.ant_glob('**/*',excl=self.get_excl()) + return files +def dist(ctx): + '''makes a tarball for redistributing the sources''' + pass +class DistCheck(Dist): + fun='distcheck' + cmd='distcheck' + def execute(self): + self.recurse([os.path.dirname(Context.g_module.root_path)]) + self.archive() + self.check() + def make_distcheck_cmd(self,tmpdir): + cfg=[] + if Options.options.distcheck_args: + cfg=shlex.split(Options.options.distcheck_args) + else: + cfg=[x for x in sys.argv if x.startswith('-')] + cmd=[sys.executable,sys.argv[0],'configure','build','install','uninstall','--destdir='+tmpdir]+cfg + return cmd + def check(self): + import tempfile,tarfile + with tarfile.open(self.get_arch_name())as t: + for x in t: + t.extract(x) + instdir=tempfile.mkdtemp('.inst',self.get_base_name()) + cmd=self.make_distcheck_cmd(instdir) + ret=Utils.subprocess.Popen(cmd,cwd=self.get_base_name()).wait() + if ret: + raise Errors.WafError('distcheck failed with code %r'%ret) + if os.path.exists(instdir): + raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir) + shutil.rmtree(self.get_base_name()) +def distcheck(ctx): + '''checks if the project compiles (tarball from 'dist')''' + pass +def autoconfigure(execute_method): + def execute(self): + if not Configure.autoconfig: + return execute_method(self) + env=ConfigSet.ConfigSet() + do_config=False + try: + env.load(os.path.join(Context.top_dir,Options.lockfile)) + except EnvironmentError: + Logs.warn('Configuring the project') + do_config=True + else: + if env.run_dir!=Context.run_dir: + do_config=True + else: + h=0 + for f in env.files: + try: + h=Utils.h_list((h,Utils.readf(f,'rb'))) + except EnvironmentError: + do_config=True + break + else: + do_config=h!=env.hash + if do_config: + cmd=env.config_cmd or'configure' + if Configure.autoconfig=='clobber': + tmp=Options.options.__dict__ + if env.options: + Options.options.__dict__=env.options + try: + run_command(cmd) + finally: + Options.options.__dict__=tmp + else: + run_command(cmd) + run_command(self.cmd) + else: + return execute_method(self) + return execute +Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute) |