From 0fa325b040d442d9b1c268f55d85c2879fff77f1 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Fri, 13 Sep 2013 11:30:51 -0500 Subject: [PATCH] waf: unpack --- waf | Bin 90488 -> 4002 bytes waflib/Build.py | 769 ++++++++++++++++++++++++++++++++++++++++++ waflib/ConfigSet.py | 152 +++++++++ waflib/Configure.py | 317 +++++++++++++++++ waflib/Context.py | 319 ++++++++++++++++++ waflib/Errors.py | 37 ++ waflib/Logs.py | 176 ++++++++++ waflib/Node.py | 466 +++++++++++++++++++++++++ waflib/Options.py | 135 ++++++++ waflib/Runner.py | 197 +++++++++++ waflib/Scripting.py | 373 ++++++++++++++++++++ waflib/Task.py | 677 +++++++++++++++++++++++++++++++++++++ waflib/TaskGen.py | 400 ++++++++++++++++++++++ waflib/Tools/__init__.py | 4 + waflib/Tools/ar.py | 11 + waflib/Tools/asm.py | 25 ++ waflib/Tools/bison.py | 28 ++ waflib/Tools/c.py | 24 ++ waflib/Tools/c_aliases.py | 55 +++ waflib/Tools/c_config.py | 728 +++++++++++++++++++++++++++++++++++++++ waflib/Tools/c_osx.py | 120 +++++++ waflib/Tools/c_preproc.py | 604 +++++++++++++++++++++++++++++++++ waflib/Tools/c_tests.py | 153 +++++++++ waflib/Tools/ccroot.py | 391 +++++++++++++++++++++ waflib/Tools/compiler_c.py | 39 +++ waflib/Tools/compiler_cxx.py | 39 +++ waflib/Tools/compiler_d.py | 29 ++ waflib/Tools/compiler_fc.py | 43 +++ waflib/Tools/cs.py | 132 ++++++++ waflib/Tools/cxx.py | 26 ++ waflib/Tools/d.py | 54 +++ waflib/Tools/d_config.py | 52 +++ waflib/Tools/d_scan.py | 133 ++++++++ waflib/Tools/dbus.py | 29 ++ waflib/Tools/dmd.py | 51 +++ waflib/Tools/errcheck.py | 161 +++++++++ waflib/Tools/fc.py | 116 +++++++ waflib/Tools/fc_config.py | 285 ++++++++++++++++ waflib/Tools/fc_scan.py | 68 ++++ waflib/Tools/flex.py | 32 ++ waflib/Tools/g95.py | 55 +++ waflib/Tools/gas.py | 12 + waflib/Tools/gcc.py | 97 ++++++ waflib/Tools/gdc.py | 36 ++ waflib/Tools/gfortran.py | 69 ++++ waflib/Tools/glib2.py | 173 ++++++++++ waflib/Tools/gnu_dirs.py | 65 ++++ waflib/Tools/gxx.py | 97 ++++++ waflib/Tools/icc.py | 30 ++ waflib/Tools/icpc.py | 29 ++ waflib/Tools/ifort.py | 49 +++ waflib/Tools/intltool.py | 77 +++++ waflib/Tools/irixcc.py | 48 +++ waflib/Tools/javaw.py | 311 +++++++++++++++++ waflib/Tools/kde4.py | 48 +++ waflib/Tools/ldc2.py | 37 ++ waflib/Tools/lua.py | 18 + waflib/Tools/msvc.py | 726 +++++++++++++++++++++++++++++++++++++++ waflib/Tools/nasm.py | 14 + waflib/Tools/perl.py | 80 +++++ waflib/Tools/python.py | 340 +++++++++++++++++++ waflib/Tools/qt4.py | 437 ++++++++++++++++++++++++ waflib/Tools/ruby.py | 103 ++++++ waflib/Tools/suncc.py | 53 +++ waflib/Tools/suncxx.py | 54 +++ waflib/Tools/tex.py | 250 ++++++++++++++ waflib/Tools/vala.py | 201 +++++++++++ waflib/Tools/waf_unit_test.py | 95 ++++++ waflib/Tools/winres.py | 85 +++++ waflib/Tools/xlc.py | 45 +++ waflib/Tools/xlcxx.py | 45 +++ waflib/Utils.py | 412 ++++++++++++++++++++++ waflib/__init__.py | 4 + waflib/ansiterm.py | 177 ++++++++++ waflib/extras/__init__.py | 4 + waflib/extras/compat15.py | 220 ++++++++++++ waflib/fixpy2.py | 53 +++ 77 files changed, 12099 insertions(+) create mode 100644 waflib/Build.py create mode 100644 waflib/ConfigSet.py create mode 100644 waflib/Configure.py create mode 100644 waflib/Context.py create mode 100644 waflib/Errors.py create mode 100644 waflib/Logs.py create mode 100644 waflib/Node.py create mode 100644 waflib/Options.py create mode 100644 waflib/Runner.py create mode 100644 waflib/Scripting.py create mode 100644 waflib/Task.py create mode 100644 waflib/TaskGen.py create mode 100644 waflib/Tools/__init__.py create mode 100644 waflib/Tools/ar.py create mode 100644 waflib/Tools/asm.py create mode 100644 waflib/Tools/bison.py create mode 100644 waflib/Tools/c.py create mode 100644 waflib/Tools/c_aliases.py create mode 100755 waflib/Tools/c_config.py create mode 100644 waflib/Tools/c_osx.py create mode 100644 waflib/Tools/c_preproc.py create mode 100644 waflib/Tools/c_tests.py create mode 100644 waflib/Tools/ccroot.py create mode 100644 waflib/Tools/compiler_c.py create mode 100644 waflib/Tools/compiler_cxx.py create mode 100644 waflib/Tools/compiler_d.py create mode 100644 waflib/Tools/compiler_fc.py create mode 100644 waflib/Tools/cs.py create mode 100644 waflib/Tools/cxx.py create mode 100644 waflib/Tools/d.py create mode 100644 waflib/Tools/d_config.py create mode 100644 waflib/Tools/d_scan.py create mode 100644 waflib/Tools/dbus.py create mode 100644 waflib/Tools/dmd.py create mode 100644 waflib/Tools/errcheck.py create mode 100644 waflib/Tools/fc.py create mode 100644 waflib/Tools/fc_config.py create mode 100644 waflib/Tools/fc_scan.py create mode 100644 waflib/Tools/flex.py create mode 100644 waflib/Tools/g95.py create mode 100644 waflib/Tools/gas.py create mode 100644 waflib/Tools/gcc.py create mode 100644 waflib/Tools/gdc.py create mode 100644 waflib/Tools/gfortran.py create mode 100644 waflib/Tools/glib2.py create mode 100644 waflib/Tools/gnu_dirs.py create mode 100644 waflib/Tools/gxx.py create mode 100644 waflib/Tools/icc.py create mode 100644 waflib/Tools/icpc.py create mode 100644 waflib/Tools/ifort.py create mode 100644 waflib/Tools/intltool.py create mode 100644 waflib/Tools/irixcc.py create mode 100644 waflib/Tools/javaw.py create mode 100644 waflib/Tools/kde4.py create mode 100644 waflib/Tools/ldc2.py create mode 100644 waflib/Tools/lua.py create mode 100644 waflib/Tools/msvc.py create mode 100644 waflib/Tools/nasm.py create mode 100644 waflib/Tools/perl.py create mode 100644 waflib/Tools/python.py create mode 100644 waflib/Tools/qt4.py create mode 100644 waflib/Tools/ruby.py create mode 100644 waflib/Tools/suncc.py create mode 100644 waflib/Tools/suncxx.py create mode 100644 waflib/Tools/tex.py create mode 100644 waflib/Tools/vala.py create mode 100644 waflib/Tools/waf_unit_test.py create mode 100644 waflib/Tools/winres.py create mode 100644 waflib/Tools/xlc.py create mode 100644 waflib/Tools/xlcxx.py create mode 100644 waflib/Utils.py create mode 100644 waflib/__init__.py create mode 100644 waflib/ansiterm.py create mode 100644 waflib/extras/__init__.py create mode 100644 waflib/extras/compat15.py create mode 100644 waflib/fixpy2.py diff --git a/waf b/waf index c55d478ff86f598a12b45baa1c9cca742395d9f1..69987d07d6fb1f685eebcec725c057e96c082089 100755 GIT binary patch delta 8 Pcmexyh;@mt delta 87175 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�Ezn@}dC% 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').ljust(cols) + msg=Utils.indicator%(left,bar,right) + return msg + def declare_chain(self,*k,**kw): + return TaskGen.declare_chain(*k,**kw) + def pre_build(self): + for m in getattr(self,'pre_funs',[]): + m(self) + def post_build(self): + for m in getattr(self,'post_funs',[]): + m(self) + def add_pre_fun(self,meth): + try: + self.pre_funs.append(meth) + except AttributeError: + self.pre_funs=[meth] + def add_post_fun(self,meth): + try: + self.post_funs.append(meth) + except AttributeError: + self.post_funs=[meth] + def get_group(self,x): + if not self.groups: + self.add_group() + if x is None: + return self.groups[self.current_group] + if x in self.group_names: + return self.group_names[x] + return self.groups[x] + def add_to_group(self,tgen,group=None): + assert(isinstance(tgen,TaskGen.task_gen)or isinstance(tgen,Task.TaskBase)) + tgen.bld=self + self.get_group(group).append(tgen) + def get_group_name(self,g): + if not isinstance(g,list): + g=self.groups[g] + for x in self.group_names: + if id(self.group_names[x])==id(g): + return x + return'' + def get_group_idx(self,tg): + se=id(tg) + for i in range(len(self.groups)): + for t in self.groups[i]: + if id(t)==se: + return i + return None + def add_group(self,name=None,move=True): + if name and name in self.group_names: + Logs.error('add_group: name %s already present'%name) + g=[] + self.group_names[name]=g + self.groups.append(g) + if move: + self.current_group=len(self.groups)-1 + def set_group(self,idx): + if isinstance(idx,str): + g=self.group_names[idx] + for i in range(len(self.groups)): + if id(g)==id(self.groups[i]): + self.current_group=i + else: + self.current_group=idx + def total(self): + total=0 + for group in self.groups: + for tg in group: + try: + total+=len(tg.tasks) + except AttributeError: + total+=1 + return total + def get_targets(self): + to_post=[] + min_grp=0 + for name in self.targets.split(','): + tg=self.get_tgen_by_name(name) + if not tg: + raise Errors.WafError('target %r does not exist'%name) + m=self.get_group_idx(tg) + if m>min_grp: + min_grp=m + to_post=[tg] + elif m==min_grp: + to_post.append(tg) + return(min_grp,to_post) + def get_all_task_gen(self): + lst=[] + for g in self.groups: + lst.extend(g) + return lst + def post_group(self): + if self.targets=='*': + for tg in self.groups[self.cur]: + try: + f=tg.post + except AttributeError: + pass + else: + f() + elif self.targets: + if self.cur%r'%(src,tgt)) + Utils.check_dir(d) + srclbl=src.replace(self.srcnode.abspath()+os.sep,'') + if not Options.options.force: + try: + st1=os.stat(tgt) + st2=os.stat(src) + except OSError: + pass + else: + if st1.st_mtime+2>=st2.st_mtime and st1.st_size==st2.st_size: + if not self.progress_bar: + Logs.info('- install %s (from %s)'%(tgt,srclbl)) + return False + if not self.progress_bar: + Logs.info('+ install %s (from %s)'%(tgt,srclbl)) + try: + os.remove(tgt) + except OSError: + pass + try: + shutil.copy2(src,tgt) + os.chmod(tgt,chmod) + except IOError: + try: + os.stat(src) + except(OSError,IOError): + Logs.error('File %r does not exist'%src) + raise Errors.WafError('Could not install the file %r'%tgt) + def do_link(self,src,tgt): + d,_=os.path.split(tgt) + Utils.check_dir(d) + link=False + if not os.path.islink(tgt): + link=True + elif os.readlink(tgt)!=src: + link=True + if link: + try:os.remove(tgt) + except OSError:pass + if not self.progress_bar: + Logs.info('+ symlink %s (to %s)'%(tgt,src)) + os.symlink(src,tgt) + else: + if not self.progress_bar: + Logs.info('- symlink %s (to %s)'%(tgt,src)) + def run_task_now(self,tsk,postpone): + tsk.post() + if not postpone: + if tsk.runnable_status()==Task.ASK_LATER: + raise self.WafError('cannot post the task %r'%tsk) + tsk.run() + def install_files(self,dest,files,env=None,chmod=Utils.O644,relative_trick=False,cwd=None,add=True,postpone=True): + tsk=inst(env=env or self.env) + tsk.bld=self + tsk.path=cwd or self.path + tsk.chmod=chmod + if isinstance(files,waflib.Node.Node): + tsk.source=[files] + else: + tsk.source=Utils.to_list(files) + tsk.dest=dest + tsk.exec_task=tsk.exec_install_files + tsk.relative_trick=relative_trick + if add:self.add_to_group(tsk) + self.run_task_now(tsk,postpone) + return tsk + def install_as(self,dest,srcfile,env=None,chmod=Utils.O644,cwd=None,add=True,postpone=True): + tsk=inst(env=env or self.env) + tsk.bld=self + tsk.path=cwd or self.path + tsk.chmod=chmod + tsk.source=[srcfile] + tsk.dest=dest + tsk.exec_task=tsk.exec_install_as + if add:self.add_to_group(tsk) + self.run_task_now(tsk,postpone) + return tsk + def symlink_as(self,dest,src,env=None,cwd=None,add=True,postpone=True,relative_trick=False): + if Utils.is_win32: + return + tsk=inst(env=env or self.env) + tsk.bld=self + tsk.dest=dest + tsk.path=cwd or self.path + tsk.source=[] + tsk.link=src + tsk.relative_trick=relative_trick + tsk.exec_task=tsk.exec_symlink_as + if add:self.add_to_group(tsk) + self.run_task_now(tsk,postpone) + return tsk +class UninstallContext(InstallContext): + '''removes the targets installed''' + cmd='uninstall' + def __init__(self,**kw): + super(UninstallContext,self).__init__(**kw) + self.is_install=UNINSTALL + def do_install(self,src,tgt,chmod=Utils.O644): + if not self.progress_bar: + Logs.info('- remove %s'%tgt) + self.uninstall.append(tgt) + try: + os.remove(tgt) + except OSError ,e: + if e.errno!=errno.ENOENT: + if not getattr(self,'uninstall_error',None): + self.uninstall_error=True + Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') + if Logs.verbose>1: + Logs.warn('Could not remove %s (error code %r)'%(e.filename,e.errno)) + while tgt: + tgt=os.path.dirname(tgt) + try: + os.rmdir(tgt) + except OSError: + break + def do_link(self,src,tgt): + try: + if not self.progress_bar: + Logs.info('- unlink %s'%tgt) + os.remove(tgt) + except OSError: + pass + while tgt: + tgt=os.path.dirname(tgt) + try: + os.rmdir(tgt) + except OSError: + break + def execute(self): + try: + def runnable_status(self): + return Task.SKIP_ME + setattr(Task.Task,'runnable_status_back',Task.Task.runnable_status) + setattr(Task.Task,'runnable_status',runnable_status) + super(UninstallContext,self).execute() + finally: + setattr(Task.Task,'runnable_status',Task.Task.runnable_status_back) +class CleanContext(BuildContext): + '''cleans the project''' + cmd='clean' + def execute(self): + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + try: + self.clean() + finally: + self.store() + def clean(self): + Logs.debug('build: clean called') + if self.bldnode!=self.srcnode: + lst=[] + for e in self.all_envs.values(): + lst.extend(self.root.find_or_declare(f)for f in e[CFG_FILES]) + for n in self.bldnode.ant_glob('**/*',excl='.lock* *conf_check_*/** config.log c4che/*',quiet=True): + if n in lst: + continue + n.delete() + self.root.children={} + for v in'node_deps task_sigs raw_deps'.split(): + setattr(self,v,{}) +class ListContext(BuildContext): + '''lists the targets to execute''' + cmd='list' + def execute(self): + self.restore() + if not self.all_envs: + self.load_envs() + self.recurse([self.run_dir]) + self.pre_build() + self.timer=Utils.Timer() + for g in self.groups: + for tg in g: + try: + f=tg.post + except AttributeError: + pass + else: + f() + try: + self.get_tgen_by_name('') + except Exception: + pass + lst=list(self.task_gen_cache_names.keys()) + lst.sort() + for k in lst: + Logs.pprint('GREEN',k) +class StepContext(BuildContext): + '''executes tasks in a step-by-step fashion, for debugging''' + cmd='step' + def __init__(self,**kw): + super(StepContext,self).__init__(**kw) + self.files=Options.options.files + def compile(self): + if not self.files: + Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') + BuildContext.compile(self) + return + targets=None + if self.targets and self.targets!='*': + targets=self.targets.split(',') + for g in self.groups: + for tg in g: + if targets and tg.name not in targets: + continue + try: + f=tg.post + except AttributeError: + pass + else: + f() + for pat in self.files.split(','): + matcher=self.get_matcher(pat) + for tg in g: + if isinstance(tg,Task.TaskBase): + lst=[tg] + else: + lst=tg.tasks + for tsk in lst: + do_exec=False + for node in getattr(tsk,'inputs',[]): + if matcher(node,output=False): + do_exec=True + break + for node in getattr(tsk,'outputs',[]): + if matcher(node,output=True): + do_exec=True + break + if do_exec: + ret=tsk.run() + Logs.info('%s -> exit %r'%(str(tsk),ret)) + def get_matcher(self,pat): + inn=True + out=True + if pat.startswith('in:'): + out=False + pat=pat.replace('in:','') + elif pat.startswith('out:'): + inn=False + pat=pat.replace('out:','') + anode=self.root.find_node(pat) + pattern=None + if not anode: + if not pat.startswith('^'): + pat='^.+?%s'%pat + if not pat.endswith('$'): + pat='%s$'%pat + pattern=re.compile(pat) + def match(node,output): + if output==True and not out: + return False + if output==False and not inn: + return False + if anode: + return anode==node + else: + return pattern.match(node.abspath()) + return match +BuildContext.store=Utils.nogc(BuildContext.store) +BuildContext.restore=Utils.nogc(BuildContext.restore) diff --git a/waflib/ConfigSet.py b/waflib/ConfigSet.py new file mode 100644 index 00000000..42ecde3e --- /dev/null +++ b/waflib/ConfigSet.py @@ -0,0 +1,152 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import copy,re,os +from waflib import Logs,Utils +re_imp=re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$',re.M) +class ConfigSet(object): + __slots__=('table','parent') + def __init__(self,filename=None): + self.table={} + if filename: + self.load(filename) + def __contains__(self,key): + if key in self.table:return True + try:return self.parent.__contains__(key) + except AttributeError:return False + def keys(self): + keys=set() + cur=self + while cur: + keys.update(cur.table.keys()) + cur=getattr(cur,'parent',None) + keys=list(keys) + keys.sort() + return keys + def __str__(self): + return"\n".join(["%r %r"%(x,self.__getitem__(x))for x in self.keys()]) + def __getitem__(self,key): + try: + while 1: + x=self.table.get(key,None) + if not x is None: + return x + self=self.parent + except AttributeError: + return[] + def __setitem__(self,key,value): + self.table[key]=value + def __delitem__(self,key): + self[key]=[] + def __getattr__(self,name): + if name in self.__slots__: + return object.__getattr__(self,name) + else: + return self[name] + def __setattr__(self,name,value): + if name in self.__slots__: + object.__setattr__(self,name,value) + else: + self[name]=value + def __delattr__(self,name): + if name in self.__slots__: + object.__delattr__(self,name) + else: + del self[name] + def derive(self): + newenv=ConfigSet() + newenv.parent=self + return newenv + def detach(self): + tbl=self.get_merged_dict() + try: + delattr(self,'parent') + except AttributeError: + pass + else: + keys=tbl.keys() + for x in keys: + tbl[x]=copy.deepcopy(tbl[x]) + self.table=tbl + def get_flat(self,key): + s=self[key] + if isinstance(s,str):return s + return' '.join(s) + def _get_list_value_for_modification(self,key): + try: + value=self.table[key] + except KeyError: + try:value=self.parent[key] + except AttributeError:value=[] + if isinstance(value,list): + value=value[:] + else: + value=[value] + else: + if not isinstance(value,list): + value=[value] + self.table[key]=value + return value + def append_value(self,var,val): + current_value=self._get_list_value_for_modification(var) + if isinstance(val,str): + val=[val] + current_value.extend(val) + def prepend_value(self,var,val): + if isinstance(val,str): + val=[val] + self.table[var]=val+self._get_list_value_for_modification(var) + def append_unique(self,var,val): + if isinstance(val,str): + val=[val] + current_value=self._get_list_value_for_modification(var) + for x in val: + if x not in current_value: + current_value.append(x) + def get_merged_dict(self): + table_list=[] + env=self + while 1: + table_list.insert(0,env.table) + try:env=env.parent + except AttributeError:break + merged_table={} + for table in table_list: + merged_table.update(table) + return merged_table + def store(self,filename): + try: + os.makedirs(os.path.split(filename)[0]) + except OSError: + pass + f=None + try: + f=open(filename,'w') + merged_table=self.get_merged_dict() + keys=list(merged_table.keys()) + keys.sort() + for k in keys: + if k!='undo_stack': + f.write('%s = %r\n'%(k,merged_table[k])) + finally: + if f: + f.close() + def load(self,filename): + tbl=self.table + code=Utils.readf(filename,m='rU') + for m in re_imp.finditer(code): + g=m.group + tbl[g(2)]=eval(g(3)) + Logs.debug('env: %s'%str(self.table)) + def update(self,d): + for k,v in d.items(): + self[k]=v + def stash(self): + orig=self.table + tbl=self.table=self.table.copy() + for x in tbl.keys(): + tbl[x]=copy.deepcopy(tbl[x]) + self.undo_stack=self.undo_stack+[orig] + def revert(self): + self.table=self.undo_stack.pop(-1) diff --git a/waflib/Configure.py b/waflib/Configure.py new file mode 100644 index 00000000..e8148d57 --- /dev/null +++ b/waflib/Configure.py @@ -0,0 +1,317 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,shlex,sys,time +from waflib import ConfigSet,Utils,Options,Logs,Context,Build,Errors +try: + from urllib import request +except ImportError: + from urllib import urlopen +else: + urlopen=request.urlopen +BREAK='break' +CONTINUE='continue' +WAF_CONFIG_LOG='config.log' +autoconfig=False +conf_template='''# project %(app)s configured on %(now)s by +# waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) +# using %(args)s +#''' +def download_check(node): + pass +def download_tool(tool,force=False,ctx=None): + for x in Utils.to_list(Context.remote_repo): + for sub in Utils.to_list(Context.remote_locs): + url='/'.join((x,sub,tool+'.py')) + try: + web=urlopen(url) + try: + if web.getcode()!=200: + continue + except AttributeError: + pass + except Exception: + continue + else: + tmp=ctx.root.make_node(os.sep.join((Context.waf_dir,'waflib','extras',tool+'.py'))) + tmp.write(web.read(),'wb') + Logs.warn('Downloaded %s from %s'%(tool,url)) + download_check(tmp) + try: + module=Context.load_tool(tool) + except Exception: + Logs.warn('The tool %s from %s is unusable'%(tool,url)) + try: + tmp.delete() + except Exception: + pass + continue + return module + raise Errors.WafError('Could not load the Waf tool') +class ConfigurationContext(Context.Context): + '''configures the project''' + cmd='configure' + error_handlers=[] + def __init__(self,**kw): + super(ConfigurationContext,self).__init__(**kw) + self.environ=dict(os.environ) + self.all_envs={} + self.top_dir=None + self.out_dir=None + self.tools=[] + self.hash=0 + self.files=[] + self.tool_cache=[] + self.setenv('') + def setenv(self,name,env=None): + if name not in self.all_envs or env: + if not env: + env=ConfigSet.ConfigSet() + self.prepare_env(env) + else: + env=env.derive() + self.all_envs[name]=env + self.variant=name + def get_env(self): + return self.all_envs[self.variant] + def set_env(self,val): + self.all_envs[self.variant]=val + env=property(get_env,set_env) + def init_dirs(self): + top=self.top_dir + if not top: + top=Options.options.top + if not top: + top=getattr(Context.g_module,Context.TOP,None) + if not top: + top=self.path.abspath() + top=os.path.abspath(top) + self.srcnode=(os.path.isabs(top)and self.root or self.path).find_dir(top) + assert(self.srcnode) + out=self.out_dir + if not out: + out=Options.options.out + if not out: + out=getattr(Context.g_module,Context.OUT,None) + if not out: + out=Options.lockfile.replace('.lock-waf_%s_'%sys.platform,'').replace('.lock-waf','') + self.bldnode=(os.path.isabs(out)and self.root or self.path).make_node(out) + self.bldnode.mkdir() + if not os.path.isdir(self.bldnode.abspath()): + conf.fatal('Could not create the build directory %s'%self.bldnode.abspath()) + def execute(self): + self.init_dirs() + self.cachedir=self.bldnode.make_node(Build.CACHE_DIR) + self.cachedir.mkdir() + path=os.path.join(self.bldnode.abspath(),WAF_CONFIG_LOG) + self.logger=Logs.make_logger(path,'cfg') + app=getattr(Context.g_module,'APPNAME','') + if app: + ver=getattr(Context.g_module,'VERSION','') + if ver: + app="%s (%s)"%(app,ver) + now=time.ctime() + pyver=sys.hexversion + systype=sys.platform + args=" ".join(sys.argv) + wafver=Context.WAFVERSION + abi=Context.ABI + self.to_log(conf_template%vars()) + self.msg('Setting top to',self.srcnode.abspath()) + self.msg('Setting out to',self.bldnode.abspath()) + if id(self.srcnode)==id(self.bldnode): + Logs.warn('Setting top == out (remember to use "update_outputs")') + elif id(self.path)!=id(self.srcnode): + if self.srcnode.is_child_of(self.path): + Logs.warn('Are you certain that you do not want to set top="." ?') + super(ConfigurationContext,self).execute() + self.store() + Context.top_dir=self.srcnode.abspath() + Context.out_dir=self.bldnode.abspath() + env=ConfigSet.ConfigSet() + env['argv']=sys.argv + env['options']=Options.options.__dict__ + env.run_dir=Context.run_dir + env.top_dir=Context.top_dir + env.out_dir=Context.out_dir + env['hash']=self.hash + env['files']=self.files + env['environ']=dict(self.environ) + if not self.env.NO_LOCK_IN_RUN: + env.store(Context.run_dir+os.sep+Options.lockfile) + if not self.env.NO_LOCK_IN_TOP: + env.store(Context.top_dir+os.sep+Options.lockfile) + if not self.env.NO_LOCK_IN_OUT: + env.store(Context.out_dir+os.sep+Options.lockfile) + def prepare_env(self,env): + if not env.PREFIX: + if Options.options.prefix or Utils.is_win32: + env.PREFIX=os.path.abspath(os.path.expanduser(Options.options.prefix)) + else: + env.PREFIX='' + if not env.BINDIR: + env.BINDIR=Utils.subst_vars('${PREFIX}/bin',env) + if not env.LIBDIR: + env.LIBDIR=Utils.subst_vars('${PREFIX}/lib',env) + def store(self): + n=self.cachedir.make_node('build.config.py') + n.write('version = 0x%x\ntools = %r\n'%(Context.HEXVERSION,self.tools)) + if not self.all_envs: + self.fatal('nothing to store in the configuration context!') + for key in self.all_envs: + tmpenv=self.all_envs[key] + tmpenv.store(os.path.join(self.cachedir.abspath(),key+Build.CACHE_SUFFIX)) + def load(self,input,tooldir=None,funs=None,download=True): + tools=Utils.to_list(input) + if tooldir:tooldir=Utils.to_list(tooldir) + for tool in tools: + mag=(tool,id(self.env),funs) + if mag in self.tool_cache: + self.to_log('(tool %s is already loaded, skipping)'%tool) + continue + self.tool_cache.append(mag) + module=None + try: + module=Context.load_tool(tool,tooldir) + except ImportError ,e: + if Options.options.download: + module=download_tool(tool,ctx=self) + if not module: + self.fatal('Could not load the Waf tool %r or download a suitable replacement from the repository (sys.path %r)\n%s'%(tool,sys.path,e)) + else: + self.fatal('Could not load the Waf tool %r from %r (try the --download option?):\n%s'%(tool,sys.path,e)) + except Exception ,e: + self.to_log('imp %r (%r & %r)'%(tool,tooldir,funs)) + self.to_log(Utils.ex_stack()) + raise + if funs is not None: + self.eval_rules(funs) + else: + func=getattr(module,'configure',None) + if func: + if type(func)is type(Utils.readf):func(self) + else:self.eval_rules(func) + self.tools.append({'tool':tool,'tooldir':tooldir,'funs':funs}) + def post_recurse(self,node): + super(ConfigurationContext,self).post_recurse(node) + self.hash=hash((self.hash,node.read('rb'))) + self.files.append(node.abspath()) + def eval_rules(self,rules): + self.rules=Utils.to_list(rules) + for x in self.rules: + f=getattr(self,x) + if not f:self.fatal("No such method '%s'."%x) + try: + f() + except Exception ,e: + ret=self.err_handler(x,e) + if ret==BREAK: + break + elif ret==CONTINUE: + continue + else: + raise + def err_handler(self,fun,error): + pass +def conf(f): + def fun(*k,**kw): + mandatory=True + if'mandatory'in kw: + mandatory=kw['mandatory'] + del kw['mandatory'] + try: + return f(*k,**kw) + except Errors.ConfigurationError: + if mandatory: + raise + setattr(ConfigurationContext,f.__name__,fun) + setattr(Build.BuildContext,f.__name__,fun) + return f +@conf +def add_os_flags(self,var,dest=None): + try:self.env.append_value(dest or var,shlex.split(self.environ[var])) + except KeyError:pass +@conf +def cmd_to_list(self,cmd): + if isinstance(cmd,str)and cmd.find(' '): + try: + os.stat(cmd) + except OSError: + return shlex.split(cmd) + else: + return[cmd] + return cmd +@conf +def check_waf_version(self,mini='1.6.99',maxi='1.8.0'): + self.start_msg('Checking for waf version in %s-%s'%(str(mini),str(maxi))) + ver=Context.HEXVERSION + if Utils.num2ver(mini)>ver: + self.fatal('waf version should be at least %r (%r found)'%(Utils.num2ver(mini),ver)) + if Utils.num2ver(maxi) %r'%(filename,path_list,var,ret)) + if not ret: + self.fatal(kw.get('errmsg','')or'Could not find the program %s'%','.join(filename)) + if var: + self.env[var]=ret + return ret +@conf +def find_perl_program(self,filename,path_list=[],var=None,environ=None,exts=''): + try: + app=self.find_program(filename,path_list=path_list,var=var,environ=environ,exts=exts) + except Exception: + self.find_program('perl',var='PERL') + app=self.find_file(filename,os.environ['PATH'].split(os.pathsep)) + if not app: + raise + if var: + self.env[var]=Utils.to_list(self.env['PERL'])+[app] + self.msg('Checking for %r'%filename,app) diff --git a/waflib/Context.py b/waflib/Context.py new file mode 100644 index 00000000..494ece2a --- /dev/null +++ b/waflib/Context.py @@ -0,0 +1,319 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,imp,sys +from waflib import Utils,Errors,Logs +import waflib.Node +HEXVERSION=0x1070900 +WAFVERSION="1.7.9" +WAFREVISION="9e92489dbc008e4abae9c147b1d63b48296797c2" +ABI=98 +DBFILE='.wafpickle-%s-%d-%d'%(sys.platform,sys.hexversion,ABI) +APPNAME='APPNAME' +VERSION='VERSION' +TOP='top' +OUT='out' +WSCRIPT_FILE='wscript' +launch_dir='' +run_dir='' +top_dir='' +out_dir='' +waf_dir='' +local_repo='' +remote_repo='http://waf.googlecode.com/git/' +remote_locs=['waflib/extras','waflib/Tools'] +g_module=None +STDOUT=1 +STDERR=-1 +BOTH=0 +classes=[] +def create_context(cmd_name,*k,**kw): + global classes + for x in classes: + if x.cmd==cmd_name: + return x(*k,**kw) + ctx=Context(*k,**kw) + ctx.fun=cmd_name + return ctx +class store_context(type): + def __init__(cls,name,bases,dict): + super(store_context,cls).__init__(name,bases,dict) + name=cls.__name__ + if name=='ctx'or name=='Context': + return + try: + cls.cmd + except AttributeError: + raise Errors.WafError('Missing command for the context class %r (cmd)'%name) + if not getattr(cls,'fun',None): + cls.fun=cls.cmd + global classes + classes.insert(0,cls) +ctx=store_context('ctx',(object,),{}) +class Context(ctx): + errors=Errors + tools={} + def __init__(self,**kw): + try: + rd=kw['run_dir'] + except KeyError: + global run_dir + rd=run_dir + class node_class(waflib.Node.Node): + pass + self.node_class=node_class + self.node_class.__module__="waflib.Node" + self.node_class.__name__="Nod3" + self.node_class.ctx=self + self.root=self.node_class('',None) + self.cur_script=None + self.path=self.root.find_dir(rd) + self.stack_path=[] + self.exec_dict={'ctx':self,'conf':self,'bld':self,'opt':self} + self.logger=None + def __hash__(self): + return id(self) + def load(self,tool_list,*k,**kw): + tools=Utils.to_list(tool_list) + path=Utils.to_list(kw.get('tooldir','')) + for t in tools: + module=load_tool(t,path) + fun=getattr(module,kw.get('name',self.fun),None) + if fun: + fun(self) + def execute(self): + global g_module + self.recurse([os.path.dirname(g_module.root_path)]) + def pre_recurse(self,node): + self.stack_path.append(self.cur_script) + self.cur_script=node + self.path=node.parent + def post_recurse(self,node): + self.cur_script=self.stack_path.pop() + if self.cur_script: + self.path=self.cur_script.parent + def recurse(self,dirs,name=None,mandatory=True,once=True): + try: + cache=self.recurse_cache + except AttributeError: + cache=self.recurse_cache={} + for d in Utils.to_list(dirs): + if not os.path.isabs(d): + d=os.path.join(self.path.abspath(),d) + WSCRIPT=os.path.join(d,WSCRIPT_FILE) + WSCRIPT_FUN=WSCRIPT+'_'+(name or self.fun) + node=self.root.find_node(WSCRIPT_FUN) + if node and(not once or node not in cache): + cache[node]=True + self.pre_recurse(node) + try: + function_code=node.read('rU') + exec(compile(function_code,node.abspath(),'exec'),self.exec_dict) + finally: + self.post_recurse(node) + elif not node: + node=self.root.find_node(WSCRIPT) + tup=(node,name or self.fun) + if node and(not once or tup not in cache): + cache[tup]=True + self.pre_recurse(node) + try: + wscript_module=load_module(node.abspath()) + user_function=getattr(wscript_module,(name or self.fun),None) + if not user_function: + if not mandatory: + continue + raise Errors.WafError('No function %s defined in %s'%(name or self.fun,node.abspath())) + user_function(self) + finally: + self.post_recurse(node) + elif not node: + if not mandatory: + continue + raise Errors.WafError('No wscript file in directory %s'%d) + def exec_command(self,cmd,**kw): + subprocess=Utils.subprocess + kw['shell']=isinstance(cmd,str) + Logs.debug('runner: %r'%cmd) + Logs.debug('runner_env: kw=%s'%kw) + if self.logger: + self.logger.info(cmd) + if'stdout'not in kw: + kw['stdout']=subprocess.PIPE + if'stderr'not in kw: + kw['stderr']=subprocess.PIPE + try: + if kw['stdout']or kw['stderr']: + p=subprocess.Popen(cmd,**kw) + (out,err)=p.communicate() + ret=p.returncode + else: + out,err=(None,None) + ret=subprocess.Popen(cmd,**kw).wait() + except Exception ,e: + raise Errors.WafError('Execution failure: %s'%str(e),ex=e) + if out: + if not isinstance(out,str): + out=out.decode(sys.stdout.encoding or'iso8859-1') + if self.logger: + self.logger.debug('out: %s'%out) + else: + sys.stdout.write(out) + if err: + if not isinstance(err,str): + err=err.decode(sys.stdout.encoding or'iso8859-1') + if self.logger: + self.logger.error('err: %s'%err) + else: + sys.stderr.write(err) + return ret + def cmd_and_log(self,cmd,**kw): + subprocess=Utils.subprocess + kw['shell']=isinstance(cmd,str) + Logs.debug('runner: %r'%cmd) + if'quiet'in kw: + quiet=kw['quiet'] + del kw['quiet'] + else: + quiet=None + if'output'in kw: + to_ret=kw['output'] + del kw['output'] + else: + to_ret=STDOUT + kw['stdout']=kw['stderr']=subprocess.PIPE + if quiet is None: + self.to_log(cmd) + try: + p=subprocess.Popen(cmd,**kw) + (out,err)=p.communicate() + except Exception ,e: + raise Errors.WafError('Execution failure: %s'%str(e),ex=e) + if not isinstance(out,str): + out=out.decode(sys.stdout.encoding or'iso8859-1') + if not isinstance(err,str): + err=err.decode(sys.stdout.encoding or'iso8859-1') + if out and quiet!=STDOUT and quiet!=BOTH: + self.to_log('out: %s'%out) + if err and quiet!=STDERR and quiet!=BOTH: + self.to_log('err: %s'%err) + if p.returncode: + e=Errors.WafError('Command %r returned %r'%(cmd,p.returncode)) + e.returncode=p.returncode + e.stderr=err + e.stdout=out + raise e + if to_ret==BOTH: + return(out,err) + elif to_ret==STDERR: + return err + return out + def fatal(self,msg,ex=None): + if self.logger: + self.logger.info('from %s: %s'%(self.path.abspath(),msg)) + try: + msg='%s\n(complete log in %s)'%(msg,self.logger.handlers[0].baseFilename) + except Exception: + pass + raise self.errors.ConfigurationError(msg,ex=ex) + def to_log(self,msg): + if not msg: + return + if self.logger: + self.logger.info(msg) + else: + sys.stderr.write(str(msg)) + sys.stderr.flush() + def msg(self,msg,result,color=None): + self.start_msg(msg) + if not isinstance(color,str): + color=result and'GREEN'or'YELLOW' + self.end_msg(result,color) + def start_msg(self,msg): + try: + if self.in_msg: + self.in_msg+=1 + return + except AttributeError: + self.in_msg=0 + self.in_msg+=1 + try: + self.line_just=max(self.line_just,len(msg)) + except AttributeError: + self.line_just=max(40,len(msg)) + for x in(self.line_just*'-',msg): + self.to_log(x) + Logs.pprint('NORMAL',"%s :"%msg.ljust(self.line_just),sep='') + def end_msg(self,result,color=None): + self.in_msg-=1 + if self.in_msg: + return + defcolor='GREEN' + if result==True: + msg='ok' + elif result==False: + msg='not found' + defcolor='YELLOW' + else: + msg=str(result) + self.to_log(msg) + Logs.pprint(color or defcolor,msg) + def load_special_tools(self,var,ban=[]): + global waf_dir + lst=self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) + for x in lst: + if not x.name in ban: + load_tool(x.name.replace('.py','')) +cache_modules={} +def load_module(path): + try: + return cache_modules[path] + except KeyError: + pass + module=imp.new_module(WSCRIPT_FILE) + try: + code=Utils.readf(path,m='rU') + except(IOError,OSError): + raise Errors.WafError('Could not read the file %r'%path) + module_dir=os.path.dirname(path) + sys.path.insert(0,module_dir) + exec(compile(code,path,'exec'),module.__dict__) + sys.path.remove(module_dir) + cache_modules[path]=module + return module +def load_tool(tool,tooldir=None): + if tool=='java': + tool='javaw' + elif tool=='compiler_cc': + tool='compiler_c' + else: + tool=tool.replace('++','xx') + if tooldir: + assert isinstance(tooldir,list) + sys.path=tooldir+sys.path + try: + __import__(tool) + ret=sys.modules[tool] + Context.tools[tool]=ret + return ret + finally: + for d in tooldir: + sys.path.remove(d) + else: + global waf_dir + try: + os.stat(os.path.join(waf_dir,'waflib','extras',tool+'.py')) + except OSError: + try: + os.stat(os.path.join(waf_dir,'waflib','Tools',tool+'.py')) + except OSError: + d=tool + else: + d='waflib.Tools.%s'%tool + else: + d='waflib.extras.%s'%tool + __import__(d) + ret=sys.modules[d] + Context.tools[tool]=ret + return ret diff --git a/waflib/Errors.py b/waflib/Errors.py new file mode 100644 index 00000000..aacc1a9f --- /dev/null +++ b/waflib/Errors.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import traceback,sys +class WafError(Exception): + def __init__(self,msg='',ex=None): + self.msg=msg + assert not isinstance(msg,Exception) + self.stack=[] + if ex: + if not msg: + self.msg=str(ex) + if isinstance(ex,WafError): + self.stack=ex.stack + else: + self.stack=traceback.extract_tb(sys.exc_info()[2]) + self.stack+=traceback.extract_stack()[:-1] + self.verbose_msg=''.join(traceback.format_list(self.stack)) + def __str__(self): + return str(self.msg) +class BuildError(WafError): + def __init__(self,error_tasks=[]): + self.tasks=error_tasks + WafError.__init__(self,self.format_error()) + def format_error(self): + lst=['Build failed'] + for tsk in self.tasks: + txt=tsk.format_error() + if txt:lst.append(txt) + return'\n'.join(lst) +class ConfigurationError(WafError): + pass +class TaskRescan(WafError): + pass +class TaskNotReady(WafError): + pass diff --git a/waflib/Logs.py b/waflib/Logs.py new file mode 100644 index 00000000..d6d4dddd --- /dev/null +++ b/waflib/Logs.py @@ -0,0 +1,176 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re,traceback,sys +try: + import threading +except ImportError: + pass +else: + wlock=threading.Lock() + class sync_stream(object): + def __init__(self,stream): + self.stream=stream + self.encoding=self.stream.encoding + def write(self,txt): + try: + wlock.acquire() + self.stream.write(txt) + self.stream.flush() + finally: + wlock.release() + def fileno(self): + return self.stream.fileno() + def flush(self): + self.stream.flush() + def isatty(self): + return self.stream.isatty() + _nocolor=os.environ.get('NOCOLOR','no')not in('no','0','false') + try: + if not _nocolor: + import waflib.ansiterm + except ImportError: + pass + if not os.environ.get('NOSYNC',False): + if id(sys.stdout)==id(sys.__stdout__): + sys.stdout=sync_stream(sys.stdout) + sys.stderr=sync_stream(sys.stderr) +import logging +LOG_FORMAT="%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s" +HOUR_FORMAT="%H:%M:%S" +zones='' +verbose=0 +colors_lst={'USE':True,'BOLD':'\x1b[01;1m','RED':'\x1b[01;31m','GREEN':'\x1b[32m','YELLOW':'\x1b[33m','PINK':'\x1b[35m','BLUE':'\x1b[01;34m','CYAN':'\x1b[36m','NORMAL':'\x1b[0m','cursor_on':'\x1b[?25h','cursor_off':'\x1b[?25l',} +got_tty=not os.environ.get('TERM','dumb')in['dumb','emacs'] +if got_tty: + try: + got_tty=sys.stderr.isatty()and sys.stdout.isatty() + except AttributeError: + got_tty=False +if(not got_tty and os.environ.get('TERM','dumb')!='msys')or _nocolor: + colors_lst['USE']=False +def get_term_cols(): + return 80 +try: + import struct,fcntl,termios +except ImportError: + pass +else: + if got_tty: + def get_term_cols_real(): + dummy_lines,cols=struct.unpack("HHHH",fcntl.ioctl(sys.stderr.fileno(),termios.TIOCGWINSZ,struct.pack("HHHH",0,0,0,0)))[:2] + return cols + try: + get_term_cols_real() + except Exception: + pass + else: + get_term_cols=get_term_cols_real +get_term_cols.__doc__=""" + Get the console width in characters. + + :return: the number of characters per line + :rtype: int + """ +def get_color(cl): + if not colors_lst['USE']:return'' + return colors_lst.get(cl,'') +class color_dict(object): + def __getattr__(self,a): + return get_color(a) + def __call__(self,a): + return get_color(a) +colors=color_dict() +re_log=re.compile(r'(\w+): (.*)',re.M) +class log_filter(logging.Filter): + def __init__(self,name=None): + pass + def filter(self,rec): + rec.c1=colors.PINK + rec.c2=colors.NORMAL + rec.zone=rec.module + if rec.levelno>=logging.INFO: + if rec.levelno>=logging.ERROR: + rec.c1=colors.RED + elif rec.levelno>=logging.WARNING: + rec.c1=colors.YELLOW + else: + rec.c1=colors.GREEN + return True + m=re_log.match(rec.msg) + if m: + rec.zone=m.group(1) + rec.msg=m.group(2) + if zones: + return getattr(rec,'zone','')in zones or'*'in zones + elif not verbose>2: + return False + return True +class formatter(logging.Formatter): + def __init__(self): + logging.Formatter.__init__(self,LOG_FORMAT,HOUR_FORMAT) + def format(self,rec): + if rec.levelno>=logging.WARNING or rec.levelno==logging.INFO: + try: + msg=rec.msg.decode('utf-8') + except Exception: + msg=rec.msg + return'%s%s%s'%(rec.c1,msg,rec.c2) + return logging.Formatter.format(self,rec) +log=None +def debug(*k,**kw): + if verbose: + k=list(k) + k[0]=k[0].replace('\n',' ') + global log + log.debug(*k,**kw) +def error(*k,**kw): + global log + log.error(*k,**kw) + if verbose>2: + st=traceback.extract_stack() + if st: + st=st[:-1] + buf=[] + for filename,lineno,name,line in st: + buf.append(' File "%s", line %d, in %s'%(filename,lineno,name)) + if line: + buf.append(' %s'%line.strip()) + if buf:log.error("\n".join(buf)) +def warn(*k,**kw): + global log + log.warn(*k,**kw) +def info(*k,**kw): + global log + log.info(*k,**kw) +def init_log(): + global log + log=logging.getLogger('waflib') + log.handlers=[] + log.filters=[] + hdlr=logging.StreamHandler() + hdlr.setFormatter(formatter()) + log.addHandler(hdlr) + log.addFilter(log_filter()) + log.setLevel(logging.DEBUG) +def make_logger(path,name): + logger=logging.getLogger(name) + hdlr=logging.FileHandler(path,'w') + formatter=logging.Formatter('%(message)s') + hdlr.setFormatter(formatter) + logger.addHandler(hdlr) + logger.setLevel(logging.DEBUG) + return logger +def make_mem_logger(name,to_log,size=10000): + from logging.handlers import MemoryHandler + logger=logging.getLogger(name) + hdlr=MemoryHandler(size,target=to_log) + formatter=logging.Formatter('%(message)s') + hdlr.setFormatter(formatter) + logger.addHandler(hdlr) + logger.memhandler=hdlr + logger.setLevel(logging.DEBUG) + return logger +def pprint(col,str,label='',sep='\n'): + sys.stderr.write("%s%s%s %s%s"%(colors(col),str,colors.NORMAL,label,sep)) diff --git a/waflib/Node.py b/waflib/Node.py new file mode 100644 index 00000000..79d6bbfc --- /dev/null +++ b/waflib/Node.py @@ -0,0 +1,466 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re,sys,shutil +from waflib import Utils,Errors +exclude_regs=''' +**/*~ +**/#*# +**/.#* +**/%*% +**/._* +**/CVS +**/CVS/** +**/.cvsignore +**/SCCS +**/SCCS/** +**/vssver.scc +**/.svn +**/.svn/** +**/BitKeeper +**/.git +**/.git/** +**/.gitignore +**/.bzr +**/.bzrignore +**/.bzr/** +**/.hg +**/.hg/** +**/_MTN +**/_MTN/** +**/.arch-ids +**/{arch} +**/_darcs +**/_darcs/** +**/.DS_Store''' +def split_path(path): + return path.split('/') +def split_path_cygwin(path): + if path.startswith('//'): + ret=path.split('/')[2:] + ret[0]='/'+ret[0] + return ret + return path.split('/') +re_sp=re.compile('[/\\\\]') +def split_path_win32(path): + if path.startswith('\\\\'): + ret=re.split(re_sp,path)[2:] + ret[0]='\\'+ret[0] + return ret + return re.split(re_sp,path) +if sys.platform=='cygwin': + split_path=split_path_cygwin +elif Utils.is_win32: + split_path=split_path_win32 +class Node(object): + __slots__=('name','sig','children','parent','cache_abspath','cache_isdir','cache_sig') + def __init__(self,name,parent): + self.name=name + self.parent=parent + if parent: + if name in parent.children: + raise Errors.WafError('node %s exists in the parent files %r already'%(name,parent)) + parent.children[name]=self + def __setstate__(self,data): + self.name=data[0] + self.parent=data[1] + if data[2]is not None: + self.children=data[2] + if data[3]is not None: + self.sig=data[3] + def __getstate__(self): + return(self.name,self.parent,getattr(self,'children',None),getattr(self,'sig',None)) + def __str__(self): + return self.name + def __repr__(self): + return self.abspath() + def __hash__(self): + return id(self) + def __eq__(self,node): + return id(self)==id(node) + def __copy__(self): + raise Errors.WafError('nodes are not supposed to be copied') + def read(self,flags='r',encoding='ISO8859-1'): + return Utils.readf(self.abspath(),flags,encoding) + def write(self,data,flags='w',encoding='ISO8859-1'): + Utils.writef(self.abspath(),data,flags,encoding) + def chmod(self,val): + os.chmod(self.abspath(),val) + def delete(self): + try: + if getattr(self,'children',None): + shutil.rmtree(self.abspath()) + else: + os.unlink(self.abspath()) + except OSError: + pass + self.evict() + def evict(self): + del self.parent.children[self.name] + def suffix(self): + k=max(0,self.name.rfind('.')) + return self.name[k:] + def height(self): + d=self + val=-1 + while d: + d=d.parent + val+=1 + return val + def listdir(self): + lst=Utils.listdir(self.abspath()) + lst.sort() + return lst + def mkdir(self): + if getattr(self,'cache_isdir',None): + return + try: + self.parent.mkdir() + except OSError: + pass + if self.name: + try: + os.makedirs(self.abspath()) + except OSError: + pass + if not os.path.isdir(self.abspath()): + raise Errors.WafError('Could not create the directory %s'%self.abspath()) + try: + self.children + except AttributeError: + self.children={} + self.cache_isdir=True + def find_node(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + cur=self + for x in lst: + if x=='..': + cur=cur.parent or cur + continue + try: + ch=cur.children + except AttributeError: + cur.children={} + else: + try: + cur=cur.children[x] + continue + except KeyError: + pass + cur=self.__class__(x,cur) + try: + os.stat(cur.abspath()) + except OSError: + cur.evict() + return None + ret=cur + try: + os.stat(ret.abspath()) + except OSError: + ret.evict() + return None + try: + while not getattr(cur.parent,'cache_isdir',None): + cur=cur.parent + cur.cache_isdir=True + except AttributeError: + pass + return ret + def make_node(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + cur=self + for x in lst: + if x=='..': + cur=cur.parent or cur + continue + if getattr(cur,'children',{}): + if x in cur.children: + cur=cur.children[x] + continue + else: + cur.children={} + cur=self.__class__(x,cur) + return cur + def search_node(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + cur=self + for x in lst: + if x=='..': + cur=cur.parent or cur + else: + try: + cur=cur.children[x] + except(AttributeError,KeyError): + return None + return cur + def path_from(self,node): + c1=self + c2=node + c1h=c1.height() + c2h=c2.height() + lst=[] + up=0 + while c1h>c2h: + lst.append(c1.name) + c1=c1.parent + c1h-=1 + while c2h>c1h: + up+=1 + c2=c2.parent + c2h-=1 + while id(c1)!=id(c2): + lst.append(c1.name) + up+=1 + c1=c1.parent + c2=c2.parent + for i in range(up): + lst.append('..') + lst.reverse() + return os.sep.join(lst)or'.' + def abspath(self): + try: + return self.cache_abspath + except AttributeError: + pass + if os.sep=='/': + if not self.parent: + val=os.sep + elif not self.parent.name: + val=os.sep+self.name + else: + val=self.parent.abspath()+os.sep+self.name + else: + if not self.parent: + val='' + elif not self.parent.name: + val=self.name+os.sep + else: + val=self.parent.abspath().rstrip(os.sep)+os.sep+self.name + self.cache_abspath=val + return val + def is_child_of(self,node): + p=self + diff=self.height()-node.height() + while diff>0: + diff-=1 + p=p.parent + return id(p)==id(node) + def ant_iter(self,accept=None,maxdepth=25,pats=[],dir=False,src=True,remove=True): + dircont=self.listdir() + dircont.sort() + try: + lst=set(self.children.keys()) + except AttributeError: + self.children={} + else: + if remove: + for x in lst-set(dircont): + self.children[x].evict() + for name in dircont: + npats=accept(name,pats) + if npats and npats[0]: + accepted=[]in npats[0] + node=self.make_node([name]) + isdir=os.path.isdir(node.abspath()) + if accepted: + if isdir: + if dir: + yield node + else: + if src: + yield node + if getattr(node,'cache_isdir',None)or isdir: + node.cache_isdir=True + if maxdepth: + for k in node.ant_iter(accept=accept,maxdepth=maxdepth-1,pats=npats,dir=dir,src=src,remove=remove): + yield k + raise StopIteration + def ant_glob(self,*k,**kw): + src=kw.get('src',True) + dir=kw.get('dir',False) + excl=kw.get('excl',exclude_regs) + incl=k and k[0]or kw.get('incl','**') + reflags=kw.get('ignorecase',0)and re.I + def to_pat(s): + lst=Utils.to_list(s) + ret=[] + for x in lst: + x=x.replace('\\','/').replace('//','/') + if x.endswith('/'): + x+='**' + lst2=x.split('/') + accu=[] + for k in lst2: + if k=='**': + accu.append(k) + else: + k=k.replace('.','[.]').replace('*','.*').replace('?','.').replace('+','\\+') + k='^%s$'%k + try: + accu.append(re.compile(k,flags=reflags)) + except Exception ,e: + raise Errors.WafError("Invalid pattern: %s"%k,e) + ret.append(accu) + return ret + def filtre(name,nn): + ret=[] + for lst in nn: + if not lst: + pass + elif lst[0]=='**': + ret.append(lst) + if len(lst)>1: + if lst[1].match(name): + ret.append(lst[2:]) + else: + ret.append([]) + elif lst[0].match(name): + ret.append(lst[1:]) + return ret + def accept(name,pats): + nacc=filtre(name,pats[0]) + nrej=filtre(name,pats[1]) + if[]in nrej: + nacc=[] + return[nacc,nrej] + ret=[x for x in self.ant_iter(accept=accept,pats=[to_pat(incl),to_pat(excl)],maxdepth=25,dir=dir,src=src,remove=kw.get('remove',True))] + if kw.get('flat',False): + return' '.join([x.path_from(self)for x in ret]) + return ret + def is_src(self): + cur=self + x=id(self.ctx.srcnode) + y=id(self.ctx.bldnode) + while cur.parent: + if id(cur)==y: + return False + if id(cur)==x: + return True + cur=cur.parent + return False + def is_bld(self): + cur=self + y=id(self.ctx.bldnode) + while cur.parent: + if id(cur)==y: + return True + cur=cur.parent + return False + def get_src(self): + cur=self + x=id(self.ctx.srcnode) + y=id(self.ctx.bldnode) + lst=[] + while cur.parent: + if id(cur)==y: + lst.reverse() + return self.ctx.srcnode.make_node(lst) + if id(cur)==x: + return self + lst.append(cur.name) + cur=cur.parent + return self + def get_bld(self): + cur=self + x=id(self.ctx.srcnode) + y=id(self.ctx.bldnode) + lst=[] + while cur.parent: + if id(cur)==y: + return self + if id(cur)==x: + lst.reverse() + return self.ctx.bldnode.make_node(lst) + lst.append(cur.name) + cur=cur.parent + lst.reverse() + if lst and Utils.is_win32 and len(lst[0])==2 and lst[0].endswith(':'): + lst[0]=lst[0][0] + return self.ctx.bldnode.make_node(['__root__']+lst) + def find_resource(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + node=self.get_bld().search_node(lst) + if not node: + self=self.get_src() + node=self.find_node(lst) + if node: + if os.path.isdir(node.abspath()): + return None + return node + def find_or_declare(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + node=self.get_bld().search_node(lst) + if node: + if not os.path.isfile(node.abspath()): + node.sig=None + node.parent.mkdir() + return node + self=self.get_src() + node=self.find_node(lst) + if node: + if not os.path.isfile(node.abspath()): + node.sig=None + node.parent.mkdir() + return node + node=self.get_bld().make_node(lst) + node.parent.mkdir() + return node + def find_dir(self,lst): + if isinstance(lst,str): + lst=[x for x in split_path(lst)if x and x!='.'] + node=self.find_node(lst) + try: + if not os.path.isdir(node.abspath()): + return None + except(OSError,AttributeError): + return None + return node + def change_ext(self,ext,ext_in=None): + name=self.name + if ext_in is None: + k=name.rfind('.') + if k>=0: + name=name[:k]+ext + else: + name=name+ext + else: + name=name[:-len(ext_in)]+ext + return self.parent.find_or_declare([name]) + def nice_path(self,env=None): + return self.path_from(self.ctx.launch_node()) + def bldpath(self): + return self.path_from(self.ctx.bldnode) + def srcpath(self): + return self.path_from(self.ctx.srcnode) + def relpath(self): + cur=self + x=id(self.ctx.bldnode) + while cur.parent: + if id(cur)==x: + return self.bldpath() + cur=cur.parent + return self.srcpath() + def bld_dir(self): + return self.parent.bldpath() + def bld_base(self): + s=os.path.splitext(self.name)[0] + return self.bld_dir()+os.sep+s + def get_bld_sig(self): + try: + return self.cache_sig + except AttributeError: + pass + if not self.is_bld()or self.ctx.bldnode is self.ctx.srcnode: + self.sig=Utils.h_file(self.abspath()) + self.cache_sig=ret=self.sig + return ret + search=search_node +pickle_lock=Utils.threading.Lock() +class Nod3(Node): + pass diff --git a/waflib/Options.py b/waflib/Options.py new file mode 100644 index 00000000..21f42543 --- /dev/null +++ b/waflib/Options.py @@ -0,0 +1,135 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,tempfile,optparse,sys,re +from waflib import Logs,Utils,Context +cmds='distclean configure build install clean uninstall check dist distcheck'.split() +options={} +commands=[] +lockfile=os.environ.get('WAFLOCK','.lock-waf_%s_build'%sys.platform) +try:cache_global=os.path.abspath(os.environ['WAFCACHE']) +except KeyError:cache_global='' +platform=Utils.unversioned_sys_platform() +class opt_parser(optparse.OptionParser): + def __init__(self,ctx): + optparse.OptionParser.__init__(self,conflict_handler="resolve",version='waf %s (%s)'%(Context.WAFVERSION,Context.WAFREVISION)) + self.formatter.width=Logs.get_term_cols() + p=self.add_option + self.ctx=ctx + jobs=ctx.jobs() + p('-j','--jobs',dest='jobs',default=jobs,type='int',help='amount of parallel jobs (%r)'%jobs) + p('-k','--keep',dest='keep',default=0,action='count',help='keep running happily even if errors are found') + p('-v','--verbose',dest='verbose',default=0,action='count',help='verbosity level -v -vv or -vvv [default: 0]') + p('--nocache',dest='nocache',default=False,action='store_true',help='ignore the WAFCACHE (if set)') + p('--zones',dest='zones',default='',action='store',help='debugging zones (task_gen, deps, tasks, etc)') + gr=optparse.OptionGroup(self,'configure options') + self.add_option_group(gr) + gr.add_option('-o','--out',action='store',default='',help='build dir for the project',dest='out') + gr.add_option('-t','--top',action='store',default='',help='src dir for the project',dest='top') + default_prefix=os.environ.get('PREFIX') + if not default_prefix: + if platform=='win32': + d=tempfile.gettempdir() + default_prefix=d[0].upper()+d[1:] + else: + default_prefix='/usr/local/' + gr.add_option('--prefix',dest='prefix',default=default_prefix,help='installation prefix [default: %r]'%default_prefix) + gr.add_option('--download',dest='download',default=False,action='store_true',help='try to download the tools if missing') + gr=optparse.OptionGroup(self,'build and install options') + self.add_option_group(gr) + gr.add_option('-p','--progress',dest='progress_bar',default=0,action='count',help='-p: progress bar; -pp: ide output') + gr.add_option('--targets',dest='targets',default='',action='store',help='task generators, e.g. "target1,target2"') + gr=optparse.OptionGroup(self,'step options') + self.add_option_group(gr) + gr.add_option('--files',dest='files',default='',action='store',help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') + default_destdir=os.environ.get('DESTDIR','') + gr=optparse.OptionGroup(self,'install/uninstall options') + self.add_option_group(gr) + gr.add_option('--destdir',help='installation root [default: %r]'%default_destdir,default=default_destdir,dest='destdir') + gr.add_option('-f','--force',dest='force',default=False,action='store_true',help='force file installation') + gr.add_option('--distcheck-args',help='arguments to pass to distcheck',default=None,action='store') + def get_usage(self): + cmds_str={} + for cls in Context.classes: + if not cls.cmd or cls.cmd=='options': + continue + s=cls.__doc__ or'' + cmds_str[cls.cmd]=s + if Context.g_module: + for(k,v)in Context.g_module.__dict__.items(): + if k in['options','init','shutdown']: + continue + if type(v)is type(Context.create_context): + if v.__doc__ and not k.startswith('_'): + cmds_str[k]=v.__doc__ + just=0 + for k in cmds_str: + just=max(just,len(k)) + lst=[' %s: %s'%(k.ljust(just),v)for(k,v)in cmds_str.items()] + lst.sort() + ret='\n'.join(lst) + return'''waf [commands] [options] + +Main commands (example: ./waf build -j4) +%s +'''%ret +class OptionsContext(Context.Context): + cmd='options' + fun='options' + def __init__(self,**kw): + super(OptionsContext,self).__init__(**kw) + self.parser=opt_parser(self) + self.option_groups={} + def jobs(self): + count=int(os.environ.get('JOBS',0)) + if count<1: + if'NUMBER_OF_PROCESSORS'in os.environ: + count=int(os.environ.get('NUMBER_OF_PROCESSORS',1)) + else: + if hasattr(os,'sysconf_names'): + if'SC_NPROCESSORS_ONLN'in os.sysconf_names: + count=int(os.sysconf('SC_NPROCESSORS_ONLN')) + elif'SC_NPROCESSORS_CONF'in os.sysconf_names: + count=int(os.sysconf('SC_NPROCESSORS_CONF')) + if not count and os.name not in('nt','java'): + try: + tmp=self.cmd_and_log(['sysctl','-n','hw.ncpu'],quiet=0) + except Exception: + pass + else: + if re.match('^[0-9]+$',tmp): + count=int(tmp) + if count<1: + count=1 + elif count>1024: + count=1024 + return count + def add_option(self,*k,**kw): + return self.parser.add_option(*k,**kw) + def add_option_group(self,*k,**kw): + try: + gr=self.option_groups[k[0]] + except KeyError: + gr=self.parser.add_option_group(*k,**kw) + self.option_groups[k[0]]=gr + return gr + def get_option_group(self,opt_str): + try: + return self.option_groups[opt_str] + except KeyError: + for group in self.parser.option_groups: + if group.title==opt_str: + return group + return None + def parse_args(self,_args=None): + global options,commands + (options,leftover_args)=self.parser.parse_args(args=_args) + commands=leftover_args + if options.destdir: + options.destdir=os.path.abspath(os.path.expanduser(options.destdir)) + if options.verbose>=1: + self.load('errcheck') + def execute(self): + super(OptionsContext,self).execute() + self.parse_args() diff --git a/waflib/Runner.py b/waflib/Runner.py new file mode 100644 index 00000000..15b6a27b --- /dev/null +++ b/waflib/Runner.py @@ -0,0 +1,197 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import random,atexit +try: + from queue import Queue +except ImportError: + from Queue import Queue +from waflib import Utils,Task,Errors,Logs +GAP=10 +class TaskConsumer(Utils.threading.Thread): + def __init__(self): + Utils.threading.Thread.__init__(self) + self.ready=Queue() + self.setDaemon(1) + self.start() + def run(self): + try: + self.loop() + except Exception: + pass + def loop(self): + while 1: + tsk=self.ready.get() + if not isinstance(tsk,Task.TaskBase): + tsk(self) + else: + tsk.process() +pool=Queue() +def get_pool(): + try: + return pool.get(False) + except Exception: + return TaskConsumer() +def put_pool(x): + pool.put(x) +def _free_resources(): + global pool + lst=[] + while pool.qsize(): + lst.append(pool.get()) + for x in lst: + x.ready.put(None) + for x in lst: + x.join() + pool=None +atexit.register(_free_resources) +class Parallel(object): + def __init__(self,bld,j=2): + self.numjobs=j + self.bld=bld + self.outstanding=[] + self.frozen=[] + self.out=Queue(0) + self.count=0 + self.processed=1 + self.stop=False + self.error=[] + self.biter=None + self.dirty=False + def get_next_task(self): + if not self.outstanding: + return None + return self.outstanding.pop(0) + def postpone(self,tsk): + if random.randint(0,1): + self.frozen.insert(0,tsk) + else: + self.frozen.append(tsk) + def refill_task_list(self): + while self.count>self.numjobs*GAP: + self.get_out() + while not self.outstanding: + if self.count: + self.get_out() + elif self.frozen: + try: + cond=self.deadlock==self.processed + except AttributeError: + pass + else: + if cond: + msg='check the build order for the tasks' + for tsk in self.frozen: + if not tsk.run_after: + msg='check the methods runnable_status' + break + lst=[] + for tsk in self.frozen: + lst.append('%s\t-> %r'%(repr(tsk),[id(x)for x in tsk.run_after])) + raise Errors.WafError('Deadlock detected: %s%s'%(msg,''.join(lst))) + self.deadlock=self.processed + if self.frozen: + self.outstanding+=self.frozen + self.frozen=[] + elif not self.count: + self.outstanding.extend(self.biter.next()) + self.total=self.bld.total() + break + def add_more_tasks(self,tsk): + if getattr(tsk,'more_tasks',None): + self.outstanding+=tsk.more_tasks + self.total+=len(tsk.more_tasks) + def get_out(self): + tsk=self.out.get() + if not self.stop: + self.add_more_tasks(tsk) + self.count-=1 + self.dirty=True + return tsk + def error_handler(self,tsk): + if not self.bld.keep: + self.stop=True + self.error.append(tsk) + def add_task(self,tsk): + try: + self.pool + except AttributeError: + self.init_task_pool() + self.ready.put(tsk) + def init_task_pool(self): + pool=self.pool=[get_pool()for i in range(self.numjobs)] + self.ready=Queue(0) + def setq(consumer): + consumer.ready=self.ready + for x in pool: + x.ready.put(setq) + return pool + def free_task_pool(self): + def setq(consumer): + consumer.ready=Queue(0) + self.out.put(self) + try: + pool=self.pool + except AttributeError: + pass + else: + for x in pool: + self.ready.put(setq) + for x in pool: + self.get_out() + for x in pool: + put_pool(x) + self.pool=[] + def start(self): + self.total=self.bld.total() + while not self.stop: + self.refill_task_list() + tsk=self.get_next_task() + if not tsk: + if self.count: + continue + else: + break + if tsk.hasrun: + self.processed+=1 + continue + if self.stop: + break + try: + st=tsk.runnable_status() + except Exception: + self.processed+=1 + tsk.err_msg=Utils.ex_stack() + if not self.stop and self.bld.keep: + tsk.hasrun=Task.SKIPPED + if self.bld.keep==1: + if Logs.verbose>1 or not self.error: + self.error.append(tsk) + self.stop=True + else: + if Logs.verbose>1: + self.error.append(tsk) + continue + tsk.hasrun=Task.EXCEPTION + self.error_handler(tsk) + continue + if st==Task.ASK_LATER: + self.postpone(tsk) + elif st==Task.SKIP_ME: + self.processed+=1 + tsk.hasrun=Task.SKIPPED + self.add_more_tasks(tsk) + else: + tsk.position=(self.processed,self.total) + self.count+=1 + tsk.master=self + self.processed+=1 + if self.numjobs==1: + tsk.process() + else: + self.add_task(tsk) + while self.error and self.count: + self.get_out() + assert(self.count==0 or self.stop) + self.free_task_pool() diff --git a/waflib/Scripting.py b/waflib/Scripting.py new file mode 100644 index 00000000..c33ab329 --- /dev/null +++ b/waflib/Scripting.py @@ -0,0 +1,373 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +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) + if'--version'in sys.argv: + Context.run_dir=current_directory + ctx=Context.create_context('options') + ctx.curdir=current_directory + ctx.parse_args() + sys.exit(0) + Context.waf_dir=wafdir + Context.launch_dir=current_directory + no_climb=os.environ.get('NOCLIMB',None) + if not no_climb: + for k in no_climb_commands: + if k in sys.argv: + no_climb=True + break + cur=current_directory + while cur: + lst=os.listdir(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 Exception: + pass + else: + for x in[env.run_dir,env.top_dir,env.out_dir]: + 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'-h'in sys.argv or'--help'in sys.argv: + Logs.warn('No wscript file found: the help message may be incomplete') + Context.run_dir=current_directory + ctx=Context.create_context('options') + ctx.curdir=current_directory + ctx.parse_args() + sys.exit(0) + Logs.error('Waf: Run from a directory containing a file named %r'%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(Context.run_dir+os.sep+Context.WSCRIPT_FILE) + except Errors.WafError ,e: + Logs.pprint('RED',e.verbose_msg) + Logs.error(str(e)) + sys.exit(1) + except Exception ,e: + Logs.error('Waf: The wscript in %r is unreadable'%Context.run_dir,e) + traceback.print_exc(file=sys.stdout) + sys.exit(2) + try: + run_commands() + except Errors.WafError ,e: + if Logs.verbose>1: + Logs.pprint('RED',e.verbose_msg) + Logs.error(e.msg) + sys.exit(1) + except SystemExit: + raise + except Exception ,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[update,dist,distclean,distcheck,update]: + 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(): + Context.create_context('options').execute() + if not Options.commands: + Options.commands=[default_cmd] + Options.commands=[x for x in Options.commands if x!='options'] + Logs.verbose=Options.options.verbose + Logs.init_log() + if Options.options.zones: + Logs.zones=Options.options.zones.split(',') + if not Logs.verbose: + Logs.verbose=1 + elif Logs.verbose>0: + Logs.zones=['runner'] + if Logs.verbose>2: + Logs.zones=['*'] +def run_command(cmd_name): + ctx=Context.create_context(cmd_name) + ctx.log_timer=Utils.Timer() + ctx.options=Options.options + ctx.cmd=cmd_name + ctx.execute() + 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,str(ctx.log_timer))) + run_command('shutdown') +def _can_distclean(name): + for k in'.o .moc .exe'.split(): + if name.endswith(k): + return True + return False +def distclean_dir(dirname): + for(root,dirs,files)in os.walk(dirname): + for f in files: + if _can_distclean(f): + fname=root+os.sep+f + try: + os.unlink(fname) + except OSError: + Logs.warn('Could not remove %r'%fname) + for x in[Context.DBFILE,'config.log']: + try: + os.unlink(x) + except OSError: + pass + try: + shutil.rmtree('c4che') + except OSError: + pass +def distclean(ctx): + '''removes the build directory''' + lst=os.listdir('.') + for f in lst: + if f==Options.lockfile: + try: + proj=ConfigSet.ConfigSet(f) + except IOError: + Logs.warn('Could not read %r'%f) + continue + if proj['out_dir']!=proj['top_dir']: + try: + shutil.rmtree(proj['out_dir']) + except IOError: + pass + except OSError ,e: + if e.errno!=errno.ENOENT: + Logs.warn('project %r cannot be removed'%proj[Context.OUT]) + else: + distclean_dir(proj['out_dir']) + for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']): + try: + os.remove(os.path.join(k,Options.lockfile)) + except OSError ,e: + if e.errno!=errno.ENOENT: + Logs.warn('file %r cannot be removed'%f) + if f.startswith('.waf')and not Options.commands: + shutil.rmtree(f,ignore_errors=True) +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 Exception: + pass + files=self.get_files() + if self.algo.startswith('tar.'): + tar=tarfile.open(arch_name,'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(arch_name,'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 or zip') + try: + from hashlib import sha1 as sha + except ImportError: + from sha import sha + try: + digest=" (sha=%r)"%sha(node.read()).hexdigest() + except Exception: + digest='' + 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' + fu=None + try: + fu=open(p,'rb') + tar.addfile(tinfo,fileobj=fu) + finally: + if fu: + fu.close() + 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-1.7.* **/.waf-1.7* **/waf3-1.7.* **/.waf3-1.7* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' + 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 check(self): + import tempfile,tarfile + t=None + try: + t=tarfile.open(self.get_arch_name()) + for x in t: + t.extract(x) + finally: + if t: + t.close() + cfg=[] + if Options.options.distcheck_args: + cfg=shlex.split(Options.options.distcheck_args) + else: + cfg=[x for x in sys.argv if x.startswith('-')] + instdir=tempfile.mkdtemp('.inst',self.get_base_name()) + ret=Utils.subprocess.Popen([sys.argv[0],'configure','install','uninstall','--destdir='+instdir]+cfg,cwd=self.get_base_name()).wait() + if ret: + raise Errors.WafError('distcheck failed with code %i'%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 update(ctx): + '''updates the plugins from the *waflib/extras* directory''' + lst=Options.options.files.split(',') + if not lst: + lst=[x for x in Utils.listdir(Context.waf_dir+'/waflib/extras')if x.endswith('.py')] + for x in lst: + tool=x.replace('.py','') + try: + Configure.download_tool(tool,force=True,ctx=ctx) + except Errors.WafError: + Logs.error('Could not find the tool %s in the remote repository'%x) +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 Exception: + 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']: + h=hash((h,Utils.readf(f,'rb'))) + do_config=h!=env.hash + if do_config: + Options.commands.insert(0,self.cmd) + Options.commands.insert(0,'configure') + return + return execute_method(self) + return execute +Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute) diff --git a/waflib/Task.py b/waflib/Task.py new file mode 100644 index 00000000..1b54a541 --- /dev/null +++ b/waflib/Task.py @@ -0,0 +1,677 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,shutil,re,tempfile +from waflib import Utils,Logs,Errors +NOT_RUN=0 +MISSING=1 +CRASHED=2 +EXCEPTION=3 +SKIPPED=8 +SUCCESS=9 +ASK_LATER=-1 +SKIP_ME=-2 +RUN_ME=-3 +COMPILE_TEMPLATE_SHELL=''' +def f(tsk): + env = tsk.env + gen = tsk.generator + bld = gen.bld + wd = getattr(tsk, 'cwd', None) + p = env.get_flat + tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s + return tsk.exec_command(cmd, cwd=wd, env=env.env or None) +''' +COMPILE_TEMPLATE_NOSHELL=''' +def f(tsk): + env = tsk.env + gen = tsk.generator + bld = gen.bld + wd = getattr(tsk, 'cwd', None) + def to_list(xx): + if isinstance(xx, str): return [xx] + return xx + tsk.last_cmd = lst = [] + %s + lst = [x for x in lst if x] + return tsk.exec_command(lst, cwd=wd, env=env.env or None) +''' +def cache_outputs(cls): + m1=cls.run + def run(self): + bld=self.generator.bld + if bld.cache_global and not bld.nocache: + if self.can_retrieve_cache(): + return 0 + return m1(self) + cls.run=run + m2=cls.post_run + def post_run(self): + bld=self.generator.bld + ret=m2(self) + if bld.cache_global and not bld.nocache: + self.put_files_cache() + return ret + cls.post_run=post_run + return cls +classes={} +class store_task_type(type): + def __init__(cls,name,bases,dict): + super(store_task_type,cls).__init__(name,bases,dict) + name=cls.__name__ + if name.endswith('_task'): + name=name.replace('_task','') + if name!='evil'and name!='TaskBase': + global classes + if getattr(cls,'run_str',None): + (f,dvars)=compile_fun(cls.run_str,cls.shell) + cls.hcode=cls.run_str + cls.run_str=None + cls.run=f + cls.vars=list(set(cls.vars+dvars)) + cls.vars.sort() + elif getattr(cls,'run',None)and not'hcode'in cls.__dict__: + cls.hcode=Utils.h_fun(cls.run) + if not getattr(cls,'nocache',None): + cls=cache_outputs(cls) + getattr(cls,'register',classes)[name]=cls +evil=store_task_type('evil',(object,),{}) +class TaskBase(evil): + color='GREEN' + ext_in=[] + ext_out=[] + before=[] + after=[] + hcode='' + def __init__(self,*k,**kw): + self.hasrun=NOT_RUN + try: + self.generator=kw['generator'] + except KeyError: + self.generator=self + def __repr__(self): + return'\n\t{task %r: %s %s}'%(self.__class__.__name__,id(self),str(getattr(self,'fun',''))) + def __str__(self): + if hasattr(self,'fun'): + return'executing: %s\n'%self.fun.__name__ + return self.__class__.__name__+'\n' + def __hash__(self): + return id(self) + def exec_command(self,cmd,**kw): + bld=self.generator.bld + try: + if not kw.get('cwd',None): + kw['cwd']=bld.cwd + except AttributeError: + bld.cwd=kw['cwd']=bld.variant_dir + return bld.exec_command(cmd,**kw) + def runnable_status(self): + return RUN_ME + def process(self): + m=self.master + if m.stop: + m.out.put(self) + return + try: + del self.generator.bld.task_sigs[self.uid()] + except KeyError: + pass + try: + self.generator.bld.returned_tasks.append(self) + self.log_display(self.generator.bld) + ret=self.run() + except Exception: + self.err_msg=Utils.ex_stack() + self.hasrun=EXCEPTION + m.error_handler(self) + m.out.put(self) + return + if ret: + self.err_code=ret + self.hasrun=CRASHED + else: + try: + self.post_run() + except Errors.WafError: + pass + except Exception: + self.err_msg=Utils.ex_stack() + self.hasrun=EXCEPTION + else: + self.hasrun=SUCCESS + if self.hasrun!=SUCCESS: + m.error_handler(self) + m.out.put(self) + def run(self): + if hasattr(self,'fun'): + return self.fun(self) + return 0 + def post_run(self): + pass + def log_display(self,bld): + bld.to_log(self.display()) + def display(self): + col1=Logs.colors(self.color) + col2=Logs.colors.NORMAL + master=self.master + def cur(): + tmp=-1 + if hasattr(master,'ready'): + tmp-=master.ready.qsize() + return master.processed+tmp + if self.generator.bld.progress_bar==1: + return self.generator.bld.progress_line(cur(),master.total,col1,col2) + if self.generator.bld.progress_bar==2: + ela=str(self.generator.bld.timer) + try: + ins=','.join([n.name for n in self.inputs]) + except AttributeError: + ins='' + try: + outs=','.join([n.name for n in self.outputs]) + except AttributeError: + outs='' + return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela) + s=str(self) + if not s: + return None + total=master.total + n=len(str(total)) + fs='[%%%dd/%%%dd] %%s%%s%%s'%(n,n) + return fs%(cur(),total,col1,s,col2) + def attr(self,att,default=None): + ret=getattr(self,att,self) + if ret is self:return getattr(self.__class__,att,default) + return ret + def hash_constraints(self): + cls=self.__class__ + tup=(str(cls.before),str(cls.after),str(cls.ext_in),str(cls.ext_out),cls.__name__,cls.hcode) + h=hash(tup) + return h + def format_error(self): + msg=getattr(self,'last_cmd','') + name=getattr(self.generator,'name','') + if getattr(self,"err_msg",None): + return self.err_msg + elif not self.hasrun: + return'task in %r was not executed for some reason: %r'%(name,self) + elif self.hasrun==CRASHED: + try: + return' -> task in %r failed (exit status %r): %r\n%r'%(name,self.err_code,self,msg) + except AttributeError: + return' -> task in %r failed: %r\n%r'%(name,self,msg) + elif self.hasrun==MISSING: + return' -> missing files in %r: %r\n%r'%(name,self,msg) + else: + return'invalid status for task in %r: %r'%(name,self.hasrun) + def colon(self,var1,var2): + tmp=self.env[var1] + if isinstance(var2,str): + it=self.env[var2] + else: + it=var2 + if isinstance(tmp,str): + return[tmp%x for x in it] + else: + if Logs.verbose and not tmp and it: + Logs.warn('Missing env variable %r for task %r (generator %r)'%(var1,self,self.generator)) + lst=[] + for y in it: + lst.extend(tmp) + lst.append(y) + return lst +class Task(TaskBase): + vars=[] + shell=False + def __init__(self,*k,**kw): + TaskBase.__init__(self,*k,**kw) + self.env=kw['env'] + self.inputs=[] + self.outputs=[] + self.dep_nodes=[] + self.run_after=set([]) + def __str__(self): + env=self.env + src_str=' '.join([a.nice_path()for a in self.inputs]) + tgt_str=' '.join([a.nice_path()for a in self.outputs]) + if self.outputs:sep=' -> ' + else:sep='' + return'%s: %s%s%s\n'%(self.__class__.__name__.replace('_task',''),src_str,sep,tgt_str) + def __repr__(self): + try: + ins=",".join([x.name for x in self.inputs]) + outs=",".join([x.name for x in self.outputs]) + except AttributeError: + ins=",".join([str(x)for x in self.inputs]) + outs=",".join([str(x)for x in self.outputs]) + return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",ins," -> ",outs,'}']) + def uid(self): + try: + return self.uid_ + except AttributeError: + m=Utils.md5() + up=m.update + up(self.__class__.__name__) + for x in self.inputs+self.outputs: + up(x.abspath()) + self.uid_=m.digest() + return self.uid_ + def set_inputs(self,inp): + if isinstance(inp,list):self.inputs+=inp + else:self.inputs.append(inp) + def set_outputs(self,out): + if isinstance(out,list):self.outputs+=out + else:self.outputs.append(out) + def set_run_after(self,task): + assert isinstance(task,TaskBase) + self.run_after.add(task) + def signature(self): + try:return self.cache_sig + except AttributeError:pass + self.m=Utils.md5() + self.m.update(self.hcode) + self.sig_explicit_deps() + self.sig_vars() + if self.scan: + try: + self.sig_implicit_deps() + except Errors.TaskRescan: + return self.signature() + ret=self.cache_sig=self.m.digest() + return ret + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return ASK_LATER + bld=self.generator.bld + try: + new_sig=self.signature() + except Errors.TaskNotReady: + return ASK_LATER + key=self.uid() + try: + prev_sig=bld.task_sigs[key] + except KeyError: + Logs.debug("task: task %r must run as it was never run before or the task code changed"%self) + return RUN_ME + for node in self.outputs: + try: + if node.sig!=new_sig: + return RUN_ME + except AttributeError: + Logs.debug("task: task %r must run as the output nodes do not exist"%self) + return RUN_ME + if new_sig!=prev_sig: + return RUN_ME + return SKIP_ME + def post_run(self): + bld=self.generator.bld + sig=self.signature() + for node in self.outputs: + try: + os.stat(node.abspath()) + except OSError: + self.hasrun=MISSING + self.err_msg='-> missing file: %r'%node.abspath() + raise Errors.WafError(self.err_msg) + node.sig=sig + bld.task_sigs[self.uid()]=self.cache_sig + def sig_explicit_deps(self): + bld=self.generator.bld + upd=self.m.update + for x in self.inputs+self.dep_nodes: + try: + upd(x.get_bld_sig()) + except(AttributeError,TypeError): + raise Errors.WafError('Missing node signature for %r (required by %r)'%(x,self)) + if bld.deps_man: + additional_deps=bld.deps_man + for x in self.inputs+self.outputs: + try: + d=additional_deps[id(x)] + except KeyError: + continue + for v in d: + if isinstance(v,bld.root.__class__): + try: + v=v.get_bld_sig() + except AttributeError: + raise Errors.WafError('Missing node signature for %r (required by %r)'%(v,self)) + elif hasattr(v,'__call__'): + v=v() + upd(v) + return self.m.digest() + def sig_vars(self): + bld=self.generator.bld + env=self.env + upd=self.m.update + act_sig=bld.hash_env_vars(env,self.__class__.vars) + upd(act_sig) + dep_vars=getattr(self,'dep_vars',None) + if dep_vars: + upd(bld.hash_env_vars(env,dep_vars)) + return self.m.digest() + scan=None + def sig_implicit_deps(self): + bld=self.generator.bld + key=self.uid() + prev=bld.task_sigs.get((key,'imp'),[]) + if prev: + try: + if prev==self.compute_sig_implicit_deps(): + return prev + except Exception: + for x in bld.node_deps.get(self.uid(),[]): + if x.is_child_of(bld.srcnode): + try: + os.stat(x.abspath()) + except OSError: + try: + del x.parent.children[x.name] + except KeyError: + pass + del bld.task_sigs[(key,'imp')] + raise Errors.TaskRescan('rescan') + (nodes,names)=self.scan() + if Logs.verbose: + Logs.debug('deps: scanner for %s returned %s %s'%(str(self),str(nodes),str(names))) + bld.node_deps[key]=nodes + bld.raw_deps[key]=names + self.are_implicit_nodes_ready() + try: + bld.task_sigs[(key,'imp')]=sig=self.compute_sig_implicit_deps() + except Exception: + if Logs.verbose: + for k in bld.node_deps.get(self.uid(),[]): + try: + k.get_bld_sig() + except Exception: + Logs.warn('Missing signature for node %r (may cause rebuilds)'%k) + else: + return sig + def compute_sig_implicit_deps(self): + upd=self.m.update + bld=self.generator.bld + self.are_implicit_nodes_ready() + for k in bld.node_deps.get(self.uid(),[]): + upd(k.get_bld_sig()) + return self.m.digest() + def are_implicit_nodes_ready(self): + bld=self.generator.bld + try: + cache=bld.dct_implicit_nodes + except AttributeError: + bld.dct_implicit_nodes=cache={} + try: + dct=cache[bld.cur] + except KeyError: + dct=cache[bld.cur]={} + for tsk in bld.cur_tasks: + for x in tsk.outputs: + dct[x]=tsk + modified=False + for x in bld.node_deps.get(self.uid(),[]): + if x in dct: + self.run_after.add(dct[x]) + modified=True + if modified: + for tsk in self.run_after: + if not tsk.hasrun: + raise Errors.TaskNotReady('not ready') + def can_retrieve_cache(self): + if not getattr(self,'outputs',None): + return None + sig=self.signature() + ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig) + dname=os.path.join(self.generator.bld.cache_global,ssig) + try: + t1=os.stat(dname).st_mtime + except OSError: + return None + for node in self.outputs: + orig=os.path.join(dname,node.name) + try: + shutil.copy2(orig,node.abspath()) + os.utime(orig,None) + except(OSError,IOError): + Logs.debug('task: failed retrieving file') + return None + try: + t2=os.stat(dname).st_mtime + except OSError: + return None + if t1!=t2: + return None + for node in self.outputs: + node.sig=sig + if self.generator.bld.progress_bar<1: + self.generator.bld.to_log('restoring from cache %r\n'%node.abspath()) + self.cached=True + return True + def put_files_cache(self): + if getattr(self,'cached',None): + return None + if not getattr(self,'outputs',None): + return None + sig=self.signature() + ssig=Utils.to_hex(self.uid())+Utils.to_hex(sig) + dname=os.path.join(self.generator.bld.cache_global,ssig) + tmpdir=tempfile.mkdtemp(prefix=self.generator.bld.cache_global+os.sep+'waf') + try: + shutil.rmtree(dname) + except Exception: + pass + try: + for node in self.outputs: + dest=os.path.join(tmpdir,node.name) + shutil.copy2(node.abspath(),dest) + except(OSError,IOError): + try: + shutil.rmtree(tmpdir) + except Exception: + pass + else: + try: + os.rename(tmpdir,dname) + except OSError: + try: + shutil.rmtree(tmpdir) + except Exception: + pass + else: + try: + os.chmod(dname,Utils.O755) + except Exception: + pass +def is_before(t1,t2): + to_list=Utils.to_list + for k in to_list(t2.ext_in): + if k in to_list(t1.ext_out): + return 1 + if t1.__class__.__name__ in to_list(t2.after): + return 1 + if t2.__class__.__name__ in to_list(t1.before): + return 1 + return 0 +def set_file_constraints(tasks): + ins=Utils.defaultdict(set) + outs=Utils.defaultdict(set) + for x in tasks: + for a in getattr(x,'inputs',[])+getattr(x,'dep_nodes',[]): + ins[id(a)].add(x) + for a in getattr(x,'outputs',[]): + outs[id(a)].add(x) + links=set(ins.keys()).intersection(outs.keys()) + for k in links: + for a in ins[k]: + a.run_after.update(outs[k]) +def set_precedence_constraints(tasks): + cstr_groups=Utils.defaultdict(list) + for x in tasks: + h=x.hash_constraints() + cstr_groups[h].append(x) + keys=list(cstr_groups.keys()) + maxi=len(keys) + for i in range(maxi): + t1=cstr_groups[keys[i]][0] + for j in range(i+1,maxi): + t2=cstr_groups[keys[j]][0] + if is_before(t1,t2): + a=i + b=j + elif is_before(t2,t1): + a=j + b=i + else: + continue + aval=set(cstr_groups[keys[a]]) + for x in cstr_groups[keys[b]]: + x.run_after.update(aval) +def funex(c): + dc={} + exec(c,dc) + return dc['f'] +reg_act=re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})",re.M) +def compile_fun_shell(line): + extr=[] + def repl(match): + g=match.group + if g('dollar'):return"$" + elif g('backslash'):return'\\\\' + elif g('subst'):extr.append((g('var'),g('code')));return"%s" + return None + line=reg_act.sub(repl,line)or line + parm=[] + dvars=[] + app=parm.append + for(var,meth)in extr: + if var=='SRC': + if meth:app('tsk.inputs%s'%meth) + else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])') + elif var=='TGT': + if meth:app('tsk.outputs%s'%meth) + else:app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])') + elif meth: + if meth.startswith(':'): + m=meth[1:] + if m=='SRC': + m='[a.path_from(bld.bldnode) for a in tsk.inputs]' + elif m=='TGT': + m='[a.path_from(bld.bldnode) for a in tsk.outputs]' + elif m[:3]not in('tsk','gen','bld'): + dvars.extend([var,meth[1:]]) + m='%r'%m + app('" ".join(tsk.colon(%r, %s))'%(var,m)) + else: + app('%s%s'%(var,meth)) + else: + if not var in dvars:dvars.append(var) + app("p('%s')"%var) + if parm:parm="%% (%s) "%(',\n\t\t'.join(parm)) + else:parm='' + c=COMPILE_TEMPLATE_SHELL%(line,parm) + Logs.debug('action: %s'%c.strip().splitlines()) + return(funex(c),dvars) +def compile_fun_noshell(line): + extr=[] + def repl(match): + g=match.group + if g('dollar'):return"$" + elif g('subst'):extr.append((g('var'),g('code')));return"<<|@|>>" + return None + line2=reg_act.sub(repl,line) + params=line2.split('<<|@|>>') + assert(extr) + buf=[] + dvars=[] + app=buf.append + for x in range(len(extr)): + params[x]=params[x].strip() + if params[x]: + app("lst.extend(%r)"%params[x].split()) + (var,meth)=extr[x] + if var=='SRC': + if meth:app('lst.append(tsk.inputs%s)'%meth) + else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])") + elif var=='TGT': + if meth:app('lst.append(tsk.outputs%s)'%meth) + else:app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])") + elif meth: + if meth.startswith(':'): + m=meth[1:] + if m=='SRC': + m='[a.path_from(bld.bldnode) for a in tsk.inputs]' + elif m=='TGT': + m='[a.path_from(bld.bldnode) for a in tsk.outputs]' + elif m[:3]not in('tsk','gen','bld'): + dvars.extend([var,m]) + m='%r'%m + app('lst.extend(tsk.colon(%r, %s))'%(var,m)) + else: + app('lst.extend(gen.to_list(%s%s))'%(var,meth)) + else: + app('lst.extend(to_list(env[%r]))'%var) + if not var in dvars:dvars.append(var) + if extr: + if params[-1]: + app("lst.extend(%r)"%params[-1].split()) + fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf) + Logs.debug('action: %s'%fun.strip().splitlines()) + return(funex(fun),dvars) +def compile_fun(line,shell=False): + if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0: + shell=True + if shell: + return compile_fun_shell(line) + else: + return compile_fun_noshell(line) +def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None): + params={'vars':vars or[],'color':color,'name':name,'ext_in':Utils.to_list(ext_in),'ext_out':Utils.to_list(ext_out),'before':Utils.to_list(before),'after':Utils.to_list(after),'shell':shell,'scan':scan,} + if isinstance(func,str): + params['run_str']=func + else: + params['run']=func + cls=type(Task)(name,(Task,),params) + global classes + classes[name]=cls + return cls +def always_run(cls): + old=cls.runnable_status + def always(self): + ret=old(self) + if ret==SKIP_ME: + ret=RUN_ME + return ret + cls.runnable_status=always + return cls +def update_outputs(cls): + old_post_run=cls.post_run + def post_run(self): + old_post_run(self) + for node in self.outputs: + node.sig=Utils.h_file(node.abspath()) + self.generator.bld.task_sigs[node.abspath()]=self.uid() + cls.post_run=post_run + old_runnable_status=cls.runnable_status + def runnable_status(self): + status=old_runnable_status(self) + if status!=RUN_ME: + return status + try: + bld=self.generator.bld + prev_sig=bld.task_sigs[self.uid()] + if prev_sig==self.signature(): + for x in self.outputs: + if not x.sig or bld.task_sigs[x.abspath()]!=self.uid(): + return RUN_ME + return SKIP_ME + except KeyError: + pass + except IndexError: + pass + except AttributeError: + pass + return RUN_ME + cls.runnable_status=runnable_status + return cls diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py new file mode 100644 index 00000000..acd51664 --- /dev/null +++ b/waflib/TaskGen.py @@ -0,0 +1,400 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import copy,re,os +from waflib import Task,Utils,Logs,Errors,ConfigSet,Node +feats=Utils.defaultdict(set) +class task_gen(object): + mappings={} + prec=Utils.defaultdict(list) + def __init__(self,*k,**kw): + self.source='' + self.target='' + self.meths=[] + self.prec=Utils.defaultdict(list) + self.mappings={} + self.features=[] + self.tasks=[] + if not'bld'in kw: + self.env=ConfigSet.ConfigSet() + self.idx=0 + self.path=None + else: + self.bld=kw['bld'] + self.env=self.bld.env.derive() + self.path=self.bld.path + try: + self.idx=self.bld.idx[id(self.path)]=self.bld.idx.get(id(self.path),0)+1 + except AttributeError: + self.bld.idx={} + self.idx=self.bld.idx[id(self.path)]=1 + for key,val in kw.items(): + setattr(self,key,val) + def __str__(self): + return""%(self.name,self.path.abspath()) + def __repr__(self): + lst=[] + for x in self.__dict__.keys(): + if x not in['env','bld','compiled_tasks','tasks']: + lst.append("%s=%s"%(x,repr(getattr(self,x)))) + return"bld(%s) in %s"%(", ".join(lst),self.path.abspath()) + def get_name(self): + try: + return self._name + except AttributeError: + if isinstance(self.target,list): + lst=[str(x)for x in self.target] + name=self._name=','.join(lst) + else: + name=self._name=str(self.target) + return name + def set_name(self,name): + self._name=name + name=property(get_name,set_name) + def to_list(self,val): + if isinstance(val,str):return val.split() + else:return val + def post(self): + if getattr(self,'posted',None): + return False + self.posted=True + keys=set(self.meths) + self.features=Utils.to_list(self.features) + for x in self.features+['*']: + st=feats[x] + if not st: + if not x in Task.classes: + Logs.warn('feature %r does not exist - bind at least one method to it'%x) + keys.update(list(st)) + prec={} + prec_tbl=self.prec or task_gen.prec + for x in prec_tbl: + if x in keys: + prec[x]=prec_tbl[x] + tmp=[] + for a in keys: + for x in prec.values(): + if a in x:break + else: + tmp.append(a) + tmp.sort() + out=[] + while tmp: + e=tmp.pop() + if e in keys:out.append(e) + try: + nlst=prec[e] + except KeyError: + pass + else: + del prec[e] + for x in nlst: + for y in prec: + if x in prec[y]: + break + else: + tmp.append(x) + if prec: + raise Errors.WafError('Cycle detected in the method execution %r'%prec) + out.reverse() + self.meths=out + Logs.debug('task_gen: posting %s %d'%(self,id(self))) + for x in out: + try: + v=getattr(self,x) + except AttributeError: + raise Errors.WafError('%r is not a valid task generator method'%x) + Logs.debug('task_gen: -> %s (%d)'%(x,id(self))) + v() + Logs.debug('task_gen: posted %s'%self.name) + return True + def get_hook(self,node): + name=node.name + for k in self.mappings: + if name.endswith(k): + return self.mappings[k] + for k in task_gen.mappings: + if name.endswith(k): + return task_gen.mappings[k] + raise Errors.WafError("File %r has no mapping in %r (did you forget to load a waf tool?)"%(node,task_gen.mappings.keys())) + def create_task(self,name,src=None,tgt=None): + task=Task.classes[name](env=self.env.derive(),generator=self) + if src: + task.set_inputs(src) + if tgt: + task.set_outputs(tgt) + self.tasks.append(task) + return task + def clone(self,env): + newobj=self.bld() + for x in self.__dict__: + if x in['env','bld']: + continue + elif x in['path','features']: + setattr(newobj,x,getattr(self,x)) + else: + setattr(newobj,x,copy.copy(getattr(self,x))) + newobj.posted=False + if isinstance(env,str): + newobj.env=self.bld.all_envs[env].derive() + else: + newobj.env=env.derive() + return newobj +def declare_chain(name='',rule=None,reentrant=None,color='BLUE',ext_in=[],ext_out=[],before=[],after=[],decider=None,scan=None,install_path=None,shell=False): + ext_in=Utils.to_list(ext_in) + ext_out=Utils.to_list(ext_out) + if not name: + name=rule + cls=Task.task_factory(name,rule,color=color,ext_in=ext_in,ext_out=ext_out,before=before,after=after,scan=scan,shell=shell) + def x_file(self,node): + ext=decider and decider(self,node)or cls.ext_out + if ext_in: + _ext_in=ext_in[0] + tsk=self.create_task(name,node) + cnt=0 + keys=list(self.mappings.keys())+list(self.__class__.mappings.keys()) + for x in ext: + k=node.change_ext(x,ext_in=_ext_in) + tsk.outputs.append(k) + if reentrant!=None: + if cnt=','exact-version':'==','max-version':'<=',} +SNIP_FUNCTION=''' +int main(int argc, char **argv) { + void *p; + (void)argc; (void)argv; + p=(void*)(%s); + return 0; +} +''' +SNIP_TYPE=''' +int main(int argc, char **argv) { + (void)argc; (void)argv; + if ((%(type_name)s *) 0) return 0; + if (sizeof (%(type_name)s)) return 0; + return 1; +} +''' +SNIP_EMPTY_PROGRAM=''' +int main(int argc, char **argv) { + (void)argc; (void)argv; + return 0; +} +''' +SNIP_FIELD=''' +int main(int argc, char **argv) { + char *off; + (void)argc; (void)argv; + off = (char*) &((%(type_name)s*)0)->%(field_name)s; + return (size_t) off < sizeof(%(type_name)s); +} +''' +MACRO_TO_DESTOS={'__linux__':'linux','__GNU__':'gnu','__FreeBSD__':'freebsd','__NetBSD__':'netbsd','__OpenBSD__':'openbsd','__sun':'sunos','__hpux':'hpux','__sgi':'irix','_AIX':'aix','__CYGWIN__':'cygwin','__MSYS__':'msys','_UWIN':'uwin','_WIN64':'win32','_WIN32':'win32','__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__':'darwin','__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__':'darwin','__QNX__':'qnx','__native_client__':'nacl'} +MACRO_TO_DEST_CPU={'__x86_64__':'x86_64','__amd64__':'x86_64','__i386__':'x86','__ia64__':'ia','__mips__':'mips','__sparc__':'sparc','__alpha__':'alpha','__aarch64__':'aarch64','__thumb__':'thumb','__arm__':'arm','__hppa__':'hppa','__powerpc__':'powerpc','__ppc__':'powerpc','__convex__':'convex','__m68k__':'m68k','__s390x__':'s390x','__s390__':'s390','__sh__':'sh',} +@conf +def parse_flags(self,line,uselib_store,env=None,force_static=False): + assert(isinstance(line,str)) + env=env or self.env + app=env.append_value + appu=env.append_unique + lex=shlex.shlex(line,posix=False) + lex.whitespace_split=True + lex.commenters='' + lst=list(lex) + uselib=uselib_store + while lst: + x=lst.pop(0) + st=x[:2] + ot=x[2:] + if st=='-I'or st=='/I': + if not ot:ot=lst.pop(0) + appu('INCLUDES_'+uselib,[ot]) + elif st=='-include': + tmp=[x,lst.pop(0)] + app('CFLAGS',tmp) + app('CXXFLAGS',tmp) + elif st=='-D'or(env.CXX_NAME=='msvc'and st=='/D'): + if not ot:ot=lst.pop(0) + app('DEFINES_'+uselib,[ot]) + elif st=='-l': + if not ot:ot=lst.pop(0) + prefix=force_static and'STLIB_'or'LIB_' + appu(prefix+uselib,[ot]) + elif st=='-L': + if not ot:ot=lst.pop(0) + appu('LIBPATH_'+uselib,[ot]) + elif x.startswith('/LIBPATH:'): + appu('LIBPATH_'+uselib,[x.replace('/LIBPATH:','')]) + elif x=='-pthread'or x.startswith('+')or x.startswith('-std'): + app('CFLAGS_'+uselib,[x]) + app('CXXFLAGS_'+uselib,[x]) + app('LINKFLAGS_'+uselib,[x]) + elif x=='-framework': + appu('FRAMEWORK_'+uselib,[lst.pop(0)]) + elif x.startswith('-F'): + appu('FRAMEWORKPATH_'+uselib,[x[2:]]) + elif x.startswith('-Wl'): + app('LINKFLAGS_'+uselib,[x]) + elif x.startswith('-m')or x.startswith('-f')or x.startswith('-dynamic'): + app('CFLAGS_'+uselib,[x]) + app('CXXFLAGS_'+uselib,[x]) + elif x.startswith('-bundle'): + app('LINKFLAGS_'+uselib,[x]) + elif x.startswith('-undefined'): + arg=lst.pop(0) + app('LINKFLAGS_'+uselib,[x,arg]) + elif x.startswith('-arch')or x.startswith('-isysroot'): + tmp=[x,lst.pop(0)] + app('CFLAGS_'+uselib,tmp) + app('CXXFLAGS_'+uselib,tmp) + app('LINKFLAGS_'+uselib,tmp) + elif x.endswith('.a')or x.endswith('.so')or x.endswith('.dylib')or x.endswith('.lib'): + appu('LINKFLAGS_'+uselib,[x]) +@conf +def ret_msg(self,f,kw): + if isinstance(f,str): + return f + return f(kw) +@conf +def validate_cfg(self,kw): + if not'path'in kw: + if not self.env.PKGCONFIG: + self.find_program('pkg-config',var='PKGCONFIG') + kw['path']=self.env.PKGCONFIG + if'atleast_pkgconfig_version'in kw: + if not'msg'in kw: + kw['msg']='Checking for pkg-config version >= %r'%kw['atleast_pkgconfig_version'] + return + if not'okmsg'in kw: + kw['okmsg']='yes' + if not'errmsg'in kw: + kw['errmsg']='not found' + if'modversion'in kw: + if not'msg'in kw: + kw['msg']='Checking for %r version'%kw['modversion'] + return + for x in cfg_ver.keys(): + y=x.replace('-','_') + if y in kw: + if not'package'in kw: + raise ValueError('%s requires a package'%x) + if not'msg'in kw: + kw['msg']='Checking for %r %s %s'%(kw['package'],cfg_ver[x],kw[y]) + return + if not'msg'in kw: + kw['msg']='Checking for %r'%(kw['package']or kw['path']) +@conf +def exec_cfg(self,kw): + def define_it(): + self.define(self.have_define(kw.get('uselib_store',kw['package'])),1,0) + if'atleast_pkgconfig_version'in kw: + cmd=[kw['path'],'--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']] + self.cmd_and_log(cmd) + if not'okmsg'in kw: + kw['okmsg']='yes' + return + for x in cfg_ver: + y=x.replace('-','_') + if y in kw: + self.cmd_and_log([kw['path'],'--%s=%s'%(x,kw[y]),kw['package']]) + if not'okmsg'in kw: + kw['okmsg']='yes' + define_it() + break + if'modversion'in kw: + version=self.cmd_and_log([kw['path'],'--modversion',kw['modversion']]).strip() + self.define('%s_VERSION'%Utils.quote_define_name(kw.get('uselib_store',kw['modversion'])),version) + return version + lst=[kw['path']] + defi=kw.get('define_variable',None) + if not defi: + defi=self.env.PKG_CONFIG_DEFINES or{} + for key,val in defi.items(): + lst.append('--define-variable=%s=%s'%(key,val)) + if'variables'in kw: + env=kw.get('env',self.env) + uselib=kw.get('uselib_store',kw['package'].upper()) + vars=Utils.to_list(kw['variables']) + for v in vars: + val=self.cmd_and_log(lst+['--variable='+v]).strip() + var='%s_%s'%(uselib,v) + env[var]=val + if not'okmsg'in kw: + kw['okmsg']='yes' + return + static=False + if'args'in kw: + args=Utils.to_list(kw['args']) + if'--static'in args or'--static-libs'in args: + static=True + lst+=args + lst.extend(Utils.to_list(kw['package'])) + ret=self.cmd_and_log(lst) + if not'okmsg'in kw: + kw['okmsg']='yes' + define_it() + self.parse_flags(ret,kw.get('uselib_store',kw['package'].upper()),kw.get('env',self.env),force_static=static) + return ret +@conf +def check_cfg(self,*k,**kw): + if k: + lst=k[0].split() + kw['package']=lst[0] + kw['args']=' '.join(lst[1:]) + self.validate_cfg(kw) + if'msg'in kw: + self.start_msg(kw['msg']) + ret=None + try: + ret=self.exec_cfg(kw) + except self.errors.WafError: + if'errmsg'in kw: + self.end_msg(kw['errmsg'],'YELLOW') + if Logs.verbose>1: + raise + else: + self.fatal('The configuration failed') + else: + kw['success']=ret + if'okmsg'in kw: + self.end_msg(self.ret_msg(kw['okmsg'],kw)) + return ret +@conf +def validate_c(self,kw): + if not'env'in kw: + kw['env']=self.env.derive() + env=kw['env'] + if not'compiler'in kw and not'features'in kw: + kw['compiler']='c' + if env['CXX_NAME']and Task.classes.get('cxx',None): + kw['compiler']='cxx' + if not self.env['CXX']: + self.fatal('a c++ compiler is required') + else: + if not self.env['CC']: + self.fatal('a c compiler is required') + if not'compile_mode'in kw: + kw['compile_mode']='c' + if'cxx'in Utils.to_list(kw.get('features',[]))or kw.get('compiler','')=='cxx': + kw['compile_mode']='cxx' + if not'type'in kw: + kw['type']='cprogram' + if not'features'in kw: + kw['features']=[kw['compile_mode'],kw['type']] + else: + kw['features']=Utils.to_list(kw['features']) + if not'compile_filename'in kw: + kw['compile_filename']='test.c'+((kw['compile_mode']=='cxx')and'pp'or'') + def to_header(dct): + if'header_name'in dct: + dct=Utils.to_list(dct['header_name']) + return''.join(['#include <%s>\n'%x for x in dct]) + return'' + if'framework_name'in kw: + fwkname=kw['framework_name'] + if not'uselib_store'in kw: + kw['uselib_store']=fwkname.upper() + if not kw.get('no_header',False): + if not'header_name'in kw: + kw['header_name']=[] + fwk='%s/%s.h'%(fwkname,fwkname) + if kw.get('remove_dot_h',None): + fwk=fwk[:-2] + kw['header_name']=Utils.to_list(kw['header_name'])+[fwk] + kw['msg']='Checking for framework %s'%fwkname + kw['framework']=fwkname + if'function_name'in kw: + fu=kw['function_name'] + if not'msg'in kw: + kw['msg']='Checking for function %s'%fu + kw['code']=to_header(kw)+SNIP_FUNCTION%fu + if not'uselib_store'in kw: + kw['uselib_store']=fu.upper() + if not'define_name'in kw: + kw['define_name']=self.have_define(fu) + elif'type_name'in kw: + tu=kw['type_name'] + if not'header_name'in kw: + kw['header_name']='stdint.h' + if'field_name'in kw: + field=kw['field_name'] + kw['code']=to_header(kw)+SNIP_FIELD%{'type_name':tu,'field_name':field} + if not'msg'in kw: + kw['msg']='Checking for field %s in %s'%(field,tu) + if not'define_name'in kw: + kw['define_name']=self.have_define((tu+'_'+field).upper()) + else: + kw['code']=to_header(kw)+SNIP_TYPE%{'type_name':tu} + if not'msg'in kw: + kw['msg']='Checking for type %s'%tu + if not'define_name'in kw: + kw['define_name']=self.have_define(tu.upper()) + elif'header_name'in kw: + if not'msg'in kw: + kw['msg']='Checking for header %s'%kw['header_name'] + l=Utils.to_list(kw['header_name']) + assert len(l)>0,'list of headers in header_name is empty' + kw['code']=to_header(kw)+SNIP_EMPTY_PROGRAM + if not'uselib_store'in kw: + kw['uselib_store']=l[0].upper() + if not'define_name'in kw: + kw['define_name']=self.have_define(l[0]) + if'lib'in kw: + if not'msg'in kw: + kw['msg']='Checking for library %s'%kw['lib'] + if not'uselib_store'in kw: + kw['uselib_store']=kw['lib'].upper() + if'stlib'in kw: + if not'msg'in kw: + kw['msg']='Checking for static library %s'%kw['stlib'] + if not'uselib_store'in kw: + kw['uselib_store']=kw['stlib'].upper() + if'fragment'in kw: + kw['code']=kw['fragment'] + if not'msg'in kw: + kw['msg']='Checking for code snippet' + if not'errmsg'in kw: + kw['errmsg']='no' + for(flagsname,flagstype)in[('cxxflags','compiler'),('cflags','compiler'),('linkflags','linker')]: + if flagsname in kw: + if not'msg'in kw: + kw['msg']='Checking for %s flags %s'%(flagstype,kw[flagsname]) + if not'errmsg'in kw: + kw['errmsg']='no' + if not'execute'in kw: + kw['execute']=False + if kw['execute']: + kw['features'].append('test_exec') + if not'errmsg'in kw: + kw['errmsg']='not found' + if not'okmsg'in kw: + kw['okmsg']='yes' + if not'code'in kw: + kw['code']=SNIP_EMPTY_PROGRAM + if self.env[INCKEYS]: + kw['code']='\n'.join(['#include <%s>'%x for x in self.env[INCKEYS]])+'\n'+kw['code'] + if not kw.get('success'):kw['success']=None + if'define_name'in kw: + self.undefine(kw['define_name']) + assert'msg'in kw,'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c' +@conf +def post_check(self,*k,**kw): + is_success=0 + if kw['execute']: + if kw['success']is not None: + if kw.get('define_ret',False): + is_success=kw['success'] + else: + is_success=(kw['success']==0) + else: + is_success=(kw['success']==0) + if'define_name'in kw: + if'header_name'in kw or'function_name'in kw or'type_name'in kw or'fragment'in kw: + if kw['execute']and kw.get('define_ret',None)and isinstance(is_success,str): + self.define(kw['define_name'],is_success,quote=kw.get('quote',1)) + else: + self.define_cond(kw['define_name'],is_success) + else: + self.define_cond(kw['define_name'],is_success) + if'header_name'in kw: + if kw.get('auto_add_header_name',False): + self.env.append_value(INCKEYS,Utils.to_list(kw['header_name'])) + if is_success and'uselib_store'in kw: + from waflib.Tools import ccroot + _vars=set([]) + for x in kw['features']: + if x in ccroot.USELIB_VARS: + _vars|=ccroot.USELIB_VARS[x] + for k in _vars: + lk=k.lower() + if k=='INCLUDES':lk='includes' + if k=='DEFINES':lk='defines' + if lk in kw: + val=kw[lk] + if isinstance(val,str): + val=val.rstrip(os.path.sep) + self.env.append_unique(k+'_'+kw['uselib_store'],val) + return is_success +@conf +def check(self,*k,**kw): + self.validate_c(kw) + self.start_msg(kw['msg']) + ret=None + try: + ret=self.run_c_code(*k,**kw) + except self.errors.ConfigurationError: + self.end_msg(kw['errmsg'],'YELLOW') + if Logs.verbose>1: + raise + else: + self.fatal('The configuration failed') + else: + kw['success']=ret + ret=self.post_check(*k,**kw) + if not ret: + self.end_msg(kw['errmsg'],'YELLOW') + self.fatal('The configuration failed %r'%ret) + else: + self.end_msg(self.ret_msg(kw['okmsg'],kw)) + return ret +class test_exec(Task.Task): + color='PINK' + def run(self): + if getattr(self.generator,'rpath',None): + if getattr(self.generator,'define_ret',False): + self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) + else: + self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()]) + else: + env=self.env.env or{} + env.update(dict(os.environ)) + for var in('LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','PATH'): + env[var]=self.inputs[0].parent.abspath()+os.path.pathsep+env.get(var,'') + if getattr(self.generator,'define_ret',False): + self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()],env=env) + else: + self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()],env=env) +@feature('test_exec') +@after_method('apply_link') +def test_exec_fun(self): + self.create_task('test_exec',self.link_task.outputs[0]) +CACHE_RESULTS=1 +COMPILE_ERRORS=2 +@conf +def run_c_code(self,*k,**kw): + lst=[str(v)for(p,v)in kw.items()if p!='env'] + h=Utils.h_list(lst) + dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h) + try: + os.makedirs(dir) + except OSError: + pass + try: + os.stat(dir) + except OSError: + self.fatal('cannot use the configuration test folder %r'%dir) + cachemode=getattr(Options.options,'confcache',None) + if cachemode==CACHE_RESULTS: + try: + proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_c_code')) + except OSError: + pass + else: + ret=proj['cache_run_c_code'] + if isinstance(ret,str)and ret.startswith('Test does not build'): + self.fatal(ret) + return ret + bdir=os.path.join(dir,'testbuild') + if not os.path.exists(bdir): + os.makedirs(bdir) + self.test_bld=bld=Build.BuildContext(top_dir=dir,out_dir=bdir) + bld.init_dirs() + bld.progress_bar=0 + bld.targets='*' + if kw['compile_filename']: + node=bld.srcnode.make_node(kw['compile_filename']) + node.write(kw['code']) + bld.logger=self.logger + bld.all_envs.update(self.all_envs) + bld.env=kw['env'] + o=bld(features=kw['features'],source=kw['compile_filename'],target='testprog') + for k,v in kw.items(): + setattr(o,k,v) + self.to_log("==>\n%s\n<=="%kw['code']) + bld.targets='*' + ret=-1 + try: + try: + bld.compile() + except Errors.WafError: + ret='Test does not build: %s'%Utils.ex_stack() + self.fatal(ret) + else: + ret=getattr(bld,'retval',0) + finally: + proj=ConfigSet.ConfigSet() + proj['cache_run_c_code']=ret + proj.store(os.path.join(dir,'cache_run_c_code')) + return ret +@conf +def check_cxx(self,*k,**kw): + kw['compiler']='cxx' + return self.check(*k,**kw) +@conf +def check_cc(self,*k,**kw): + kw['compiler']='c' + return self.check(*k,**kw) +@conf +def define(self,key,val,quote=True): + assert key and isinstance(key,str) + if val is True: + val=1 + elif val in(False,None): + val=0 + if isinstance(val,int)or isinstance(val,float): + s='%s=%s' + else: + s=quote and'%s="%s"'or'%s=%s' + app=s%(key,str(val)) + ban=key+'=' + lst=self.env['DEFINES'] + for x in lst: + if x.startswith(ban): + lst[lst.index(x)]=app + break + else: + self.env.append_value('DEFINES',app) + self.env.append_unique(DEFKEYS,key) +@conf +def undefine(self,key): + assert key and isinstance(key,str) + ban=key+'=' + lst=[x for x in self.env['DEFINES']if not x.startswith(ban)] + self.env['DEFINES']=lst + self.env.append_unique(DEFKEYS,key) +@conf +def define_cond(self,key,val): + assert key and isinstance(key,str) + if val: + self.define(key,1) + else: + self.undefine(key) +@conf +def is_defined(self,key): + assert key and isinstance(key,str) + ban=key+'=' + for x in self.env['DEFINES']: + if x.startswith(ban): + return True + return False +@conf +def get_define(self,key): + assert key and isinstance(key,str) + ban=key+'=' + for x in self.env['DEFINES']: + if x.startswith(ban): + return x[len(ban):] + return None +@conf +def have_define(self,key): + return(self.env.HAVE_PAT or'HAVE_%s')%Utils.quote_define_name(key) +@conf +def write_config_header(self,configfile='',guard='',top=False,env=None,defines=True,headers=False,remove=True,define_prefix=''): + if env: + Logs.warn('Cannot pass env to write_config_header') + if not configfile:configfile=WAF_CONFIG_H + waf_guard=guard or'W_%s_WAF'%Utils.quote_define_name(configfile) + node=top and self.bldnode or self.path.get_bld() + node=node.make_node(configfile) + node.parent.mkdir() + lst=['/* WARNING! All changes made to this file will be lost! */\n'] + lst.append('#ifndef %s\n#define %s\n'%(waf_guard,waf_guard)) + lst.append(self.get_config_header(defines,headers,define_prefix=define_prefix)) + lst.append('\n#endif /* %s */\n'%waf_guard) + node.write('\n'.join(lst)) + self.env.append_unique(Build.CFG_FILES,[node.abspath()]) + if remove: + for key in self.env[DEFKEYS]: + self.undefine(key) + self.env[DEFKEYS]=[] +@conf +def get_config_header(self,defines=True,headers=False,define_prefix=''): + lst=[] + if headers: + for x in self.env[INCKEYS]: + lst.append('#include <%s>'%x) + if defines: + for x in self.env[DEFKEYS]: + if self.is_defined(x): + val=self.get_define(x) + lst.append('#define %s %s'%(define_prefix+x,val)) + else: + lst.append('/* #undef %s */'%(define_prefix+x)) + return"\n".join(lst) +@conf +def cc_add_flags(conf): + conf.add_os_flags('CPPFLAGS','CFLAGS') + conf.add_os_flags('CFLAGS') +@conf +def cxx_add_flags(conf): + conf.add_os_flags('CPPFLAGS','CXXFLAGS') + conf.add_os_flags('CXXFLAGS') +@conf +def link_add_flags(conf): + conf.add_os_flags('LINKFLAGS') + conf.add_os_flags('LDFLAGS','LINKFLAGS') +@conf +def cc_load_tools(conf): + if not conf.env.DEST_OS: + conf.env.DEST_OS=Utils.unversioned_sys_platform() + conf.load('c') +@conf +def cxx_load_tools(conf): + if not conf.env.DEST_OS: + conf.env.DEST_OS=Utils.unversioned_sys_platform() + conf.load('cxx') +@conf +def get_cc_version(conf,cc,gcc=False,icc=False): + cmd=cc+['-dM','-E','-'] + env=conf.env.env or None + try: + p=Utils.subprocess.Popen(cmd,stdin=Utils.subprocess.PIPE,stdout=Utils.subprocess.PIPE,stderr=Utils.subprocess.PIPE,env=env) + p.stdin.write('\n') + out=p.communicate()[0] + except Exception: + conf.fatal('Could not determine the compiler version %r'%cmd) + if not isinstance(out,str): + out=out.decode(sys.stdout.encoding or'iso8859-1') + if gcc: + if out.find('__INTEL_COMPILER')>=0: + conf.fatal('The intel compiler pretends to be gcc') + if out.find('__GNUC__')<0: + conf.fatal('Could not determine the compiler type') + if icc and out.find('__INTEL_COMPILER')<0: + conf.fatal('Not icc/icpc') + k={} + if icc or gcc: + out=out.splitlines() + for line in out: + lst=shlex.split(line) + if len(lst)>2: + key=lst[1] + val=lst[2] + k[key]=val + def isD(var): + return var in k + def isT(var): + return var in k and k[var]!='0' + if not conf.env.DEST_OS: + conf.env.DEST_OS='' + for i in MACRO_TO_DESTOS: + if isD(i): + conf.env.DEST_OS=MACRO_TO_DESTOS[i] + break + else: + if isD('__APPLE__')and isD('__MACH__'): + conf.env.DEST_OS='darwin' + elif isD('__unix__'): + conf.env.DEST_OS='generic' + if isD('__ELF__'): + conf.env.DEST_BINFMT='elf' + elif isD('__WINNT__')or isD('__CYGWIN__'): + conf.env.DEST_BINFMT='pe' + conf.env.LIBDIR=conf.env['PREFIX']+'/bin' + elif isD('__APPLE__'): + conf.env.DEST_BINFMT='mac-o' + if not conf.env.DEST_BINFMT: + conf.env.DEST_BINFMT=Utils.destos_to_binfmt(conf.env.DEST_OS) + for i in MACRO_TO_DEST_CPU: + if isD(i): + conf.env.DEST_CPU=MACRO_TO_DEST_CPU[i] + break + Logs.debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')])) + if icc: + ver=k['__INTEL_COMPILER'] + conf.env['CC_VERSION']=(ver[:-2],ver[-2],ver[-1]) + else: + if isD('__clang__'): + conf.env['CC_VERSION']=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__']) + else: + conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__']) + return k +@conf +def get_xlc_version(conf,cc): + cmd=cc+['-qversion'] + try: + out,err=conf.cmd_and_log(cmd,output=0) + except Errors.WafError: + conf.fatal('Could not find xlc %r'%cmd) + for v in(r"IBM XL C/C\+\+.* V(?P\d*)\.(?P\d*)",): + version_re=re.compile(v,re.I).search + match=version_re(out or err) + if match: + k=match.groupdict() + conf.env['CC_VERSION']=(k['major'],k['minor']) + break + else: + conf.fatal('Could not determine the XLC version.') +@conf +def add_as_needed(self): + if self.env.DEST_BINFMT=='elf'and'gcc'in(self.env.CXX_NAME,self.env.CC_NAME): + self.env.append_unique('LINKFLAGS','--as-needed') +class cfgtask(Task.TaskBase): + def display(self): + return'' + def runnable_status(self): + return Task.RUN_ME + def uid(self): + return Utils.SIG_NIL + def run(self): + conf=self.conf + bld=Build.BuildContext(top_dir=conf.srcnode.abspath(),out_dir=conf.bldnode.abspath()) + bld.env=conf.env + bld.init_dirs() + bld.in_msg=1 + bld.logger=self.logger + try: + bld.check(**self.args) + except Exception: + return 1 +@conf +def multicheck(self,*k,**kw): + self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k))) + class par(object): + def __init__(self): + self.keep=False + self.cache_global=Options.cache_global + self.nocache=Options.options.nocache + self.returned_tasks=[] + self.task_sigs={} + def total(self): + return len(tasks) + def to_log(self,*k,**kw): + return + bld=par() + tasks=[] + for dct in k: + x=cfgtask(bld=bld) + tasks.append(x) + x.args=dct + x.bld=bld + x.conf=self + x.args=dct + x.logger=Logs.make_mem_logger(str(id(x)),self.logger) + def it(): + yield tasks + while 1: + yield[] + p=Runner.Parallel(bld,Options.options.jobs) + p.biter=it() + p.start() + for x in tasks: + x.logger.memhandler.flush() + for x in tasks: + if x.hasrun!=Task.SUCCESS: + self.end_msg(kw.get('errmsg','no'),color='YELLOW') + self.fatal(kw.get('fatalmsg',None)or'One of the tests has failed, see the config.log for more information') + self.end_msg('ok') diff --git a/waflib/Tools/c_osx.py b/waflib/Tools/c_osx.py new file mode 100644 index 00000000..579b2a78 --- /dev/null +++ b/waflib/Tools/c_osx.py @@ -0,0 +1,120 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,shutil,sys,platform +from waflib import TaskGen,Task,Build,Options,Utils,Errors +from waflib.TaskGen import taskgen_method,feature,after_method,before_method +app_info=''' + + + + + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Waf + CFBundleSignature + ???? + NOTE + THIS IS A GENERATED FILE, DO NOT MODIFY + CFBundleExecutable + %s + + +''' +@feature('c','cxx') +def set_macosx_deployment_target(self): + if self.env['MACOSX_DEPLOYMENT_TARGET']: + os.environ['MACOSX_DEPLOYMENT_TARGET']=self.env['MACOSX_DEPLOYMENT_TARGET'] + elif'MACOSX_DEPLOYMENT_TARGET'not in os.environ: + if Utils.unversioned_sys_platform()=='darwin': + os.environ['MACOSX_DEPLOYMENT_TARGET']='.'.join(platform.mac_ver()[0].split('.')[:2]) +@taskgen_method +def create_bundle_dirs(self,name,out): + bld=self.bld + dir=out.parent.find_or_declare(name) + dir.mkdir() + macos=dir.find_or_declare(['Contents','MacOS']) + macos.mkdir() + return dir +def bundle_name_for_output(out): + name=out.name + k=name.rfind('.') + if k>=0: + name=name[:k]+'.app' + else: + name=name+'.app' + return name +@feature('cprogram','cxxprogram') +@after_method('apply_link') +def create_task_macapp(self): + if self.env['MACAPP']or getattr(self,'mac_app',False): + out=self.link_task.outputs[0] + name=bundle_name_for_output(out) + dir=self.create_bundle_dirs(name,out) + n1=dir.find_or_declare(['Contents','MacOS',out.name]) + self.apptask=self.create_task('macapp',self.link_task.outputs,n1) + inst_to=getattr(self,'install_path','/Applications')+'/%s/Contents/MacOS/'%name + self.bld.install_files(inst_to,n1,chmod=Utils.O755) + if getattr(self,'mac_resources',None): + res_dir=n1.parent.parent.make_node('Resources') + inst_to=getattr(self,'install_path','/Applications')+'/%s/Resources'%name + for x in self.to_list(self.mac_resources): + node=self.path.find_node(x) + if not node: + raise Errors.WafError('Missing mac_resource %r in %r'%(x,self)) + parent=node.parent + if os.path.isdir(node.abspath()): + nodes=node.ant_glob('**') + else: + nodes=[node] + for node in nodes: + rel=node.path_from(parent) + tsk=self.create_task('macapp',node,res_dir.make_node(rel)) + self.bld.install_as(inst_to+'/%s'%rel,node) + if getattr(self.bld,'is_install',None): + self.install_task.hasrun=Task.SKIP_ME +@feature('cprogram','cxxprogram') +@after_method('apply_link') +def create_task_macplist(self): + if self.env['MACAPP']or getattr(self,'mac_app',False): + out=self.link_task.outputs[0] + name=bundle_name_for_output(out) + dir=self.create_bundle_dirs(name,out) + n1=dir.find_or_declare(['Contents','Info.plist']) + self.plisttask=plisttask=self.create_task('macplist',[],n1) + if getattr(self,'mac_plist',False): + node=self.path.find_resource(self.mac_plist) + if node: + plisttask.inputs.append(node) + else: + plisttask.code=self.mac_plist + else: + plisttask.code=app_info%self.link_task.outputs[0].name + inst_to=getattr(self,'install_path','/Applications')+'/%s/Contents/'%name + self.bld.install_files(inst_to,n1) +@feature('cshlib','cxxshlib') +@before_method('apply_link','propagate_uselib_vars') +def apply_bundle(self): + if self.env['MACBUNDLE']or getattr(self,'mac_bundle',False): + self.env['LINKFLAGS_cshlib']=self.env['LINKFLAGS_cxxshlib']=[] + self.env['cshlib_PATTERN']=self.env['cxxshlib_PATTERN']=self.env['macbundle_PATTERN'] + use=self.use=self.to_list(getattr(self,'use',[])) + if not'MACBUNDLE'in use: + use.append('MACBUNDLE') +app_dirs=['Contents','Contents/MacOS','Contents/Resources'] +class macapp(Task.Task): + color='PINK' + def run(self): + self.outputs[0].parent.mkdir() + shutil.copy2(self.inputs[0].srcpath(),self.outputs[0].abspath()) +class macplist(Task.Task): + color='PINK' + ext_in=['.bin'] + def run(self): + if getattr(self,'code',None): + txt=self.code + else: + txt=self.inputs[0].read() + self.outputs[0].write(txt) diff --git a/waflib/Tools/c_preproc.py b/waflib/Tools/c_preproc.py new file mode 100644 index 00000000..9dfd8ca8 --- /dev/null +++ b/waflib/Tools/c_preproc.py @@ -0,0 +1,604 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re,string,traceback +from waflib import Logs,Utils,Errors +from waflib.Logs import debug,error +class PreprocError(Errors.WafError): + pass +POPFILE='-' +recursion_limit=150 +go_absolute=False +standard_includes=['/usr/include'] +if Utils.is_win32: + standard_includes=[] +use_trigraphs=0 +strict_quotes=0 +g_optrans={'not':'!','and':'&&','bitand':'&','and_eq':'&=','or':'||','bitor':'|','or_eq':'|=','xor':'^','xor_eq':'^=','compl':'~',} +re_lines=re.compile('^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$',re.IGNORECASE|re.MULTILINE) +re_mac=re.compile("^[a-zA-Z_]\w*") +re_fun=re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') +re_pragma_once=re.compile('^\s*once\s*',re.IGNORECASE) +re_nl=re.compile('\\\\\r*\n',re.MULTILINE) +re_cpp=re.compile(r"""(/\*[^*]*\*+([^/*][^*]*\*+)*/)|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)""",re.MULTILINE) +trig_def=[('??'+a,b)for a,b in zip("=-/!'()<>",r'#~\|^[]{}')] +chr_esc={'0':0,'a':7,'b':8,'t':9,'n':10,'f':11,'v':12,'r':13,'\\':92,"'":39} +NUM='i' +OP='O' +IDENT='T' +STR='s' +CHAR='c' +tok_types=[NUM,STR,IDENT,OP] +exp_types=[r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""",r'L?"([^"\\]|\\.)*"',r'[a-zA-Z_]\w*',r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]',] +re_clexer=re.compile('|'.join(["(?P<%s>%s)"%(name,part)for name,part in zip(tok_types,exp_types)]),re.M) +accepted='a' +ignored='i' +undefined='u' +skipped='s' +def repl(m): + s=m.group(1) + if s: + return' ' + return m.group(3)or'' +def filter_comments(filename): + code=Utils.readf(filename) + if use_trigraphs: + for(a,b)in trig_def:code=code.split(a).join(b) + code=re_nl.sub('',code) + code=re_cpp.sub(repl,code) + return[(m.group(2),m.group(3))for m in re.finditer(re_lines,code)] +prec={} +ops=['* / %','+ -','<< >>','< <= >= >','== !=','& | ^','&& ||',','] +for x in range(len(ops)): + syms=ops[x] + for u in syms.split(): + prec[u]=x +def trimquotes(s): + if not s:return'' + s=s.rstrip() + if s[0]=="'"and s[-1]=="'":return s[1:-1] + return s +def reduce_nums(val_1,val_2,val_op): + try:a=0+val_1 + except TypeError:a=int(val_1) + try:b=0+val_2 + except TypeError:b=int(val_2) + d=val_op + if d=='%':c=a%b + elif d=='+':c=a+b + elif d=='-':c=a-b + elif d=='*':c=a*b + elif d=='/':c=a/b + elif d=='^':c=a^b + elif d=='|':c=a|b + elif d=='||':c=int(a or b) + elif d=='&':c=a&b + elif d=='&&':c=int(a and b) + elif d=='==':c=int(a==b) + elif d=='!=':c=int(a!=b) + elif d=='<=':c=int(a<=b) + elif d=='<':c=int(a':c=int(a>b) + elif d=='>=':c=int(a>=b) + elif d=='^':c=int(a^b) + elif d=='<<':c=a<>':c=a>>b + else:c=0 + return c +def get_num(lst): + if not lst:raise PreprocError("empty list for get_num") + (p,v)=lst[0] + if p==OP: + if v=='(': + count_par=1 + i=1 + while i=prec[v]: + num2=reduce_nums(num,num2,v) + return get_term([(NUM,num2)]+lst) + else: + num3,lst=get_num(lst[1:]) + num3=reduce_nums(num2,num3,v2) + return get_term([(NUM,num),(p,v),(NUM,num3)]+lst) + raise PreprocError("cannot reduce %r"%lst) +def reduce_eval(lst): + num,lst=get_term(lst) + return(NUM,num) +def stringize(lst): + lst=[str(v2)for(p2,v2)in lst] + return"".join(lst) +def paste_tokens(t1,t2): + p1=None + if t1[0]==OP and t2[0]==OP: + p1=OP + elif t1[0]==IDENT and(t2[0]==IDENT or t2[0]==NUM): + p1=IDENT + elif t1[0]==NUM and t2[0]==NUM: + p1=NUM + if not p1: + raise PreprocError('tokens do not make a valid paste %r and %r'%(t1,t2)) + return(p1,t1[1]+t2[1]) +def reduce_tokens(lst,defs,ban=[]): + i=0 + while i=len(lst): + raise PreprocError("expected '(' after %r (got nothing)"%v) + (p2,v2)=lst[i] + if p2!=OP or v2!='(': + raise PreprocError("expected '(' after %r"%v) + del lst[i] + one_param=[] + count_paren=0 + while i1: + (p3,v3)=accu[-1] + (p4,v4)=accu[-2] + if v3=='##': + accu.pop() + if v4==','and pt.*)>|"(?P.*)")') +def extract_include(txt,defs): + m=re_include.search(txt) + if m: + if m.group('a'):return'<',m.group('a') + if m.group('b'):return'"',m.group('b') + toks=tokenize(txt) + reduce_tokens(toks,defs,['waf_include']) + if not toks: + raise PreprocError("could not parse include %s"%txt) + if len(toks)==1: + if toks[0][0]==STR: + return'"',toks[0][1] + else: + if toks[0][1]=='<'and toks[-1][1]=='>': + return stringize(toks).lstrip('<').rstrip('>') + raise PreprocError("could not parse include %s."%txt) +def parse_char(txt): + if not txt:raise PreprocError("attempted to parse a null char") + if txt[0]!='\\': + return ord(txt) + c=txt[1] + if c=='x': + if len(txt)==4 and txt[3]in string.hexdigits:return int(txt[2:],16) + return int(txt[2:],16) + elif c.isdigit(): + if c=='0'and len(txt)==2:return 0 + for i in 3,2,1: + if len(txt)>i and txt[1:1+i].isdigit(): + return(1+i,int(txt[1:1+i],8)) + else: + try:return chr_esc[c] + except KeyError:raise PreprocError("could not parse char literal '%s'"%txt) +def tokenize(s): + return tokenize_private(s)[:] +@Utils.run_once +def tokenize_private(s): + ret=[] + for match in re_clexer.finditer(s): + m=match.group + for name in tok_types: + v=m(name) + if v: + if name==IDENT: + try:v=g_optrans[v];name=OP + except KeyError: + if v.lower()=="true": + v=1 + name=NUM + elif v.lower()=="false": + v=0 + name=NUM + elif name==NUM: + if m('oct'):v=int(v,8) + elif m('hex'):v=int(m('hex'),16) + elif m('n0'):v=m('n0') + else: + v=m('char') + if v:v=parse_char(v) + else:v=m('n2')or m('n4') + elif name==OP: + if v=='%:':v='#' + elif v=='%:%:':v='##' + elif name==STR: + v=v[1:-1] + ret.append((name,v)) + break + return ret +@Utils.run_once +def define_name(line): + return re_mac.match(line).group(0) +class c_parser(object): + def __init__(self,nodepaths=None,defines=None): + self.lines=[] + if defines is None: + self.defs={} + else: + self.defs=dict(defines) + self.state=[] + self.count_files=0 + self.currentnode_stack=[] + self.nodepaths=nodepaths or[] + self.nodes=[] + self.names=[] + self.curfile='' + self.ban_includes=set([]) + def cached_find_resource(self,node,filename): + try: + nd=node.ctx.cache_nd + except AttributeError: + nd=node.ctx.cache_nd={} + tup=(node,filename) + try: + return nd[tup] + except KeyError: + ret=node.find_resource(filename) + if ret: + if getattr(ret,'children',None): + ret=None + elif ret.is_child_of(node.ctx.bldnode): + tmp=node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) + if tmp and getattr(tmp,'children',None): + ret=None + nd[tup]=ret + return ret + def tryfind(self,filename): + self.curfile=filename + found=self.cached_find_resource(self.currentnode_stack[-1],filename) + for n in self.nodepaths: + if found: + break + found=self.cached_find_resource(n,filename) + if found: + self.nodes.append(found) + if filename[-4:]!='.moc': + self.addlines(found) + else: + if not filename in self.names: + self.names.append(filename) + return found + def addlines(self,node): + self.currentnode_stack.append(node.parent) + filepath=node.abspath() + self.count_files+=1 + if self.count_files>recursion_limit: + raise PreprocError("recursion limit exceeded") + pc=self.parse_cache + debug('preproc: reading file %r',filepath) + try: + lns=pc[filepath] + except KeyError: + pass + else: + self.lines.extend(lns) + return + try: + lines=filter_comments(filepath) + lines.append((POPFILE,'')) + lines.reverse() + pc[filepath]=lines + self.lines.extend(lines) + except IOError: + raise PreprocError("could not read the file %s"%filepath) + except Exception: + if Logs.verbose>0: + error("parsing %s failed"%filepath) + traceback.print_exc() + def start(self,node,env): + debug('preproc: scanning %s (in %s)',node.name,node.parent.name) + bld=node.ctx + try: + self.parse_cache=bld.parse_cache + except AttributeError: + bld.parse_cache={} + self.parse_cache=bld.parse_cache + self.addlines(node) + if env['DEFINES']: + try: + lst=['%s %s'%(x[0],trimquotes('='.join(x[1:])))for x in[y.split('=')for y in env['DEFINES']]] + lst.reverse() + self.lines.extend([('define',x)for x in lst]) + except AttributeError: + pass + while self.lines: + (token,line)=self.lines.pop() + if token==POPFILE: + self.count_files-=1 + self.currentnode_stack.pop() + continue + try: + ve=Logs.verbose + if ve:debug('preproc: line is %s - %s state is %s',token,line,self.state) + state=self.state + if token[:2]=='if': + state.append(undefined) + elif token=='endif': + state.pop() + if token[0]!='e': + if skipped in self.state or ignored in self.state: + continue + if token=='if': + ret=eval_macro(tokenize(line),self.defs) + if ret:state[-1]=accepted + else:state[-1]=ignored + elif token=='ifdef': + m=re_mac.match(line) + if m and m.group(0)in self.defs:state[-1]=accepted + else:state[-1]=ignored + elif token=='ifndef': + m=re_mac.match(line) + if m and m.group(0)in self.defs:state[-1]=ignored + else:state[-1]=accepted + elif token=='include'or token=='import': + (kind,inc)=extract_include(line,self.defs) + if inc in self.ban_includes: + continue + if token=='import':self.ban_includes.add(inc) + if ve:debug('preproc: include found %s (%s) ',inc,kind) + if kind=='"'or not strict_quotes: + self.tryfind(inc) + elif token=='elif': + if state[-1]==accepted: + state[-1]=skipped + elif state[-1]==ignored: + if eval_macro(tokenize(line),self.defs): + state[-1]=accepted + elif token=='else': + if state[-1]==accepted:state[-1]=skipped + elif state[-1]==ignored:state[-1]=accepted + elif token=='define': + try: + self.defs[define_name(line)]=line + except Exception: + raise PreprocError("Invalid define line %s"%line) + elif token=='undef': + m=re_mac.match(line) + if m and m.group(0)in self.defs: + self.defs.__delitem__(m.group(0)) + elif token=='pragma': + if re_pragma_once.match(line.lower()): + self.ban_includes.add(self.curfile) + except Exception ,e: + if Logs.verbose: + debug('preproc: line parsing failed (%s): %s %s',e,line,Utils.ex_stack()) +def scan(task): + global go_absolute + try: + incn=task.generator.includes_nodes + except AttributeError: + raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": '%task.generator) + if go_absolute: + nodepaths=incn+[task.generator.bld.root.find_dir(x)for x in standard_includes] + else: + nodepaths=[x for x in incn if x.is_child_of(x.ctx.srcnode)or x.is_child_of(x.ctx.bldnode)] + tmp=c_parser(nodepaths) + tmp.start(task.inputs[0],task.env) + if Logs.verbose: + debug('deps: deps for %r: %r; unresolved %r'%(task.inputs,tmp.nodes,tmp.names)) + return(tmp.nodes,tmp.names) diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py new file mode 100644 index 00000000..f275977b --- /dev/null +++ b/waflib/Tools/c_tests.py @@ -0,0 +1,153 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib import Task +from waflib.Configure import conf +from waflib.TaskGen import feature,before_method,after_method +import sys +LIB_CODE=''' +#ifdef _MSC_VER +#define testEXPORT __declspec(dllexport) +#else +#define testEXPORT +#endif +testEXPORT int lib_func(void) { return 9; } +''' +MAIN_CODE=''' +#ifdef _MSC_VER +#define testEXPORT __declspec(dllimport) +#else +#define testEXPORT +#endif +testEXPORT int lib_func(void); +int main(int argc, char **argv) { + (void)argc; (void)argv; + return !(lib_func() == 9); +} +''' +@feature('link_lib_test') +@before_method('process_source') +def link_lib_test_fun(self): + def write_test_file(task): + task.outputs[0].write(task.generator.code) + rpath=[] + if getattr(self,'add_rpath',False): + rpath=[self.bld.path.get_bld().abspath()] + mode=self.mode + m='%s %s'%(mode,mode) + ex=self.test_exec and'test_exec'or'' + bld=self.bld + bld(rule=write_test_file,target='test.'+mode,code=LIB_CODE) + bld(rule=write_test_file,target='main.'+mode,code=MAIN_CODE) + bld(features='%sshlib'%m,source='test.'+mode,target='test') + bld(features='%sprogram %s'%(m,ex),source='main.'+mode,target='app',use='test',rpath=rpath) +@conf +def check_library(self,mode=None,test_exec=True): + if not mode: + mode='c' + if self.env.CXX: + mode='cxx' + self.check(compile_filename=[],features='link_lib_test',msg='Checking for libraries',mode=mode,test_exec=test_exec,) +INLINE_CODE=''' +typedef int foo_t; +static %s foo_t static_foo () {return 0; } +%s foo_t foo () { + return 0; +} +''' +INLINE_VALUES=['inline','__inline__','__inline'] +@conf +def check_inline(self,**kw): + self.start_msg('Checking for inline') + if not'define_name'in kw: + kw['define_name']='INLINE_MACRO' + if not'features'in kw: + if self.env.CXX: + kw['features']=['cxx'] + else: + kw['features']=['c'] + for x in INLINE_VALUES: + kw['fragment']=INLINE_CODE%(x,x) + try: + self.check(**kw) + except self.errors.ConfigurationError: + continue + else: + self.end_msg(x) + if x!='inline': + self.define('inline',x,quote=False) + return x + self.fatal('could not use inline functions') +LARGE_FRAGMENT='''#include +int main(int argc, char **argv) { + (void)argc; (void)argv; + return !(sizeof(off_t) >= 8); +} +''' +@conf +def check_large_file(self,**kw): + if not'define_name'in kw: + kw['define_name']='HAVE_LARGEFILE' + if not'execute'in kw: + kw['execute']=True + if not'features'in kw: + if self.env.CXX: + kw['features']=['cxx','cxxprogram'] + else: + kw['features']=['c','cprogram'] + kw['fragment']=LARGE_FRAGMENT + kw['msg']='Checking for large file support' + ret=True + try: + if self.env.DEST_BINFMT!='pe': + ret=self.check(**kw) + except self.errors.ConfigurationError: + pass + else: + if ret: + return True + kw['msg']='Checking for -D_FILE_OFFSET_BITS=64' + kw['defines']=['_FILE_OFFSET_BITS=64'] + try: + ret=self.check(**kw) + except self.errors.ConfigurationError: + pass + else: + self.define('_FILE_OFFSET_BITS',64) + return ret + self.fatal('There is no support for large files') +ENDIAN_FRAGMENT=''' +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; +} +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; +} +extern int foo; +''' +class grep_for_endianness(Task.Task): + color='PINK' + def run(self): + txt=self.inputs[0].read(flags='rb').decode('iso8859-1') + if txt.find('LiTTleEnDian')>-1: + self.generator.tmp.append('little') + elif txt.find('BIGenDianSyS')>-1: + self.generator.tmp.append('big') + else: + return-1 +@feature('grep_for_endianness') +@after_method('process_source') +def grep_for_endianness_fun(self): + self.create_task('grep_for_endianness',self.compiled_tasks[0].outputs[0]) +@conf +def check_endianness(self): + tmp=[] + def check_msg(self): + return tmp[0] + self.check(fragment=ENDIAN_FRAGMENT,features='c grep_for_endianness',msg="Checking for endianness",define='ENDIANNESS',tmp=tmp,okmsg=check_msg) + return tmp[0] diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py new file mode 100644 index 00000000..18c57ce9 --- /dev/null +++ b/waflib/Tools/ccroot.py @@ -0,0 +1,391 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Task,Utils,Node,Errors +from waflib.TaskGen import after_method,before_method,feature,taskgen_method,extension +from waflib.Tools import c_aliases,c_preproc,c_config,c_osx,c_tests +from waflib.Configure import conf +SYSTEM_LIB_PATHS=['/usr/lib64','/usr/lib','/usr/local/lib64','/usr/local/lib'] +USELIB_VARS=Utils.defaultdict(set) +USELIB_VARS['c']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CCDEPS','CFLAGS','ARCH']) +USELIB_VARS['cxx']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CXXDEPS','CXXFLAGS','ARCH']) +USELIB_VARS['d']=set(['INCLUDES','DFLAGS']) +USELIB_VARS['includes']=set(['INCLUDES','FRAMEWORKPATH','ARCH']) +USELIB_VARS['cprogram']=USELIB_VARS['cxxprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH']) +USELIB_VARS['cshlib']=USELIB_VARS['cxxshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH']) +USELIB_VARS['cstlib']=USELIB_VARS['cxxstlib']=set(['ARFLAGS','LINKDEPS']) +USELIB_VARS['dprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) +USELIB_VARS['dshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) +USELIB_VARS['dstlib']=set(['ARFLAGS','LINKDEPS']) +USELIB_VARS['asm']=set(['ASFLAGS']) +@taskgen_method +def create_compiled_task(self,name,node): + out='%s.%d.o'%(node.name,self.idx) + task=self.create_task(name,node,node.parent.find_or_declare(out)) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks=[task] + return task +@taskgen_method +def to_incnodes(self,inlst): + lst=[] + seen=set([]) + for x in self.to_list(inlst): + if x in seen or not x: + continue + seen.add(x) + if isinstance(x,Node.Node): + lst.append(x) + else: + if os.path.isabs(x): + lst.append(self.bld.root.make_node(x)or x) + else: + if x[0]=='#': + p=self.bld.bldnode.make_node(x[1:]) + v=self.bld.srcnode.make_node(x[1:]) + else: + p=self.path.get_bld().make_node(x) + v=self.path.make_node(x) + if p.is_child_of(self.bld.bldnode): + p.mkdir() + lst.append(p) + lst.append(v) + return lst +@feature('c','cxx','d','asm','fc','includes') +@after_method('propagate_uselib_vars','process_source') +def apply_incpaths(self): + lst=self.to_incnodes(self.to_list(getattr(self,'includes',[]))+self.env['INCLUDES']) + self.includes_nodes=lst + self.env['INCPATHS']=[x.abspath()for x in lst] +class link_task(Task.Task): + color='YELLOW' + inst_to=None + chmod=Utils.O755 + def add_target(self,target): + if isinstance(target,str): + pattern=self.env[self.__class__.__name__+'_PATTERN'] + if not pattern: + pattern='%s' + folder,name=os.path.split(target) + if self.__class__.__name__.find('shlib')>0: + if self.env.DEST_BINFMT=='pe'and getattr(self.generator,'vnum',None): + name=name+'-'+self.generator.vnum.split('.')[0] + tmp=folder+os.sep+pattern%name + target=self.generator.path.find_or_declare(tmp) + self.set_outputs(target) +class stlink_task(link_task): + run_str='${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' +def rm_tgt(cls): + old=cls.run + def wrap(self): + try:os.remove(self.outputs[0].abspath()) + except OSError:pass + return old(self) + setattr(cls,'run',wrap) +rm_tgt(stlink_task) +@feature('c','cxx','d','fc','asm') +@after_method('process_source') +def apply_link(self): + for x in self.features: + if x=='cprogram'and'cxx'in self.features: + x='cxxprogram' + elif x=='cshlib'and'cxx'in self.features: + x='cxxshlib' + if x in Task.classes: + if issubclass(Task.classes[x],link_task): + link=x + break + else: + return + objs=[t.outputs[0]for t in getattr(self,'compiled_tasks',[])] + self.link_task=self.create_task(link,objs) + self.link_task.add_target(self.target) + try: + inst_to=self.install_path + except AttributeError: + inst_to=self.link_task.__class__.inst_to + if inst_to: + self.install_task=self.bld.install_files(inst_to,self.link_task.outputs[:],env=self.env,chmod=self.link_task.chmod) +@taskgen_method +def use_rec(self,name,**kw): + if name in self.tmp_use_not or name in self.tmp_use_seen: + return + try: + y=self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.uselib.append(name) + self.tmp_use_not.add(name) + return + self.tmp_use_seen.append(name) + y.post() + y.tmp_use_objects=objects=kw.get('objects',True) + y.tmp_use_stlib=stlib=kw.get('stlib',True) + try: + link_task=y.link_task + except AttributeError: + y.tmp_use_var='' + else: + objects=False + if not isinstance(link_task,stlink_task): + stlib=False + y.tmp_use_var='LIB' + else: + y.tmp_use_var='STLIB' + p=self.tmp_use_prec + for x in self.to_list(getattr(y,'use',[])): + try: + p[x].append(name) + except KeyError: + p[x]=[name] + self.use_rec(x,objects=objects,stlib=stlib) +@feature('c','cxx','d','use','fc') +@before_method('apply_incpaths','propagate_uselib_vars') +@after_method('apply_link','process_source') +def process_use(self): + use_not=self.tmp_use_not=set([]) + self.tmp_use_seen=[] + use_prec=self.tmp_use_prec={} + self.uselib=self.to_list(getattr(self,'uselib',[])) + self.includes=self.to_list(getattr(self,'includes',[])) + names=self.to_list(getattr(self,'use',[])) + for x in names: + self.use_rec(x) + for x in use_not: + if x in use_prec: + del use_prec[x] + out=[] + tmp=[] + for x in self.tmp_use_seen: + for k in use_prec.values(): + if x in k: + break + else: + tmp.append(x) + while tmp: + e=tmp.pop() + out.append(e) + try: + nlst=use_prec[e] + except KeyError: + pass + else: + del use_prec[e] + for x in nlst: + for y in use_prec: + if x in use_prec[y]: + break + else: + tmp.append(x) + if use_prec: + raise Errors.WafError('Cycle detected in the use processing %r'%use_prec) + out.reverse() + link_task=getattr(self,'link_task',None) + for x in out: + y=self.bld.get_tgen_by_name(x) + var=y.tmp_use_var + if var and link_task: + if var=='LIB'or y.tmp_use_stlib: + self.env.append_value(var,[y.target[y.target.rfind(os.sep)+1:]]) + self.link_task.dep_nodes.extend(y.link_task.outputs) + tmp_path=y.link_task.outputs[0].parent.path_from(self.bld.bldnode) + self.env.append_value(var+'PATH',[tmp_path]) + else: + if y.tmp_use_objects: + self.add_objects_from_tgen(y) + if getattr(y,'export_includes',None): + self.includes.extend(y.to_incnodes(y.export_includes)) + for x in names: + try: + y=self.bld.get_tgen_by_name(x) + except Exception: + if not self.env['STLIB_'+x]and not x in self.uselib: + self.uselib.append(x) + else: + for k in self.to_list(getattr(y,'uselib',[])): + if not self.env['STLIB_'+k]and not k in self.uselib: + self.uselib.append(k) +@taskgen_method +def accept_node_to_link(self,node): + return not node.name.endswith('.pdb') +@taskgen_method +def add_objects_from_tgen(self,tg): + try: + link_task=self.link_task + except AttributeError: + pass + else: + for tsk in getattr(tg,'compiled_tasks',[]): + for x in tsk.outputs: + if self.accept_node_to_link(x): + link_task.inputs.append(x) +@taskgen_method +def get_uselib_vars(self): + _vars=set([]) + for x in self.features: + if x in USELIB_VARS: + _vars|=USELIB_VARS[x] + return _vars +@feature('c','cxx','d','fc','javac','cs','uselib','asm') +@after_method('process_use') +def propagate_uselib_vars(self): + _vars=self.get_uselib_vars() + env=self.env + for x in _vars: + y=x.lower() + env.append_unique(x,self.to_list(getattr(self,y,[]))) + for x in self.features: + for var in _vars: + compvar='%s_%s'%(var,x) + env.append_value(var,env[compvar]) + for x in self.to_list(getattr(self,'uselib',[])): + for v in _vars: + env.append_value(v,env[v+'_'+x]) +@feature('cshlib','cxxshlib','fcshlib') +@after_method('apply_link') +def apply_implib(self): + if not self.env.DEST_BINFMT=='pe': + return + dll=self.link_task.outputs[0] + if isinstance(self.target,Node.Node): + name=self.target.name + else: + name=os.path.split(self.target)[1] + implib=self.env['implib_PATTERN']%name + implib=dll.parent.find_or_declare(implib) + self.env.append_value('LINKFLAGS',self.env['IMPLIB_ST']%implib.bldpath()) + self.link_task.outputs.append(implib) + if getattr(self,'defs',None)and self.env.DEST_BINFMT=='pe': + node=self.path.find_resource(self.defs) + if not node: + raise Errors.WafError('invalid def file %r'%self.defs) + if'msvc'in(self.env.CC_NAME,self.env.CXX_NAME): + self.env.append_value('LINKFLAGS','/def:%s'%node.path_from(self.bld.bldnode)) + self.link_task.dep_nodes.append(node) + else: + self.link_task.inputs.append(node) + try: + inst_to=self.install_path + except AttributeError: + inst_to=self.link_task.__class__.inst_to + if not inst_to: + return + self.implib_install_task=self.bld.install_as('${LIBDIR}/%s'%implib.name,implib,self.env) +@feature('cshlib','cxxshlib','dshlib','fcshlib','vnum') +@after_method('apply_link','propagate_uselib_vars') +def apply_vnum(self): + if not getattr(self,'vnum','')or os.name!='posix'or self.env.DEST_BINFMT not in('elf','mac-o'): + return + link=self.link_task + nums=self.vnum.split('.') + node=link.outputs[0] + libname=node.name + if libname.endswith('.dylib'): + name3=libname.replace('.dylib','.%s.dylib'%self.vnum) + name2=libname.replace('.dylib','.%s.dylib'%nums[0]) + else: + name3=libname+'.'+self.vnum + name2=libname+'.'+nums[0] + if self.env.SONAME_ST: + v=self.env.SONAME_ST%name2 + self.env.append_value('LINKFLAGS',v.split()) + self.create_task('vnum',node,[node.parent.find_or_declare(name2),node.parent.find_or_declare(name3)]) + if getattr(self,'install_task',None): + self.install_task.hasrun=Task.SKIP_ME + bld=self.bld + path=self.install_task.dest + t1=bld.install_as(path+os.sep+name3,node,env=self.env,chmod=self.link_task.chmod) + t2=bld.symlink_as(path+os.sep+name2,name3) + t3=bld.symlink_as(path+os.sep+libname,name3) + self.vnum_install_task=(t1,t2,t3) + if'-dynamiclib'in self.env['LINKFLAGS']: + try: + inst_to=self.install_path + except AttributeError: + inst_to=self.link_task.__class__.inst_to + if inst_to: + p=Utils.subst_vars(inst_to,self.env) + path=os.path.join(p,self.link_task.outputs[0].name) + self.env.append_value('LINKFLAGS',['-install_name',path]) +class vnum(Task.Task): + color='CYAN' + quient=True + ext_in=['.bin'] + def run(self): + for x in self.outputs: + path=x.abspath() + try: + os.remove(path) + except OSError: + pass + try: + os.symlink(self.inputs[0].name,path) + except OSError: + return 1 +class fake_shlib(link_task): + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + for x in self.outputs: + x.sig=Utils.h_file(x.abspath()) + return Task.SKIP_ME +class fake_stlib(stlink_task): + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + for x in self.outputs: + x.sig=Utils.h_file(x.abspath()) + return Task.SKIP_ME +@conf +def read_shlib(self,name,paths=[]): + return self(name=name,features='fake_lib',lib_paths=paths,lib_type='shlib') +@conf +def read_stlib(self,name,paths=[]): + return self(name=name,features='fake_lib',lib_paths=paths,lib_type='stlib') +lib_patterns={'shlib':['lib%s.so','%s.so','lib%s.dylib','lib%s.dll','%s.dll'],'stlib':['lib%s.a','%s.a','lib%s.dll','%s.dll','lib%s.lib','%s.lib'],} +@feature('fake_lib') +def process_lib(self): + node=None + names=[x%self.name for x in lib_patterns[self.lib_type]] + for x in self.lib_paths+[self.path]+SYSTEM_LIB_PATHS: + if not isinstance(x,Node.Node): + x=self.bld.root.find_node(x)or self.path.find_node(x) + if not x: + continue + for y in names: + node=x.find_node(y) + if node: + node.sig=Utils.h_file(node.abspath()) + break + else: + continue + break + else: + raise Errors.WafError('could not find library %r'%self.name) + self.link_task=self.create_task('fake_%s'%self.lib_type,[],[node]) + self.target=self.name +class fake_o(Task.Task): + def runnable_status(self): + return Task.SKIP_ME +@extension('.o','.obj') +def add_those_o_files(self,node): + tsk=self.create_task('fake_o',[],node) + try: + self.compiled_tasks.append(tsk) + except AttributeError: + self.compiled_tasks=[tsk] +@feature('fake_obj') +@before_method('process_source') +def process_objs(self): + for node in self.to_nodes(self.source): + self.add_those_o_files(node) + self.source=[] +@conf +def read_object(self,obj): + if not isinstance(obj,self.path.__class__): + obj=self.path.find_resource(obj) + return self(features='fake_obj',source=obj,name=obj.name) diff --git a/waflib/Tools/compiler_c.py b/waflib/Tools/compiler_c.py new file mode 100644 index 00000000..04504fa0 --- /dev/null +++ b/waflib/Tools/compiler_c.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,imp,types +from waflib.Tools import ccroot +from waflib import Utils,Configure +from waflib.Logs import debug +c_compiler={'win32':['msvc','gcc'],'cygwin':['gcc'],'darwin':['gcc'],'aix':['xlc','gcc'],'linux':['gcc','icc'],'sunos':['suncc','gcc'],'irix':['gcc','irixcc'],'hpux':['gcc'],'gnu':['gcc'],'java':['gcc','msvc','icc'],'default':['gcc'],} +def configure(conf): + try:test_for_compiler=conf.options.check_c_compiler + except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_c')") + for compiler in test_for_compiler.split(): + conf.env.stash() + conf.start_msg('Checking for %r (c compiler)'%compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError ,e: + conf.env.revert() + conf.end_msg(False) + debug('compiler_c: %r'%e) + else: + if conf.env['CC']: + conf.end_msg(conf.env.get_flat('CC')) + conf.env['COMPILER_CC']=compiler + break + conf.end_msg(False) + else: + conf.fatal('could not configure a c compiler!') +def options(opt): + opt.load_special_tools('c_*.py',ban=['c_dumbpreproc.py']) + global c_compiler + build_platform=Utils.unversioned_sys_platform() + possible_compiler_list=c_compiler[build_platform in c_compiler and build_platform or'default'] + test_for_compiler=' '.join(possible_compiler_list) + cc_compiler_opts=opt.add_option_group("C Compiler Options") + cc_compiler_opts.add_option('--check-c-compiler',default="%s"%test_for_compiler,help='On this platform (%s) the following C-Compiler will be checked by default: "%s"'%(build_platform,test_for_compiler),dest="check_c_compiler") + for x in test_for_compiler.split(): + opt.load('%s'%x) diff --git a/waflib/Tools/compiler_cxx.py b/waflib/Tools/compiler_cxx.py new file mode 100644 index 00000000..14b7c7da --- /dev/null +++ b/waflib/Tools/compiler_cxx.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,imp,types +from waflib.Tools import ccroot +from waflib import Utils,Configure +from waflib.Logs import debug +cxx_compiler={'win32':['msvc','g++'],'cygwin':['g++'],'darwin':['g++'],'aix':['xlc++','g++'],'linux':['g++','icpc'],'sunos':['sunc++','g++'],'irix':['g++'],'hpux':['g++'],'gnu':['g++'],'java':['g++','msvc','icpc'],'default':['g++']} +def configure(conf): + try:test_for_compiler=conf.options.check_cxx_compiler + except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_cxx')") + for compiler in test_for_compiler.split(): + conf.env.stash() + conf.start_msg('Checking for %r (c++ compiler)'%compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError ,e: + conf.env.revert() + conf.end_msg(False) + debug('compiler_cxx: %r'%e) + else: + if conf.env['CXX']: + conf.end_msg(conf.env.get_flat('CXX')) + conf.env['COMPILER_CXX']=compiler + break + conf.end_msg(False) + else: + conf.fatal('could not configure a c++ compiler!') +def options(opt): + opt.load_special_tools('cxx_*.py') + global cxx_compiler + build_platform=Utils.unversioned_sys_platform() + possible_compiler_list=cxx_compiler[build_platform in cxx_compiler and build_platform or'default'] + test_for_compiler=' '.join(possible_compiler_list) + cxx_compiler_opts=opt.add_option_group('C++ Compiler Options') + cxx_compiler_opts.add_option('--check-cxx-compiler',default="%s"%test_for_compiler,help='On this platform (%s) the following C++ Compiler will be checked by default: "%s"'%(build_platform,test_for_compiler),dest="check_cxx_compiler") + for x in test_for_compiler.split(): + opt.load('%s'%x) diff --git a/waflib/Tools/compiler_d.py b/waflib/Tools/compiler_d.py new file mode 100644 index 00000000..ee173e10 --- /dev/null +++ b/waflib/Tools/compiler_d.py @@ -0,0 +1,29 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,imp,types +from waflib import Utils,Configure,Options,Logs +def configure(conf): + for compiler in conf.options.dcheck.split(','): + conf.env.stash() + conf.start_msg('Checking for %r (d compiler)'%compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError ,e: + conf.env.revert() + conf.end_msg(False) + Logs.debug('compiler_d: %r'%e) + else: + if conf.env.D: + conf.end_msg(conf.env.get_flat('D')) + conf.env['COMPILER_D']=compiler + break + conf.end_msg(False) + else: + conf.fatal('no suitable d compiler was found') +def options(opt): + d_compiler_opts=opt.add_option_group('D Compiler Options') + d_compiler_opts.add_option('--check-d-compiler',default='gdc,dmd,ldc2',action='store',help='check for the compiler [Default:gdc,dmd,ldc2]',dest='dcheck') + for d_compiler in['gdc','dmd','ldc2']: + opt.load('%s'%d_compiler) diff --git a/waflib/Tools/compiler_fc.py b/waflib/Tools/compiler_fc.py new file mode 100644 index 00000000..ec5d2ead --- /dev/null +++ b/waflib/Tools/compiler_fc.py @@ -0,0 +1,43 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,imp,types +from waflib import Utils,Configure,Options,Logs,Errors +from waflib.Tools import fc +fc_compiler={'win32':['gfortran','ifort'],'darwin':['gfortran','g95','ifort'],'linux':['gfortran','g95','ifort'],'java':['gfortran','g95','ifort'],'default':['gfortran'],'aix':['gfortran']} +def __list_possible_compiler(platform): + try: + return fc_compiler[platform] + except KeyError: + return fc_compiler["default"] +def configure(conf): + try:test_for_compiler=conf.options.check_fc + except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_fc')") + for compiler in test_for_compiler.split(): + conf.env.stash() + conf.start_msg('Checking for %r (fortran compiler)'%compiler) + try: + conf.load(compiler) + except conf.errors.ConfigurationError ,e: + conf.env.revert() + conf.end_msg(False) + Logs.debug('compiler_fortran: %r'%e) + else: + if conf.env['FC']: + conf.end_msg(conf.env.get_flat('FC')) + conf.env.COMPILER_FORTRAN=compiler + break + conf.end_msg(False) + else: + conf.fatal('could not configure a fortran compiler!') +def options(opt): + opt.load_special_tools('fc_*.py') + build_platform=Utils.unversioned_sys_platform() + detected_platform=Options.platform + possible_compiler_list=__list_possible_compiler(detected_platform) + test_for_compiler=' '.join(possible_compiler_list) + fortran_compiler_opts=opt.add_option_group("Fortran Compiler Options") + fortran_compiler_opts.add_option('--check-fortran-compiler',default="%s"%test_for_compiler,help='On this platform (%s) the following Fortran Compiler will be checked by default: "%s"'%(detected_platform,test_for_compiler),dest="check_fc") + for compiler in test_for_compiler.split(): + opt.load('%s'%compiler) diff --git a/waflib/Tools/cs.py b/waflib/Tools/cs.py new file mode 100644 index 00000000..ee4d3190 --- /dev/null +++ b/waflib/Tools/cs.py @@ -0,0 +1,132 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib import Utils,Task,Options,Logs,Errors +from waflib.TaskGen import before_method,after_method,feature +from waflib.Tools import ccroot +from waflib.Configure import conf +import os,tempfile +ccroot.USELIB_VARS['cs']=set(['CSFLAGS','ASSEMBLIES','RESOURCES']) +ccroot.lib_patterns['csshlib']=['%s'] +@feature('cs') +@before_method('process_source') +def apply_cs(self): + cs_nodes=[] + no_nodes=[] + for x in self.to_nodes(self.source): + if x.name.endswith('.cs'): + cs_nodes.append(x) + else: + no_nodes.append(x) + self.source=no_nodes + bintype=getattr(self,'bintype',self.gen.endswith('.dll')and'library'or'exe') + self.cs_task=tsk=self.create_task('mcs',cs_nodes,self.path.find_or_declare(self.gen)) + tsk.env.CSTYPE='/target:%s'%bintype + tsk.env.OUT='/out:%s'%tsk.outputs[0].abspath() + self.env.append_value('CSFLAGS','/platform:%s'%getattr(self,'platform','anycpu')) + inst_to=getattr(self,'install_path',bintype=='exe'and'${BINDIR}'or'${LIBDIR}') + if inst_to: + mod=getattr(self,'chmod',bintype=='exe'and Utils.O755 or Utils.O644) + self.install_task=self.bld.install_files(inst_to,self.cs_task.outputs[:],env=self.env,chmod=mod) +@feature('cs') +@after_method('apply_cs') +def use_cs(self): + names=self.to_list(getattr(self,'use',[])) + get=self.bld.get_tgen_by_name + for x in names: + try: + y=get(x) + except Errors.WafError: + self.env.append_value('CSFLAGS','/reference:%s'%x) + continue + y.post() + tsk=getattr(y,'cs_task',None)or getattr(y,'link_task',None) + if not tsk: + self.bld.fatal('cs task has no link task for use %r'%self) + self.cs_task.dep_nodes.extend(tsk.outputs) + self.cs_task.set_run_after(tsk) + self.env.append_value('CSFLAGS','/reference:%s'%tsk.outputs[0].abspath()) +@feature('cs') +@after_method('apply_cs','use_cs') +def debug_cs(self): + csdebug=getattr(self,'csdebug',self.env.CSDEBUG) + if not csdebug: + return + node=self.cs_task.outputs[0] + if self.env.CS_NAME=='mono': + out=node.parent.find_or_declare(node.name+'.mdb') + else: + out=node.change_ext('.pdb') + self.cs_task.outputs.append(out) + try: + self.install_task.source.append(out) + except AttributeError: + pass + if csdebug=='pdbonly': + val=['/debug+','/debug:pdbonly'] + elif csdebug=='full': + val=['/debug+','/debug:full'] + else: + val=['/debug-'] + self.env.append_value('CSFLAGS',val) +class mcs(Task.Task): + color='YELLOW' + run_str='${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' + def exec_command(self,cmd,**kw): + bld=self.generator.bld + try: + if not kw.get('cwd',None): + kw['cwd']=bld.cwd + except AttributeError: + bld.cwd=kw['cwd']=bld.variant_dir + try: + tmp=None + if isinstance(cmd,list)and len(' '.join(cmd))>=8192: + program=cmd[0] + cmd=[self.quote_response_command(x)for x in cmd] + (fd,tmp)=tempfile.mkstemp() + os.write(fd,'\r\n'.join(i.replace('\\','\\\\')for i in cmd[1:])) + os.close(fd) + cmd=[program,'@'+tmp] + ret=self.generator.bld.exec_command(cmd,**kw) + finally: + if tmp: + try: + os.remove(tmp) + except OSError: + pass + return ret + def quote_response_command(self,flag): + if flag.lower()=='/noconfig': + return'' + if flag.find(' ')>-1: + for x in('/r:','/reference:','/resource:','/lib:','/out:'): + if flag.startswith(x): + flag='%s"%s"'%(x,flag[len(x):]) + break + else: + flag='"%s"'%flag + return flag +def configure(conf): + csc=getattr(Options.options,'cscbinary',None) + if csc: + conf.env.MCS=csc + conf.find_program(['csc','mcs','gmcs'],var='MCS') + conf.env.ASS_ST='/r:%s' + conf.env.RES_ST='/resource:%s' + conf.env.CS_NAME='csc' + if str(conf.env.MCS).lower().find('mcs')>-1: + conf.env.CS_NAME='mono' +def options(opt): + opt.add_option('--with-csc-binary',type='string',dest='cscbinary') +class fake_csshlib(Task.Task): + color='YELLOW' + inst_to=None + def runnable_status(self): + for x in self.outputs: + x.sig=Utils.h_file(x.abspath()) + return Task.SKIP_ME +@conf +def read_csshlib(self,name,paths=[]): + return self(name=name,features='fake_lib',lib_paths=paths,lib_type='csshlib') diff --git a/waflib/Tools/cxx.py b/waflib/Tools/cxx.py new file mode 100644 index 00000000..b744a8d2 --- /dev/null +++ b/waflib/Tools/cxx.py @@ -0,0 +1,26 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib import TaskGen,Task,Utils +from waflib.Tools import c_preproc +from waflib.Tools.ccroot import link_task,stlink_task +@TaskGen.extension('.cpp','.cc','.cxx','.C','.c++') +def cxx_hook(self,node): + return self.create_compiled_task('cxx',node) +if not'.c'in TaskGen.task_gen.mappings: + TaskGen.task_gen.mappings['.c']=TaskGen.task_gen.mappings['.cpp'] +class cxx(Task.Task): + run_str='${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}' + vars=['CXXDEPS'] + ext_in=['.h'] + scan=c_preproc.scan +class cxxprogram(link_task): + run_str='${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' + vars=['LINKDEPS'] + ext_out=['.bin'] + inst_to='${BINDIR}' +class cxxshlib(cxxprogram): + inst_to='${LIBDIR}' +class cxxstlib(stlink_task): + pass diff --git a/waflib/Tools/d.py b/waflib/Tools/d.py new file mode 100644 index 00000000..1838740c --- /dev/null +++ b/waflib/Tools/d.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib import Utils,Task,Errors +from waflib.TaskGen import taskgen_method,feature,extension +from waflib.Tools import d_scan,d_config +from waflib.Tools.ccroot import link_task,stlink_task +class d(Task.Task): + color='GREEN' + run_str='${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' + scan=d_scan.scan +class d_with_header(d): + run_str='${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' +class d_header(Task.Task): + color='BLUE' + run_str='${D} ${D_HEADER} ${SRC}' +class dprogram(link_task): + run_str='${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' + inst_to='${BINDIR}' +class dshlib(dprogram): + inst_to='${LIBDIR}' +class dstlib(stlink_task): + pass +@extension('.d','.di','.D') +def d_hook(self,node): + ext=Utils.destos_to_binfmt(self.env.DEST_OS)=='pe'and'obj'or'o' + out='%s.%d.%s'%(node.name,self.idx,ext) + def create_compiled_task(self,name,node): + task=self.create_task(name,node,node.parent.find_or_declare(out)) + try: + self.compiled_tasks.append(task) + except AttributeError: + self.compiled_tasks=[task] + return task + if getattr(self,'generate_headers',None): + tsk=create_compiled_task(self,'d_with_header',node) + tsk.outputs.append(node.change_ext(self.env['DHEADER_ext'])) + else: + tsk=create_compiled_task(self,'d',node) + return tsk +@taskgen_method +def generate_header(self,filename): + try: + self.header_lst.append([filename,self.install_path]) + except AttributeError: + self.header_lst=[[filename,self.install_path]] +@feature('d') +def process_header(self): + for i in getattr(self,'header_lst',[]): + node=self.path.find_resource(i[0]) + if not node: + raise Errors.WafError('file %r not found on d obj'%i[0]) + self.create_task('d_header',node,node.change_ext('.di')) diff --git a/waflib/Tools/d_config.py b/waflib/Tools/d_config.py new file mode 100644 index 00000000..50660ea8 --- /dev/null +++ b/waflib/Tools/d_config.py @@ -0,0 +1,52 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib import Utils +from waflib.Configure import conf +@conf +def d_platform_flags(self): + v=self.env + if not v.DEST_OS: + v.DEST_OS=Utils.unversioned_sys_platform() + binfmt=Utils.destos_to_binfmt(self.env.DEST_OS) + if binfmt=='pe': + v['dprogram_PATTERN']='%s.exe' + v['dshlib_PATTERN']='lib%s.dll' + v['dstlib_PATTERN']='lib%s.a' + elif binfmt=='mac-o': + v['dprogram_PATTERN']='%s' + v['dshlib_PATTERN']='lib%s.dylib' + v['dstlib_PATTERN']='lib%s.a' + else: + v['dprogram_PATTERN']='%s' + v['dshlib_PATTERN']='lib%s.so' + v['dstlib_PATTERN']='lib%s.a' +DLIB=''' +version(D_Version2) { + import std.stdio; + int main() { + writefln("phobos2"); + return 0; + } +} else { + version(Tango) { + import tango.stdc.stdio; + int main() { + printf("tango"); + return 0; + } + } else { + import std.stdio; + int main() { + writefln("phobos1"); + return 0; + } + } +} +''' +@conf +def check_dlibrary(self,execute=True): + ret=self.check_cc(features='d dprogram',fragment=DLIB,compile_filename='test.d',execute=execute,define_ret=True) + if execute: + self.env.DLIBRARY=ret.strip() diff --git a/waflib/Tools/d_scan.py b/waflib/Tools/d_scan.py new file mode 100644 index 00000000..ee80c5ff --- /dev/null +++ b/waflib/Tools/d_scan.py @@ -0,0 +1,133 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re +from waflib import Utils,Logs +def filter_comments(filename): + txt=Utils.readf(filename) + i=0 + buf=[] + max=len(txt) + begin=0 + while i-1: + conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead') + conf.load('ar') + conf.load('d') + conf.common_flags_dmd() + conf.d_platform_flags() + if str(conf.env.D).find('ldc')>-1: + conf.common_flags_ldc() diff --git a/waflib/Tools/errcheck.py b/waflib/Tools/errcheck.py new file mode 100644 index 00000000..3b064939 --- /dev/null +++ b/waflib/Tools/errcheck.py @@ -0,0 +1,161 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +typos={'feature':'features','sources':'source','targets':'target','include':'includes','export_include':'export_includes','define':'defines','importpath':'includes','installpath':'install_path','iscopy':'is_copy',} +meths_typos=['__call__','program','shlib','stlib','objects'] +from waflib import Logs,Build,Node,Task,TaskGen,ConfigSet,Errors,Utils +import waflib.Tools.ccroot +def check_same_targets(self): + mp=Utils.defaultdict(list) + uids={} + def check_task(tsk): + if not isinstance(tsk,Task.Task): + return + for node in tsk.outputs: + mp[node].append(tsk) + try: + uids[tsk.uid()].append(tsk) + except KeyError: + uids[tsk.uid()]=[tsk] + for g in self.groups: + for tg in g: + try: + for tsk in tg.tasks: + check_task(tsk) + except AttributeError: + check_task(tg) + dupe=False + for(k,v)in mp.items(): + if len(v)>1: + dupe=True + msg='* Node %r is created more than once%s. The task generators are:'%(k,Logs.verbose==1 and" (full message on 'waf -v -v')"or"") + Logs.error(msg) + for x in v: + if Logs.verbose>1: + Logs.error(' %d. %r'%(1+v.index(x),x.generator)) + else: + Logs.error(' %d. %r in %r'%(1+v.index(x),x.generator.name,getattr(x.generator,'path',None))) + if not dupe: + for(k,v)in uids.items(): + if len(v)>1: + Logs.error('* Several tasks use the same identifier. Please check the information on\n http://docs.waf.googlecode.com/git/apidocs_16/Task.html#waflib.Task.Task.uid') + for tsk in v: + Logs.error(' - object %r (%r) defined in %r'%(tsk.__class__.__name__,tsk,tsk.generator)) +def check_invalid_constraints(self): + feat=set([]) + for x in list(TaskGen.feats.values()): + feat.union(set(x)) + for(x,y)in TaskGen.task_gen.prec.items(): + feat.add(x) + feat.union(set(y)) + ext=set([]) + for x in TaskGen.task_gen.mappings.values(): + ext.add(x.__name__) + invalid=ext&feat + if invalid: + Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method'%list(invalid)) + for cls in list(Task.classes.values()): + for x in('before','after'): + for y in Utils.to_list(getattr(cls,x,[])): + if not Task.classes.get(y,None): + Logs.error('Erroneous order constraint %r=%r on task class %r'%(x,y,cls.__name__)) + if getattr(cls,'rule',None): + Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")'%cls.__name__) +def replace(m): + oldcall=getattr(Build.BuildContext,m) + def call(self,*k,**kw): + ret=oldcall(self,*k,**kw) + for x in typos: + if x in kw: + if x=='iscopy'and'subst'in getattr(self,'features',''): + continue + err=True + Logs.error('Fix the typo %r -> %r on %r'%(x,typos[x],ret)) + return ret + setattr(Build.BuildContext,m,call) +def enhance_lib(): + for m in meths_typos: + replace(m) + def ant_glob(self,*k,**kw): + if k: + lst=Utils.to_list(k[0]) + for pat in lst: + if'..'in pat.split('/'): + Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'"%k[0]) + if kw.get('remove',True): + try: + if self.is_child_of(self.ctx.bldnode)and not kw.get('quiet',False): + Logs.error('Using ant_glob on the build folder (%r) is dangerous (quiet=True to disable this warning)'%self) + except AttributeError: + pass + return self.old_ant_glob(*k,**kw) + Node.Node.old_ant_glob=Node.Node.ant_glob + Node.Node.ant_glob=ant_glob + old=Task.is_before + def is_before(t1,t2): + ret=old(t1,t2) + if ret and old(t2,t1): + Logs.error('Contradictory order constraints in classes %r %r'%(t1,t2)) + return ret + Task.is_before=is_before + def check_err_features(self): + lst=self.to_list(self.features) + if'shlib'in lst: + Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') + for x in('c','cxx','d','fc'): + if not x in lst and lst and lst[0]in[x+y for y in('program','shlib','stlib')]: + Logs.error('%r features is probably missing %r'%(self,x)) + TaskGen.feature('*')(check_err_features) + def check_err_order(self): + if not hasattr(self,'rule')and not'subst'in Utils.to_list(self.features): + for x in('before','after','ext_in','ext_out'): + if hasattr(self,x): + Logs.warn('Erroneous order constraint %r on non-rule based task generator %r'%(x,self)) + else: + for x in('before','after'): + for y in self.to_list(getattr(self,x,[])): + if not Task.classes.get(y,None): + Logs.error('Erroneous order constraint %s=%r on %r (no such class)'%(x,y,self)) + TaskGen.feature('*')(check_err_order) + def check_compile(self): + check_invalid_constraints(self) + try: + ret=self.orig_compile() + finally: + check_same_targets(self) + return ret + Build.BuildContext.orig_compile=Build.BuildContext.compile + Build.BuildContext.compile=check_compile + def use_rec(self,name,**kw): + try: + y=self.bld.get_tgen_by_name(name) + except Errors.WafError: + pass + else: + idx=self.bld.get_group_idx(self) + odx=self.bld.get_group_idx(y) + if odx>idx: + msg="Invalid 'use' across build groups:" + if Logs.verbose>1: + msg+='\n target %r\n uses:\n %r'%(self,y) + else: + msg+=" %r uses %r (try 'waf -v -v' for the full error)"%(self.name,name) + raise Errors.WafError(msg) + self.orig_use_rec(name,**kw) + TaskGen.task_gen.orig_use_rec=TaskGen.task_gen.use_rec + TaskGen.task_gen.use_rec=use_rec + def getattri(self,name,default=None): + if name=='append'or name=='add': + raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') + elif name=='prepend': + raise Errors.WafError('env.prepend does not exist: use env.prepend_value') + if name in self.__slots__: + return object.__getattr__(self,name,default) + else: + return self[name] + ConfigSet.ConfigSet.__getattr__=getattri +def options(opt): + enhance_lib() +def configure(conf): + pass diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py new file mode 100644 index 00000000..35897998 --- /dev/null +++ b/waflib/Tools/fc.py @@ -0,0 +1,116 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re +from waflib import Utils,Task,TaskGen,Logs +from waflib.Tools import ccroot,fc_config,fc_scan +from waflib.TaskGen import feature,before_method,after_method,extension +from waflib.Configure import conf +ccroot.USELIB_VARS['fc']=set(['FCFLAGS','DEFINES','INCLUDES']) +ccroot.USELIB_VARS['fcprogram_test']=ccroot.USELIB_VARS['fcprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) +ccroot.USELIB_VARS['fcshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) +ccroot.USELIB_VARS['fcstlib']=set(['ARFLAGS','LINKDEPS']) +@feature('fcprogram','fcshlib','fcstlib','fcprogram_test') +def dummy(self): + pass +@extension('.f','.f90','.F','.F90','.for','.FOR') +def fc_hook(self,node): + return self.create_compiled_task('fc',node) +@conf +def modfile(conf,name): + return{'lower':name.lower()+'.mod','lower.MOD':name.upper()+'.MOD','UPPER.mod':name.upper()+'.mod','UPPER':name.upper()+'.MOD'}[conf.env.FC_MOD_CAPITALIZATION or'lower'] +def get_fortran_tasks(tsk): + bld=tsk.generator.bld + tasks=bld.get_tasks_group(bld.get_group_idx(tsk.generator)) + return[x for x in tasks if isinstance(x,fc)and not getattr(x,'nomod',None)and not getattr(x,'mod_fortran_done',None)] +class fc(Task.Task): + color='GREEN' + run_str='${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()}' + vars=["FORTRANMODPATHFLAG"] + def scan(self): + tmp=fc_scan.fortran_parser(self.generator.includes_nodes) + tmp.task=self + tmp.start(self.inputs[0]) + if Logs.verbose: + Logs.debug('deps: deps for %r: %r; unresolved %r'%(self.inputs,tmp.nodes,tmp.names)) + return(tmp.nodes,tmp.names) + def runnable_status(self): + if getattr(self,'mod_fortran_done',None): + return super(fc,self).runnable_status() + bld=self.generator.bld + lst=get_fortran_tasks(self) + for tsk in lst: + tsk.mod_fortran_done=True + for tsk in lst: + ret=tsk.runnable_status() + if ret==Task.ASK_LATER: + for x in lst: + x.mod_fortran_done=None + return Task.ASK_LATER + ins=Utils.defaultdict(set) + outs=Utils.defaultdict(set) + for tsk in lst: + key=tsk.uid() + for x in bld.raw_deps[key]: + if x.startswith('MOD@'): + name=bld.modfile(x.replace('MOD@','')) + node=bld.srcnode.find_or_declare(name) + tsk.set_outputs(node) + outs[id(node)].add(tsk) + for tsk in lst: + key=tsk.uid() + for x in bld.raw_deps[key]: + if x.startswith('USE@'): + name=bld.modfile(x.replace('USE@','')) + node=bld.srcnode.find_resource(name) + if node and node not in tsk.outputs: + if not node in bld.node_deps[key]: + bld.node_deps[key].append(node) + ins[id(node)].add(tsk) + for k in ins.keys(): + for a in ins[k]: + a.run_after.update(outs[k]) + tmp=[] + for t in outs[k]: + tmp.extend(t.outputs) + a.dep_nodes.extend(tmp) + a.dep_nodes.sort(key=lambda x:x.abspath()) + for tsk in lst: + try: + delattr(tsk,'cache_sig') + except AttributeError: + pass + return super(fc,self).runnable_status() +class fcprogram(ccroot.link_task): + color='YELLOW' + run_str='${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB}' + inst_to='${BINDIR}' +class fcshlib(fcprogram): + inst_to='${LIBDIR}' +class fcprogram_test(fcprogram): + def can_retrieve_cache(self): + return False + def runnable_status(self): + ret=super(fcprogram_test,self).runnable_status() + if ret==Task.SKIP_ME: + ret=Task.RUN_ME + return ret + def exec_command(self,cmd,**kw): + bld=self.generator.bld + kw['shell']=isinstance(cmd,str) + kw['stdout']=kw['stderr']=Utils.subprocess.PIPE + kw['cwd']=bld.variant_dir + bld.out=bld.err='' + bld.to_log('command: %s\n'%cmd) + kw['output']=0 + try: + (bld.out,bld.err)=bld.cmd_and_log(cmd,**kw) + except Exception ,e: + return-1 + if bld.out: + bld.to_log("out: %s\n"%bld.out) + if bld.err: + bld.to_log("err: %s\n"%bld.err) +class fcstlib(ccroot.stlink_task): + pass diff --git a/waflib/Tools/fc_config.py b/waflib/Tools/fc_config.py new file mode 100644 index 00000000..0130a57d --- /dev/null +++ b/waflib/Tools/fc_config.py @@ -0,0 +1,285 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re,shutil,os,sys,string,shlex +from waflib.Configure import conf +from waflib.TaskGen import feature,after_method,before_method +from waflib import Build,Utils +FC_FRAGMENT=' program main\n end program main\n' +FC_FRAGMENT2=' PROGRAM MAIN\n END\n' +@conf +def fc_flags(conf): + v=conf.env + v['FC_SRC_F']=[] + v['FC_TGT_F']=['-c','-o'] + v['FCINCPATH_ST']='-I%s' + v['FCDEFINES_ST']='-D%s' + if not v['LINK_FC']:v['LINK_FC']=v['FC'] + v['FCLNK_SRC_F']=[] + v['FCLNK_TGT_F']=['-o'] + v['FCFLAGS_fcshlib']=['-fpic'] + v['LINKFLAGS_fcshlib']=['-shared'] + v['fcshlib_PATTERN']='lib%s.so' + v['fcstlib_PATTERN']='lib%s.a' + v['FCLIB_ST']='-l%s' + v['FCLIBPATH_ST']='-L%s' + v['FCSTLIB_ST']='-l%s' + v['FCSTLIBPATH_ST']='-L%s' + v['FCSTLIB_MARKER']='-Wl,-Bstatic' + v['FCSHLIB_MARKER']='-Wl,-Bdynamic' + v['SONAME_ST']='-Wl,-h,%s' +@conf +def fc_add_flags(conf): + conf.add_os_flags('FCFLAGS') + conf.add_os_flags('LDFLAGS','LINKFLAGS') +@conf +def check_fortran(self,*k,**kw): + self.check_cc(fragment=FC_FRAGMENT,compile_filename='test.f',features='fc fcprogram',msg='Compiling a simple fortran app') +@conf +def check_fc(self,*k,**kw): + kw['compiler']='fc' + if not'compile_mode'in kw: + kw['compile_mode']='fc' + if not'type'in kw: + kw['type']='fcprogram' + if not'compile_filename'in kw: + kw['compile_filename']='test.f90' + if not'code'in kw: + kw['code']=FC_FRAGMENT + return self.check(*k,**kw) +@conf +def fortran_modifier_darwin(conf): + v=conf.env + v['FCFLAGS_fcshlib']=['-fPIC','-compatibility_version','1','-current_version','1'] + v['LINKFLAGS_fcshlib']=['-dynamiclib'] + v['fcshlib_PATTERN']='lib%s.dylib' + v['FRAMEWORKPATH_ST']='-F%s' + v['FRAMEWORK_ST']='-framework %s' + v['LINKFLAGS_fcstlib']=[] + v['FCSHLIB_MARKER']='' + v['FCSTLIB_MARKER']='' + v['SONAME_ST']='' +@conf +def fortran_modifier_win32(conf): + v=conf.env + v['fcprogram_PATTERN']=v['fcprogram_test_PATTERN']='%s.exe' + v['fcshlib_PATTERN']='%s.dll' + v['implib_PATTERN']='lib%s.dll.a' + v['IMPLIB_ST']='-Wl,--out-implib,%s' + v['FCFLAGS_fcshlib']=[] + v.append_value('FCFLAGS_fcshlib',['-DDLL_EXPORT']) + v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) +@conf +def fortran_modifier_cygwin(conf): + fortran_modifier_win32(conf) + v=conf.env + v['fcshlib_PATTERN']='cyg%s.dll' + v.append_value('LINKFLAGS_fcshlib',['-Wl,--enable-auto-image-base']) + v['FCFLAGS_fcshlib']=[] +@conf +def check_fortran_dummy_main(self,*k,**kw): + if not self.env.CC: + self.fatal('A c compiler is required for check_fortran_dummy_main') + lst=['MAIN__','__MAIN','_MAIN','MAIN_','MAIN'] + lst.extend([m.lower()for m in lst]) + lst.append('') + self.start_msg('Detecting whether we need a dummy main') + for main in lst: + kw['fortran_main']=main + try: + self.check_cc(fragment='int %s() { return 0; }\n'%(main or'test'),features='c fcprogram',mandatory=True) + if not main: + self.env.FC_MAIN=-1 + self.end_msg('no') + else: + self.env.FC_MAIN=main + self.end_msg('yes %s'%main) + break + except self.errors.ConfigurationError: + pass + else: + self.end_msg('not found') + self.fatal('could not detect whether fortran requires a dummy main, see the config.log') +GCC_DRIVER_LINE=re.compile('^Driving:') +POSIX_STATIC_EXT=re.compile('\S+\.a') +POSIX_LIB_FLAGS=re.compile('-l\S+') +@conf +def is_link_verbose(self,txt): + assert isinstance(txt,str) + for line in txt.splitlines(): + if not GCC_DRIVER_LINE.search(line): + if POSIX_STATIC_EXT.search(line)or POSIX_LIB_FLAGS.search(line): + return True + return False +@conf +def check_fortran_verbose_flag(self,*k,**kw): + self.start_msg('fortran link verbose flag') + for x in['-v','--verbose','-verbose','-V']: + try: + self.check_cc(features='fc fcprogram_test',fragment=FC_FRAGMENT2,compile_filename='test.f',linkflags=[x],mandatory=True) + except self.errors.ConfigurationError: + pass + else: + if self.is_link_verbose(self.test_bld.err)or self.is_link_verbose(self.test_bld.out): + self.end_msg(x) + break + else: + self.end_msg('failure') + self.fatal('Could not obtain the fortran link verbose flag (see config.log)') + self.env.FC_VERBOSE_FLAG=x + return x +LINKFLAGS_IGNORED=[r'-lang*',r'-lcrt[a-zA-Z0-9\.]*\.o',r'-lc$',r'-lSystem',r'-libmil',r'-LIST:*',r'-LNO:*'] +if os.name=='nt': + LINKFLAGS_IGNORED.extend([r'-lfrt*',r'-luser32',r'-lkernel32',r'-ladvapi32',r'-lmsvcrt',r'-lshell32',r'-lmingw',r'-lmoldname']) +else: + LINKFLAGS_IGNORED.append(r'-lgcc*') +RLINKFLAGS_IGNORED=[re.compile(f)for f in LINKFLAGS_IGNORED] +def _match_ignore(line): + for i in RLINKFLAGS_IGNORED: + if i.match(line): + return True + return False +def parse_fortran_link(lines): + final_flags=[] + for line in lines: + if not GCC_DRIVER_LINE.match(line): + _parse_flink_line(line,final_flags) + return final_flags +SPACE_OPTS=re.compile('^-[LRuYz]$') +NOSPACE_OPTS=re.compile('^-[RL]') +def _parse_flink_line(line,final_flags): + lexer=shlex.shlex(line,posix=True) + lexer.whitespace_split=True + t=lexer.get_token() + tmp_flags=[] + while t: + def parse(token): + if _match_ignore(token): + pass + elif token.startswith('-lkernel32')and sys.platform=='cygwin': + tmp_flags.append(token) + elif SPACE_OPTS.match(token): + t=lexer.get_token() + if t.startswith('P,'): + t=t[2:] + for opt in t.split(os.pathsep): + tmp_flags.append('-L%s'%opt) + elif NOSPACE_OPTS.match(token): + tmp_flags.append(token) + elif POSIX_LIB_FLAGS.match(token): + tmp_flags.append(token) + else: + pass + t=lexer.get_token() + return t + t=parse(t) + final_flags.extend(tmp_flags) + return final_flags +@conf +def check_fortran_clib(self,autoadd=True,*k,**kw): + if not self.env.FC_VERBOSE_FLAG: + self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') + self.start_msg('Getting fortran runtime link flags') + try: + self.check_cc(fragment=FC_FRAGMENT2,compile_filename='test.f',features='fc fcprogram_test',linkflags=[self.env.FC_VERBOSE_FLAG]) + except Exception: + self.end_msg(False) + if kw.get('mandatory',True): + conf.fatal('Could not find the c library flags') + else: + out=self.test_bld.err + flags=parse_fortran_link(out.splitlines()) + self.end_msg('ok (%s)'%' '.join(flags)) + self.env.LINKFLAGS_CLIB=flags + return flags + return[] +def getoutput(conf,cmd,stdin=False): + if stdin: + stdin=Utils.subprocess.PIPE + else: + stdin=None + env=conf.env.env or None + try: + p=Utils.subprocess.Popen(cmd,stdin=stdin,stdout=Utils.subprocess.PIPE,stderr=Utils.subprocess.PIPE,env=env) + if stdin: + p.stdin.write('\n') + out,err=p.communicate() + except Exception: + conf.fatal('could not determine the compiler version %r'%cmd) + if not isinstance(out,str): + out=out.decode(sys.stdout.encoding or'iso8859-1') + if not isinstance(err,str): + err=err.decode(sys.stdout.encoding or'iso8859-1') + return(out,err) +ROUTINES_CODE="""\ + subroutine foobar() + return + end + subroutine foo_bar() + return + end +""" +MAIN_CODE=""" +void %(dummy_func_nounder)s(void); +void %(dummy_func_under)s(void); +int %(main_func_name)s() { + %(dummy_func_nounder)s(); + %(dummy_func_under)s(); + return 0; +} +""" +@feature('link_main_routines_func') +@before_method('process_source') +def link_main_routines_tg_method(self): + def write_test_file(task): + task.outputs[0].write(task.generator.code) + bld=self.bld + bld(rule=write_test_file,target='main.c',code=MAIN_CODE%self.__dict__) + bld(rule=write_test_file,target='test.f',code=ROUTINES_CODE) + bld(features='fc fcstlib',source='test.f',target='test') + bld(features='c fcprogram',source='main.c',target='app',use='test') +def mangling_schemes(): + for u in['_','']: + for du in['','_']: + for c in["lower","upper"]: + yield(u,du,c) +def mangle_name(u,du,c,name): + return getattr(name,c)()+u+(name.find('_')!=-1 and du or'') +@conf +def check_fortran_mangling(self,*k,**kw): + if not self.env.CC: + self.fatal('A c compiler is required for link_main_routines') + if not self.env.FC: + self.fatal('A fortran compiler is required for link_main_routines') + if not self.env.FC_MAIN: + self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') + self.start_msg('Getting fortran mangling scheme') + for(u,du,c)in mangling_schemes(): + try: + self.check_cc(compile_filename=[],features='link_main_routines_func',msg='nomsg',errmsg='nomsg',mandatory=True,dummy_func_nounder=mangle_name(u,du,c,"foobar"),dummy_func_under=mangle_name(u,du,c,"foo_bar"),main_func_name=self.env.FC_MAIN) + except self.errors.ConfigurationError: + pass + else: + self.end_msg("ok ('%s', '%s', '%s-case')"%(u,du,c)) + self.env.FORTRAN_MANGLING=(u,du,c) + break + else: + self.end_msg(False) + self.fatal('mangler not found') + return(u,du,c) +@feature('pyext') +@before_method('propagate_uselib_vars','apply_link') +def set_lib_pat(self): + self.env['fcshlib_PATTERN']=self.env['pyext_PATTERN'] +@conf +def detect_openmp(self): + for x in['-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp']: + try: + self.check_fc(msg='Checking for OpenMP flag %s'%x,fragment='program main\n call omp_get_num_threads()\nend program main',fcflags=x,linkflags=x,uselib_store='OPENMP') + except self.errors.ConfigurationError: + pass + else: + break + else: + self.fatal('Could not find OpenMP') diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py new file mode 100644 index 00000000..48e06b53 --- /dev/null +++ b/waflib/Tools/fc_scan.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re +from waflib import Utils,Task,TaskGen,Logs +from waflib.TaskGen import feature,before_method,after_method,extension +from waflib.Configure import conf +INC_REGEX="""(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" +USE_REGEX="""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +MOD_REGEX="""(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +re_inc=re.compile(INC_REGEX,re.I) +re_use=re.compile(USE_REGEX,re.I) +re_mod=re.compile(MOD_REGEX,re.I) +class fortran_parser(object): + def __init__(self,incpaths): + self.seen=[] + self.nodes=[] + self.names=[] + self.incpaths=incpaths + def find_deps(self,node): + txt=node.read() + incs=[] + uses=[] + mods=[] + for line in txt.splitlines(): + m=re_inc.search(line) + if m: + incs.append(m.group(1)) + m=re_use.search(line) + if m: + uses.append(m.group(1)) + m=re_mod.search(line) + if m: + mods.append(m.group(1)) + return(incs,uses,mods) + def start(self,node): + self.waiting=[node] + while self.waiting: + nd=self.waiting.pop(0) + self.iter(nd) + def iter(self,node): + path=node.abspath() + incs,uses,mods=self.find_deps(node) + for x in incs: + if x in self.seen: + continue + self.seen.append(x) + self.tryfind_header(x) + for x in uses: + name="USE@%s"%x + if not name in self.names: + self.names.append(name) + for x in mods: + name="MOD@%s"%x + if not name in self.names: + self.names.append(name) + def tryfind_header(self,filename): + found=None + for n in self.incpaths: + found=n.find_resource(filename) + if found: + self.nodes.append(found) + self.waiting.append(found) + break + if not found: + if not filename in self.names: + self.names.append(filename) diff --git a/waflib/Tools/flex.py b/waflib/Tools/flex.py new file mode 100644 index 00000000..13f6207e --- /dev/null +++ b/waflib/Tools/flex.py @@ -0,0 +1,32 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import waflib.TaskGen,os,re +def decide_ext(self,node): + if'cxx'in self.features: + return['.lex.cc'] + return['.lex.c'] +def flexfun(tsk): + env=tsk.env + bld=tsk.generator.bld + wd=bld.variant_dir + def to_list(xx): + if isinstance(xx,str):return[xx] + return xx + tsk.last_cmd=lst=[] + lst.extend(to_list(env['FLEX'])) + lst.extend(to_list(env['FLEXFLAGS'])) + inputs=[a.path_from(bld.bldnode)for a in tsk.inputs] + if env.FLEX_MSYS: + inputs=[x.replace(os.sep,'/')for x in inputs] + lst.extend(inputs) + lst=[x for x in lst if x] + txt=bld.cmd_and_log(lst,cwd=wd,env=env.env or None,quiet=0) + tsk.outputs[0].write(txt.replace('\r\n','\n').replace('\r','\n')) +waflib.TaskGen.declare_chain(name='flex',rule=flexfun,ext_in='.l',decider=decide_ext,) +def configure(conf): + conf.find_program('flex',var='FLEX') + conf.env.FLEXFLAGS=['-t'] + if re.search(r"\\msys\\[0-9.]+\\bin\\flex.exe$",conf.env.FLEX): + conf.env.FLEX_MSYS=True diff --git a/waflib/Tools/g95.py b/waflib/Tools/g95.py new file mode 100644 index 00000000..9bc331aa --- /dev/null +++ b/waflib/Tools/g95.py @@ -0,0 +1,55 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re +from waflib import Utils +from waflib.Tools import fc,fc_config,fc_scan,ar +from waflib.Configure import conf +@conf +def find_g95(conf): + fc=conf.find_program('g95',var='FC') + fc=conf.cmd_to_list(fc) + conf.get_g95_version(fc) + conf.env.FC_NAME='G95' +@conf +def g95_flags(conf): + v=conf.env + v['FCFLAGS_fcshlib']=['-fPIC'] + v['FORTRANMODFLAG']=['-fmod=',''] + v['FCFLAGS_DEBUG']=['-Werror'] +@conf +def g95_modifier_win32(conf): + fc_config.fortran_modifier_win32(conf) +@conf +def g95_modifier_cygwin(conf): + fc_config.fortran_modifier_cygwin(conf) +@conf +def g95_modifier_darwin(conf): + fc_config.fortran_modifier_darwin(conf) +@conf +def g95_modifier_platform(conf): + dest_os=conf.env['DEST_OS']or Utils.unversioned_sys_platform() + g95_modifier_func=getattr(conf,'g95_modifier_'+dest_os,None) + if g95_modifier_func: + g95_modifier_func() +@conf +def get_g95_version(conf,fc): + version_re=re.compile(r"g95\s*(?P\d*)\.(?P\d*)").search + cmd=fc+['--version'] + out,err=fc_config.getoutput(conf,cmd,stdin=False) + if out: + match=version_re(out) + else: + match=version_re(err) + if not match: + conf.fatal('cannot determine g95 version') + k=match.groupdict() + conf.env['FC_VERSION']=(k['major'],k['minor']) +def configure(conf): + conf.find_g95() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.g95_flags() + conf.g95_modifier_platform() diff --git a/waflib/Tools/gas.py b/waflib/Tools/gas.py new file mode 100644 index 00000000..b714ca18 --- /dev/null +++ b/waflib/Tools/gas.py @@ -0,0 +1,12 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import waflib.Tools.asm +from waflib.Tools import ar +def configure(conf): + conf.find_program(['gas','gcc'],var='AS') + conf.env.AS_TGT_F=['-c','-o'] + conf.env.ASLNK_TGT_F=['-o'] + conf.find_ar() + conf.load('asm') diff --git a/waflib/Tools/gcc.py b/waflib/Tools/gcc.py new file mode 100644 index 00000000..adf11da2 --- /dev/null +++ b/waflib/Tools/gcc.py @@ -0,0 +1,97 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys +from waflib import Configure,Options,Utils +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_gcc(conf): + cc=conf.find_program(['gcc','cc'],var='CC') + cc=conf.cmd_to_list(cc) + conf.get_cc_version(cc,gcc=True) + conf.env.CC_NAME='gcc' + conf.env.CC=cc +@conf +def gcc_common_flags(conf): + v=conf.env + v['CC_SRC_F']=[] + v['CC_TGT_F']=['-c','-o'] + if not v['LINK_CC']:v['LINK_CC']=v['CC'] + v['CCLNK_SRC_F']=[] + v['CCLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['RPATH_ST']='-Wl,-rpath,%s' + v['SONAME_ST']='-Wl,-h,%s' + v['SHLIB_MARKER']='-Wl,-Bdynamic' + v['STLIB_MARKER']='-Wl,-Bstatic' + v['cprogram_PATTERN']='%s' + v['CFLAGS_cshlib']=['-fPIC'] + v['LINKFLAGS_cshlib']=['-shared'] + v['cshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cstlib']=['-Wl,-Bstatic'] + v['cstlib_PATTERN']='lib%s.a' + v['LINKFLAGS_MACBUNDLE']=['-bundle','-undefined','dynamic_lookup'] + v['CFLAGS_MACBUNDLE']=['-fPIC'] + v['macbundle_PATTERN']='%s.bundle' +@conf +def gcc_modifier_win32(conf): + v=conf.env + v['cprogram_PATTERN']='%s.exe' + v['cshlib_PATTERN']='%s.dll' + v['implib_PATTERN']='lib%s.dll.a' + v['IMPLIB_ST']='-Wl,--out-implib,%s' + v['CFLAGS_cshlib']=[] + v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) +@conf +def gcc_modifier_cygwin(conf): + gcc_modifier_win32(conf) + v=conf.env + v['cshlib_PATTERN']='cyg%s.dll' + v.append_value('LINKFLAGS_cshlib',['-Wl,--enable-auto-image-base']) + v['CFLAGS_cshlib']=[] +@conf +def gcc_modifier_darwin(conf): + v=conf.env + v['CFLAGS_cshlib']=['-fPIC','-compatibility_version','1','-current_version','1'] + v['LINKFLAGS_cshlib']=['-dynamiclib'] + v['cshlib_PATTERN']='lib%s.dylib' + v['FRAMEWORKPATH_ST']='-F%s' + v['FRAMEWORK_ST']=['-framework'] + v['ARCH_ST']=['-arch'] + v['LINKFLAGS_cstlib']=[] + v['SHLIB_MARKER']=[] + v['STLIB_MARKER']=[] + v['SONAME_ST']=[] +@conf +def gcc_modifier_aix(conf): + v=conf.env + v['LINKFLAGS_cprogram']=['-Wl,-brtl'] + v['LINKFLAGS_cshlib']=['-shared','-Wl,-brtl,-bexpfull'] + v['SHLIB_MARKER']=[] +@conf +def gcc_modifier_hpux(conf): + v=conf.env + v['SHLIB_MARKER']=[] + v['STLIB_MARKER']='-Bstatic' + v['CFLAGS_cshlib']=['-fPIC','-DPIC'] + v['cshlib_PATTERN']='lib%s.sl' +@conf +def gcc_modifier_platform(conf): + gcc_modifier_func=getattr(conf,'gcc_modifier_'+conf.env.DEST_OS,None) + if gcc_modifier_func: + gcc_modifier_func() +def configure(conf): + conf.find_gcc() + conf.find_ar() + conf.gcc_common_flags() + conf.gcc_modifier_platform() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/waflib/Tools/gdc.py b/waflib/Tools/gdc.py new file mode 100644 index 00000000..da966ec0 --- /dev/null +++ b/waflib/Tools/gdc.py @@ -0,0 +1,36 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import sys +from waflib.Tools import ar,d +from waflib.Configure import conf +@conf +def find_gdc(conf): + conf.find_program('gdc',var='D') + out=conf.cmd_and_log([conf.env.D,'--version']) + if out.find("gdc ")==-1: + conf.fatal("detected compiler is not gdc") +@conf +def common_flags_gdc(conf): + v=conf.env + v['DFLAGS']=[] + v['D_SRC_F']=['-c'] + v['D_TGT_F']='-o%s' + v['D_LINKER']=v['D'] + v['DLNK_SRC_F']='' + v['DLNK_TGT_F']='-o%s' + v['DINC_ST']='-I%s' + v['DSHLIB_MARKER']=v['DSTLIB_MARKER']='' + v['DSTLIB_ST']=v['DSHLIB_ST']='-l%s' + v['DSTLIBPATH_ST']=v['DLIBPATH_ST']='-L%s' + v['LINKFLAGS_dshlib']=['-shared'] + v['DHEADER_ext']='.di' + v.DFLAGS_d_with_header='-fintfc' + v['D_HDR_F']='-fintfc-file=%s' +def configure(conf): + conf.find_gdc() + conf.load('ar') + conf.load('d') + conf.common_flags_gdc() + conf.d_platform_flags() diff --git a/waflib/Tools/gfortran.py b/waflib/Tools/gfortran.py new file mode 100644 index 00000000..854a93db --- /dev/null +++ b/waflib/Tools/gfortran.py @@ -0,0 +1,69 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re +from waflib import Utils +from waflib.Tools import fc,fc_config,fc_scan,ar +from waflib.Configure import conf +@conf +def find_gfortran(conf): + fc=conf.find_program(['gfortran','g77'],var='FC') + fc=conf.cmd_to_list(fc) + conf.get_gfortran_version(fc) + conf.env.FC_NAME='GFORTRAN' +@conf +def gfortran_flags(conf): + v=conf.env + v['FCFLAGS_fcshlib']=['-fPIC'] + v['FORTRANMODFLAG']=['-J',''] + v['FCFLAGS_DEBUG']=['-Werror'] +@conf +def gfortran_modifier_win32(conf): + fc_config.fortran_modifier_win32(conf) +@conf +def gfortran_modifier_cygwin(conf): + fc_config.fortran_modifier_cygwin(conf) +@conf +def gfortran_modifier_darwin(conf): + fc_config.fortran_modifier_darwin(conf) +@conf +def gfortran_modifier_platform(conf): + dest_os=conf.env['DEST_OS']or Utils.unversioned_sys_platform() + gfortran_modifier_func=getattr(conf,'gfortran_modifier_'+dest_os,None) + if gfortran_modifier_func: + gfortran_modifier_func() +@conf +def get_gfortran_version(conf,fc): + version_re=re.compile(r"GNU\s*Fortran",re.I).search + cmd=fc+['--version'] + out,err=fc_config.getoutput(conf,cmd,stdin=False) + if out:match=version_re(out) + else:match=version_re(err) + if not match: + conf.fatal('Could not determine the compiler type') + cmd=fc+['-dM','-E','-'] + out,err=fc_config.getoutput(conf,cmd,stdin=True) + if out.find('__GNUC__')<0: + conf.fatal('Could not determine the compiler type') + k={} + out=out.split('\n') + import shlex + for line in out: + lst=shlex.split(line) + if len(lst)>2: + key=lst[1] + val=lst[2] + k[key]=val + def isD(var): + return var in k + def isT(var): + return var in k and k[var]!='0' + conf.env['FC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__']) +def configure(conf): + conf.find_gfortran() + conf.find_ar() + conf.fc_flags() + conf.fc_add_flags() + conf.gfortran_flags() + conf.gfortran_modifier_platform() diff --git a/waflib/Tools/glib2.py b/waflib/Tools/glib2.py new file mode 100644 index 00000000..1d75510b --- /dev/null +++ b/waflib/Tools/glib2.py @@ -0,0 +1,173 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Task,Utils,Options,Errors,Logs +from waflib.TaskGen import taskgen_method,before_method,after_method,feature +@taskgen_method +def add_marshal_file(self,filename,prefix): + if not hasattr(self,'marshal_list'): + self.marshal_list=[] + self.meths.append('process_marshal') + self.marshal_list.append((filename,prefix)) +@before_method('process_source') +def process_marshal(self): + for f,prefix in getattr(self,'marshal_list',[]): + node=self.path.find_resource(f) + if not node: + raise Errors.WafError('file not found %r'%f) + h_node=node.change_ext('.h') + c_node=node.change_ext('.c') + task=self.create_task('glib_genmarshal',node,[h_node,c_node]) + task.env.GLIB_GENMARSHAL_PREFIX=prefix + self.source=self.to_nodes(getattr(self,'source',[])) + self.source.append(c_node) +class glib_genmarshal(Task.Task): + def run(self): + bld=self.inputs[0].__class__.ctx + get=self.env.get_flat + cmd1="%s %s --prefix=%s --header > %s"%(get('GLIB_GENMARSHAL'),self.inputs[0].srcpath(),get('GLIB_GENMARSHAL_PREFIX'),self.outputs[0].abspath()) + ret=bld.exec_command(cmd1) + if ret:return ret + c='''#include "%s"\n'''%self.outputs[0].name + self.outputs[1].write(c) + cmd2="%s %s --prefix=%s --body >> %s"%(get('GLIB_GENMARSHAL'),self.inputs[0].srcpath(),get('GLIB_GENMARSHAL_PREFIX'),self.outputs[1].abspath()) + return bld.exec_command(cmd2) + vars=['GLIB_GENMARSHAL_PREFIX','GLIB_GENMARSHAL'] + color='BLUE' + ext_out=['.h'] +@taskgen_method +def add_enums_from_template(self,source='',target='',template='',comments=''): + if not hasattr(self,'enums_list'): + self.enums_list=[] + self.meths.append('process_enums') + self.enums_list.append({'source':source,'target':target,'template':template,'file-head':'','file-prod':'','file-tail':'','enum-prod':'','value-head':'','value-prod':'','value-tail':'','comments':comments}) +@taskgen_method +def add_enums(self,source='',target='',file_head='',file_prod='',file_tail='',enum_prod='',value_head='',value_prod='',value_tail='',comments=''): + if not hasattr(self,'enums_list'): + self.enums_list=[] + self.meths.append('process_enums') + self.enums_list.append({'source':source,'template':'','target':target,'file-head':file_head,'file-prod':file_prod,'file-tail':file_tail,'enum-prod':enum_prod,'value-head':value_head,'value-prod':value_prod,'value-tail':value_tail,'comments':comments}) +@before_method('process_source') +def process_enums(self): + for enum in getattr(self,'enums_list',[]): + task=self.create_task('glib_mkenums') + env=task.env + inputs=[] + source_list=self.to_list(enum['source']) + if not source_list: + raise Errors.WafError('missing source '+str(enum)) + source_list=[self.path.find_resource(k)for k in source_list] + inputs+=source_list + env['GLIB_MKENUMS_SOURCE']=[k.abspath()for k in source_list] + if not enum['target']: + raise Errors.WafError('missing target '+str(enum)) + tgt_node=self.path.find_or_declare(enum['target']) + if tgt_node.name.endswith('.c'): + self.source.append(tgt_node) + env['GLIB_MKENUMS_TARGET']=tgt_node.abspath() + options=[] + if enum['template']: + template_node=self.path.find_resource(enum['template']) + options.append('--template %s'%(template_node.abspath())) + inputs.append(template_node) + params={'file-head':'--fhead','file-prod':'--fprod','file-tail':'--ftail','enum-prod':'--eprod','value-head':'--vhead','value-prod':'--vprod','value-tail':'--vtail','comments':'--comments'} + for param,option in params.items(): + if enum[param]: + options.append('%s %r'%(option,enum[param])) + env['GLIB_MKENUMS_OPTIONS']=' '.join(options) + task.set_inputs(inputs) + task.set_outputs(tgt_node) +class glib_mkenums(Task.Task): + run_str='${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' + color='PINK' + ext_out=['.h'] +@taskgen_method +def add_settings_schemas(self,filename_list): + if not hasattr(self,'settings_schema_files'): + self.settings_schema_files=[] + if not isinstance(filename_list,list): + filename_list=[filename_list] + self.settings_schema_files.extend(filename_list) +@taskgen_method +def add_settings_enums(self,namespace,filename_list): + if hasattr(self,'settings_enum_namespace'): + raise Errors.WafError("Tried to add gsettings enums to '%s' more than once"%self.name) + self.settings_enum_namespace=namespace + if type(filename_list)!='list': + filename_list=[filename_list] + self.settings_enum_files=filename_list +def r_change_ext(self,ext): + name=self.name + k=name.rfind('.') + if k>=0: + name=name[:k]+ext + else: + name=name+ext + return self.parent.find_or_declare([name]) +@feature('glib2') +def process_settings(self): + enums_tgt_node=[] + install_files=[] + settings_schema_files=getattr(self,'settings_schema_files',[]) + if settings_schema_files and not self.env['GLIB_COMPILE_SCHEMAS']: + raise Errors.WafError("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") + if hasattr(self,'settings_enum_files'): + enums_task=self.create_task('glib_mkenums') + source_list=self.settings_enum_files + source_list=[self.path.find_resource(k)for k in source_list] + enums_task.set_inputs(source_list) + enums_task.env['GLIB_MKENUMS_SOURCE']=[k.abspath()for k in source_list] + target=self.settings_enum_namespace+'.enums.xml' + tgt_node=self.path.find_or_declare(target) + enums_task.set_outputs(tgt_node) + enums_task.env['GLIB_MKENUMS_TARGET']=tgt_node.abspath() + enums_tgt_node=[tgt_node] + install_files.append(tgt_node) + options='--comments "" --fhead "" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " " --vtail " " --ftail "" '%(self.settings_enum_namespace) + enums_task.env['GLIB_MKENUMS_OPTIONS']=options + for schema in settings_schema_files: + schema_task=self.create_task('glib_validate_schema') + schema_node=self.path.find_resource(schema) + if not schema_node: + raise Errors.WafError("Cannot find the schema file '%s'"%schema) + install_files.append(schema_node) + source_list=enums_tgt_node+[schema_node] + schema_task.set_inputs(source_list) + schema_task.env['GLIB_COMPILE_SCHEMAS_OPTIONS']=[("--schema-file="+k.abspath())for k in source_list] + target_node=r_change_ext(schema_node,'.xml.valid') + schema_task.set_outputs(target_node) + schema_task.env['GLIB_VALIDATE_SCHEMA_OUTPUT']=target_node.abspath() + def compile_schemas_callback(bld): + if not bld.is_install:return + Logs.pprint('YELLOW','Updating GSettings schema cache') + command=Utils.subst_vars("${GLIB_COMPILE_SCHEMAS} ${GSETTINGSSCHEMADIR}",bld.env) + ret=self.bld.exec_command(command) + if self.bld.is_install: + if not self.env['GSETTINGSSCHEMADIR']: + raise Errors.WafError('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') + if install_files: + self.bld.install_files(self.env['GSETTINGSSCHEMADIR'],install_files) + if not hasattr(self.bld,'_compile_schemas_registered'): + self.bld.add_post_fun(compile_schemas_callback) + self.bld._compile_schemas_registered=True +class glib_validate_schema(Task.Task): + run_str='rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' + color='PINK' +def configure(conf): + conf.find_program('glib-genmarshal',var='GLIB_GENMARSHAL') + conf.find_perl_program('glib-mkenums',var='GLIB_MKENUMS') + conf.find_program('glib-compile-schemas',var='GLIB_COMPILE_SCHEMAS',mandatory=False) + def getstr(varname): + return getattr(Options.options,varname,getattr(conf.env,varname,'')) + gsettingsschemadir=getstr('GSETTINGSSCHEMADIR') + if not gsettingsschemadir: + datadir=getstr('DATADIR') + if not datadir: + prefix=conf.env['PREFIX'] + datadir=os.path.join(prefix,'share') + gsettingsschemadir=os.path.join(datadir,'glib-2.0','schemas') + conf.env['GSETTINGSSCHEMADIR']=gsettingsschemadir +def options(opt): + opt.add_option('--gsettingsschemadir',help='GSettings schema location [Default: ${datadir}/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR') diff --git a/waflib/Tools/gnu_dirs.py b/waflib/Tools/gnu_dirs.py new file mode 100644 index 00000000..9c8a3041 --- /dev/null +++ b/waflib/Tools/gnu_dirs.py @@ -0,0 +1,65 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Utils,Options,Context +_options=[x.split(', ')for x in''' +bindir, user executables, ${EXEC_PREFIX}/bin +sbindir, system admin executables, ${EXEC_PREFIX}/sbin +libexecdir, program executables, ${EXEC_PREFIX}/libexec +sysconfdir, read-only single-machine data, ${PREFIX}/etc +sharedstatedir, modifiable architecture-independent data, ${PREFIX}/com +localstatedir, modifiable single-machine data, ${PREFIX}/var +libdir, object code libraries, ${EXEC_PREFIX}/lib +includedir, C header files, ${PREFIX}/include +oldincludedir, C header files for non-gcc, /usr/include +datarootdir, read-only arch.-independent data root, ${PREFIX}/share +datadir, read-only architecture-independent data, ${DATAROOTDIR} +infodir, info documentation, ${DATAROOTDIR}/info +localedir, locale-dependent data, ${DATAROOTDIR}/locale +mandir, man documentation, ${DATAROOTDIR}/man +docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} +htmldir, html documentation, ${DOCDIR} +dvidir, dvi documentation, ${DOCDIR} +pdfdir, pdf documentation, ${DOCDIR} +psdir, ps documentation, ${DOCDIR} +'''.split('\n')if x] +def configure(conf): + def get_param(varname,default): + return getattr(Options.options,varname,'')or default + env=conf.env + env.LIBDIR=env.BINDIR=[] + env.EXEC_PREFIX=get_param('EXEC_PREFIX',env.PREFIX) + env.PACKAGE=getattr(Context.g_module,'APPNAME',None)or env.PACKAGE + complete=False + iter=0 + while not complete and iter\d*)\.(?P\d*)",re.I).search + cmd=fc+['--version'] + out,err=fc_config.getoutput(conf,cmd,stdin=False) + if out: + match=version_re(out) + else: + match=version_re(err) + if not match: + conf.fatal('cannot determine ifort version.') + k=match.groupdict() + conf.env['FC_VERSION']=(k['major'],k['minor']) +def configure(conf): + conf.find_ifort() + conf.find_program('xiar',var='AR') + conf.env.ARFLAGS='rcs' + conf.fc_flags() + conf.fc_add_flags() + conf.ifort_modifier_platform() diff --git a/waflib/Tools/intltool.py b/waflib/Tools/intltool.py new file mode 100644 index 00000000..d558674f --- /dev/null +++ b/waflib/Tools/intltool.py @@ -0,0 +1,77 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re +from waflib import Configure,TaskGen,Task,Utils,Runner,Options,Build,Logs +import waflib.Tools.ccroot +from waflib.TaskGen import feature,before_method +from waflib.Logs import error +@before_method('process_source') +@feature('intltool_in') +def apply_intltool_in_f(self): + try:self.meths.remove('process_source') + except ValueError:pass + if not self.env.LOCALEDIR: + self.env.LOCALEDIR=self.env.PREFIX+'/share/locale' + for i in self.to_list(self.source): + node=self.path.find_resource(i) + podir=getattr(self,'podir','po') + podirnode=self.path.find_dir(podir) + if not podirnode: + error("could not find the podir %r"%podir) + continue + cache=getattr(self,'intlcache','.intlcache') + self.env['INTLCACHE']=os.path.join(self.path.bldpath(),podir,cache) + self.env['INTLPODIR']=podirnode.bldpath() + self.env['INTLFLAGS']=getattr(self,'flags',['-q','-u','-c']) + task=self.create_task('intltool',node,node.change_ext('')) + inst=getattr(self,'install_path','${LOCALEDIR}') + if inst: + self.bld.install_files(inst,task.outputs) +@feature('intltool_po') +def apply_intltool_po(self): + try:self.meths.remove('process_source') + except ValueError:pass + if not self.env.LOCALEDIR: + self.env.LOCALEDIR=self.env.PREFIX+'/share/locale' + appname=getattr(self,'appname','set_your_app_name') + podir=getattr(self,'podir','') + inst=getattr(self,'install_path','${LOCALEDIR}') + linguas=self.path.find_node(os.path.join(podir,'LINGUAS')) + if linguas: + file=open(linguas.abspath()) + langs=[] + for line in file.readlines(): + if not line.startswith('#'): + langs+=line.split() + file.close() + re_linguas=re.compile('[-a-zA-Z_@.]+') + for lang in langs: + if re_linguas.match(lang): + node=self.path.find_resource(os.path.join(podir,re_linguas.match(lang).group()+'.po')) + task=self.create_task('po',node,node.change_ext('.mo')) + if inst: + filename=task.outputs[0].name + (langname,ext)=os.path.splitext(filename) + inst_file=inst+os.sep+langname+os.sep+'LC_MESSAGES'+os.sep+appname+'.mo' + self.bld.install_as(inst_file,task.outputs[0],chmod=getattr(self,'chmod',Utils.O644),env=task.env) + else: + Logs.pprint('RED',"Error no LINGUAS file found in po directory") +class po(Task.Task): + run_str='${MSGFMT} -o ${TGT} ${SRC}' + color='BLUE' +class intltool(Task.Task): + run_str='${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' + color='BLUE' +def configure(conf): + conf.find_program('msgfmt',var='MSGFMT') + conf.find_perl_program('intltool-merge',var='INTLTOOL') + prefix=conf.env.PREFIX + datadir=conf.env.DATADIR + if not datadir: + datadir=os.path.join(prefix,'share') + conf.define('LOCALEDIR',os.path.join(datadir,'locale').replace('\\','\\\\')) + conf.define('DATADIR',datadir.replace('\\','\\\\')) + if conf.env.CC or conf.env.CXX: + conf.check(header_name='locale.h') diff --git a/waflib/Tools/irixcc.py b/waflib/Tools/irixcc.py new file mode 100644 index 00000000..8dbdfcae --- /dev/null +++ b/waflib/Tools/irixcc.py @@ -0,0 +1,48 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Utils +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_irixcc(conf): + v=conf.env + cc=None + if v['CC']:cc=v['CC'] + elif'CC'in conf.environ:cc=conf.environ['CC'] + if not cc:cc=conf.find_program('cc',var='CC') + if not cc:conf.fatal('irixcc was not found') + cc=conf.cmd_to_list(cc) + try: + conf.cmd_and_log(cc+['-version']) + except Exception: + conf.fatal('%r -version could not be executed'%cc) + v['CC']=cc + v['CC_NAME']='irix' +@conf +def irixcc_common_flags(conf): + v=conf.env + v['CC_SRC_F']='' + v['CC_TGT_F']=['-c','-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + if not v['LINK_CC']:v['LINK_CC']=v['CC'] + v['CCLNK_SRC_F']='' + v['CCLNK_TGT_F']=['-o'] + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['cprogram_PATTERN']='%s' + v['cshlib_PATTERN']='lib%s.so' + v['cstlib_PATTERN']='lib%s.a' +def configure(conf): + conf.find_irixcc() + conf.find_cpp() + conf.find_ar() + conf.irixcc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py new file mode 100644 index 00000000..5750f401 --- /dev/null +++ b/waflib/Tools/javaw.py @@ -0,0 +1,311 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re,tempfile,shutil +from waflib import TaskGen,Task,Utils,Options,Build,Errors,Node,Logs +from waflib.Configure import conf +from waflib.TaskGen import feature,before_method,after_method +from waflib.Tools import ccroot +ccroot.USELIB_VARS['javac']=set(['CLASSPATH','JAVACFLAGS']) +SOURCE_RE='**/*.java' +JAR_RE='**/*' +class_check_source=''' +public class Test { + public static void main(String[] argv) { + Class lib; + if (argv.length < 1) { + System.err.println("Missing argument"); + System.exit(77); + } + try { + lib = Class.forName(argv[0]); + } catch (ClassNotFoundException e) { + System.err.println("ClassNotFoundException"); + System.exit(1); + } + lib = null; + System.exit(0); + } +} +''' +@feature('javac') +@before_method('process_source') +def apply_java(self): + Utils.def_attrs(self,jarname='',classpath='',sourcepath='.',srcdir='.',jar_mf_attributes={},jar_mf_classpath=[]) + nodes_lst=[] + outdir=getattr(self,'outdir',None) + if outdir: + if not isinstance(outdir,Node.Node): + outdir=self.path.get_bld().make_node(self.outdir) + else: + outdir=self.path.get_bld() + outdir.mkdir() + self.outdir=outdir + self.env['OUTDIR']=outdir.abspath() + self.javac_task=tsk=self.create_task('javac') + tmp=[] + srcdir=getattr(self,'srcdir','') + if isinstance(srcdir,Node.Node): + srcdir=[srcdir] + for x in Utils.to_list(srcdir): + if isinstance(x,Node.Node): + y=x + else: + y=self.path.find_dir(x) + if not y: + self.bld.fatal('Could not find the folder %s from %s'%(x,self.path)) + tmp.append(y) + tsk.srcdir=tmp + if getattr(self,'compat',None): + tsk.env.append_value('JAVACFLAGS',['-source',self.compat]) + if hasattr(self,'sourcepath'): + fold=[isinstance(x,Node.Node)and x or self.path.find_dir(x)for x in self.to_list(self.sourcepath)] + names=os.pathsep.join([x.srcpath()for x in fold]) + else: + names=[x.srcpath()for x in tsk.srcdir] + if names: + tsk.env.append_value('JAVACFLAGS',['-sourcepath',names]) +@feature('javac') +@after_method('apply_java') +def use_javac_files(self): + lst=[] + self.uselib=self.to_list(getattr(self,'uselib',[])) + names=self.to_list(getattr(self,'use',[])) + get=self.bld.get_tgen_by_name + for x in names: + try: + y=get(x) + except Exception: + self.uselib.append(x) + else: + y.post() + lst.append(y.jar_task.outputs[0].abspath()) + self.javac_task.set_run_after(y.jar_task) + if lst: + self.env.append_value('CLASSPATH',lst) +@feature('javac') +@after_method('apply_java','propagate_uselib_vars','use_javac_files') +def set_classpath(self): + self.env.append_value('CLASSPATH',getattr(self,'classpath',[])) + for x in self.tasks: + x.env.CLASSPATH=os.pathsep.join(self.env.CLASSPATH)+os.pathsep +@feature('jar') +@after_method('apply_java','use_javac_files') +@before_method('process_source') +def jar_files(self): + destfile=getattr(self,'destfile','test.jar') + jaropts=getattr(self,'jaropts',[]) + manifest=getattr(self,'manifest',None) + basedir=getattr(self,'basedir',None) + if basedir: + if not isinstance(self.basedir,Node.Node): + basedir=self.path.get_bld().make_node(basedir) + else: + basedir=self.path.get_bld() + if not basedir: + self.bld.fatal('Could not find the basedir %r for %r'%(self.basedir,self)) + self.jar_task=tsk=self.create_task('jar_create') + if manifest: + jarcreate=getattr(self,'jarcreate','cfm') + node=self.path.find_node(manifest) + tsk.dep_nodes.append(node) + jaropts.insert(0,node.abspath()) + else: + jarcreate=getattr(self,'jarcreate','cf') + if not isinstance(destfile,Node.Node): + destfile=self.path.find_or_declare(destfile) + if not destfile: + self.bld.fatal('invalid destfile %r for %r'%(destfile,self)) + tsk.set_outputs(destfile) + tsk.basedir=basedir + jaropts.append('-C') + jaropts.append(basedir.bldpath()) + jaropts.append('.') + tsk.env['JAROPTS']=jaropts + tsk.env['JARCREATE']=jarcreate + if getattr(self,'javac_task',None): + tsk.set_run_after(self.javac_task) +@feature('jar') +@after_method('jar_files') +def use_jar_files(self): + lst=[] + self.uselib=self.to_list(getattr(self,'uselib',[])) + names=self.to_list(getattr(self,'use',[])) + get=self.bld.get_tgen_by_name + for x in names: + try: + y=get(x) + except Exception: + self.uselib.append(x) + else: + y.post() + self.jar_task.run_after.update(y.tasks) +class jar_create(Task.Task): + color='GREEN' + run_str='${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + if not self.inputs: + global JAR_RE + try: + self.inputs=[x for x in self.basedir.ant_glob(JAR_RE,remove=False)if id(x)!=id(self.outputs[0])] + except Exception: + raise Errors.WafError('Could not find the basedir %r for %r'%(self.basedir,self)) + return super(jar_create,self).runnable_status() +class javac(Task.Task): + color='BLUE' + nocache=True + vars=['CLASSPATH','JAVACFLAGS','JAVAC','OUTDIR'] + def runnable_status(self): + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + if not self.inputs: + global SOURCE_RE + self.inputs=[] + for x in self.srcdir: + self.inputs.extend(x.ant_glob(SOURCE_RE,remove=False)) + return super(javac,self).runnable_status() + def run(self): + env=self.env + gen=self.generator + bld=gen.bld + wd=bld.bldnode.abspath() + def to_list(xx): + if isinstance(xx,str):return[xx] + return xx + cmd=[] + cmd.extend(to_list(env['JAVAC'])) + cmd.extend(['-classpath']) + cmd.extend(to_list(env['CLASSPATH'])) + cmd.extend(['-d']) + cmd.extend(to_list(env['OUTDIR'])) + cmd.extend(to_list(env['JAVACFLAGS'])) + files=[a.path_from(bld.bldnode)for a in self.inputs] + tmp=None + try: + if len(str(files))+len(str(cmd))>8192: + (fd,tmp)=tempfile.mkstemp(dir=bld.bldnode.abspath()) + try: + os.write(fd,'\n'.join(files)) + finally: + if tmp: + os.close(fd) + if Logs.verbose: + Logs.debug('runner: %r'%(cmd+files)) + cmd.append('@'+tmp) + else: + cmd+=files + ret=self.exec_command(cmd,cwd=wd,env=env.env or None) + finally: + if tmp: + os.unlink(tmp) + return ret + def post_run(self): + for n in self.generator.outdir.ant_glob('**/*.class'): + n.sig=Utils.h_file(n.abspath()) + self.generator.bld.task_sigs[self.uid()]=self.cache_sig +@feature('javadoc') +@after_method('process_rule') +def create_javadoc(self): + tsk=self.create_task('javadoc') + tsk.classpath=getattr(self,'classpath',[]) + self.javadoc_package=Utils.to_list(self.javadoc_package) + if not isinstance(self.javadoc_output,Node.Node): + self.javadoc_output=self.bld.path.find_or_declare(self.javadoc_output) +class javadoc(Task.Task): + color='BLUE' + def __str__(self): + return'%s: %s -> %s\n'%(self.__class__.__name__,self.generator.srcdir,self.generator.javadoc_output) + def run(self): + env=self.env + bld=self.generator.bld + wd=bld.bldnode.abspath() + srcpath=self.generator.path.abspath()+os.sep+self.generator.srcdir + srcpath+=os.pathsep + srcpath+=self.generator.path.get_bld().abspath()+os.sep+self.generator.srcdir + classpath=env.CLASSPATH + classpath+=os.pathsep + classpath+=os.pathsep.join(self.classpath) + classpath="".join(classpath) + self.last_cmd=lst=[] + lst.extend(Utils.to_list(env['JAVADOC'])) + lst.extend(['-d',self.generator.javadoc_output.abspath()]) + lst.extend(['-sourcepath',srcpath]) + lst.extend(['-classpath',classpath]) + lst.extend(['-subpackages']) + lst.extend(self.generator.javadoc_package) + lst=[x for x in lst if x] + self.generator.bld.cmd_and_log(lst,cwd=wd,env=env.env or None,quiet=0) + def post_run(self): + nodes=self.generator.javadoc_output.ant_glob('**') + for x in nodes: + x.sig=Utils.h_file(x.abspath()) + self.generator.bld.task_sigs[self.uid()]=self.cache_sig +def configure(self): + java_path=self.environ['PATH'].split(os.pathsep) + v=self.env + if'JAVA_HOME'in self.environ: + java_path=[os.path.join(self.environ['JAVA_HOME'],'bin')]+java_path + self.env['JAVA_HOME']=[self.environ['JAVA_HOME']] + for x in'javac java jar javadoc'.split(): + self.find_program(x,var=x.upper(),path_list=java_path) + self.env[x.upper()]=self.cmd_to_list(self.env[x.upper()]) + if'CLASSPATH'in self.environ: + v['CLASSPATH']=self.environ['CLASSPATH'] + if not v['JAR']:self.fatal('jar is required for making java packages') + if not v['JAVAC']:self.fatal('javac is required for compiling java classes') + v['JARCREATE']='cf' + v['JAVACFLAGS']=[] +@conf +def check_java_class(self,classname,with_classpath=None): + javatestdir='.waf-javatest' + classpath=javatestdir + if self.env['CLASSPATH']: + classpath+=os.pathsep+self.env['CLASSPATH'] + if isinstance(with_classpath,str): + classpath+=os.pathsep+with_classpath + shutil.rmtree(javatestdir,True) + os.mkdir(javatestdir) + java_file=open(os.path.join(javatestdir,'Test.java'),'w') + java_file.write(class_check_source) + java_file.close() + self.exec_command(self.env['JAVAC']+[os.path.join(javatestdir,'Test.java')],shell=False) + cmd=self.env['JAVA']+['-cp',classpath,'Test',classname] + self.to_log("%s\n"%str(cmd)) + found=self.exec_command(cmd,shell=False) + self.msg('Checking for java class %s'%classname,not found) + shutil.rmtree(javatestdir,True) + return found +@conf +def check_jni_headers(conf): + if not conf.env.CC_NAME and not conf.env.CXX_NAME: + conf.fatal('load a compiler first (gcc, g++, ..)') + if not conf.env.JAVA_HOME: + conf.fatal('set JAVA_HOME in the system environment') + javaHome=conf.env['JAVA_HOME'][0] + dir=conf.root.find_dir(conf.env.JAVA_HOME[0]+'/include') + if dir is None: + dir=conf.root.find_dir(conf.env.JAVA_HOME[0]+'/../Headers') + if dir is None: + conf.fatal('JAVA_HOME does not seem to be set properly') + f=dir.ant_glob('**/(jni|jni_md).h') + incDirs=[x.parent.abspath()for x in f] + dir=conf.root.find_dir(conf.env.JAVA_HOME[0]) + f=dir.ant_glob('**/*jvm.(so|dll|dylib)') + libDirs=[x.parent.abspath()for x in f]or[javaHome] + f=dir.ant_glob('**/*jvm.(lib)') + if f: + libDirs=[[x,y.parent.abspath()]for x in libDirs for y in f] + for d in libDirs: + try: + conf.check(header_name='jni.h',define_name='HAVE_JNI_H',lib='jvm',libpath=d,includes=incDirs,uselib_store='JAVA',uselib='JAVA') + except Exception: + pass + else: + break + else: + conf.fatal('could not find lib jvm in %r (see config.log)'%libDirs) diff --git a/waflib/Tools/kde4.py b/waflib/Tools/kde4.py new file mode 100644 index 00000000..cd51f5f7 --- /dev/null +++ b/waflib/Tools/kde4.py @@ -0,0 +1,48 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,re +from waflib import Options,TaskGen,Task,Utils +from waflib.TaskGen import feature,after_method +@feature('msgfmt') +def apply_msgfmt(self): + for lang in self.to_list(self.langs): + node=self.path.find_resource(lang+'.po') + task=self.create_task('msgfmt',node,node.change_ext('.mo')) + langname=lang.split('/') + langname=langname[-1] + inst=getattr(self,'install_path','${KDE4_LOCALE_INSTALL_DIR}') + self.bld.install_as(inst+os.sep+langname+os.sep+'LC_MESSAGES'+os.sep+getattr(self,'appname','set_your_appname')+'.mo',task.outputs[0],chmod=getattr(self,'chmod',Utils.O644)) +class msgfmt(Task.Task): + color='BLUE' + run_str='${MSGFMT} ${SRC} -o ${TGT}' +def configure(self): + kdeconfig=self.find_program('kde4-config') + prefix=self.cmd_and_log('%s --prefix'%kdeconfig).strip() + fname='%s/share/apps/cmake/modules/KDELibsDependencies.cmake'%prefix + try:os.stat(fname) + except OSError: + fname='%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake'%prefix + try:os.stat(fname) + except OSError:self.fatal('could not open %s'%fname) + try: + txt=Utils.readf(fname) + except(OSError,IOError): + self.fatal('could not read %s'%fname) + txt=txt.replace('\\\n','\n') + fu=re.compile('#(.*)\n') + txt=fu.sub('',txt) + setregexp=re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') + found=setregexp.findall(txt) + for(_,key,val)in found: + self.env[key]=val + self.env['LIB_KDECORE']=['kdecore'] + self.env['LIB_KDEUI']=['kdeui'] + self.env['LIB_KIO']=['kio'] + self.env['LIB_KHTML']=['khtml'] + self.env['LIB_KPARTS']=['kparts'] + self.env['LIBPATH_KDECORE']=[os.path.join(self.env.KDE4_LIB_INSTALL_DIR,'kde4','devel'),self.env.KDE4_LIB_INSTALL_DIR] + self.env['INCLUDES_KDECORE']=[self.env['KDE4_INCLUDE_INSTALL_DIR']] + self.env.append_value('INCLUDES_KDECORE',[self.env['KDE4_INCLUDE_INSTALL_DIR']+os.sep+'KDE']) + self.find_program('msgfmt',var='MSGFMT') diff --git a/waflib/Tools/ldc2.py b/waflib/Tools/ldc2.py new file mode 100644 index 00000000..25b99e53 --- /dev/null +++ b/waflib/Tools/ldc2.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import sys +from waflib.Tools import ar,d +from waflib.Configure import conf +@conf +def find_ldc2(conf): + conf.find_program(['ldc2'],var='D') + out=conf.cmd_and_log([conf.env.D,'-version']) + if out.find("based on DMD v2.")==-1: + conf.fatal("detected compiler is not ldc2") +@conf +def common_flags_ldc2(conf): + v=conf.env + v['D_SRC_F']=['-c'] + v['D_TGT_F']='-of%s' + v['D_LINKER']=v['D'] + v['DLNK_SRC_F']='' + v['DLNK_TGT_F']='-of%s' + v['DINC_ST']='-I%s' + v['DSHLIB_MARKER']=v['DSTLIB_MARKER']='' + v['DSTLIB_ST']=v['DSHLIB_ST']='-L-l%s' + v['DSTLIBPATH_ST']=v['DLIBPATH_ST']='-L-L%s' + v['LINKFLAGS_dshlib']=['-L-shared'] + v['DHEADER_ext']='.di' + v['DFLAGS_d_with_header']=['-H','-Hf'] + v['D_HDR_F']='%s' + v['LINKFLAGS']=[] + v['DFLAGS_dshlib']=['-relocation-model=pic'] +def configure(conf): + conf.find_ldc2() + conf.load('ar') + conf.load('d') + conf.common_flags_ldc2() + conf.d_platform_flags() diff --git a/waflib/Tools/lua.py b/waflib/Tools/lua.py new file mode 100644 index 00000000..a0a35fce --- /dev/null +++ b/waflib/Tools/lua.py @@ -0,0 +1,18 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib.TaskGen import extension +from waflib import Task,Utils +@extension('.lua') +def add_lua(self,node): + tsk=self.create_task('luac',node,node.change_ext('.luac')) + inst_to=getattr(self,'install_path',self.env.LUADIR and'${LUADIR}'or None) + if inst_to: + self.bld.install_files(inst_to,tsk.outputs) + return tsk +class luac(Task.Task): + run_str='${LUAC} -s -o ${TGT} ${SRC}' + color='PINK' +def configure(conf): + conf.find_program('luac',var='LUAC') diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py new file mode 100644 index 00000000..289cd47d --- /dev/null +++ b/waflib/Tools/msvc.py @@ -0,0 +1,726 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,re,tempfile +from waflib import Utils,Task,Logs,Options +from waflib.Logs import debug,warn +from waflib.TaskGen import after_method,feature +from waflib.Configure import conf +from waflib.Tools import ccroot,c,cxx,ar,winres +g_msvc_systemlibs=''' +aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet +cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs +credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d +ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp +faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid +gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop +kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi +mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree +msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm +netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp +odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 +osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu +ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm +rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 +shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 +traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg +version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm +wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp +'''.split() +all_msvc_platforms=[('x64','amd64'),('x86','x86'),('ia64','ia64'),('x86_amd64','amd64'),('x86_ia64','ia64')] +all_wince_platforms=[('armv4','arm'),('armv4i','arm'),('mipsii','mips'),('mipsii_fp','mips'),('mipsiv','mips'),('mipsiv_fp','mips'),('sh4','sh'),('x86','cex86')] +all_icl_platforms=[('intel64','amd64'),('em64t','amd64'),('ia32','x86'),('Itanium','ia64')] +def options(opt): + opt.add_option('--msvc_version',type='string',help='msvc version, eg: "msvc 10.0,msvc 9.0"',default='') + opt.add_option('--msvc_targets',type='string',help='msvc targets, eg: "x64,arm"',default='') +def setup_msvc(conf,versions,arch=False): + platforms=getattr(Options.options,'msvc_targets','').split(',') + if platforms==['']: + platforms=Utils.to_list(conf.env['MSVC_TARGETS'])or[i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] + desired_versions=getattr(Options.options,'msvc_version','').split(',') + if desired_versions==['']: + desired_versions=conf.env['MSVC_VERSIONS']or[v for v,_ in versions][::-1] + versiondict=dict(versions) + for version in desired_versions: + try: + targets=dict(versiondict[version]) + for target in platforms: + try: + arch,(p1,p2,p3)=targets[target] + compiler,revision=version.rsplit(' ',1) + if arch: + return compiler,revision,p1,p2,p3,arch + else: + return compiler,revision,p1,p2,p3 + except KeyError:continue + except KeyError:continue + conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') +@conf +def get_msvc_version(conf,compiler,version,target,vcvars): + debug('msvc: get_msvc_version: %r %r %r',compiler,version,target) + batfile=conf.bldnode.make_node('waf-print-msvc.bat') + batfile.write("""@echo off +set INCLUDE= +set LIB= +call "%s" %s +echo PATH=%%PATH%% +echo INCLUDE=%%INCLUDE%% +echo LIB=%%LIB%% +"""%(vcvars,target)) + sout=conf.cmd_and_log(['cmd','/E:on','/V:on','/C',batfile.abspath()]) + lines=sout.splitlines() + if not lines[0]: + lines.pop(0) + if version=='11.0': + if lines[0].startswith('Error'): + conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_1)') + else: + for x in('Setting environment','Setting SDK environment','Intel(R) C++ Compiler','Intel Parallel Studio','Intel(R) Parallel Studio','Intel(R) Composer','Intel Corporation. All rights reserved.'): + if lines[0].find(x)>-1: + lines.pop(0) + break + else: + debug('msvc: get_msvc_version: %r %r %r -> not found',compiler,version,target) + conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_2)') + MSVC_PATH=MSVC_INCDIR=MSVC_LIBDIR=None + for line in lines: + if line.startswith('PATH='): + path=line[5:] + MSVC_PATH=path.split(';') + elif line.startswith('INCLUDE='): + MSVC_INCDIR=[i for i in line[8:].split(';')if i] + elif line.startswith('LIB='): + MSVC_LIBDIR=[i for i in line[4:].split(';')if i] + if None in(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR): + conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)') + env=dict(os.environ) + env.update(PATH=path) + compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) + cxx=conf.find_program(compiler_name,path_list=MSVC_PATH) + cxx=conf.cmd_to_list(cxx) + if'CL'in env: + del(env['CL']) + try: + try: + conf.cmd_and_log(cxx+['/help'],env=env) + except Exception ,e: + debug('msvc: get_msvc_version: %r %r %r -> failure'%(compiler,version,target)) + debug(str(e)) + conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') + else: + debug('msvc: get_msvc_version: %r %r %r -> OK',compiler,version,target) + finally: + conf.env[compiler_name]='' + return(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR) +@conf +def gather_wsdk_versions(conf,versions): + version_pattern=re.compile('^v..?.?\...?.?') + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') + except WindowsError: + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') + except WindowsError: + return + index=0 + while 1: + try: + version=Utils.winreg.EnumKey(all_versions,index) + except WindowsError: + break + index=index+1 + if not version_pattern.match(version): + continue + try: + msvc_version=Utils.winreg.OpenKey(all_versions,version) + path,type=Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') + except WindowsError: + continue + if os.path.isfile(os.path.join(path,'bin','SetEnv.cmd')): + targets=[] + for target,arch in all_msvc_platforms: + try: + targets.append((target,(arch,conf.get_msvc_version('wsdk',version,'/'+target,os.path.join(path,'bin','SetEnv.cmd'))))) + except conf.errors.ConfigurationError: + pass + versions.append(('wsdk '+version[1:],targets)) +def gather_wince_supported_platforms(): + supported_wince_platforms=[] + try: + ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') + except WindowsError: + try: + ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') + except WindowsError: + ce_sdk='' + if not ce_sdk: + return supported_wince_platforms + ce_index=0 + while 1: + try: + sdk_device=Utils.winreg.EnumKey(ce_sdk,ce_index) + except WindowsError: + break + ce_index=ce_index+1 + sdk=Utils.winreg.OpenKey(ce_sdk,sdk_device) + try: + path,type=Utils.winreg.QueryValueEx(sdk,'SDKRootDir') + except WindowsError: + try: + path,type=Utils.winreg.QueryValueEx(sdk,'SDKInformation') + path,xml=os.path.split(path) + except WindowsError: + continue + path=str(path) + path,device=os.path.split(path) + if not device: + path,device=os.path.split(path) + for arch,compiler in all_wince_platforms: + platforms=[] + if os.path.isdir(os.path.join(path,device,'Lib',arch)): + platforms.append((arch,compiler,os.path.join(path,device,'Include',arch),os.path.join(path,device,'Lib',arch))) + if platforms: + supported_wince_platforms.append((device,platforms)) + return supported_wince_platforms +def gather_msvc_detected_versions(): + version_pattern=re.compile('^(\d\d?\.\d\d?)(Exp)?$') + detected_versions=[] + for vcver,vcvar in[('VCExpress','Exp'),('VisualStudio','')]: + try: + prefix='SOFTWARE\\Wow6432node\\Microsoft\\'+vcver + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix) + except WindowsError: + try: + prefix='SOFTWARE\\Microsoft\\'+vcver + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix) + except WindowsError: + continue + index=0 + while 1: + try: + version=Utils.winreg.EnumKey(all_versions,index) + except WindowsError: + break + index=index+1 + match=version_pattern.match(version) + if not match: + continue + else: + versionnumber=float(match.group(1)) + detected_versions.append((versionnumber,version+vcvar,prefix+"\\"+version)) + def fun(tup): + return tup[0] + detected_versions.sort(key=fun) + return detected_versions +@conf +def gather_msvc_targets(conf,versions,version,vc_path): + targets=[] + if os.path.isfile(os.path.join(vc_path,'vcvarsall.bat')): + for target,realtarget in all_msvc_platforms[::-1]: + try: + targets.append((target,(realtarget,conf.get_msvc_version('msvc',version,target,os.path.join(vc_path,'vcvarsall.bat'))))) + except conf.errors.ConfigurationError: + pass + elif os.path.isfile(os.path.join(vc_path,'Common7','Tools','vsvars32.bat')): + try: + targets.append(('x86',('x86',conf.get_msvc_version('msvc',version,'x86',os.path.join(vc_path,'Common7','Tools','vsvars32.bat'))))) + except conf.errors.ConfigurationError: + pass + elif os.path.isfile(os.path.join(vc_path,'Bin','vcvars32.bat')): + try: + targets.append(('x86',('x86',conf.get_msvc_version('msvc',version,'',os.path.join(vc_path,'Bin','vcvars32.bat'))))) + except conf.errors.ConfigurationError: + pass + versions.append(('msvc '+version,targets)) +@conf +def gather_wince_targets(conf,versions,version,vc_path,vsvars,supported_platforms): + for device,platforms in supported_platforms: + cetargets=[] + for platform,compiler,include,lib in platforms: + winCEpath=os.path.join(vc_path,'ce') + if not os.path.isdir(winCEpath): + continue + try: + common_bindirs,_1,_2=conf.get_msvc_version('msvc',version,'x86',vsvars) + except conf.errors.ConfigurationError: + continue + if os.path.isdir(os.path.join(winCEpath,'lib',platform)): + bindirs=[os.path.join(winCEpath,'bin',compiler),os.path.join(winCEpath,'bin','x86_'+compiler)]+common_bindirs + incdirs=[os.path.join(winCEpath,'include'),os.path.join(winCEpath,'atlmfc','include'),include] + libdirs=[os.path.join(winCEpath,'lib',platform),os.path.join(winCEpath,'atlmfc','lib',platform),lib] + cetargets.append((platform,(platform,(bindirs,incdirs,libdirs)))) + if cetargets: + versions.append((device+' '+version,cetargets)) +@conf +def gather_msvc_versions(conf,versions): + vc_paths=[] + for(v,version,reg)in gather_msvc_detected_versions(): + try: + try: + msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\VC") + except WindowsError: + msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\Microsoft Visual C++") + path,type=Utils.winreg.QueryValueEx(msvc_version,'ProductDir') + vc_paths.append((version,os.path.abspath(str(path)))) + except WindowsError: + continue + wince_supported_platforms=gather_wince_supported_platforms() + for version,vc_path in vc_paths: + vs_path=os.path.dirname(vc_path) + vsvars=os.path.join(vs_path,'Common7','Tools','vsvars32.bat') + if wince_supported_platforms and os.path.isfile(vsvars): + conf.gather_wince_targets(versions,version,vc_path,vsvars,wince_supported_platforms) + for version,vc_path in vc_paths: + vs_path=os.path.dirname(vc_path) + conf.gather_msvc_targets(versions,version,vc_path) +@conf +def gather_icl_versions(conf,versions): + version_pattern=re.compile('^...?.?\....?.?') + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') + except WindowsError: + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Compilers\\C++') + except WindowsError: + return + index=0 + while 1: + try: + version=Utils.winreg.EnumKey(all_versions,index) + except WindowsError: + break + index=index+1 + if not version_pattern.match(version): + continue + targets=[] + for target,arch in all_icl_platforms: + try: + if target=='intel64':targetDir='EM64T_NATIVE' + else:targetDir=target + Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) + icl_version=Utils.winreg.OpenKey(all_versions,version) + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + try: + targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file)))) + except conf.errors.ConfigurationError: + pass + except WindowsError: + pass + for target,arch in all_icl_platforms: + try: + icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+target) + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + try: + targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file)))) + except conf.errors.ConfigurationError: + pass + except WindowsError: + continue + major=version[0:2] + versions.append(('intel '+major,targets)) +@conf +def gather_intel_composer_versions(conf,versions): + version_pattern=re.compile('^...?.?\...?.?.?') + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Suites') + except WindowsError: + try: + all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Suites') + except WindowsError: + return + index=0 + while 1: + try: + version=Utils.winreg.EnumKey(all_versions,index) + except WindowsError: + break + index=index+1 + if not version_pattern.match(version): + continue + targets=[] + for target,arch in all_icl_platforms: + try: + if target=='intel64':targetDir='EM64T_NATIVE' + else:targetDir=target + try: + defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) + except WindowsError: + if targetDir=='EM64T_NATIVE': + defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') + else: + raise WindowsError + uid,type=Utils.winreg.QueryValueEx(defaults,'SubKey') + Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) + icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') + path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') + batch_file=os.path.join(path,'bin','iclvars.bat') + if os.path.isfile(batch_file): + try: + targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file)))) + except conf.errors.ConfigurationError ,e: + pass + compilervars_warning_attr='_compilervars_warning_key' + if version[0:2]=='13'and getattr(conf,compilervars_warning_attr,True): + setattr(conf,compilervars_warning_attr,False) + patch_url='http://software.intel.com/en-us/forums/topic/328487' + compilervars_arch=os.path.join(path,'bin','compilervars_arch.bat') + vs_express_path=os.environ['VS110COMNTOOLS']+r'..\IDE\VSWinExpress.exe' + dev_env_path=os.environ['VS110COMNTOOLS']+r'..\IDE\devenv.exe' + if(r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"'in Utils.readf(compilervars_arch)and not os.path.exists(vs_express_path)and not os.path.exists(dev_env_path)): + Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ''(VSWinExpress.exe) but it does not seem to be installed at %r. ''The intel command line set up will fail to configure unless the file %r''is patched. See: %s')%(vs_express_path,compilervars_arch,patch_url)) + except WindowsError: + pass + major=version[0:2] + versions.append(('intel '+major,targets)) +@conf +def get_msvc_versions(conf): + if not conf.env['MSVC_INSTALLED_VERSIONS']: + lst=[] + conf.gather_icl_versions(lst) + conf.gather_intel_composer_versions(lst) + conf.gather_wsdk_versions(lst) + conf.gather_msvc_versions(lst) + conf.env['MSVC_INSTALLED_VERSIONS']=lst + return conf.env['MSVC_INSTALLED_VERSIONS'] +@conf +def print_all_msvc_detected(conf): + for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']: + Logs.info(version) + for target,l in targets: + Logs.info("\t"+target) +@conf +def detect_msvc(conf,arch=False): + versions=get_msvc_versions(conf) + return setup_msvc(conf,versions,arch) +@conf +def find_lt_names_msvc(self,libname,is_static=False): + lt_names=['lib%s.la'%libname,'%s.la'%libname,] + for path in self.env['LIBPATH']: + for la in lt_names: + laf=os.path.join(path,la) + dll=None + if os.path.exists(laf): + ltdict=Utils.read_la_file(laf) + lt_libdir=None + if ltdict.get('libdir',''): + lt_libdir=ltdict['libdir'] + if not is_static and ltdict.get('library_names',''): + dllnames=ltdict['library_names'].split() + dll=dllnames[0].lower() + dll=re.sub('\.dll$','',dll) + return(lt_libdir,dll,False) + elif ltdict.get('old_library',''): + olib=ltdict['old_library'] + if os.path.exists(os.path.join(path,olib)): + return(path,olib,True) + elif lt_libdir!=''and os.path.exists(os.path.join(lt_libdir,olib)): + return(lt_libdir,olib,True) + else: + return(None,olib,True) + else: + raise self.errors.WafError('invalid libtool object file: %s'%laf) + return(None,None,None) +@conf +def libname_msvc(self,libname,is_static=False): + lib=libname.lower() + lib=re.sub('\.lib$','',lib) + if lib in g_msvc_systemlibs: + return lib + lib=re.sub('^lib','',lib) + if lib=='m': + return None + (lt_path,lt_libname,lt_static)=self.find_lt_names_msvc(lib,is_static) + if lt_path!=None and lt_libname!=None: + if lt_static==True: + return os.path.join(lt_path,lt_libname) + if lt_path!=None: + _libpaths=[lt_path]+self.env['LIBPATH'] + else: + _libpaths=self.env['LIBPATH'] + static_libs=['lib%ss.lib'%lib,'lib%s.lib'%lib,'%ss.lib'%lib,'%s.lib'%lib,] + dynamic_libs=['lib%s.dll.lib'%lib,'lib%s.dll.a'%lib,'%s.dll.lib'%lib,'%s.dll.a'%lib,'lib%s_d.lib'%lib,'%s_d.lib'%lib,'%s.lib'%lib,] + libnames=static_libs + if not is_static: + libnames=dynamic_libs+static_libs + for path in _libpaths: + for libn in libnames: + if os.path.exists(os.path.join(path,libn)): + debug('msvc: lib found: %s'%os.path.join(path,libn)) + return re.sub('\.lib$','',libn) + self.fatal("The library %r could not be found"%libname) + return re.sub('\.lib$','',libname) +@conf +def check_lib_msvc(self,libname,is_static=False,uselib_store=None): + libn=self.libname_msvc(libname,is_static) + if not uselib_store: + uselib_store=libname.upper() + if False and is_static: + self.env['STLIB_'+uselib_store]=[libn] + else: + self.env['LIB_'+uselib_store]=[libn] +@conf +def check_libs_msvc(self,libnames,is_static=False): + for libname in Utils.to_list(libnames): + self.check_lib_msvc(libname,is_static) +def configure(conf): + conf.autodetect(True) + conf.find_msvc() + conf.msvc_common_flags() + conf.cc_load_tools() + conf.cxx_load_tools() + conf.cc_add_flags() + conf.cxx_add_flags() + conf.link_add_flags() + conf.visual_studio_add_flags() +@conf +def no_autodetect(conf): + conf.env.NO_MSVC_DETECT=1 + configure(conf) +@conf +def autodetect(conf,arch=False): + v=conf.env + if v.NO_MSVC_DETECT: + return + if arch: + compiler,version,path,includes,libdirs,arch=conf.detect_msvc(True) + v['DEST_CPU']=arch + else: + compiler,version,path,includes,libdirs=conf.detect_msvc() + v['PATH']=path + v['INCLUDES']=includes + v['LIBPATH']=libdirs + v['MSVC_COMPILER']=compiler + try: + v['MSVC_VERSION']=float(version) + except Exception: + v['MSVC_VERSION']=float(version[:-3]) +def _get_prog_names(conf,compiler): + if compiler=='intel': + compiler_name='ICL' + linker_name='XILINK' + lib_name='XILIB' + else: + compiler_name='CL' + linker_name='LINK' + lib_name='LIB' + return compiler_name,linker_name,lib_name +@conf +def find_msvc(conf): + if sys.platform=='cygwin': + conf.fatal('MSVC module does not work under cygwin Python!') + v=conf.env + path=v['PATH'] + compiler=v['MSVC_COMPILER'] + version=v['MSVC_VERSION'] + compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) + v.MSVC_MANIFEST=(compiler=='msvc'and version>=8)or(compiler=='wsdk'and version>=6)or(compiler=='intel'and version>=11) + cxx=None + if v['CXX']:cxx=v['CXX'] + elif'CXX'in conf.environ:cxx=conf.environ['CXX'] + cxx=conf.find_program(compiler_name,var='CXX',path_list=path) + cxx=conf.cmd_to_list(cxx) + env=dict(conf.environ) + if path:env.update(PATH=';'.join(path)) + if not conf.cmd_and_log(cxx+['/nologo','/help'],env=env): + conf.fatal('the msvc compiler could not be identified') + v['CC']=v['CXX']=cxx + v['CC_NAME']=v['CXX_NAME']='msvc' + if not v['LINK_CXX']: + link=conf.find_program(linker_name,path_list=path) + if link:v['LINK_CXX']=link + else:conf.fatal('%s was not found (linker)'%linker_name) + v['LINK']=link + if not v['LINK_CC']: + v['LINK_CC']=v['LINK_CXX'] + if not v['AR']: + stliblink=conf.find_program(lib_name,path_list=path,var='AR') + if not stliblink:return + v['ARFLAGS']=['/NOLOGO'] + if v.MSVC_MANIFEST: + conf.find_program('MT',path_list=path,var='MT') + v['MTFLAGS']=['/NOLOGO'] + conf.load('winres') + if not conf.env['WINRC']: + warn('Resource compiler not found. Compiling resource file is disabled') +@conf +def visual_studio_add_flags(self): + v=self.env + try:v.prepend_value('INCLUDES',[x for x in self.environ['INCLUDE'].split(';')if x]) + except Exception:pass + try:v.prepend_value('LIBPATH',[x for x in self.environ['LIB'].split(';')if x]) + except Exception:pass +@conf +def msvc_common_flags(conf): + v=conf.env + v['DEST_BINFMT']='pe' + v.append_value('CFLAGS',['/nologo']) + v.append_value('CXXFLAGS',['/nologo']) + v['DEFINES_ST']='/D%s' + v['CC_SRC_F']='' + v['CC_TGT_F']=['/c','/Fo'] + if v['MSVC_VERSION']>=8: + v['CC_TGT_F']=['/FC']+v['CC_TGT_F'] + v['CXX_SRC_F']='' + v['CXX_TGT_F']=['/c','/Fo'] + if v['MSVC_VERSION']>=8: + v['CXX_TGT_F']=['/FC']+v['CXX_TGT_F'] + v['CPPPATH_ST']='/I%s' + v['AR_TGT_F']=v['CCLNK_TGT_F']=v['CXXLNK_TGT_F']='/OUT:' + v['CFLAGS_CONSOLE']=v['CXXFLAGS_CONSOLE']=['/SUBSYSTEM:CONSOLE'] + v['CFLAGS_NATIVE']=v['CXXFLAGS_NATIVE']=['/SUBSYSTEM:NATIVE'] + v['CFLAGS_POSIX']=v['CXXFLAGS_POSIX']=['/SUBSYSTEM:POSIX'] + v['CFLAGS_WINDOWS']=v['CXXFLAGS_WINDOWS']=['/SUBSYSTEM:WINDOWS'] + v['CFLAGS_WINDOWSCE']=v['CXXFLAGS_WINDOWSCE']=['/SUBSYSTEM:WINDOWSCE'] + v['CFLAGS_CRT_MULTITHREADED']=v['CXXFLAGS_CRT_MULTITHREADED']=['/MT'] + v['CFLAGS_CRT_MULTITHREADED_DLL']=v['CXXFLAGS_CRT_MULTITHREADED_DLL']=['/MD'] + v['CFLAGS_CRT_MULTITHREADED_DBG']=v['CXXFLAGS_CRT_MULTITHREADED_DBG']=['/MTd'] + v['CFLAGS_CRT_MULTITHREADED_DLL_DBG']=v['CXXFLAGS_CRT_MULTITHREADED_DLL_DBG']=['/MDd'] + v['LIB_ST']='%s.lib' + v['LIBPATH_ST']='/LIBPATH:%s' + v['STLIB_ST']='%s.lib' + v['STLIBPATH_ST']='/LIBPATH:%s' + v.append_value('LINKFLAGS',['/NOLOGO']) + if v['MSVC_MANIFEST']: + v.append_value('LINKFLAGS',['/MANIFEST']) + v['CFLAGS_cshlib']=[] + v['CXXFLAGS_cxxshlib']=[] + v['LINKFLAGS_cshlib']=v['LINKFLAGS_cxxshlib']=['/DLL'] + v['cshlib_PATTERN']=v['cxxshlib_PATTERN']='%s.dll' + v['implib_PATTERN']='%s.lib' + v['IMPLIB_ST']='/IMPLIB:%s' + v['LINKFLAGS_cstlib']=[] + v['cstlib_PATTERN']=v['cxxstlib_PATTERN']='%s.lib' + v['cprogram_PATTERN']=v['cxxprogram_PATTERN']='%s.exe' +@after_method('apply_link') +@feature('c','cxx') +def apply_flags_msvc(self): + if self.env.CC_NAME!='msvc'or not getattr(self,'link_task',None): + return + is_static=isinstance(self.link_task,ccroot.stlink_task) + subsystem=getattr(self,'subsystem','') + if subsystem: + subsystem='/subsystem:%s'%subsystem + flags=is_static and'ARFLAGS'or'LINKFLAGS' + self.env.append_value(flags,subsystem) + if not is_static: + for f in self.env.LINKFLAGS: + d=f.lower() + if d[1:]=='debug': + pdbnode=self.link_task.outputs[0].change_ext('.pdb') + self.link_task.outputs.append(pdbnode) + try: + self.install_task.source.append(pdbnode) + except AttributeError: + pass + break +@feature('cprogram','cshlib','cxxprogram','cxxshlib') +@after_method('apply_link') +def apply_manifest(self): + if self.env.CC_NAME=='msvc'and self.env.MSVC_MANIFEST and getattr(self,'link_task',None): + out_node=self.link_task.outputs[0] + man_node=out_node.parent.find_or_declare(out_node.name+'.manifest') + self.link_task.outputs.append(man_node) + self.link_task.do_manifest=True +def exec_mf(self): + env=self.env + mtool=env['MT'] + if not mtool: + return 0 + self.do_manifest=False + outfile=self.outputs[0].abspath() + manifest=None + for out_node in self.outputs: + if out_node.name.endswith('.manifest'): + manifest=out_node.abspath() + break + if manifest is None: + return 0 + mode='' + if'cprogram'in self.generator.features or'cxxprogram'in self.generator.features: + mode='1' + elif'cshlib'in self.generator.features or'cxxshlib'in self.generator.features: + mode='2' + debug('msvc: embedding manifest in mode %r'%mode) + lst=[] + lst.append(env['MT']) + lst.extend(Utils.to_list(env['MTFLAGS'])) + lst.extend(['-manifest',manifest]) + lst.append('-outputresource:%s;%s'%(outfile,mode)) + lst=[lst] + return self.exec_command(*lst) +def quote_response_command(self,flag): + if flag.find(' ')>-1: + for x in('/LIBPATH:','/IMPLIB:','/OUT:','/I'): + if flag.startswith(x): + flag='%s"%s"'%(x,flag[len(x):]) + break + else: + flag='"%s"'%flag + return flag +def exec_response_command(self,cmd,**kw): + try: + tmp=None + if sys.platform.startswith('win')and isinstance(cmd,list)and len(' '.join(cmd))>=8192: + program=cmd[0] + cmd=[self.quote_response_command(x)for x in cmd] + (fd,tmp)=tempfile.mkstemp() + os.write(fd,'\r\n'.join(i.replace('\\','\\\\')for i in cmd[1:])) + os.close(fd) + cmd=[program,'@'+tmp] + ret=self.generator.bld.exec_command(cmd,**kw) + finally: + if tmp: + try: + os.remove(tmp) + except OSError: + pass + return ret +def exec_command_msvc(self,*k,**kw): + assert self.env['CC_NAME']=='msvc' + if isinstance(k[0],list): + lst=[] + carry='' + for a in k[0]: + if a=='/Fo'or a=='/doc'or a[-1]==':': + carry=a + else: + lst.append(carry+a) + carry='' + k=[lst] + if self.env['PATH']: + env=dict(self.env.env or os.environ) + env.update(PATH=';'.join(self.env['PATH'])) + kw['env']=env + bld=self.generator.bld + try: + if not kw.get('cwd',None): + kw['cwd']=bld.cwd + except AttributeError: + bld.cwd=kw['cwd']=bld.variant_dir + ret=self.exec_response_command(k[0],**kw) + if not ret and getattr(self,'do_manifest',None): + ret=self.exec_mf() + return ret +def wrap_class(class_name): + cls=Task.classes.get(class_name,None) + if not cls: + return None + derived_class=type(class_name,(cls,),{}) + def exec_command(self,*k,**kw): + if self.env['CC_NAME']=='msvc': + return self.exec_command_msvc(*k,**kw) + else: + return super(derived_class,self).exec_command(*k,**kw) + derived_class.exec_command=exec_command + derived_class.exec_response_command=exec_response_command + derived_class.quote_response_command=quote_response_command + derived_class.exec_command_msvc=exec_command_msvc + derived_class.exec_mf=exec_mf + return derived_class +for k in'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): + wrap_class(k) diff --git a/waflib/Tools/nasm.py b/waflib/Tools/nasm.py new file mode 100644 index 00000000..e3126ddb --- /dev/null +++ b/waflib/Tools/nasm.py @@ -0,0 +1,14 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import waflib.Tools.asm +from waflib.TaskGen import feature +@feature('asm') +def apply_nasm_vars(self): + self.env.append_value('ASFLAGS',self.to_list(getattr(self,'nasm_flags',[]))) +def configure(conf): + nasm=conf.find_program(['nasm','yasm'],var='AS') + conf.env.AS_TGT_F=['-o'] + conf.env.ASLNK_TGT_F=['-o'] + conf.load('asm') diff --git a/waflib/Tools/perl.py b/waflib/Tools/perl.py new file mode 100644 index 00000000..8b6c2f80 --- /dev/null +++ b/waflib/Tools/perl.py @@ -0,0 +1,80 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Task,Options,Utils +from waflib.Configure import conf +from waflib.TaskGen import extension,feature,before_method +@before_method('apply_incpaths','apply_link','propagate_uselib_vars') +@feature('perlext') +def init_perlext(self): + self.uselib=self.to_list(getattr(self,'uselib',[])) + if not'PERLEXT'in self.uselib:self.uselib.append('PERLEXT') + self.env['cshlib_PATTERN']=self.env['cxxshlib_PATTERN']=self.env['perlext_PATTERN'] +@extension('.xs') +def xsubpp_file(self,node): + outnode=node.change_ext('.c') + self.create_task('xsubpp',node,outnode) + self.source.append(outnode) +class xsubpp(Task.Task): + run_str='${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' + color='BLUE' + ext_out=['.h'] +@conf +def check_perl_version(self,minver=None): + res=True + if minver: + cver='.'.join(map(str,minver)) + else: + cver='' + self.start_msg('Checking for minimum perl version %s'%cver) + perl=getattr(Options.options,'perlbinary',None) + if not perl: + perl=self.find_program('perl',var='PERL') + if not perl: + self.end_msg("Perl not found",color="YELLOW") + return False + self.env['PERL']=perl + version=self.cmd_and_log([perl,"-e",'printf \"%vd\", $^V']) + if not version: + res=False + version="Unknown" + elif not minver is None: + ver=tuple(map(int,version.split("."))) + if ver +#ifdef __cplusplus +extern "C" { +#endif + void Py_Initialize(void); + void Py_Finalize(void); +#ifdef __cplusplus +} +#endif +int main(int argc, char **argv) +{ + (void)argc; (void)argv; + Py_Initialize(); + Py_Finalize(); + return 0; +} +''' +INST=''' +import sys, py_compile +py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3]) +''' +DISTUTILS_IMP=['from distutils.sysconfig import get_config_var, get_python_lib'] +@extension('.py') +def process_py(self,node): + try: + if not self.bld.is_install: + return + except AttributeError: + return + try: + if not self.install_path: + return + except AttributeError: + self.install_path='${PYTHONDIR}' + def inst_py(ctx): + install_from=getattr(self,'install_from',None) + if install_from: + install_from=self.path.find_dir(install_from) + install_pyfile(self,node,install_from) + self.bld.add_post_fun(inst_py) +def install_pyfile(self,node,install_from=None): + from_node=install_from or node.parent + tsk=self.bld.install_as(self.install_path+'/'+node.path_from(from_node),node,postpone=False) + path=tsk.get_install_path() + if self.bld.is_install<0: + Logs.info("+ removing byte compiled python files") + for x in'co': + try: + os.remove(path+x) + except OSError: + pass + if self.bld.is_install>0: + try: + st1=os.stat(path) + except OSError: + Logs.error('The python file is missing, this should not happen') + for x in['c','o']: + do_inst=self.env['PY'+x.upper()] + try: + st2=os.stat(path+x) + except OSError: + pass + else: + if st1.st_mtime<=st2.st_mtime: + do_inst=False + if do_inst: + lst=(x=='o')and[self.env['PYFLAGS_OPT']]or[] + (a,b,c)=(path,path+x,tsk.get_install_path(destdir=False)+x) + argv=self.env['PYTHON']+lst+['-c',INST,a,b,c] + Logs.info('+ byte compiling %r'%(path+x)) + env=self.env.env or None + ret=Utils.subprocess.Popen(argv,env=env).wait() + if ret: + raise Errors.WafError('py%s compilation failed %r'%(x,path)) +@feature('py') +def feature_py(self): + pass +@feature('pyext') +@before_method('propagate_uselib_vars','apply_link') +@after_method('apply_bundle') +def init_pyext(self): + self.uselib=self.to_list(getattr(self,'uselib',[])) + if not'PYEXT'in self.uselib: + self.uselib.append('PYEXT') + self.env.cshlib_PATTERN=self.env.cxxshlib_PATTERN=self.env.macbundle_PATTERN=self.env.pyext_PATTERN + self.env.fcshlib_PATTERN=self.env.dshlib_PATTERN=self.env.pyext_PATTERN + try: + if not self.install_path: + return + except AttributeError: + self.install_path='${PYTHONARCHDIR}' +@feature('pyext') +@before_method('apply_link','apply_bundle') +def set_bundle(self): + if Utils.unversioned_sys_platform()=='darwin': + self.mac_bundle=True +@before_method('propagate_uselib_vars') +@feature('pyembed') +def init_pyembed(self): + self.uselib=self.to_list(getattr(self,'uselib',[])) + if not'PYEMBED'in self.uselib: + self.uselib.append('PYEMBED') +@conf +def get_python_variables(self,variables,imports=None): + if not imports: + try: + imports=self.python_imports + except AttributeError: + imports=DISTUTILS_IMP + program=list(imports) + program.append('') + for v in variables: + program.append("print(repr(%s))"%v) + os_env=dict(os.environ) + try: + del os_env['MACOSX_DEPLOYMENT_TARGET'] + except KeyError: + pass + try: + out=self.cmd_and_log(self.env.PYTHON+['-c','\n'.join(program)],env=os_env) + except Errors.WafError: + self.fatal('The distutils module is unusable: install "python-devel"?') + self.to_log(out) + return_values=[] + for s in out.split('\n'): + s=s.strip() + if not s: + continue + if s=='None': + return_values.append(None) + elif(s[0]=="'"and s[-1]=="'")or(s[0]=='"'and s[-1]=='"'): + return_values.append(eval(s)) + elif s[0].isdigit(): + return_values.append(int(s)) + else:break + return return_values +@conf +def check_python_headers(conf): + env=conf.env + if not env['CC_NAME']and not env['CXX_NAME']: + conf.fatal('load a compiler first (gcc, g++, ..)') + if not env['PYTHON_VERSION']: + conf.check_python_version() + pybin=conf.env.PYTHON + if not pybin: + conf.fatal('Could not find the python executable') + v='prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS'.split() + try: + lst=conf.get_python_variables(["get_config_var('%s') or ''"%x for x in v]) + except RuntimeError: + conf.fatal("Python development headers not found (-v for details).") + vals=['%s = %r'%(x,y)for(x,y)in zip(v,lst)] + conf.to_log("Configuration returned from %r:\n%r\n"%(pybin,'\n'.join(vals))) + dct=dict(zip(v,lst)) + x='MACOSX_DEPLOYMENT_TARGET' + if dct[x]: + conf.env[x]=conf.environ[x]=dct[x] + env['pyext_PATTERN']='%s'+dct['SO'] + all_flags=dct['LDFLAGS']+' '+dct['CFLAGS'] + conf.parse_flags(all_flags,'PYEMBED') + all_flags=dct['LDFLAGS']+' '+dct['LDSHARED']+' '+dct['CFLAGS'] + conf.parse_flags(all_flags,'PYEXT') + result=None + for name in('python'+env['PYTHON_VERSION'],'python'+env['PYTHON_VERSION'].replace('.','')): + if not result and env['LIBPATH_PYEMBED']: + path=env['LIBPATH_PYEMBED'] + conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n"%path) + result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in LIBPATH_PYEMBED'%name) + if not result and dct['LIBDIR']: + path=[dct['LIBDIR']] + conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n"%path) + result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in LIBDIR'%name) + if not result and dct['LIBPL']: + path=[dct['LIBPL']] + conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") + result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in python_LIBPL'%name) + if not result: + path=[os.path.join(dct['prefix'],"libs")] + conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") + result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in $prefix/libs'%name) + if result: + break + if result: + env['LIBPATH_PYEMBED']=path + env.append_value('LIB_PYEMBED',[name]) + else: + conf.to_log("\n\n### LIB NOT FOUND\n") + if(Utils.is_win32 or sys.platform.startswith('os2')or dct['Py_ENABLE_SHARED']): + env['LIBPATH_PYEXT']=env['LIBPATH_PYEMBED'] + env['LIB_PYEXT']=env['LIB_PYEMBED'] + num='.'.join(env['PYTHON_VERSION'].split('.')[:2]) + conf.find_program([''.join(pybin)+'-config','python%s-config'%num,'python-config-%s'%num,'python%sm-config'%num],var='PYTHON_CONFIG',mandatory=False) + includes=[] + if conf.env.PYTHON_CONFIG: + for incstr in conf.cmd_and_log([conf.env.PYTHON_CONFIG,'--includes']).strip().split(): + if(incstr.startswith('-I')or incstr.startswith('/I')): + incstr=incstr[2:] + if incstr not in includes: + includes.append(incstr) + conf.to_log("Include path for Python extensions (found via python-config --includes): %r\n"%(includes,)) + env['INCLUDES_PYEXT']=includes + env['INCLUDES_PYEMBED']=includes + else: + conf.to_log("Include path for Python extensions ""(found via distutils module): %r\n"%(dct['INCLUDEPY'],)) + env['INCLUDES_PYEXT']=[dct['INCLUDEPY']] + env['INCLUDES_PYEMBED']=[dct['INCLUDEPY']] + if env['CC_NAME']=='gcc': + env.append_value('CFLAGS_PYEMBED',['-fno-strict-aliasing']) + env.append_value('CFLAGS_PYEXT',['-fno-strict-aliasing']) + if env['CXX_NAME']=='gcc': + env.append_value('CXXFLAGS_PYEMBED',['-fno-strict-aliasing']) + env.append_value('CXXFLAGS_PYEXT',['-fno-strict-aliasing']) + if env.CC_NAME=="msvc": + from distutils.msvccompiler import MSVCCompiler + dist_compiler=MSVCCompiler() + dist_compiler.initialize() + env.append_value('CFLAGS_PYEXT',dist_compiler.compile_options) + env.append_value('CXXFLAGS_PYEXT',dist_compiler.compile_options) + env.append_value('LINKFLAGS_PYEXT',dist_compiler.ldflags_shared) + try: + conf.check(header_name='Python.h',define_name='HAVE_PYTHON_H',uselib='PYEMBED',fragment=FRAG,errmsg=':-(') + except conf.errors.ConfigurationError: + xx=conf.env.CXX_NAME and'cxx'or'c' + conf.check_cfg(msg='Asking python-config for the flags (pyembed)',path=conf.env.PYTHON_CONFIG,package='',uselib_store='PYEMBED',args=['--cflags','--libs','--ldflags']) + conf.check(header_name='Python.h',define_name='HAVE_PYTHON_H',msg='Getting pyembed flags from python-config',fragment=FRAG,errmsg='Could not build a python embedded interpreter',features='%s %sprogram pyembed'%(xx,xx)) + conf.check_cfg(msg='Asking python-config for the flags (pyext)',path=conf.env.PYTHON_CONFIG,package='',uselib_store='PYEXT',args=['--cflags','--libs','--ldflags']) + conf.check(header_name='Python.h',define_name='HAVE_PYTHON_H',msg='Getting pyext flags from python-config',features='%s %sshlib pyext'%(xx,xx),fragment=FRAG,errmsg='Could not build python extensions') +@conf +def check_python_version(conf,minver=None): + assert minver is None or isinstance(minver,tuple) + pybin=conf.env['PYTHON'] + if not pybin: + conf.fatal('could not find the python executable') + cmd=pybin+['-c','import sys\nfor x in sys.version_info: print(str(x))'] + Logs.debug('python: Running python command %r'%cmd) + lines=conf.cmd_and_log(cmd).split() + assert len(lines)==5,"found %i lines, expected 5: %r"%(len(lines),lines) + pyver_tuple=(int(lines[0]),int(lines[1]),int(lines[2]),lines[3],int(lines[4])) + result=(minver is None)or(pyver_tuple>=minver) + if result: + pyver='.'.join([str(x)for x in pyver_tuple[:2]]) + conf.env['PYTHON_VERSION']=pyver + if'PYTHONDIR'in conf.environ: + pydir=conf.environ['PYTHONDIR'] + else: + if Utils.is_win32: + (python_LIBDEST,pydir)=conf.get_python_variables(["get_config_var('LIBDEST') or ''","get_python_lib(standard_lib=0, prefix=%r) or ''"%conf.env['PREFIX']]) + else: + python_LIBDEST=None + (pydir,)=conf.get_python_variables(["get_python_lib(standard_lib=0, prefix=%r) or ''"%conf.env['PREFIX']]) + if python_LIBDEST is None: + if conf.env['LIBDIR']: + python_LIBDEST=os.path.join(conf.env['LIBDIR'],"python"+pyver) + else: + python_LIBDEST=os.path.join(conf.env['PREFIX'],"lib","python"+pyver) + if'PYTHONARCHDIR'in conf.environ: + pyarchdir=conf.environ['PYTHONARCHDIR'] + else: + (pyarchdir,)=conf.get_python_variables(["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''"%conf.env['PREFIX']]) + if not pyarchdir: + pyarchdir=pydir + if hasattr(conf,'define'): + conf.define('PYTHONDIR',pydir) + conf.define('PYTHONARCHDIR',pyarchdir) + conf.env['PYTHONDIR']=pydir + conf.env['PYTHONARCHDIR']=pyarchdir + pyver_full='.'.join(map(str,pyver_tuple[:3])) + if minver is None: + conf.msg('Checking for python version',pyver_full) + else: + minver_str='.'.join(map(str,minver)) + conf.msg('Checking for python version',pyver_tuple,">= %s"%(minver_str,)and'GREEN'or'YELLOW') + if not result: + conf.fatal('The python version is too old, expecting %r'%(minver,)) +PYTHON_MODULE_TEMPLATE=''' +import %s as current_module +version = getattr(current_module, '__version__', None) +if version is not None: + print(str(version)) +else: + print('unknown version') +''' +@conf +def check_python_module(conf,module_name,condition=''): + msg='Python module %s'%module_name + if condition: + msg='%s (%s)'%(msg,condition) + conf.start_msg(msg) + try: + ret=conf.cmd_and_log(conf.env['PYTHON']+['-c',PYTHON_MODULE_TEMPLATE%module_name]) + except Exception: + conf.end_msg(False) + conf.fatal('Could not find the python module %r'%module_name) + ret=ret.strip() + if condition: + conf.end_msg(ret) + if ret=='unknown version': + conf.fatal('Could not check the %s version'%module_name) + from distutils.version import LooseVersion + def num(*k): + if isinstance(k[0],int): + return LooseVersion('.'.join([str(x)for x in k])) + else: + return LooseVersion(k[0]) + d={'num':num,'ver':LooseVersion(ret)} + ev=eval(condition,{},d) + if not ev: + conf.fatal('The %s version does not satisfy the requirements'%module_name) + else: + if ret=='unknown version': + conf.end_msg(True) + else: + conf.end_msg(ret) +def configure(conf): + try: + conf.find_program('python',var='PYTHON') + except conf.errors.ConfigurationError: + Logs.warn("could not find a python executable, setting to sys.executable '%s'"%sys.executable) + conf.env.PYTHON=sys.executable + if conf.env.PYTHON!=sys.executable: + Logs.warn("python executable %r differs from system %r"%(conf.env.PYTHON,sys.executable)) + conf.env.PYTHON=conf.cmd_to_list(conf.env.PYTHON) + v=conf.env + v['PYCMD']='"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"' + v['PYFLAGS']='' + v['PYFLAGS_OPT']='-O' + v['PYC']=getattr(Options.options,'pyc',1) + v['PYO']=getattr(Options.options,'pyo',1) +def options(opt): + opt.add_option('--nopyc',action='store_false',default=1,help='Do not install bytecode compiled .pyc files (configuration) [Default:install]',dest='pyc') + opt.add_option('--nopyo',action='store_false',default=1,help='Do not install optimised compiled .pyo files (configuration) [Default:install]',dest='pyo') diff --git a/waflib/Tools/qt4.py b/waflib/Tools/qt4.py new file mode 100644 index 00000000..4300a57d --- /dev/null +++ b/waflib/Tools/qt4.py @@ -0,0 +1,437 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +try: + from xml.sax import make_parser + from xml.sax.handler import ContentHandler +except ImportError: + has_xml=False + ContentHandler=object +else: + has_xml=True +import os,sys +from waflib.Tools import c_preproc,cxx +from waflib import Task,Utils,Options,Errors +from waflib.TaskGen import feature,after_method,extension +from waflib.Configure import conf +from waflib import Logs +MOC_H=['.h','.hpp','.hxx','.hh'] +EXT_RCC=['.qrc'] +EXT_UI=['.ui'] +EXT_QT4=['.cpp','.cc','.cxx','.C'] +QT4_LIBS="QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative" +class qxx(cxx.cxx): + def __init__(self,*k,**kw): + Task.Task.__init__(self,*k,**kw) + self.moc_done=0 + def scan(self): + (nodes,names)=c_preproc.scan(self) + for x in nodes: + if x.name.endswith('.moc'): + nodes.remove(x) + names.append(x.path_from(self.inputs[0].parent.get_bld())) + return(nodes,names) + def runnable_status(self): + if self.moc_done: + return Task.Task.runnable_status(self) + else: + for t in self.run_after: + if not t.hasrun: + return Task.ASK_LATER + self.add_moc_tasks() + return Task.Task.runnable_status(self) + def add_moc_tasks(self): + node=self.inputs[0] + bld=self.generator.bld + try: + self.signature() + except KeyError: + pass + else: + delattr(self,'cache_sig') + moctasks=[] + mocfiles=[] + try: + tmp_lst=bld.raw_deps[self.uid()] + bld.raw_deps[self.uid()]=[] + except KeyError: + tmp_lst=[] + for d in tmp_lst: + if not d.endswith('.moc'): + continue + if d in mocfiles: + Logs.error("paranoia owns") + continue + mocfiles.append(d) + h_node=None + try:ext=Options.options.qt_header_ext.split() + except AttributeError:pass + if not ext:ext=MOC_H + base2=d[:-4] + for x in[node.parent]+self.generator.includes_nodes: + for e in ext: + h_node=x.find_node(base2+e) + if h_node: + break + if h_node: + m_node=h_node.change_ext('.moc') + break + else: + for k in EXT_QT4: + if base2.endswith(k): + for x in[node.parent]+self.generator.includes_nodes: + h_node=x.find_node(base2) + if h_node: + break + if h_node: + m_node=h_node.change_ext(k+'.moc') + break + if not h_node: + raise Errors.WafError('no header found for %r which is a moc file'%d) + bld.node_deps[(self.inputs[0].parent.abspath(),m_node.name)]=h_node + task=Task.classes['moc'](env=self.env,generator=self.generator) + task.set_inputs(h_node) + task.set_outputs(m_node) + gen=bld.producer + gen.outstanding.insert(0,task) + gen.total+=1 + moctasks.append(task) + tmp_lst=bld.raw_deps[self.uid()]=mocfiles + lst=bld.node_deps.get(self.uid(),()) + for d in lst: + name=d.name + if name.endswith('.moc'): + task=Task.classes['moc'](env=self.env,generator=self.generator) + task.set_inputs(bld.node_deps[(self.inputs[0].parent.abspath(),name)]) + task.set_outputs(d) + gen=bld.producer + gen.outstanding.insert(0,task) + gen.total+=1 + moctasks.append(task) + self.run_after.update(set(moctasks)) + self.moc_done=1 + run=Task.classes['cxx'].__dict__['run'] +class trans_update(Task.Task): + run_str='${QT_LUPDATE} ${SRC} -ts ${TGT}' + color='BLUE' +Task.update_outputs(trans_update) +class XMLHandler(ContentHandler): + def __init__(self): + self.buf=[] + self.files=[] + def startElement(self,name,attrs): + if name=='file': + self.buf=[] + def endElement(self,name): + if name=='file': + self.files.append(str(''.join(self.buf))) + def characters(self,cars): + self.buf.append(cars) +@extension(*EXT_RCC) +def create_rcc_task(self,node): + rcnode=node.change_ext('_rc.cpp') + rcctask=self.create_task('rcc',node,rcnode) + cpptask=self.create_task('cxx',rcnode,rcnode.change_ext('.o')) + try: + self.compiled_tasks.append(cpptask) + except AttributeError: + self.compiled_tasks=[cpptask] + return cpptask +@extension(*EXT_UI) +def create_uic_task(self,node): + uictask=self.create_task('ui4',node) + uictask.outputs=[self.path.find_or_declare(self.env['ui_PATTERN']%node.name[:-3])] +@extension('.ts') +def add_lang(self,node): + self.lang=self.to_list(getattr(self,'lang',[]))+[node] +@feature('qt4') +@after_method('apply_link') +def apply_qt4(self): + if getattr(self,'lang',None): + qmtasks=[] + for x in self.to_list(self.lang): + if isinstance(x,str): + x=self.path.find_resource(x+'.ts') + qmtasks.append(self.create_task('ts2qm',x,x.change_ext('.qm'))) + if getattr(self,'update',None)and Options.options.trans_qt4: + cxxnodes=[a.inputs[0]for a in self.compiled_tasks]+[a.inputs[0]for a in self.tasks if getattr(a,'inputs',None)and a.inputs[0].name.endswith('.ui')] + for x in qmtasks: + self.create_task('trans_update',cxxnodes,x.inputs) + if getattr(self,'langname',None): + qmnodes=[x.outputs[0]for x in qmtasks] + rcnode=self.langname + if isinstance(rcnode,str): + rcnode=self.path.find_or_declare(rcnode+'.qrc') + t=self.create_task('qm2rcc',qmnodes,rcnode) + k=create_rcc_task(self,t.outputs[0]) + self.link_task.inputs.append(k.outputs[0]) + lst=[] + for flag in self.to_list(self.env['CXXFLAGS']): + if len(flag)<2:continue + f=flag[0:2] + if f in['-D','-I','/D','/I']: + if(f[0]=='/'): + lst.append('-'+flag[1:]) + else: + lst.append(flag) + self.env['MOC_FLAGS']=lst +@extension(*EXT_QT4) +def cxx_hook(self,node): + return self.create_compiled_task('qxx',node) +class rcc(Task.Task): + color='BLUE' + run_str='${QT_RCC} -name ${SRC[0].name} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' + ext_out=['.h'] + def scan(self): + node=self.inputs[0] + if not has_xml: + Logs.error('no xml support was found, the rcc dependencies will be incomplete!') + return([],[]) + parser=make_parser() + curHandler=XMLHandler() + parser.setContentHandler(curHandler) + fi=open(self.inputs[0].abspath(),'r') + try: + parser.parse(fi) + finally: + fi.close() + nodes=[] + names=[] + root=self.inputs[0].parent + for x in curHandler.files: + nd=root.find_resource(x) + if nd:nodes.append(nd) + else:names.append(x) + return(nodes,names) +class moc(Task.Task): + color='BLUE' + run_str='${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' +class ui4(Task.Task): + color='BLUE' + run_str='${QT_UIC} ${SRC} -o ${TGT}' + ext_out=['.h'] +class ts2qm(Task.Task): + color='BLUE' + run_str='${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' +class qm2rcc(Task.Task): + color='BLUE' + after='ts2qm' + def run(self): + txt='\n'.join(['%s'%k.path_from(self.outputs[0].parent)for k in self.inputs]) + code='\n\n%s\n\n'%txt + self.outputs[0].write(code) +def configure(self): + self.find_qt4_binaries() + self.set_qt4_libs_to_check() + self.find_qt4_libraries() + self.add_qt4_rpath() + self.simplify_qt4_libs() +@conf +def find_qt4_binaries(self): + env=self.env + opt=Options.options + qtdir=getattr(opt,'qtdir','') + qtbin=getattr(opt,'qtbin','') + paths=[] + if qtdir: + qtbin=os.path.join(qtdir,'bin') + if not qtdir: + qtdir=os.environ.get('QT4_ROOT','') + qtbin=os.environ.get('QT4_BIN',None)or os.path.join(qtdir,'bin') + if qtbin: + paths=[qtbin] + if not qtdir: + paths=os.environ.get('PATH','').split(os.pathsep) + paths.append('/usr/share/qt4/bin/') + try: + lst=Utils.listdir('/usr/local/Trolltech/') + except OSError: + pass + else: + if lst: + lst.sort() + lst.reverse() + qtdir='/usr/local/Trolltech/%s/'%lst[0] + qtbin=os.path.join(qtdir,'bin') + paths.append(qtbin) + cand=None + prev_ver=['4','0','0'] + for qmk in['qmake-qt4','qmake4','qmake']: + try: + qmake=self.find_program(qmk,path_list=paths) + except self.errors.ConfigurationError: + pass + else: + try: + version=self.cmd_and_log([qmake,'-query','QT_VERSION']).strip() + except self.errors.WafError: + pass + else: + if version: + new_ver=version.split('.') + if new_ver>prev_ver: + cand=qmake + prev_ver=new_ver + if cand: + self.env.QMAKE=cand + else: + self.fatal('Could not find qmake for qt4') + qtbin=self.cmd_and_log([self.env.QMAKE,'-query','QT_INSTALL_BINS']).strip()+os.sep + def find_bin(lst,var): + if var in env: + return + for f in lst: + try: + ret=self.find_program(f,path_list=paths) + except self.errors.ConfigurationError: + pass + else: + env[var]=ret + break + find_bin(['uic-qt3','uic3'],'QT_UIC3') + find_bin(['uic-qt4','uic'],'QT_UIC') + if not env['QT_UIC']: + self.fatal('cannot find the uic compiler for qt4') + try: + uicver=self.cmd_and_log(env['QT_UIC']+" -version 2>&1").strip() + except self.errors.ConfigurationError: + self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') + uicver=uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt','') + self.msg('Checking for uic version','%s'%uicver) + if uicver.find(' 3.')!=-1: + self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') + find_bin(['moc-qt4','moc'],'QT_MOC') + find_bin(['rcc'],'QT_RCC') + find_bin(['lrelease-qt4','lrelease'],'QT_LRELEASE') + find_bin(['lupdate-qt4','lupdate'],'QT_LUPDATE') + env['UIC3_ST']='%s -o %s' + env['UIC_ST']='%s -o %s' + env['MOC_ST']='-o' + env['ui_PATTERN']='ui_%s.h' + env['QT_LRELEASE_FLAGS']=['-silent'] + env.MOCCPPPATH_ST='-I%s' + env.MOCDEFINES_ST='-D%s' +@conf +def find_qt4_libraries(self): + qtlibs=getattr(Options.options,'qtlibs',None)or os.environ.get("QT4_LIBDIR",None) + if not qtlibs: + try: + qtlibs=self.cmd_and_log([self.env.QMAKE,'-query','QT_INSTALL_LIBS']).strip() + except Errors.WafError: + qtdir=self.cmd_and_log([self.env.QMAKE,'-query','QT_INSTALL_PREFIX']).strip()+os.sep + qtlibs=os.path.join(qtdir,'lib') + self.msg('Found the Qt4 libraries in',qtlibs) + qtincludes=os.environ.get("QT4_INCLUDES",None)or self.cmd_and_log([self.env.QMAKE,'-query','QT_INSTALL_HEADERS']).strip() + env=self.env + if not'PKG_CONFIG_PATH'in os.environ: + os.environ['PKG_CONFIG_PATH']='%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib'%(qtlibs,qtlibs) + try: + if os.environ.get("QT4_XCOMPILE",None): + raise self.errors.ConfigurationError() + self.check_cfg(atleast_pkgconfig_version='0.1') + except self.errors.ConfigurationError: + for i in self.qt4_vars: + uselib=i.upper() + if Utils.unversioned_sys_platform()=="darwin": + frameworkName=i+".framework" + qtDynamicLib=os.path.join(qtlibs,frameworkName,i) + if os.path.exists(qtDynamicLib): + env.append_unique('FRAMEWORK_'+uselib,i) + self.msg('Checking for %s'%i,qtDynamicLib,'GREEN') + else: + self.msg('Checking for %s'%i,False,'YELLOW') + env.append_unique('INCLUDES_'+uselib,os.path.join(qtlibs,frameworkName,'Headers')) + elif env.DEST_OS!="win32": + qtDynamicLib=os.path.join(qtlibs,"lib"+i+".so") + qtStaticLib=os.path.join(qtlibs,"lib"+i+".a") + if os.path.exists(qtDynamicLib): + env.append_unique('LIB_'+uselib,i) + self.msg('Checking for %s'%i,qtDynamicLib,'GREEN') + elif os.path.exists(qtStaticLib): + env.append_unique('LIB_'+uselib,i) + self.msg('Checking for %s'%i,qtStaticLib,'GREEN') + else: + self.msg('Checking for %s'%i,False,'YELLOW') + env.append_unique('LIBPATH_'+uselib,qtlibs) + env.append_unique('INCLUDES_'+uselib,qtincludes) + env.append_unique('INCLUDES_'+uselib,os.path.join(qtincludes,i)) + else: + for k in("lib%s.a","lib%s4.a","%s.lib","%s4.lib"): + lib=os.path.join(qtlibs,k%i) + if os.path.exists(lib): + env.append_unique('LIB_'+uselib,i+k[k.find("%s")+2:k.find('.')]) + self.msg('Checking for %s'%i,lib,'GREEN') + break + else: + self.msg('Checking for %s'%i,False,'YELLOW') + env.append_unique('LIBPATH_'+uselib,qtlibs) + env.append_unique('INCLUDES_'+uselib,qtincludes) + env.append_unique('INCLUDES_'+uselib,os.path.join(qtincludes,i)) + uselib=i.upper()+"_debug" + for k in("lib%sd.a","lib%sd4.a","%sd.lib","%sd4.lib"): + lib=os.path.join(qtlibs,k%i) + if os.path.exists(lib): + env.append_unique('LIB_'+uselib,i+k[k.find("%s")+2:k.find('.')]) + self.msg('Checking for %s'%i,lib,'GREEN') + break + else: + self.msg('Checking for %s'%i,False,'YELLOW') + env.append_unique('LIBPATH_'+uselib,qtlibs) + env.append_unique('INCLUDES_'+uselib,qtincludes) + env.append_unique('INCLUDES_'+uselib,os.path.join(qtincludes,i)) + else: + for i in self.qt4_vars_debug+self.qt4_vars: + self.check_cfg(package=i,args='--cflags --libs',mandatory=False) +@conf +def simplify_qt4_libs(self): + env=self.env + def process_lib(vars_,coreval): + for d in vars_: + var=d.upper() + if var=='QTCORE': + continue + value=env['LIBPATH_'+var] + if value: + core=env[coreval] + accu=[] + for lib in value: + if lib in core: + continue + accu.append(lib) + env['LIBPATH_'+var]=accu + process_lib(self.qt4_vars,'LIBPATH_QTCORE') + process_lib(self.qt4_vars_debug,'LIBPATH_QTCORE_DEBUG') +@conf +def add_qt4_rpath(self): + env=self.env + if Options.options.want_rpath: + def process_rpath(vars_,coreval): + for d in vars_: + var=d.upper() + value=env['LIBPATH_'+var] + if value: + core=env[coreval] + accu=[] + for lib in value: + if var!='QTCORE': + if lib in core: + continue + accu.append('-Wl,--rpath='+lib) + env['RPATH_'+var]=accu + process_rpath(self.qt4_vars,'LIBPATH_QTCORE') + process_rpath(self.qt4_vars_debug,'LIBPATH_QTCORE_DEBUG') +@conf +def set_qt4_libs_to_check(self): + if not hasattr(self,'qt4_vars'): + self.qt4_vars=QT4_LIBS + self.qt4_vars=Utils.to_list(self.qt4_vars) + if not hasattr(self,'qt4_vars_debug'): + self.qt4_vars_debug=[a+'_debug'for a in self.qt4_vars] + self.qt4_vars_debug=Utils.to_list(self.qt4_vars_debug) +def options(opt): + opt.add_option('--want-rpath',action='store_true',default=False,dest='want_rpath',help='enable the rpath for qt libraries') + opt.add_option('--header-ext',type='string',default='',help='header extension for moc files',dest='qt_header_ext') + for i in'qtdir qtbin qtlibs'.split(): + opt.add_option('--'+i,type='string',default='',dest=i) + opt.add_option('--translate',action="store_true",help="collect translation strings",dest="trans_qt4",default=False) diff --git a/waflib/Tools/ruby.py b/waflib/Tools/ruby.py new file mode 100644 index 00000000..04cddfb1 --- /dev/null +++ b/waflib/Tools/ruby.py @@ -0,0 +1,103 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Task,Options,Utils +from waflib.TaskGen import before_method,feature,after_method,Task,extension +from waflib.Configure import conf +@feature('rubyext') +@before_method('apply_incpaths','apply_lib_vars','apply_bundle','apply_link') +def init_rubyext(self): + self.install_path='${ARCHDIR_RUBY}' + self.uselib=self.to_list(getattr(self,'uselib','')) + if not'RUBY'in self.uselib: + self.uselib.append('RUBY') + if not'RUBYEXT'in self.uselib: + self.uselib.append('RUBYEXT') +@feature('rubyext') +@before_method('apply_link','propagate_uselib') +def apply_ruby_so_name(self): + self.env['cshlib_PATTERN']=self.env['cxxshlib_PATTERN']=self.env['rubyext_PATTERN'] +@conf +def check_ruby_version(self,minver=()): + if Options.options.rubybinary: + self.env.RUBY=Options.options.rubybinary + else: + self.find_program('ruby',var='RUBY') + ruby=self.env.RUBY + try: + version=self.cmd_and_log([ruby,'-e','puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() + except Exception: + self.fatal('could not determine ruby version') + self.env.RUBY_VERSION=version + try: + ver=tuple(map(int,version.split("."))) + except Exception: + self.fatal('unsupported ruby version %r'%version) + cver='' + if minver: + if ver=(1,9,0): + ruby_hdrdir=read_config('rubyhdrdir') + cpppath+=ruby_hdrdir + cpppath+=[os.path.join(ruby_hdrdir[0],read_config('arch')[0])] + self.check(header_name='ruby.h',includes=cpppath,errmsg='could not find ruby header file') + self.env.LIBPATH_RUBYEXT=read_config('libdir') + self.env.LIBPATH_RUBYEXT+=archdir + self.env.INCLUDES_RUBYEXT=cpppath + self.env.CFLAGS_RUBYEXT=read_config('CCDLFLAGS') + self.env.rubyext_PATTERN='%s.'+read_config('DLEXT')[0] + flags=read_config('LDSHARED') + while flags and flags[0][0]!='-': + flags=flags[1:] + if len(flags)>1 and flags[1]=="ppc": + flags=flags[2:] + self.env.LINKFLAGS_RUBYEXT=flags + self.env.LINKFLAGS_RUBYEXT+=read_config('LIBS') + self.env.LINKFLAGS_RUBYEXT+=read_config('LIBRUBYARG_SHARED') + if Options.options.rubyarchdir: + self.env.ARCHDIR_RUBY=Options.options.rubyarchdir + else: + self.env.ARCHDIR_RUBY=read_config('sitearchdir')[0] + if Options.options.rubylibdir: + self.env.LIBDIR_RUBY=Options.options.rubylibdir + else: + self.env.LIBDIR_RUBY=read_config('sitelibdir')[0] +@conf +def check_ruby_module(self,module_name): + self.start_msg('Ruby module %s'%module_name) + try: + self.cmd_and_log([self.env['RUBY'],'-e','require \'%s\';puts 1'%module_name]) + except Exception: + self.end_msg(False) + self.fatal('Could not find the ruby module %r'%module_name) + self.end_msg(True) +@extension('.rb') +def process(self,node): + tsk=self.create_task('run_ruby',node) +class run_ruby(Task.Task): + run_str='${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' +def options(opt): + opt.add_option('--with-ruby-archdir',type='string',dest='rubyarchdir',help='Specify directory where to install arch specific files') + opt.add_option('--with-ruby-libdir',type='string',dest='rubylibdir',help='Specify alternate ruby library path') + opt.add_option('--with-ruby-binary',type='string',dest='rubybinary',help='Specify alternate ruby binary') diff --git a/waflib/Tools/suncc.py b/waflib/Tools/suncc.py new file mode 100644 index 00000000..edd24cd5 --- /dev/null +++ b/waflib/Tools/suncc.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Utils +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_scc(conf): + v=conf.env + cc=None + if v['CC']:cc=v['CC'] + elif'CC'in conf.environ:cc=conf.environ['CC'] + if not cc:cc=conf.find_program('cc',var='CC') + if not cc:conf.fatal('Could not find a Sun C compiler') + cc=conf.cmd_to_list(cc) + try: + conf.cmd_and_log(cc+['-flags']) + except Exception: + conf.fatal('%r is not a Sun compiler'%cc) + v['CC']=cc + v['CC_NAME']='sun' +@conf +def scc_common_flags(conf): + v=conf.env + v['CC_SRC_F']=[] + v['CC_TGT_F']=['-c','-o'] + if not v['LINK_CC']:v['LINK_CC']=v['CC'] + v['CCLNK_SRC_F']='' + v['CCLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['SONAME_ST']='-Wl,-h,%s' + v['SHLIB_MARKER']='-Bdynamic' + v['STLIB_MARKER']='-Bstatic' + v['cprogram_PATTERN']='%s' + v['CFLAGS_cshlib']=['-Kpic','-DPIC'] + v['LINKFLAGS_cshlib']=['-G'] + v['cshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cstlib']=['-Bstatic'] + v['cstlib_PATTERN']='lib%s.a' +def configure(conf): + conf.find_scc() + conf.find_ar() + conf.scc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/waflib/Tools/suncxx.py b/waflib/Tools/suncxx.py new file mode 100644 index 00000000..4b8b931a --- /dev/null +++ b/waflib/Tools/suncxx.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +from waflib import Utils +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_sxx(conf): + v=conf.env + cc=None + if v['CXX']:cc=v['CXX'] + elif'CXX'in conf.environ:cc=conf.environ['CXX'] + if not cc:cc=conf.find_program('CC',var='CXX') + if not cc:cc=conf.find_program('c++',var='CXX') + if not cc:conf.fatal('Could not find a Sun C++ compiler') + cc=conf.cmd_to_list(cc) + try: + conf.cmd_and_log(cc+['-flags']) + except Exception: + conf.fatal('%r is not a Sun compiler'%cc) + v['CXX']=cc + v['CXX_NAME']='sun' +@conf +def sxx_common_flags(conf): + v=conf.env + v['CXX_SRC_F']=[] + v['CXX_TGT_F']=['-c','-o'] + if not v['LINK_CXX']:v['LINK_CXX']=v['CXX'] + v['CXXLNK_SRC_F']=[] + v['CXXLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['SONAME_ST']='-Wl,-h,%s' + v['SHLIB_MARKER']='-Bdynamic' + v['STLIB_MARKER']='-Bstatic' + v['cxxprogram_PATTERN']='%s' + v['CXXFLAGS_cxxshlib']=['-Kpic','-DPIC'] + v['LINKFLAGS_cxxshlib']=['-G'] + v['cxxshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cxxstlib']=['-Bstatic'] + v['cxxstlib_PATTERN']='lib%s.a' +def configure(conf): + conf.find_sxx() + conf.find_ar() + conf.sxx_common_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() diff --git a/waflib/Tools/tex.py b/waflib/Tools/tex.py new file mode 100644 index 00000000..4448381f --- /dev/null +++ b/waflib/Tools/tex.py @@ -0,0 +1,250 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,re +from waflib import Utils,Task,Errors,Logs +from waflib.TaskGen import feature,before_method +re_bibunit=re.compile(r'\\(?Pputbib)\[(?P[^\[\]]*)\]',re.M) +def bibunitscan(self): + node=self.inputs[0] + nodes=[] + if not node:return nodes + code=node.read() + for match in re_bibunit.finditer(code): + path=match.group('file') + if path: + for k in['','.bib']: + Logs.debug('tex: trying %s%s'%(path,k)) + fi=node.parent.find_resource(path+k) + if fi: + nodes.append(fi) + else: + Logs.debug('tex: could not find %s'%path) + Logs.debug("tex: found the following bibunit files: %s"%nodes) + return nodes +exts_deps_tex=['','.ltx','.tex','.bib','.pdf','.png','.eps','.ps'] +exts_tex=['.ltx','.tex'] +re_tex=re.compile(r'\\(?Pinclude|bibliography|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P[^{}]*)}',re.M) +g_bibtex_re=re.compile('bibdata',re.M) +class tex(Task.Task): + bibtex_fun,_=Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}',shell=False) + bibtex_fun.__doc__=""" + Execute the program **bibtex** + """ + makeindex_fun,_=Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}',shell=False) + makeindex_fun.__doc__=""" + Execute the program **makeindex** + """ + def exec_command(self,cmd,**kw): + bld=self.generator.bld + try: + if not kw.get('cwd',None): + kw['cwd']=bld.cwd + except AttributeError: + bld.cwd=kw['cwd']=bld.variant_dir + return Utils.subprocess.Popen(cmd,**kw).wait() + def scan_aux(self,node): + nodes=[node] + re_aux=re.compile(r'\\@input{(?P[^{}]*)}',re.M) + def parse_node(node): + code=node.read() + for match in re_aux.finditer(code): + path=match.group('file') + found=node.parent.find_or_declare(path) + if found and found not in nodes: + Logs.debug('tex: found aux node '+found.abspath()) + nodes.append(found) + parse_node(found) + parse_node(node) + return nodes + def scan(self): + node=self.inputs[0] + nodes=[] + names=[] + seen=[] + if not node:return(nodes,names) + def parse_node(node): + if node in seen: + return + seen.append(node) + code=node.read() + global re_tex + for match in re_tex.finditer(code): + for path in match.group('file').split(','): + if path: + add_name=True + found=None + for k in exts_deps_tex: + Logs.debug('tex: trying %s%s'%(path,k)) + found=node.parent.find_resource(path+k) + if found and not found in self.outputs: + nodes.append(found) + add_name=False + for ext in exts_tex: + if found.name.endswith(ext): + parse_node(found) + break + if add_name: + names.append(path) + parse_node(node) + for x in nodes: + x.parent.get_bld().mkdir() + Logs.debug("tex: found the following : %s and names %s"%(nodes,names)) + return(nodes,names) + def check_status(self,msg,retcode): + if retcode!=0: + raise Errors.WafError("%r command exit status %r"%(msg,retcode)) + def bibfile(self): + need_bibtex=False + try: + for aux_node in self.aux_nodes: + ct=aux_node.read() + if g_bibtex_re.findall(ct): + need_bibtex=True + break + except(OSError,IOError): + Logs.error('error bibtex scan') + else: + if need_bibtex: + Logs.warn('calling bibtex') + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=self.aux_nodes[0].name[:-4] + self.check_status('error when calling bibtex',self.bibtex_fun()) + def bibunits(self): + try: + bibunits=bibunitscan(self) + except OSError: + Logs.error('error bibunitscan') + else: + if bibunits: + fn=['bu'+str(i)for i in xrange(1,len(bibunits)+1)] + if fn: + Logs.warn('calling bibtex on bibunits') + for f in fn: + self.env.env={'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS} + self.env.SRCFILE=f + self.check_status('error when calling bibtex',self.bibtex_fun()) + def makeindex(self): + try: + idx_path=self.idx_node.abspath() + os.stat(idx_path) + except OSError: + Logs.warn('index file %s absent, not calling makeindex'%idx_path) + else: + Logs.warn('calling makeindex') + self.env.SRCFILE=self.idx_node.name + self.env.env={} + self.check_status('error when calling makeindex %s'%idx_path,self.makeindex_fun()) + def run(self): + env=self.env + if not env['PROMPT_LATEX']: + env.append_value('LATEXFLAGS','-interaction=batchmode') + env.append_value('PDFLATEXFLAGS','-interaction=batchmode') + env.append_value('XELATEXFLAGS','-interaction=batchmode') + fun=self.texfun + node=self.inputs[0] + srcfile=node.abspath() + texinputs=self.env.TEXINPUTS or'' + self.TEXINPUTS=node.parent.get_bld().abspath()+os.pathsep+node.parent.get_src().abspath()+os.pathsep+texinputs+os.pathsep + self.cwd=self.inputs[0].parent.get_bld().abspath() + Logs.warn('first pass on %s'%self.__class__.__name__) + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'TEXINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=srcfile + self.check_status('error when calling latex',fun()) + self.aux_nodes=self.scan_aux(node.change_ext('.aux')) + self.idx_node=node.change_ext('.idx') + self.bibfile() + self.bibunits() + self.makeindex() + hash='' + for i in range(10): + prev_hash=hash + try: + hashes=[Utils.h_file(x.abspath())for x in self.aux_nodes] + hash=Utils.h_list(hashes) + except(OSError,IOError): + Logs.error('could not read aux.h') + pass + if hash and hash==prev_hash: + break + Logs.warn('calling %s'%self.__class__.__name__) + self.env.env={} + self.env.env.update(os.environ) + self.env.env.update({'TEXINPUTS':self.TEXINPUTS}) + self.env.SRCFILE=srcfile + self.check_status('error when calling %s'%self.__class__.__name__,fun()) +class latex(tex): + texfun,vars=Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}',shell=False) +class pdflatex(tex): + texfun,vars=Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}',shell=False) +class xelatex(tex): + texfun,vars=Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}',shell=False) +class dvips(Task.Task): + run_str='${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +class dvipdf(Task.Task): + run_str='${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +class pdf2ps(Task.Task): + run_str='${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' + color='BLUE' + after=['latex','pdflatex','xelatex'] +@feature('tex') +@before_method('process_source') +def apply_tex(self): + if not getattr(self,'type',None)in['latex','pdflatex','xelatex']: + self.type='pdflatex' + tree=self.bld + outs=Utils.to_list(getattr(self,'outs',[])) + self.env['PROMPT_LATEX']=getattr(self,'prompt',1) + deps_lst=[] + if getattr(self,'deps',None): + deps=self.to_list(self.deps) + for filename in deps: + n=self.path.find_resource(filename) + if not n: + self.bld.fatal('Could not find %r for %r'%(filename,self)) + if not n in deps_lst: + deps_lst.append(n) + for node in self.to_nodes(self.source): + if self.type=='latex': + task=self.create_task('latex',node,node.change_ext('.dvi')) + elif self.type=='pdflatex': + task=self.create_task('pdflatex',node,node.change_ext('.pdf')) + elif self.type=='xelatex': + task=self.create_task('xelatex',node,node.change_ext('.pdf')) + task.env=self.env + if deps_lst: + try: + lst=tree.node_deps[task.uid()] + for n in deps_lst: + if not n in lst: + lst.append(n) + except KeyError: + tree.node_deps[task.uid()]=deps_lst + if self.type=='latex': + if'ps'in outs: + tsk=self.create_task('dvips',task.outputs,node.change_ext('.ps')) + tsk.env.env={'TEXINPUTS':node.parent.abspath()+os.pathsep+self.path.abspath()+os.pathsep+self.path.get_bld().abspath()} + if'pdf'in outs: + tsk=self.create_task('dvipdf',task.outputs,node.change_ext('.pdf')) + tsk.env.env={'TEXINPUTS':node.parent.abspath()+os.pathsep+self.path.abspath()+os.pathsep+self.path.get_bld().abspath()} + elif self.type=='pdflatex': + if'ps'in outs: + self.create_task('pdf2ps',task.outputs,node.change_ext('.ps')) + self.source=[] +def configure(self): + v=self.env + for p in'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): + try: + self.find_program(p,var=p.upper()) + except self.errors.ConfigurationError: + pass + v['DVIPSFLAGS']='-Ppdf' diff --git a/waflib/Tools/vala.py b/waflib/Tools/vala.py new file mode 100644 index 00000000..96248c1c --- /dev/null +++ b/waflib/Tools/vala.py @@ -0,0 +1,201 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os.path,shutil,re +from waflib import Context,Task,Utils,Logs,Options,Errors +from waflib.TaskGen import extension,taskgen_method +from waflib.Configure import conf +class valac(Task.Task): + vars=["VALAC","VALAC_VERSION","VALAFLAGS"] + ext_out=['.h'] + def run(self): + cmd=[self.env['VALAC']]+self.env['VALAFLAGS'] + cmd.extend([a.abspath()for a in self.inputs]) + ret=self.exec_command(cmd,cwd=self.outputs[0].parent.abspath()) + if ret: + return ret + for x in self.outputs: + if id(x.parent)!=id(self.outputs[0].parent): + shutil.move(self.outputs[0].parent.abspath()+os.sep+x.name,x.abspath()) + if self.generator.dump_deps_node: + self.generator.dump_deps_node.write('\n'.join(self.generator.packages)) + return ret +valac=Task.update_outputs(valac) +@taskgen_method +def init_vala_task(self): + self.profile=getattr(self,'profile','gobject') + if self.profile=='gobject': + self.uselib=Utils.to_list(getattr(self,'uselib',[])) + if not'GOBJECT'in self.uselib: + self.uselib.append('GOBJECT') + def addflags(flags): + self.env.append_value('VALAFLAGS',flags) + if self.profile: + addflags('--profile=%s'%self.profile) + if hasattr(self,'threading'): + if self.profile=='gobject': + if not'GTHREAD'in self.uselib: + self.uselib.append('GTHREAD') + else: + Logs.warn("Profile %s means no threading support"%self.profile) + self.threading=False + if self.threading: + addflags('--threading') + valatask=self.valatask + self.is_lib='cprogram'not in self.features + if self.is_lib: + addflags('--library=%s'%self.target) + h_node=self.path.find_or_declare('%s.h'%self.target) + valatask.outputs.append(h_node) + addflags('--header=%s'%h_node.name) + valatask.outputs.append(self.path.find_or_declare('%s.vapi'%self.target)) + if getattr(self,'gir',None): + gir_node=self.path.find_or_declare('%s.gir'%self.gir) + addflags('--gir=%s'%gir_node.name) + valatask.outputs.append(gir_node) + self.vala_target_glib=getattr(self,'vala_target_glib',getattr(Options.options,'vala_target_glib',None)) + if self.vala_target_glib: + addflags('--target-glib=%s'%self.vala_target_glib) + addflags(['--define=%s'%x for x in getattr(self,'vala_defines',[])]) + packages_private=Utils.to_list(getattr(self,'packages_private',[])) + addflags(['--pkg=%s'%x for x in packages_private]) + def _get_api_version(): + api_version='1.0' + if hasattr(Context.g_module,'API_VERSION'): + version=Context.g_module.API_VERSION.split(".") + if version[0]=="0": + api_version="0."+version[1] + else: + api_version=version[0]+".0" + return api_version + self.includes=Utils.to_list(getattr(self,'includes',[])) + self.uselib=self.to_list(getattr(self,'uselib',[])) + valatask.install_path=getattr(self,'install_path','') + valatask.vapi_path=getattr(self,'vapi_path','${DATAROOTDIR}/vala/vapi') + valatask.pkg_name=getattr(self,'pkg_name',self.env['PACKAGE']) + valatask.header_path=getattr(self,'header_path','${INCLUDEDIR}/%s-%s'%(valatask.pkg_name,_get_api_version())) + valatask.install_binding=getattr(self,'install_binding',True) + self.packages=packages=Utils.to_list(getattr(self,'packages',[])) + self.vapi_dirs=vapi_dirs=Utils.to_list(getattr(self,'vapi_dirs',[])) + includes=[] + if hasattr(self,'use'): + local_packages=Utils.to_list(self.use)[:] + seen=[] + while len(local_packages)>0: + package=local_packages.pop() + if package in seen: + continue + seen.append(package) + try: + package_obj=self.bld.get_tgen_by_name(package) + except Errors.WafError: + continue + package_name=package_obj.target + package_node=package_obj.path + package_dir=package_node.path_from(self.path) + for task in package_obj.tasks: + for output in task.outputs: + if output.name==package_name+".vapi": + valatask.set_run_after(task) + if package_name not in packages: + packages.append(package_name) + if package_dir not in vapi_dirs: + vapi_dirs.append(package_dir) + if package_dir not in includes: + includes.append(package_dir) + if hasattr(package_obj,'use'): + lst=self.to_list(package_obj.use) + lst.reverse() + local_packages=[pkg for pkg in lst if pkg not in seen]+local_packages + addflags(['--pkg=%s'%p for p in packages]) + for vapi_dir in vapi_dirs: + v_node=self.path.find_dir(vapi_dir) + if not v_node: + Logs.warn('Unable to locate Vala API directory: %r'%vapi_dir) + else: + addflags('--vapidir=%s'%v_node.abspath()) + addflags('--vapidir=%s'%v_node.get_bld().abspath()) + self.dump_deps_node=None + if self.is_lib and self.packages: + self.dump_deps_node=self.path.find_or_declare('%s.deps'%self.target) + valatask.outputs.append(self.dump_deps_node) + self.includes.append(self.bld.srcnode.abspath()) + self.includes.append(self.bld.bldnode.abspath()) + for include in includes: + try: + self.includes.append(self.path.find_dir(include).abspath()) + self.includes.append(self.path.find_dir(include).get_bld().abspath()) + except AttributeError: + Logs.warn("Unable to locate include directory: '%s'"%include) + if self.is_lib and valatask.install_binding: + headers_list=[o for o in valatask.outputs if o.suffix()==".h"] + try: + self.install_vheader.source=headers_list + except AttributeError: + self.install_vheader=self.bld.install_files(valatask.header_path,headers_list,self.env) + vapi_list=[o for o in valatask.outputs if(o.suffix()in(".vapi",".deps"))] + try: + self.install_vapi.source=vapi_list + except AttributeError: + self.install_vapi=self.bld.install_files(valatask.vapi_path,vapi_list,self.env) + gir_list=[o for o in valatask.outputs if o.suffix()=='.gir'] + try: + self.install_gir.source=gir_list + except AttributeError: + self.install_gir=self.bld.install_files(getattr(self,'gir_path','${DATAROOTDIR}/gir-1.0'),gir_list,self.env) +@extension('.vala','.gs') +def vala_file(self,node): + try: + valatask=self.valatask + except AttributeError: + valatask=self.valatask=self.create_task('valac') + self.init_vala_task() + valatask.inputs.append(node) + c_node=node.change_ext('.c') + valatask.outputs.append(c_node) + self.source.append(c_node) +@conf +def find_valac(self,valac_name,min_version): + valac=self.find_program(valac_name,var='VALAC') + try: + output=self.cmd_and_log(valac+' --version') + except Exception: + valac_version=None + else: + ver=re.search(r'\d+.\d+.\d+',output).group(0).split('.') + valac_version=tuple([int(x)for x in ver]) + self.msg('Checking for %s version >= %r'%(valac_name,min_version),valac_version,valac_version and valac_version>=min_version) + if valac and valac_version= %r"%(valac_name,valac_version,min_version)) + self.env['VALAC_VERSION']=valac_version + return valac +@conf +def check_vala(self,min_version=(0,8,0),branch=None): + if not branch: + branch=min_version[:2] + try: + find_valac(self,'valac-%d.%d'%(branch[0],branch[1]),min_version) + except self.errors.ConfigurationError: + find_valac(self,'valac',min_version) +@conf +def check_vala_deps(self): + if not self.env['HAVE_GOBJECT']: + pkg_args={'package':'gobject-2.0','uselib_store':'GOBJECT','args':'--cflags --libs'} + if getattr(Options.options,'vala_target_glib',None): + pkg_args['atleast_version']=Options.options.vala_target_glib + self.check_cfg(**pkg_args) + if not self.env['HAVE_GTHREAD']: + pkg_args={'package':'gthread-2.0','uselib_store':'GTHREAD','args':'--cflags --libs'} + if getattr(Options.options,'vala_target_glib',None): + pkg_args['atleast_version']=Options.options.vala_target_glib + self.check_cfg(**pkg_args) +def configure(self): + self.load('gnu_dirs') + self.check_vala_deps() + self.check_vala() + self.env.VALAFLAGS=['-C','--quiet'] +def options(opt): + opt.load('gnu_dirs') + valaopts=opt.add_option_group('Vala Compiler Options') + valaopts.add_option('--vala-target-glib',default=None,dest='vala_target_glib',metavar='MAJOR.MINOR',help='Target version of glib for Vala GObject code generation') diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py new file mode 100644 index 00000000..f461be10 --- /dev/null +++ b/waflib/Tools/waf_unit_test.py @@ -0,0 +1,95 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys +from waflib.TaskGen import feature,after_method +from waflib import Utils,Task,Logs,Options +testlock=Utils.threading.Lock() +@feature('test') +@after_method('apply_link') +def make_test(self): + if getattr(self,'link_task',None): + self.create_task('utest',self.link_task.outputs) +class utest(Task.Task): + color='PINK' + after=['vnum','inst'] + vars=[] + def runnable_status(self): + if getattr(Options.options,'no_tests',False): + return Task.SKIP_ME + ret=super(utest,self).runnable_status() + if ret==Task.SKIP_ME: + if getattr(Options.options,'all_tests',False): + return Task.RUN_ME + return ret + def run(self): + filename=self.inputs[0].abspath() + self.ut_exec=getattr(self.generator,'ut_exec',[filename]) + if getattr(self.generator,'ut_fun',None): + self.generator.ut_fun(self) + try: + fu=getattr(self.generator.bld,'all_test_paths') + except AttributeError: + fu=os.environ.copy() + lst=[] + for g in self.generator.bld.groups: + for tg in g: + if getattr(tg,'link_task',None): + lst.append(tg.link_task.outputs[0].parent.abspath()) + def add_path(dct,path,var): + dct[var]=os.pathsep.join(Utils.to_list(path)+[os.environ.get(var,'')]) + if Utils.is_win32: + add_path(fu,lst,'PATH') + elif Utils.unversioned_sys_platform()=='darwin': + add_path(fu,lst,'DYLD_LIBRARY_PATH') + add_path(fu,lst,'LD_LIBRARY_PATH') + else: + add_path(fu,lst,'LD_LIBRARY_PATH') + self.generator.bld.all_test_paths=fu + cwd=getattr(self.generator,'ut_cwd','')or self.inputs[0].parent.abspath() + testcmd=getattr(Options.options,'testcmd',False) + if testcmd: + self.ut_exec=(testcmd%self.ut_exec[0]).split(' ') + proc=Utils.subprocess.Popen(self.ut_exec,cwd=cwd,env=fu,stderr=Utils.subprocess.PIPE,stdout=Utils.subprocess.PIPE) + (stdout,stderr)=proc.communicate() + tup=(filename,proc.returncode,stdout,stderr) + self.generator.utest_result=tup + testlock.acquire() + try: + bld=self.generator.bld + Logs.debug("ut: %r",tup) + try: + bld.utest_results.append(tup) + except AttributeError: + bld.utest_results=[tup] + finally: + testlock.release() +def summary(bld): + lst=getattr(bld,'utest_results',[]) + if lst: + Logs.pprint('CYAN','execution summary') + total=len(lst) + tfail=len([x for x in lst if x[1]]) + Logs.pprint('CYAN',' tests that pass %d/%d'%(total-tfail,total)) + for(f,code,out,err)in lst: + if not code: + Logs.pprint('CYAN',' %s'%f) + Logs.pprint('CYAN',' tests that fail %d/%d'%(tfail,total)) + for(f,code,out,err)in lst: + if code: + Logs.pprint('CYAN',' %s'%f) +def set_exit_code(bld): + lst=getattr(bld,'utest_results',[]) + for(f,code,out,err)in lst: + if code: + msg=[] + if out: + msg.append('stdout:%s%s'%(os.linesep,out.decode('utf-8'))) + if err: + msg.append('stderr:%s%s'%(os.linesep,err.decode('utf-8'))) + bld.fatal(os.linesep.join(msg)) +def options(opt): + opt.add_option('--notests',action='store_true',default=False,help='Exec no unit tests',dest='no_tests') + opt.add_option('--alltests',action='store_true',default=False,help='Exec all unit tests',dest='all_tests') + opt.add_option('--testcmd',action='store',default=False,help='Run the unit tests using the test-cmd string'' example "--test-cmd="valgrind --error-exitcode=1'' %s" to run under valgrind',dest='testcmd') diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py new file mode 100644 index 00000000..88904af4 --- /dev/null +++ b/waflib/Tools/winres.py @@ -0,0 +1,85 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re,traceback +from waflib import Task,Logs,Utils +from waflib.TaskGen import extension +from waflib.Tools import c_preproc +@extension('.rc') +def rc_file(self,node): + obj_ext='.rc.o' + if self.env['WINRC_TGT_F']=='/fo': + obj_ext='.res' + rctask=self.create_task('winrc',node,node.change_ext(obj_ext)) + try: + self.compiled_tasks.append(rctask) + except AttributeError: + self.compiled_tasks=[rctask] +re_lines=re.compile('(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|''(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)',re.IGNORECASE|re.MULTILINE) +class rc_parser(c_preproc.c_parser): + def filter_comments(self,filepath): + code=Utils.readf(filepath) + if c_preproc.use_trigraphs: + for(a,b)in c_preproc.trig_def:code=code.split(a).join(b) + code=c_preproc.re_nl.sub('',code) + code=c_preproc.re_cpp.sub(c_preproc.repl,code) + ret=[] + for m in re.finditer(re_lines,code): + if m.group(2): + ret.append((m.group(2),m.group(3))) + else: + ret.append(('include',m.group(5))) + return ret + def addlines(self,node): + self.currentnode_stack.append(node.parent) + filepath=node.abspath() + self.count_files+=1 + if self.count_files>c_preproc.recursion_limit: + raise c_preproc.PreprocError("recursion limit exceeded") + pc=self.parse_cache + Logs.debug('preproc: reading file %r',filepath) + try: + lns=pc[filepath] + except KeyError: + pass + else: + self.lines.extend(lns) + return + try: + lines=self.filter_comments(filepath) + lines.append((c_preproc.POPFILE,'')) + lines.reverse() + pc[filepath]=lines + self.lines.extend(lines) + except IOError: + raise c_preproc.PreprocError("could not read the file %s"%filepath) + except Exception: + if Logs.verbose>0: + Logs.error("parsing %s failed"%filepath) + traceback.print_exc() +class winrc(Task.Task): + run_str='${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' + color='BLUE' + def scan(self): + tmp=rc_parser(self.generator.includes_nodes) + tmp.start(self.inputs[0],self.env) + nodes=tmp.nodes + names=tmp.names + if Logs.verbose: + Logs.debug('deps: deps for %s: %r; unresolved %r'%(str(self),nodes,names)) + return(nodes,names) +def configure(conf): + v=conf.env + v['WINRC_TGT_F']='-o' + v['WINRC_SRC_F']='-i' + if not conf.env.WINRC: + if v.CC_NAME=='msvc': + conf.find_program('RC',var='WINRC',path_list=v['PATH']) + v['WINRC_TGT_F']='/fo' + v['WINRC_SRC_F']='' + else: + conf.find_program('windres',var='WINRC',path_list=v['PATH']) + if not conf.env.WINRC: + conf.fatal('winrc was not found!') + v['WINRCFLAGS']=[] diff --git a/waflib/Tools/xlc.py b/waflib/Tools/xlc.py new file mode 100644 index 00000000..fbf0fcfd --- /dev/null +++ b/waflib/Tools/xlc.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_xlc(conf): + cc=conf.find_program(['xlc_r','xlc'],var='CC') + cc=conf.cmd_to_list(cc) + conf.get_xlc_version(cc) + conf.env.CC_NAME='xlc' + conf.env.CC=cc +@conf +def xlc_common_flags(conf): + v=conf.env + v['CC_SRC_F']=[] + v['CC_TGT_F']=['-c','-o'] + if not v['LINK_CC']:v['LINK_CC']=v['CC'] + v['CCLNK_SRC_F']=[] + v['CCLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['RPATH_ST']='-Wl,-rpath,%s' + v['SONAME_ST']=[] + v['SHLIB_MARKER']=[] + v['STLIB_MARKER']=[] + v['LINKFLAGS_cprogram']=['-Wl,-brtl'] + v['cprogram_PATTERN']='%s' + v['CFLAGS_cshlib']=['-fPIC'] + v['LINKFLAGS_cshlib']=['-G','-Wl,-brtl,-bexpfull'] + v['cshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cstlib']=[] + v['cstlib_PATTERN']='lib%s.a' +def configure(conf): + conf.find_xlc() + conf.find_ar() + conf.xlc_common_flags() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/waflib/Tools/xlcxx.py b/waflib/Tools/xlcxx.py new file mode 100644 index 00000000..b7efb239 --- /dev/null +++ b/waflib/Tools/xlcxx.py @@ -0,0 +1,45 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +from waflib.Tools import ccroot,ar +from waflib.Configure import conf +@conf +def find_xlcxx(conf): + cxx=conf.find_program(['xlc++_r','xlc++'],var='CXX') + cxx=conf.cmd_to_list(cxx) + conf.get_xlc_version(cxx) + conf.env.CXX_NAME='xlc++' + conf.env.CXX=cxx +@conf +def xlcxx_common_flags(conf): + v=conf.env + v['CXX_SRC_F']=[] + v['CXX_TGT_F']=['-c','-o'] + if not v['LINK_CXX']:v['LINK_CXX']=v['CXX'] + v['CXXLNK_SRC_F']=[] + v['CXXLNK_TGT_F']=['-o'] + v['CPPPATH_ST']='-I%s' + v['DEFINES_ST']='-D%s' + v['LIB_ST']='-l%s' + v['LIBPATH_ST']='-L%s' + v['STLIB_ST']='-l%s' + v['STLIBPATH_ST']='-L%s' + v['RPATH_ST']='-Wl,-rpath,%s' + v['SONAME_ST']=[] + v['SHLIB_MARKER']=[] + v['STLIB_MARKER']=[] + v['LINKFLAGS_cxxprogram']=['-Wl,-brtl'] + v['cxxprogram_PATTERN']='%s' + v['CXXFLAGS_cxxshlib']=['-fPIC'] + v['LINKFLAGS_cxxshlib']=['-G','-Wl,-brtl,-bexpfull'] + v['cxxshlib_PATTERN']='lib%s.so' + v['LINKFLAGS_cxxstlib']=[] + v['cxxstlib_PATTERN']='lib%s.a' +def configure(conf): + conf.find_xlcxx() + conf.find_ar() + conf.xlcxx_common_flags() + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() diff --git a/waflib/Utils.py b/waflib/Utils.py new file mode 100644 index 00000000..9532a3b8 --- /dev/null +++ b/waflib/Utils.py @@ -0,0 +1,412 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os,sys,errno,traceback,inspect,re,shutil,datetime,gc +import subprocess +try: + from collections import deque +except ImportError: + class deque(list): + def popleft(self): + return self.pop(0) +try: + import _winreg as winreg +except ImportError: + try: + import winreg + except ImportError: + winreg=None +from waflib import Errors +try: + from collections import UserDict +except ImportError: + from UserDict import UserDict +try: + from hashlib import md5 +except ImportError: + try: + from md5 import md5 + except ImportError: + pass +try: + import threading +except ImportError: + class threading(object): + pass + class Lock(object): + def acquire(self): + pass + def release(self): + pass + threading.Lock=threading.Thread=Lock +else: + run_old=threading.Thread.run + def run(*args,**kwargs): + try: + run_old(*args,**kwargs) + except(KeyboardInterrupt,SystemExit): + raise + except Exception: + sys.excepthook(*sys.exc_info()) + threading.Thread.run=run +SIG_NIL='iluvcuteoverload' +O644=420 +O755=493 +rot_chr=['\\','|','/','-'] +rot_idx=0 +try: + from collections import defaultdict +except ImportError: + class defaultdict(dict): + def __init__(self,default_factory): + super(defaultdict,self).__init__() + self.default_factory=default_factory + def __getitem__(self,key): + try: + return super(defaultdict,self).__getitem__(key) + except KeyError: + value=self.default_factory() + self[key]=value + return value +is_win32=sys.platform in('win32','cli') +indicator='\x1b[K%s%s%s\r' +if is_win32 and'NOCOLOR'in os.environ: + indicator='%s%s%s\r' +def readf(fname,m='r',encoding='ISO8859-1'): + if sys.hexversion>0x3000000 and not'b'in m: + m+='b' + f=open(fname,m) + try: + txt=f.read() + finally: + f.close() + txt=txt.decode(encoding) + else: + f=open(fname,m) + try: + txt=f.read() + finally: + f.close() + return txt +def writef(fname,data,m='w',encoding='ISO8859-1'): + if sys.hexversion>0x3000000 and not'b'in m: + data=data.encode(encoding) + m+='b' + f=open(fname,m) + try: + f.write(data) + finally: + f.close() +def h_file(fname): + f=open(fname,'rb') + m=md5() + try: + while fname: + fname=f.read(200000) + m.update(fname) + finally: + f.close() + return m.digest() +if hasattr(os,'O_NOINHERIT'): + def readf_win32(f,m='r',encoding='ISO8859-1'): + flags=os.O_NOINHERIT|os.O_RDONLY + if'b'in m: + flags|=os.O_BINARY + if'+'in m: + flags|=os.O_RDWR + try: + fd=os.open(f,flags) + except OSError: + raise IOError('Cannot read from %r'%f) + if sys.hexversion>0x3000000 and not'b'in m: + m+='b' + f=os.fdopen(fd,m) + try: + txt=f.read() + finally: + f.close() + txt=txt.decode(encoding) + else: + f=os.fdopen(fd,m) + try: + txt=f.read() + finally: + f.close() + return txt + def writef_win32(f,data,m='w',encoding='ISO8859-1'): + if sys.hexversion>0x3000000 and not'b'in m: + data=data.encode(encoding) + m+='b' + flags=os.O_CREAT|os.O_TRUNC|os.O_WRONLY|os.O_NOINHERIT + if'b'in m: + flags|=os.O_BINARY + if'+'in m: + flags|=os.O_RDWR + try: + fd=os.open(f,flags) + except OSError: + raise IOError('Cannot write to %r'%f) + f=os.fdopen(fd,m) + try: + f.write(data) + finally: + f.close() + def h_file_win32(fname): + try: + fd=os.open(fname,os.O_BINARY|os.O_RDONLY|os.O_NOINHERIT) + except OSError: + raise IOError('Cannot read from %r'%fname) + f=os.fdopen(fd,'rb') + m=md5() + try: + while fname: + fname=f.read(200000) + m.update(fname) + finally: + f.close() + return m.digest() + readf_old=readf + writef_old=writef + h_file_old=h_file + readf=readf_win32 + writef=writef_win32 + h_file=h_file_win32 +try: + x=''.encode('hex') +except LookupError: + import binascii + def to_hex(s): + ret=binascii.hexlify(s) + if not isinstance(ret,str): + ret=ret.decode('utf-8') + return ret +else: + def to_hex(s): + return s.encode('hex') +to_hex.__doc__=""" +Return the hexadecimal representation of a string + +:param s: string to convert +:type s: string +""" +listdir=os.listdir +if is_win32: + def listdir_win32(s): + if not s: + try: + import ctypes + except ImportError: + return[x+':\\'for x in list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')] + else: + dlen=4 + maxdrives=26 + buf=ctypes.create_string_buffer(maxdrives*dlen) + ndrives=ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen,ctypes.byref(buf)) + return[str(buf.raw[4*i:4*i+2].decode('ascii'))for i in range(int(ndrives/dlen))] + if len(s)==2 and s[1]==":": + s+=os.sep + if not os.path.isdir(s): + e=OSError('%s is not a directory'%s) + e.errno=errno.ENOENT + raise e + return os.listdir(s) + listdir=listdir_win32 +def num2ver(ver): + if isinstance(ver,str): + ver=tuple(ver.split('.')) + if isinstance(ver,tuple): + ret=0 + for i in range(4): + if i=6 + try: + _type=unicode + except NameError: + _type=str + to_int=lambda number,default:number and int(number)or default + wlock=threading.Lock() + STD_OUTPUT_HANDLE=-11 + STD_ERROR_HANDLE=-12 + class AnsiTerm(object): + def __init__(self): + self.encoding=sys.stdout.encoding + self.hconsole=windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) + self.cursor_history=[] + self.orig_sbinfo=CONSOLE_SCREEN_BUFFER_INFO() + self.orig_csinfo=CONSOLE_CURSOR_INFO() + windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(self.orig_sbinfo)) + windll.kernel32.GetConsoleCursorInfo(hconsole,byref(self.orig_csinfo)) + def screen_buffer_info(self): + sbinfo=CONSOLE_SCREEN_BUFFER_INFO() + windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(sbinfo)) + return sbinfo + def clear_line(self,param): + mode=param and int(param)or 0 + sbinfo=self.screen_buffer_info() + if mode==1: + line_start=COORD(0,sbinfo.CursorPosition.Y) + line_length=sbinfo.Size.X + elif mode==2: + line_start=COORD(sbinfo.CursorPosition.X,sbinfo.CursorPosition.Y) + line_length=sbinfo.Size.X-sbinfo.CursorPosition.X + else: + line_start=sbinfo.CursorPosition + line_length=sbinfo.Size.X-sbinfo.CursorPosition.X + chars_written=c_int() + windll.kernel32.FillConsoleOutputCharacterA(self.hconsole,c_wchar(' '),line_length,line_start,byref(chars_written)) + windll.kernel32.FillConsoleOutputAttribute(self.hconsole,sbinfo.Attributes,line_length,line_start,byref(chars_written)) + def clear_screen(self,param): + mode=to_int(param,0) + sbinfo=self.screen_buffer_info() + if mode==1: + clear_start=COORD(0,0) + clear_length=sbinfo.CursorPosition.X*sbinfo.CursorPosition.Y + elif mode==2: + clear_start=COORD(0,0) + clear_length=sbinfo.Size.X*sbinfo.Size.Y + windll.kernel32.SetConsoleCursorPosition(self.hconsole,clear_start) + else: + clear_start=sbinfo.CursorPosition + clear_length=((sbinfo.Size.X-sbinfo.CursorPosition.X)+sbinfo.Size.X*(sbinfo.Size.Y-sbinfo.CursorPosition.Y)) + chars_written=c_int() + windll.kernel32.FillConsoleOutputCharacterA(self.hconsole,c_wchar(' '),clear_length,clear_start,byref(chars_written)) + windll.kernel32.FillConsoleOutputAttribute(self.hconsole,sbinfo.Attributes,clear_length,clear_start,byref(chars_written)) + def push_cursor(self,param): + sbinfo=self.screen_buffer_info() + self.cursor_history.append(sbinfo.CursorPosition) + def pop_cursor(self,param): + if self.cursor_history: + old_pos=self.cursor_history.pop() + windll.kernel32.SetConsoleCursorPosition(self.hconsole,old_pos) + def set_cursor(self,param): + y,sep,x=param.partition(';') + x=to_int(x,1)-1 + y=to_int(y,1)-1 + sbinfo=self.screen_buffer_info() + new_pos=COORD(min(max(0,x),sbinfo.Size.X),min(max(0,y),sbinfo.Size.Y)) + windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) + def set_column(self,param): + x=to_int(param,1)-1 + sbinfo=self.screen_buffer_info() + new_pos=COORD(min(max(0,x),sbinfo.Size.X),sbinfo.CursorPosition.Y) + windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) + def move_cursor(self,x_offset=0,y_offset=0): + sbinfo=self.screen_buffer_info() + new_pos=COORD(min(max(0,sbinfo.CursorPosition.X+x_offset),sbinfo.Size.X),min(max(0,sbinfo.CursorPosition.Y+y_offset),sbinfo.Size.Y)) + windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) + def move_up(self,param): + self.move_cursor(y_offset=-to_int(param,1)) + def move_down(self,param): + self.move_cursor(y_offset=to_int(param,1)) + def move_left(self,param): + self.move_cursor(x_offset=-to_int(param,1)) + def move_right(self,param): + self.move_cursor(x_offset=to_int(param,1)) + def next_line(self,param): + sbinfo=self.screen_buffer_info() + self.move_cursor(x_offset=-sbinfo.CursorPosition.X,y_offset=to_int(param,1)) + def prev_line(self,param): + sbinfo=self.screen_buffer_info() + self.move_cursor(x_offset=-sbinfo.CursorPosition.X,y_offset=-to_int(param,1)) + def rgb2bgr(self,c): + return((c&1)<<2)|(c&2)|((c&4)>>2) + def set_color(self,param): + cols=param.split(';') + sbinfo=CONSOLE_SCREEN_BUFFER_INFO() + windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(sbinfo)) + attr=sbinfo.Attributes + for c in cols: + if is_vista: + c=int(c) + else: + c=to_int(c,0) + if c in range(30,38): + attr=(attr&0xfff0)|self.rgb2bgr(c-30) + elif c in range(40,48): + attr=(attr&0xff0f)|(self.rgb2bgr(c-40)<<4) + elif c==0: + attr=self.orig_sbinfo.Attributes + elif c==1: + attr|=0x08 + elif c==4: + attr|=0x80 + elif c==7: + attr=(attr&0xff88)|((attr&0x70)>>4)|((attr&0x07)<<4) + windll.kernel32.SetConsoleTextAttribute(self.hconsole,attr) + def show_cursor(self,param): + csinfo.bVisible=1 + windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(csinfo)) + def hide_cursor(self,param): + csinfo.bVisible=0 + windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(csinfo)) + ansi_command_table={'A':move_up,'B':move_down,'C':move_right,'D':move_left,'E':next_line,'F':prev_line,'G':set_column,'H':set_cursor,'f':set_cursor,'J':clear_screen,'K':clear_line,'h':show_cursor,'l':hide_cursor,'m':set_color,'s':push_cursor,'u':pop_cursor,} + ansi_tokens=re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') + def write(self,text): + try: + wlock.acquire() + for param,cmd,txt in self.ansi_tokens.findall(text): + if cmd: + cmd_func=self.ansi_command_table.get(cmd) + if cmd_func: + cmd_func(self,param) + else: + self.writeconsole(txt) + finally: + wlock.release() + def writeconsole(self,txt): + chars_written=c_int() + writeconsole=windll.kernel32.WriteConsoleA + if isinstance(txt,_type): + writeconsole=windll.kernel32.WriteConsoleW + TINY_STEP=3000 + for x in range(0,len(txt),TINY_STEP): + tiny=txt[x:x+TINY_STEP] + writeconsole(self.hconsole,tiny,len(tiny),byref(chars_written),None) + def flush(self): + pass + def isatty(self): + return True + sys.stderr=sys.stdout=AnsiTerm() + os.environ['TERM']='vt100' diff --git a/waflib/extras/__init__.py b/waflib/extras/__init__.py new file mode 100644 index 00000000..efeed79d --- /dev/null +++ b/waflib/extras/__init__.py @@ -0,0 +1,4 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + diff --git a/waflib/extras/compat15.py b/waflib/extras/compat15.py new file mode 100644 index 00000000..3343afc6 --- /dev/null +++ b/waflib/extras/compat15.py @@ -0,0 +1,220 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import sys +from waflib import ConfigSet,Logs,Options,Scripting,Task,Build,Configure,Node,Runner,TaskGen,Utils,Errors,Context +sys.modules['Environment']=ConfigSet +ConfigSet.Environment=ConfigSet.ConfigSet +sys.modules['Logs']=Logs +sys.modules['Options']=Options +sys.modules['Scripting']=Scripting +sys.modules['Task']=Task +sys.modules['Build']=Build +sys.modules['Configure']=Configure +sys.modules['Node']=Node +sys.modules['Runner']=Runner +sys.modules['TaskGen']=TaskGen +sys.modules['Utils']=Utils +from waflib.Tools import c_preproc +sys.modules['preproc']=c_preproc +from waflib.Tools import c_config +sys.modules['config_c']=c_config +ConfigSet.ConfigSet.copy=ConfigSet.ConfigSet.derive +ConfigSet.ConfigSet.set_variant=Utils.nada +Build.BuildContext.add_subdirs=Build.BuildContext.recurse +Build.BuildContext.new_task_gen=Build.BuildContext.__call__ +Build.BuildContext.is_install=0 +Node.Node.relpath_gen=Node.Node.path_from +def name_to_obj(self,s,env=None): + Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') + return self.get_tgen_by_name(s) +Build.BuildContext.name_to_obj=name_to_obj +def env_of_name(self,name): + try: + return self.all_envs[name] + except KeyError: + Logs.error('no such environment: '+name) + return None +Build.BuildContext.env_of_name=env_of_name +def set_env_name(self,name,env): + self.all_envs[name]=env + return env +Configure.ConfigurationContext.set_env_name=set_env_name +def retrieve(self,name,fromenv=None): + try: + env=self.all_envs[name] + except KeyError: + env=ConfigSet.ConfigSet() + self.prepare_env(env) + self.all_envs[name]=env + else: + if fromenv:Logs.warn("The environment %s may have been configured already"%name) + return env +Configure.ConfigurationContext.retrieve=retrieve +Configure.ConfigurationContext.sub_config=Configure.ConfigurationContext.recurse +Configure.ConfigurationContext.check_tool=Configure.ConfigurationContext.load +Configure.conftest=Configure.conf +Configure.ConfigurationError=Errors.ConfigurationError +Options.OptionsContext.sub_options=Options.OptionsContext.recurse +Options.OptionsContext.tool_options=Context.Context.load +Options.Handler=Options.OptionsContext +Task.simple_task_type=Task.task_type_from_func=Task.task_factory +Task.TaskBase.classes=Task.classes +def setitem(self,key,value): + if key.startswith('CCFLAGS'): + key=key[1:] + self.table[key]=value +ConfigSet.ConfigSet.__setitem__=setitem +@TaskGen.feature('d') +@TaskGen.before('apply_incpaths') +def old_importpaths(self): + if getattr(self,'importpaths',[]): + self.includes=self.importpaths +from waflib import Context +eld=Context.load_tool +def load_tool(*k,**kw): + ret=eld(*k,**kw) + if'set_options'in ret.__dict__: + Logs.warn('compat: rename "set_options" to options') + ret.options=ret.set_options + if'detect'in ret.__dict__: + Logs.warn('compat: rename "detect" to "configure"') + ret.configure=ret.detect + return ret +Context.load_tool=load_tool +rev=Context.load_module +def load_module(path): + ret=rev(path) + if'set_options'in ret.__dict__: + Logs.warn('compat: rename "set_options" to "options" (%r)'%path) + ret.options=ret.set_options + if'srcdir'in ret.__dict__: + Logs.warn('compat: rename "srcdir" to "top" (%r)'%path) + ret.top=ret.srcdir + if'blddir'in ret.__dict__: + Logs.warn('compat: rename "blddir" to "out" (%r)'%path) + ret.out=ret.blddir + return ret +Context.load_module=load_module +old_post=TaskGen.task_gen.post +def post(self): + self.features=self.to_list(self.features) + if'cc'in self.features: + Logs.warn('compat: the feature cc does not exist anymore (use "c")') + self.features.remove('cc') + self.features.append('c') + if'cstaticlib'in self.features: + Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') + self.features.remove('cstaticlib') + self.features.append(('cxx'in self.features)and'cxxstlib'or'cstlib') + if getattr(self,'ccflags',None): + Logs.warn('compat: "ccflags" was renamed to "cflags"') + self.cflags=self.ccflags + return old_post(self) +TaskGen.task_gen.post=post +def waf_version(*k,**kw): + Logs.warn('wrong version (waf_version was removed in waf 1.6)') +Utils.waf_version=waf_version +import os +@TaskGen.feature('c','cxx','d') +@TaskGen.before('apply_incpaths','propagate_uselib_vars') +@TaskGen.after('apply_link','process_source') +def apply_uselib_local(self): + env=self.env + from waflib.Tools.ccroot import stlink_task + self.uselib=self.to_list(getattr(self,'uselib',[])) + self.includes=self.to_list(getattr(self,'includes',[])) + names=self.to_list(getattr(self,'uselib_local',[])) + get=self.bld.get_tgen_by_name + seen=set([]) + tmp=Utils.deque(names) + if tmp: + Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') + while tmp: + lib_name=tmp.popleft() + if lib_name in seen: + continue + y=get(lib_name) + y.post() + seen.add(lib_name) + if getattr(y,'uselib_local',None): + for x in self.to_list(getattr(y,'uselib_local',[])): + obj=get(x) + obj.post() + if getattr(obj,'link_task',None): + if not isinstance(obj.link_task,stlink_task): + tmp.append(x) + if getattr(y,'link_task',None): + link_name=y.target[y.target.rfind(os.sep)+1:] + if isinstance(y.link_task,stlink_task): + env.append_value('STLIB',[link_name]) + else: + env.append_value('LIB',[link_name]) + self.link_task.set_run_after(y.link_task) + self.link_task.dep_nodes+=y.link_task.outputs + tmp_path=y.link_task.outputs[0].parent.bldpath() + if not tmp_path in env['LIBPATH']: + env.prepend_value('LIBPATH',[tmp_path]) + for v in self.to_list(getattr(y,'uselib',[])): + if not env['STLIB_'+v]: + if not v in self.uselib: + self.uselib.insert(0,v) + if getattr(y,'export_includes',None): + self.includes.extend(y.to_incnodes(y.export_includes)) +@TaskGen.feature('cprogram','cxxprogram','cstlib','cxxstlib','cshlib','cxxshlib','dprogram','dstlib','dshlib') +@TaskGen.after('apply_link') +def apply_objdeps(self): + names=getattr(self,'add_objects',[]) + if not names: + return + names=self.to_list(names) + get=self.bld.get_tgen_by_name + seen=[] + while names: + x=names[0] + if x in seen: + names=names[1:] + continue + y=get(x) + if getattr(y,'add_objects',None): + added=0 + lst=y.to_list(y.add_objects) + lst.reverse() + for u in lst: + if u in seen:continue + added=1 + names=[u]+names + if added:continue + y.post() + seen.append(x) + for t in getattr(y,'compiled_tasks',[]): + self.link_task.inputs.extend(t.outputs) +@TaskGen.after('apply_link') +def process_obj_files(self): + if not hasattr(self,'obj_files'): + return + for x in self.obj_files: + node=self.path.find_resource(x) + self.link_task.inputs.append(node) +@TaskGen.taskgen_method +def add_obj_file(self,file): + if not hasattr(self,'obj_files'):self.obj_files=[] + if not'process_obj_files'in self.meths:self.meths.append('process_obj_files') + self.obj_files.append(file) +old_define=Configure.ConfigurationContext.__dict__['define'] +@Configure.conf +def define(self,key,val,quote=True): + old_define(self,key,val,quote) + if key.startswith('HAVE_'): + self.env[key]=1 +old_undefine=Configure.ConfigurationContext.__dict__['undefine'] +@Configure.conf +def undefine(self,key): + old_undefine(self,key) + if key.startswith('HAVE_'): + self.env[key]=0 +def set_incdirs(self,val): + Logs.warn('compat: change "export_incdirs" by "export_includes"') + self.export_includes=val +TaskGen.task_gen.export_incdirs=property(None,set_incdirs) diff --git a/waflib/fixpy2.py b/waflib/fixpy2.py new file mode 100644 index 00000000..98f70361 --- /dev/null +++ b/waflib/fixpy2.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import os +all_modifs={} +def fixdir(dir): + global all_modifs + for k in all_modifs: + for v in all_modifs[k]: + modif(os.path.join(dir,'waflib'),k,v) +def modif(dir,name,fun): + if name=='*': + lst=[] + for y in'. Tools extras'.split(): + for x in os.listdir(os.path.join(dir,y)): + if x.endswith('.py'): + lst.append(y+os.sep+x) + for x in lst: + modif(dir,x,fun) + return + filename=os.path.join(dir,name) + f=open(filename,'r') + try: + txt=f.read() + finally: + f.close() + txt=fun(txt) + f=open(filename,'w') + try: + f.write(txt) + finally: + f.close() +def subst(*k): + def do_subst(fun): + global all_modifs + for x in k: + try: + all_modifs[x].append(fun) + except KeyError: + all_modifs[x]=[fun] + return fun + return do_subst +@subst('*') +def r1(code): + code=code.replace(',e:',',e:') + code=code.replace("",'') + code=code.replace('','') + return code +@subst('Runner.py') +def r4(code): + code=code.replace('next(self.biter)','self.biter.next()') + return code -- 2.11.0