waf, waflib: update to 1.8.7
authorPaul Brossier <piem@piem.org>
Sat, 14 Mar 2015 17:06:10 +0000 (18:06 +0100)
committerPaul Brossier <piem@piem.org>
Sat, 14 Mar 2015 17:06:10 +0000 (18:06 +0100)
61 files changed:
waf
waflib/Build.py
waflib/ConfigSet.py
waflib/Configure.py
waflib/Context.py
waflib/Logs.py
waflib/Node.py
waflib/Options.py
waflib/Runner.py
waflib/Scripting.py
waflib/Task.py
waflib/TaskGen.py
waflib/Tools/ar.py
waflib/Tools/asm.py
waflib/Tools/c.py
waflib/Tools/c_aliases.py
waflib/Tools/c_config.py
waflib/Tools/c_preproc.py
waflib/Tools/ccroot.py
waflib/Tools/clang.py [new file with mode: 0644]
waflib/Tools/clangxx.py [new file with mode: 0644]
waflib/Tools/compiler_c.py
waflib/Tools/compiler_cxx.py
waflib/Tools/compiler_d.py
waflib/Tools/compiler_fc.py
waflib/Tools/cxx.py
waflib/Tools/dmd.py
waflib/Tools/fc.py
waflib/Tools/fc_config.py
waflib/Tools/flex.py
waflib/Tools/g95.py
waflib/Tools/gcc.py
waflib/Tools/gdc.py
waflib/Tools/gfortran.py
waflib/Tools/glib2.py
waflib/Tools/gnu_dirs.py
waflib/Tools/gxx.py
waflib/Tools/icc.py
waflib/Tools/icpc.py
waflib/Tools/ifort.py
waflib/Tools/intltool.py
waflib/Tools/irixcc.py
waflib/Tools/javaw.py
waflib/Tools/kde4.py
waflib/Tools/ldc2.py
waflib/Tools/msvc.py
waflib/Tools/perl.py
waflib/Tools/python.py
waflib/Tools/qt4.py
waflib/Tools/qt5.py [new file with mode: 0644]
waflib/Tools/ruby.py
waflib/Tools/suncc.py
waflib/Tools/suncxx.py
waflib/Tools/tex.py
waflib/Tools/vala.py
waflib/Tools/waf_unit_test.py
waflib/Tools/xlc.py
waflib/Tools/xlcxx.py
waflib/Utils.py
waflib/ansiterm.py
waflib/extras/compat15.py

diff --git a/waf b/waf
index 75496f7..5b7160a 100755 (executable)
--- a/waf
+++ b/waf
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 # encoding: ISO8859-1
-# Thomas Nagy, 2005-2012
+# Thomas Nagy, 2005-2015
 
 """
 Redistribution and use in source and binary forms, with or without
@@ -30,13 +30,15 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 """
 
-import os, sys
+import os, sys, inspect
 
-VERSION="1.7.15"
-REVISION="de1cb53b86321cda764be4b3c38c3d20"
+VERSION="1.8.7"
+REVISION="073060339ba56c09e143ed641610cbec"
+GIT="x"
 INSTALL=''
-C1='#+'
-C2='#&'
+C1='#/'
+C2='#-'
+C3='#+'
 cwd = os.getcwd()
 join = os.path.join
 
@@ -53,8 +55,8 @@ def err(m):
        print(('\033[91mError: %s\033[0m' % m))
        sys.exit(1)
 
-def unpack_wafdir(dir):
-       f = open(sys.argv[0],'rb')
+def unpack_wafdir(dir, src):
+       f = open(src,'rb')
        c = 'corrupt archive (%d)'
        while 1:
                line = f.readline()
@@ -65,13 +67,13 @@ def unpack_wafdir(dir):
                        if f.readline() != b('#<==\n'): err(c % 2)
                        break
        if not txt: err(c % 3)
-       txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r'))
+       txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00'))
 
        import shutil, tarfile
        try: shutil.rmtree(dir)
        except OSError: pass
        try:
-               for x in ['Tools', 'extras']:
+               for x in ('Tools', 'extras'):
                        os.makedirs(join(dir, 'waflib', x))
        except OSError:
                err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir)
@@ -100,7 +102,7 @@ def unpack_wafdir(dir):
        finally:
                t.close()
 
-       for x in ['Tools', 'extras']:
+       for x in ('Tools', 'extras'):
                os.chmod(join('waflib',x), 493)
 
        if sys.hexversion<0x300000f:
@@ -127,8 +129,8 @@ def test(dir):
                pass
 
 def find_lib():
-       name = sys.argv[0]
-       base = os.path.dirname(os.path.abspath(name))
+       src = os.path.abspath(inspect.getfile(inspect.getmodule(err)))
+       base, name = os.path.split(src)
 
        #devs use $WAFDIR
        w=test(os.environ.get('WAFDIR', ''))
@@ -141,7 +143,7 @@ def find_lib():
                err('waf-light requires waflib -> export WAFDIR=/folder')
 
        dirname = '%s-%s-%s' % (WAF, VERSION, REVISION)
-       for i in [INSTALL,'/usr','/usr/local','/opt']:
+       for i in (INSTALL,'/usr','/usr/local','/opt'):
                w = test(i + '/lib/' + dirname)
                if w: return w
 
@@ -151,7 +153,7 @@ def find_lib():
        if w: return w
 
        #unpack
-       unpack_wafdir(dir)
+       unpack_wafdir(dir, src)
        return dir
 
 wafdir = find_lib()
index f76933a..1012da2 100644 (file)
@@ -2,7 +2,7 @@
 # encoding: utf-8
 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
 
-import os,sys,errno,re,shutil
+import os,sys,errno,re,shutil,stat
 try:
        import cPickle
 except ImportError:
@@ -31,7 +31,7 @@ class BuildContext(Context.Context):
                self.out_dir=kw.get('out_dir',Context.out_dir)
                self.cache_dir=kw.get('cache_dir',None)
                if not self.cache_dir:
-                       self.cache_dir=self.out_dir+os.sep+CACHE_DIR
+                       self.cache_dir=os.path.join(self.out_dir,CACHE_DIR)
                self.all_envs={}
                self.task_sigs={}
                self.node_deps={}
@@ -42,8 +42,6 @@ class BuildContext(Context.Context):
                self.jobs=Options.options.jobs
                self.targets=Options.options.targets
                self.keep=Options.options.keep
-               self.cache_global=Options.cache_global
-               self.nocache=Options.options.nocache
                self.progress_bar=Options.options.progress_bar
                self.deps_man=Utils.defaultdict(list)
                self.current_group=0
@@ -109,23 +107,19 @@ class BuildContext(Context.Context):
                self.recurse([self.run_dir])
                self.pre_build()
                self.timer=Utils.Timer()
-               if self.progress_bar:
-                       sys.stderr.write(Logs.colors.cursor_off)
                try:
                        self.compile()
                finally:
-                       if self.progress_bar==1:
+                       if self.progress_bar==1 and sys.stderr.isatty():
                                c=len(self.returned_tasks)or 1
-                               self.to_log(self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL))
-                               print('')
-                               sys.stdout.flush()
-                               sys.stderr.write(Logs.colors.cursor_on)
+                               m=self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL)
+                               Logs.info(m,extra={'stream':sys.stderr,'c1':Logs.colors.cursor_off,'c2':Logs.colors.cursor_on})
                        Logs.info("Waf: Leaving directory `%s'"%self.variant_dir)
                self.post_build()
        def restore(self):
                try:
                        env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,'build.config.py'))
-               except(IOError,OSError):
+               except EnvironmentError:
                        pass
                else:
                        if env['version']<Context.HEXVERSION:
@@ -253,6 +247,8 @@ class BuildContext(Context.Context):
                except KeyError:
                        raise Errors.WafError('Could not find a task generator for the name %r'%name)
        def progress_line(self,state,total,col1,col2):
+               if not sys.stderr.isatty():
+                       return''
                n=len(str(total))
                Utils.rot_idx+=1
                ind=Utils.rot_chr[Utils.rot_idx%4]
@@ -265,7 +261,7 @@ class BuildContext(Context.Context):
                if cols<7:cols=7
                ratio=((cols*state)//total)-1
                bar=('='*ratio+'>').ljust(cols)
-               msg=Utils.indicator%(left,bar,right)
+               msg=Logs.indicator%(left,bar,right)
                return msg
        def declare_chain(self,*k,**kw):
                return TaskGen.declare_chain(*k,**kw)
@@ -325,6 +321,7 @@ class BuildContext(Context.Context):
                        for i in range(len(self.groups)):
                                if id(g)==id(self.groups[i]):
                                        self.current_group=i
+                                       break
                else:
                        self.current_group=idx
        def total(self):
@@ -473,16 +470,16 @@ class inst(Task.Task):
                                destfile=os.path.join(destpath,y.path_from(self.path))
                        else:
                                destfile=os.path.join(destpath,y.name)
-                       self.generator.bld.do_install(y.abspath(),destfile,self.chmod)
+                       self.generator.bld.do_install(y.abspath(),destfile,chmod=self.chmod,tsk=self)
        def exec_install_as(self):
                destfile=self.get_install_path()
-               self.generator.bld.do_install(self.inputs[0].abspath(),destfile,self.chmod)
+               self.generator.bld.do_install(self.inputs[0].abspath(),destfile,chmod=self.chmod,tsk=self)
        def exec_symlink_as(self):
                destfile=self.get_install_path()
                src=self.link
                if self.relative_trick:
                        src=os.path.relpath(src,os.path.dirname(destfile))
-               self.generator.bld.do_link(src,destfile)
+               self.generator.bld.do_link(src,destfile,tsk=self)
 class InstallContext(BuildContext):
        '''installs the targets on the system'''
        cmd='install'
@@ -490,7 +487,12 @@ class InstallContext(BuildContext):
                super(InstallContext,self).__init__(**kw)
                self.uninstall=[]
                self.is_install=INSTALL
-       def do_install(self,src,tgt,chmod=Utils.O644):
+       def copy_fun(self,src,tgt,**kw):
+               if Utils.is_win32 and len(tgt)>259 and not tgt.startswith('\\\\?\\'):
+                       tgt='\\\\?\\'+tgt
+               shutil.copy2(src,tgt)
+               os.chmod(tgt,kw.get('chmod',Utils.O644))
+       def do_install(self,src,tgt,**kw):
                d,_=os.path.split(tgt)
                if not d:
                        raise Errors.WafError('Invalid installation given %r->%r'%(src,tgt))
@@ -510,19 +512,22 @@ class InstallContext(BuildContext):
                if not self.progress_bar:
                        Logs.info('+ install %s (from %s)'%(tgt,srclbl))
                try:
+                       os.chmod(tgt,Utils.O644|stat.S_IMODE(os.stat(tgt).st_mode))
+               except EnvironmentError:
+                       pass
+               try:
                        os.remove(tgt)
                except OSError:
                        pass
                try:
-                       shutil.copy2(src,tgt)
-                       os.chmod(tgt,chmod)
+                       self.copy_fun(src,tgt,**kw)
                except IOError:
                        try:
                                os.stat(src)
-                       except(OSError,IOError):
+                       except EnvironmentError:
                                Logs.error('File %r does not exist'%src)
                        raise Errors.WafError('Could not install the file %r'%tgt)
-       def do_link(self,src,tgt):
+       def do_link(self,src,tgt,**kw):
                d,_=os.path.split(tgt)
                Utils.check_dir(d)
                link=False
@@ -545,11 +550,12 @@ class InstallContext(BuildContext):
                        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):
+       def install_files(self,dest,files,env=None,chmod=Utils.O644,relative_trick=False,cwd=None,add=True,postpone=True,task=None):
                tsk=inst(env=env or self.env)
                tsk.bld=self
                tsk.path=cwd or self.path
                tsk.chmod=chmod
+               tsk.task=task
                if isinstance(files,waflib.Node.Node):
                        tsk.source=[files]
                else:
@@ -560,18 +566,19 @@ class InstallContext(BuildContext):
                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):
+       def install_as(self,dest,srcfile,env=None,chmod=Utils.O644,cwd=None,add=True,postpone=True,task=None):
                tsk=inst(env=env or self.env)
                tsk.bld=self
                tsk.path=cwd or self.path
                tsk.chmod=chmod
                tsk.source=[srcfile]
+               tsk.task=task
                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):
+       def symlink_as(self,dest,src,env=None,cwd=None,add=True,postpone=True,relative_trick=False,task=None):
                if Utils.is_win32:
                        return
                tsk=inst(env=env or self.env)
@@ -579,6 +586,7 @@ class InstallContext(BuildContext):
                tsk.dest=dest
                tsk.path=cwd or self.path
                tsk.source=[]
+               tsk.task=task
                tsk.link=src
                tsk.relative_trick=relative_trick
                tsk.exec_task=tsk.exec_symlink_as
@@ -591,7 +599,14 @@ class UninstallContext(InstallContext):
        def __init__(self,**kw):
                super(UninstallContext,self).__init__(**kw)
                self.is_install=UNINSTALL
-       def do_install(self,src,tgt,chmod=Utils.O644):
+       def rm_empty_dirs(self,tgt):
+               while tgt:
+                       tgt=os.path.dirname(tgt)
+                       try:
+                               os.rmdir(tgt)
+                       except OSError:
+                               break
+       def do_install(self,src,tgt,**kw):
                if not self.progress_bar:
                        Logs.info('- remove %s'%tgt)
                self.uninstall.append(tgt)
@@ -604,25 +619,15 @@ class UninstallContext(InstallContext):
                                        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):
+               self.rm_empty_dirs(tgt)
+       def do_link(self,src,tgt,**kw):
                try:
                        if not self.progress_bar:
                                Logs.info('- remove %s'%tgt)
                        os.remove(tgt)
                except OSError:
                        pass
-               while tgt:
-                       tgt=os.path.dirname(tgt)
-                       try:
-                               os.rmdir(tgt)
-                       except OSError:
-                               break
+               self.rm_empty_dirs(tgt)
        def execute(self):
                try:
                        def runnable_status(self):
@@ -754,5 +759,3 @@ class StepContext(BuildContext):
                        else:
                                return pattern.match(node.abspath())
                return match
-BuildContext.store=Utils.nogc(BuildContext.store)
-BuildContext.restore=Utils.nogc(BuildContext.restore)
index f9fdcc7..2b2cfe0 100644 (file)
@@ -89,9 +89,9 @@ class ConfigSet(object):
                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=self._get_list_value_for_modification(var)
                current_value.extend(val)
        def prepend_value(self,var,val):
                if isinstance(val,str):
index 2814e61..7f328f9 100644 (file)
@@ -2,14 +2,8 @@
 # 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
+import os,shlex,sys,time,re,shutil
 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'
@@ -18,37 +12,6 @@ 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'
@@ -96,6 +59,7 @@ class ConfigurationContext(Context.Context):
                        out=getattr(Context.g_module,Context.OUT,None)
                if not out:
                        out=Options.lockfile.replace('.lock-waf_%s_'%sys.platform,'').replace('.lock-waf','')
+               out=os.path.realpath(out)
                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()):
@@ -139,11 +103,11 @@ class ConfigurationContext(Context.Context):
                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)
+                       env.store(os.path.join(Context.run_dir,Options.lockfile))
                if not self.env.NO_LOCK_IN_TOP:
-                       env.store(Context.top_dir+os.sep+Options.lockfile)
+                       env.store(os.path.join(Context.top_dir,Options.lockfile))
                if not self.env.NO_LOCK_IN_OUT:
-                       env.store(Context.out_dir+os.sep+Options.lockfile)
+                       env.store(os.path.join(Context.out_dir,Options.lockfile))
        def prepare_env(self,env):
                if not env.PREFIX:
                        if Options.options.prefix or Utils.is_win32:
@@ -151,9 +115,15 @@ class ConfigurationContext(Context.Context):
                        else:
                                env.PREFIX=''
                if not env.BINDIR:
-                       env.BINDIR=Utils.subst_vars('${PREFIX}/bin',env)
+                       if Options.options.bindir:
+                               env.BINDIR=os.path.abspath(os.path.expanduser(Options.options.bindir))
+                       else:
+                               env.BINDIR=Utils.subst_vars('${PREFIX}/bin',env)
                if not env.LIBDIR:
-                       env.LIBDIR=Utils.subst_vars('${PREFIX}/lib',env)
+                       if Options.options.libdir:
+                               env.LIBDIR=os.path.abspath(os.path.expanduser(Options.options.libdir))
+                       else:
+                               env.LIBDIR=Utils.subst_vars('${PREFIX}/lib%s'%Utils.lib64(),env)
        def store(self):
                n=self.cachedir.make_node('build.config.py')
                n.write('version = 0x%x\ntools = %r\n'%(Context.HEXVERSION,self.tools))
@@ -162,7 +132,7 @@ class ConfigurationContext(Context.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):
+       def load(self,input,tooldir=None,funs=None):
                tools=Utils.to_list(input)
                if tooldir:tooldir=Utils.to_list(tooldir)
                for tool in tools:
@@ -173,14 +143,9 @@ class ConfigurationContext(Context.Context):
                        self.tool_cache.append(mag)
                        module=None
                        try:
-                               module=Context.load_tool(tool,tooldir)
+                               module=Context.load_tool(tool,tooldir,ctx=self)
                        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))
+                               self.fatal('Could not load the Waf tool %r from %r\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())
@@ -243,14 +208,14 @@ def cmd_to_list(self,cmd):
                        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)))
+def check_waf_version(self,mini='1.7.99',maxi='1.9.0',**kw):
+       self.start_msg('Checking for waf version in %s-%s'%(str(mini),str(maxi)),**kw)
        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)<ver:
                self.fatal('waf version should be at most %r (%r found)'%(Utils.num2ver(maxi),ver))
-       self.end_msg('ok')
+       self.end_msg('ok',**kw)
 @conf
 def find_file(self,filename,path_list=[]):
        for n in Utils.to_list(filename):
@@ -262,56 +227,153 @@ def find_file(self,filename,path_list=[]):
 @conf
 def find_program(self,filename,**kw):
        exts=kw.get('exts',Utils.is_win32 and'.exe,.com,.bat,.cmd'or',.sh,.pl,.py')
-       environ=kw.get('environ',os.environ)
+       environ=kw.get('environ',getattr(self,'environ',os.environ))
        ret=''
        filename=Utils.to_list(filename)
+       msg=kw.get('msg',', '.join(filename))
        var=kw.get('var','')
        if not var:
-               var=filename[0].upper()
-       if self.env[var]:
-               ret=self.env[var]
-       elif var in environ:
-               ret=environ[var]
+               var=re.sub(r'[-.]','_',filename[0].upper())
        path_list=kw.get('path_list','')
-       if not ret:
-               if path_list:
-                       path_list=Utils.to_list(path_list)
+       if path_list:
+               path_list=Utils.to_list(path_list)
+       else:
+               path_list=environ.get('PATH','').split(os.pathsep)
+       if var in environ:
+               filename=environ[var]
+               if os.path.isfile(filename):
+                       ret=[filename]
                else:
-                       path_list=environ.get('PATH','').split(os.pathsep)
-               if not isinstance(filename,list):
-                       filename=[filename]
-               for a in exts.split(','):
-                       if ret:
-                               break
-                       for b in filename:
-                               if ret:
-                                       break
-                               for c in path_list:
-                                       if ret:
-                                               break
-                                       x=os.path.expanduser(os.path.join(c,b+a))
-                                       if os.path.isfile(x):
-                                               ret=x
-       if not ret and Utils.winreg:
-               ret=Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER,filename)
-       if not ret and Utils.winreg:
-               ret=Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE,filename)
-       self.msg('Checking for program '+','.join(filename),ret or False)
-       self.to_log('find program=%r paths=%r var=%r -> %r'%(filename,path_list,var,ret))
+                       ret=self.cmd_to_list(filename)
+       elif self.env[var]:
+               ret=self.env[var]
+               ret=self.cmd_to_list(ret)
+       else:
+               if not ret:
+                       ret=self.find_binary(filename,exts.split(','),path_list)
+               if not ret and Utils.winreg:
+                       ret=Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER,filename)
+               if not ret and Utils.winreg:
+                       ret=Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE,filename)
+               ret=self.cmd_to_list(ret)
+       if ret:
+               if len(ret)==1:
+                       retmsg=ret[0]
+               else:
+                       retmsg=ret
+       else:
+               retmsg=False
+       self.msg("Checking for program '%s'"%msg,retmsg,**kw)
+       if not kw.get('quiet',None):
+               self.to_log('find program=%r paths=%r var=%r -> %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.fatal(kw.get('errmsg','')or'Could not find the program %r'%filename)
+       interpreter=kw.get('interpreter',None)
+       if interpreter is None:
+               if not Utils.check_exe(ret[0],env=environ):
+                       self.fatal('Program %r is not executable'%ret)
                self.env[var]=ret
+       else:
+               self.env[var]=self.env[interpreter]+ret
        return ret
 @conf
-def find_perl_program(self,filename,path_list=[],var=None,environ=None,exts=''):
+def find_binary(self,filenames,exts,paths):
+       for f in filenames:
+               for ext in exts:
+                       exe_name=f+ext
+                       if os.path.isabs(exe_name):
+                               if os.path.isfile(exe_name):
+                                       return exe_name
+                       else:
+                               for path in paths:
+                                       x=os.path.expanduser(os.path.join(path,exe_name))
+                                       if os.path.isfile(x):
+                                               return x
+       return None
+@conf
+def run_build(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:
-               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:
+               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==1:
+               try:
+                       proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_build'))
+               except OSError:
+                       pass
+               except IOError:
+                       pass
+               else:
+                       ret=proj['cache_run_build']
+                       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='*'
+       bld.logger=self.logger
+       bld.all_envs.update(self.all_envs)
+       bld.env=kw['env']
+       bld.kw=kw
+       bld.conf=self
+       kw['build_fun'](bld)
+       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:
+               if cachemode==1:
+                       proj=ConfigSet.ConfigSet()
+                       proj['cache_run_build']=ret
+                       proj.store(os.path.join(dir,'cache_run_build'))
+               else:
+                       shutil.rmtree(dir)
+       return ret
+@conf
+def ret_msg(self,msg,args):
+       if isinstance(msg,str):
+               return msg
+       return msg(args)
+@conf
+def test(self,*k,**kw):
+       if not'env'in kw:
+               kw['env']=self.env.derive()
+       if kw.get('validate',None):
+               kw['validate'](kw)
+       self.start_msg(kw['msg'],**kw)
+       ret=None
+       try:
+               ret=self.run_build(*k,**kw)
+       except self.errors.ConfigurationError:
+               self.end_msg(kw['errmsg'],'YELLOW',**kw)
+               if Logs.verbose>1:
                        raise
-               if var:
-                       self.env[var]=Utils.to_list(self.env['PERL'])+[app]
-       self.msg('Checking for %r'%filename,app)
+               else:
+                       self.fatal('The configuration failed')
+       else:
+               kw['success']=ret
+       if kw.get('post_check',None):
+               ret=kw['post_check'](kw)
+       if ret:
+               self.end_msg(kw['errmsg'],'YELLOW',**kw)
+               self.fatal('The configuration failed %r'%ret)
+       else:
+               self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
+       return ret
index ab8d047..dc66e65 100644 (file)
@@ -2,12 +2,12 @@
 # encoding: utf-8
 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
 
-import os,imp,sys
+import os,re,imp,sys
 from waflib import Utils,Errors,Logs
 import waflib.Node
-HEXVERSION=0x1070f00
-WAFVERSION="1.7.15"
-WAFREVISION="f63ac9793de2d4eaae884e55d4ff70a761dcbab2"
+HEXVERSION=0x1080700
+WAFVERSION="1.8.7"
+WAFREVISION="e5056b9ade7bb224f53baab13a0ce136344ab602"
 ABI=98
 DBFILE='.wafpickle-%s-%d-%d'%(sys.platform,sys.hexversion,ABI)
 APPNAME='APPNAME'
@@ -71,6 +71,14 @@ class Context(ctx):
                self.logger=None
        def __hash__(self):
                return id(self)
+       def finalize(self):
+               try:
+                       logger=self.logger
+               except AttributeError:
+                       pass
+               else:
+                       Logs.free_logger(logger)
+                       delattr(self,'logger')
        def load(self,tool_list,*k,**kw):
                tools=Utils.to_list(tool_list)
                path=Utils.to_list(kw.get('tooldir',''))
@@ -90,7 +98,7 @@ class Context(ctx):
                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):
+       def recurse(self,dirs,name=None,mandatory=True,once=True,encoding=None):
                try:
                        cache=self.recurse_cache
                except AttributeError:
@@ -105,7 +113,7 @@ class Context(ctx):
                                cache[node]=True
                                self.pre_recurse(node)
                                try:
-                                       function_code=node.read('rU')
+                                       function_code=node.read('rU',encoding)
                                        exec(compile(function_code,node.abspath(),'exec'),self.exec_dict)
                                finally:
                                        self.post_recurse(node)
@@ -116,7 +124,7 @@ class Context(ctx):
                                        cache[tup]=True
                                        self.pre_recurse(node)
                                        try:
-                                               wscript_module=load_module(node.abspath())
+                                               wscript_module=load_module(node.abspath(),encoding=encoding)
                                                user_function=getattr(wscript_module,(name or self.fun),None)
                                                if not user_function:
                                                        if not mandatory:
@@ -140,6 +148,8 @@ class Context(ctx):
                        kw['stdout']=subprocess.PIPE
                if'stderr'not in kw:
                        kw['stderr']=subprocess.PIPE
+               if Logs.verbose and not kw['shell']and not Utils.check_exe(cmd[0]):
+                       raise Errors.WafError("Program %s not found!"%cmd[0])
                try:
                        if kw['stdout']or kw['stderr']:
                                p=subprocess.Popen(cmd,**kw)
@@ -156,14 +166,14 @@ class Context(ctx):
                        if self.logger:
                                self.logger.debug('out: %s'%out)
                        else:
-                               sys.stdout.write(out)
+                               Logs.info(out,extra={'stream':sys.stdout,'c1':''})
                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)
+                               Logs.info(err,extra={'stream':sys.stderr,'c1':''})
                return ret
        def cmd_and_log(self,cmd,**kw):
                subprocess=Utils.subprocess
@@ -179,6 +189,8 @@ class Context(ctx):
                        del kw['output']
                else:
                        to_ret=STDOUT
+               if Logs.verbose and not kw['shell']and not Utils.check_exe(cmd[0]):
+                       raise Errors.WafError("Program %s not found!"%cmd[0])
                kw['stdout']=kw['stderr']=subprocess.PIPE
                if quiet is None:
                        self.to_log(cmd)
@@ -222,12 +234,24 @@ class Context(ctx):
                else:
                        sys.stderr.write(str(msg))
                        sys.stderr.flush()
-       def msg(self,msg,result,color=None):
-               self.start_msg(msg)
+       def msg(self,*k,**kw):
+               try:
+                       msg=kw['msg']
+               except KeyError:
+                       msg=k[0]
+               self.start_msg(msg,**kw)
+               try:
+                       result=kw['result']
+               except KeyError:
+                       result=k[1]
+               color=kw.get('color',None)
                if not isinstance(color,str):
                        color=result and'GREEN'or'YELLOW'
-               self.end_msg(result,color)
-       def start_msg(self,msg):
+               self.end_msg(result,color,**kw)
+       def start_msg(self,*k,**kw):
+               if kw.get('quiet',None):
+                       return
+               msg=kw.get('msg',None)or k[0]
                try:
                        if self.in_msg:
                                self.in_msg+=1
@@ -242,10 +266,13 @@ class Context(ctx):
                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):
+       def end_msg(self,*k,**kw):
+               if kw.get('quiet',None):
+                       return
                self.in_msg-=1
                if self.in_msg:
                        return
+               result=kw.get('result',None)or k[0]
                defcolor='GREEN'
                if result==True:
                        msg='ok'
@@ -255,23 +282,47 @@ class Context(ctx):
                else:
                        msg=str(result)
                self.to_log(msg)
-               Logs.pprint(color or defcolor,msg)
+               try:
+                       color=kw['color']
+               except KeyError:
+                       if len(k)>1 and k[1]in Logs.colors_lst:
+                               color=k[1]
+                       else:
+                               color=defcolor
+               Logs.pprint(color,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',''))
+               if os.path.isdir(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',''))
+               else:
+                       from zipfile import PyZipFile
+                       waflibs=PyZipFile(waf_dir)
+                       lst=waflibs.namelist()
+                       for x in lst:
+                               if not re.match("waflib/extras/%s"%var.replace("*",".*"),var):
+                                       continue
+                               f=os.path.basename(x)
+                               doban=False
+                               for b in ban:
+                                       r=b.replace("*",".*")
+                                       if re.match(b,f):
+                                               doban=True
+                               if not doban:
+                                       f=f.replace('.py','')
+                                       load_tool(f)
 cache_modules={}
-def load_module(path):
+def load_module(path,encoding=None):
        try:
                return cache_modules[path]
        except KeyError:
                pass
        module=imp.new_module(WSCRIPT_FILE)
        try:
-               code=Utils.readf(path,m='rU')
-       except(IOError,OSError):
+               code=Utils.readf(path,m='rU',encoding=encoding)
+       except EnvironmentError:
                raise Errors.WafError('Could not read the file %r'%path)
        module_dir=os.path.dirname(path)
        sys.path.insert(0,module_dir)
@@ -279,11 +330,9 @@ def load_module(path):
        sys.path.remove(module_dir)
        cache_modules[path]=module
        return module
-def load_tool(tool,tooldir=None):
+def load_tool(tool,tooldir=None,ctx=None):
        if tool=='java':
                tool='javaw'
-       elif tool=='compiler_cc':
-               tool='compiler_c'
        else:
                tool=tool.replace('++','xx')
        if tooldir:
@@ -298,19 +347,14 @@ def load_tool(tool,tooldir=None):
                        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:
+               for x in('waflib.Tools.%s','waflib.extras.%s','waflib.%s','%s'):
                        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]
+                               __import__(x%tool)
+                               break
+                       except ImportError:
+                               x=None
+               if x is None:
+                       __import__(tool)
+               ret=sys.modules[x%tool]
                Context.tools[tool]=ret
                return ret
index ef62452..713fd56 100644 (file)
@@ -2,72 +2,38 @@
 # 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
-_nocolor=os.environ.get('NOCOLOR','no')not in('no','0','false')
-try:
-       if not _nocolor:
-               import waflib.ansiterm
-except ImportError:
-       pass
-try:
-       import threading
-except ImportError:
-       if not'JOBS'in os.environ:
-               os.environ['JOBS']='1'
-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()
-       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 os,re,traceback,sys,types
+from waflib import Utils,ansiterm
+if not os.environ.get('NOSYNC',False):
+       if sys.stdout.isatty()and id(sys.stdout)==id(sys.__stdout__):
+               sys.stdout=ansiterm.AnsiTerm(sys.stdout)
+       if sys.stderr.isatty()and id(sys.stderr)==id(sys.__stderr__):
+               sys.stderr=ansiterm.AnsiTerm(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
+indicator='\r\x1b[K%s%s%s'
+def enable_colors(use):
+       if use==1:
+               if not(sys.stderr.isatty()or sys.stdout.isatty()):
+                       use=0
+               if Utils.is_win32:
+                       term=os.environ.get('TERM','')
                else:
-                       get_term_cols=get_term_cols_real
+                       term=os.environ.get('TERM','dumb')
+               if term in('dumb','emacs'):
+                       use=0
+       if use>=1:
+               os.environ['TERM']='vt100'
+       colors_lst['USE']=use
+try:
+       get_term_cols=ansiterm.get_term_cols
+except AttributeError:
+       def get_term_cols():
+               return 80
 get_term_cols.__doc__="""
        Get the console width in characters.
 
@@ -88,16 +54,8 @@ 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:
@@ -108,16 +66,70 @@ class log_filter(logging.Filter):
                elif not verbose>2:
                        return False
                return True
+class log_handler(logging.StreamHandler):
+       def emit(self,record):
+               try:
+                       try:
+                               self.stream=record.stream
+                       except AttributeError:
+                               if record.levelno>=logging.WARNING:
+                                       record.stream=self.stream=sys.stderr
+                               else:
+                                       record.stream=self.stream=sys.stdout
+                       self.emit_override(record)
+                       self.flush()
+               except(KeyboardInterrupt,SystemExit):
+                       raise
+               except:
+                       self.handleError(record)
+       def emit_override(self,record,**kw):
+               self.terminator=getattr(record,'terminator','\n')
+               stream=self.stream
+               if hasattr(types,"UnicodeType"):
+                       msg=self.formatter.format(record)
+                       fs='%s'+self.terminator
+                       try:
+                               if(isinstance(msg,unicode)and getattr(stream,'encoding',None)):
+                                       fs=fs.decode(stream.encoding)
+                                       try:
+                                               stream.write(fs%msg)
+                                       except UnicodeEncodeError:
+                                               stream.write((fs%msg).encode(stream.encoding))
+                               else:
+                                       stream.write(fs%msg)
+                       except UnicodeError:
+                               stream.write((fs%msg).encode("UTF-8"))
+               else:
+                       logging.StreamHandler.emit(self,record)
 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)
+               try:
+                       msg=rec.msg.decode('utf-8')
+               except Exception:
+                       msg=rec.msg
+               use=colors_lst['USE']
+               if(use==1 and rec.stream.isatty())or use==2:
+                       c1=getattr(rec,'c1',None)
+                       if c1 is None:
+                               c1=''
+                               if rec.levelno>=logging.ERROR:
+                                       c1=colors.RED
+                               elif rec.levelno>=logging.WARNING:
+                                       c1=colors.YELLOW
+                               elif rec.levelno>=logging.INFO:
+                                       c1=colors.GREEN
+                       c2=getattr(rec,'c2',colors.NORMAL)
+                       msg='%s%s%s'%(c1,msg,c2)
+               else:
+                       msg=msg.replace('\r','\n')
+                       msg=re.sub(r'\x1B\[(K|.*?(m|h|l))','',msg)
+               if rec.levelno>=logging.INFO:
+                       return msg
+               rec.msg=msg
+               rec.c1=colors.PINK
+               rec.c2=colors.NORMAL
                return logging.Formatter.format(self,rec)
 log=None
 def debug(*k,**kw):
@@ -150,7 +162,7 @@ def init_log():
        log=logging.getLogger('waflib')
        log.handlers=[]
        log.filters=[]
-       hdlr=logging.StreamHandler()
+       hdlr=log_handler()
        hdlr.setFormatter(formatter())
        log.addHandler(hdlr)
        log.addFilter(log_filter())
@@ -163,7 +175,7 @@ def make_logger(path,name):
        logger.addHandler(hdlr)
        logger.setLevel(logging.DEBUG)
        return logger
-def make_mem_logger(name,to_log,size=10000):
+def make_mem_logger(name,to_log,size=8192):
        from logging.handlers import MemoryHandler
        logger=logging.getLogger(name)
        hdlr=MemoryHandler(size,target=to_log)
@@ -173,5 +185,12 @@ def make_mem_logger(name,to_log,size=10000):
        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))
+def free_logger(logger):
+       try:
+               for x in logger.handlers:
+                       x.close()
+                       logger.removeHandler(x)
+       except Exception ,e:
+               pass
+def pprint(col,msg,label='',sep='\n'):
+       info("%s%s%s %s"%(colors(col),msg,colors.NORMAL,label),extra={'terminator':sep})
index 7729613..09dfb5a 100644 (file)
@@ -46,15 +46,19 @@ def split_path_cygwin(path):
 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
+               if path.startswith('\\\\?'):
+                       path=path[4:]
+               else:
+                       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):
+       dict_class=dict
        __slots__=('name','sig','children','parent','cache_abspath','cache_isdir','cache_sig')
        def __init__(self,name,parent):
                self.name=name
@@ -67,7 +71,7 @@ class Node(object):
                self.name=data[0]
                self.parent=data[1]
                if data[2]is not None:
-                       self.children=data[2]
+                       self.children=self.dict_class(data[2])
                if data[3]is not None:
                        self.sig=data[3]
        def __getstate__(self):
@@ -90,13 +94,16 @@ class Node(object):
                os.chmod(self.abspath(),val)
        def delete(self):
                try:
-                       if hasattr(self,'children'):
-                               shutil.rmtree(self.abspath())
-                       else:
-                               os.remove(self.abspath())
-               except OSError:
-                       pass
-               self.evict()
+                       try:
+                               if hasattr(self,'children'):
+                                       shutil.rmtree(self.abspath())
+                               else:
+                                       os.remove(self.abspath())
+                       except OSError ,e:
+                               if os.path.exists(self.abspath()):
+                                       raise e
+               finally:
+                       self.evict()
        def evict(self):
                del self.parent.children[self.name]
        def suffix(self):
@@ -130,7 +137,7 @@ class Node(object):
                        try:
                                self.children
                        except AttributeError:
-                               self.children={}
+                               self.children=self.dict_class()
                self.cache_isdir=True
        def find_node(self,lst):
                if isinstance(lst,str):
@@ -143,7 +150,7 @@ class Node(object):
                        try:
                                ch=cur.children
                        except AttributeError:
-                               cur.children={}
+                               cur.children=self.dict_class()
                        else:
                                try:
                                        cur=cur.children[x]
@@ -182,7 +189,7 @@ class Node(object):
                                        cur=cur.children[x]
                                        continue
                        else:
-                               cur.children={}
+                               cur.children=self.dict_class()
                        cur=self.__class__(x,cur)
                return cur
        def search_node(self,lst):
@@ -218,8 +225,12 @@ class Node(object):
                        up+=1
                        c1=c1.parent
                        c2=c2.parent
-               for i in range(up):
-                       lst.append('..')
+               if c1.parent:
+                       for i in range(up):
+                               lst.append('..')
+               else:
+                       if os.sep=='/'and lst:
+                               lst.append('')
                lst.reverse()
                return os.sep.join(lst)or'.'
        def abspath(self):
@@ -256,7 +267,7 @@ class Node(object):
                try:
                        lst=set(self.children.keys())
                except AttributeError:
-                       self.children={}
+                       self.children=self.dict_class()
                else:
                        if remove:
                                for x in lst-set(dircont):
@@ -433,8 +444,6 @@ class Node(object):
                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):
@@ -449,9 +458,6 @@ class Node(object):
                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
@@ -461,7 +467,6 @@ class Node(object):
                        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
index 21f4254..926161b 100644 (file)
@@ -7,58 +7,26 @@ from waflib import Logs,Utils,Context
 cmds='distclean configure build install clean uninstall check dist distcheck'.split()
 options={}
 commands=[]
+envvars=[]
 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 print_usage(self,file=None):
+               return self.print_help(file)
        def get_usage(self):
                cmds_str={}
                for cls in Context.classes:
-                       if not cls.cmd or cls.cmd=='options':
+                       if not cls.cmd or cls.cmd=='options'or cls.cmd.startswith('_'):
                                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']:
+                               if k in('options','init','shutdown'):
                                        continue
                                if type(v)is type(Context.create_context):
                                        if v.__doc__ and not k.startswith('_'):
@@ -81,6 +49,41 @@ class OptionsContext(Context.Context):
                super(OptionsContext,self).__init__(**kw)
                self.parser=opt_parser(self)
                self.option_groups={}
+               jobs=self.jobs()
+               p=self.add_option
+               color=os.environ.get('NOCOLOR','')and'no'or'auto'
+               p('-c','--color',dest='colors',default=color,action='store',help='whether to use colors (yes/no/auto) [default: auto]',choices=('yes','no','auto'))
+               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='continue despite errors (-kk to try harder)')
+               p('-v','--verbose',dest='verbose',default=0,action='count',help='verbosity level -v -vv or -vvv [default: 0]')
+               p('--zones',dest='zones',default='',action='store',help='debugging zones (task_gen, deps, tasks, etc)')
+               gr=self.add_option_group('Configuration options')
+               self.option_groups['configure options']=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=getattr(Context.g_module,'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('--bindir',dest='bindir',help='bindir')
+               gr.add_option('--libdir',dest='libdir',help='libdir')
+               gr=self.add_option_group('Build and installation options')
+               self.option_groups['build and install options']=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=self.add_option_group('Step options')
+               self.option_groups['step options']=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=self.add_option_group('Installation and uninstallation options')
+               self.option_groups['install/uninstall options']=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',metavar='ARGS',help='arguments to pass to distcheck',default=None,action='store')
        def jobs(self):
                count=int(os.environ.get('JOBS',0))
                if count<1:
@@ -123,13 +126,19 @@ class OptionsContext(Context.Context):
                                        return group
                        return None
        def parse_args(self,_args=None):
-               global options,commands
+               global options,commands,envvars
                (options,leftover_args)=self.parser.parse_args(args=_args)
-               commands=leftover_args
+               for arg in leftover_args:
+                       if'='in arg:
+                               envvars.append(arg)
+                       else:
+                               commands.append(arg)
                if options.destdir:
                        options.destdir=os.path.abspath(os.path.expanduser(options.destdir))
                if options.verbose>=1:
                        self.load('errcheck')
+               colors={'yes':2,'auto':1,'no':0}[options.colors]
+               Logs.enable_colors(colors)
        def execute(self):
                super(OptionsContext,self).execute()
                self.parse_args()
index 15b6a27..7b29265 100644 (file)
@@ -109,10 +109,6 @@ class Parallel(object):
                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
@@ -143,6 +139,31 @@ class Parallel(object):
                        for x in pool:
                                put_pool(x)
                        self.pool=[]
+       def skip(self,tsk):
+               tsk.hasrun=Task.SKIPPED
+       def error_handler(self,tsk):
+               if not self.bld.keep:
+                       self.stop=True
+               self.error.append(tsk)
+       def task_status(self,tsk):
+               try:
+                       return tsk.runnable_status()
+               except Exception:
+                       self.processed+=1
+                       tsk.err_msg=Utils.ex_stack()
+                       if not self.stop and self.bld.keep:
+                               self.skip(tsk)
+                               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)
+                               return Task.EXCEPTION
+                       tsk.hasrun=Task.EXCEPTION
+                       self.error_handler(tsk)
+                       return Task.EXCEPTION
        def start(self):
                self.total=self.bld.total()
                while not self.stop:
@@ -158,31 +179,8 @@ class Parallel(object):
                                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:
+                       st=self.task_status(tsk)
+                       if st==Task.RUN_ME:
                                tsk.position=(self.processed,self.total)
                                self.count+=1
                                tsk.master=self
@@ -191,6 +189,12 @@ class Parallel(object):
                                        tsk.process()
                                else:
                                        self.add_task(tsk)
+                       if st==Task.ASK_LATER:
+                               self.postpone(tsk)
+                       elif st==Task.SKIP_ME:
+                               self.processed+=1
+                               self.skip(tsk)
+                               self.add_more_tasks(tsk)
                while self.error and self.count:
                        self.get_out()
                assert(self.count==0 or self.stop)
index aec7124..54d191a 100644 (file)
@@ -18,14 +18,20 @@ def waf_entry_point(current_directory,version,wafdir):
                ctx.curdir=current_directory
                ctx.parse_args()
                sys.exit(0)
+       if len(sys.argv)>1:
+               potential_wscript=os.path.join(current_directory,sys.argv[1])
+               if os.path.basename(potential_wscript)=='wscript'and os.path.isfile(potential_wscript):
+                       current_directory=os.path.normpath(os.path.dirname(potential_wscript))
+                       sys.argv.pop(1)
        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
+                       for y in sys.argv:
+                               if y.startswith(k):
+                                       no_climb=True
+                                       break
        cur=current_directory
        while cur:
                lst=os.listdir(cur)
@@ -37,7 +43,7 @@ def waf_entry_point(current_directory,version,wafdir):
                        except Exception:
                                pass
                        else:
-                               for x in[env.run_dir,env.top_dir,env.out_dir]:
+                               for x in(env.run_dir,env.top_dir,env.out_dir):
                                        if Utils.is_win32:
                                                if cur==x:
                                                        load=True
@@ -84,7 +90,7 @@ def waf_entry_point(current_directory,version,wafdir):
                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)
+               set_main_module(os.path.join(Context.run_dir,Context.WSCRIPT_FILE))
        except Errors.WafError ,e:
                Logs.pprint('RED',e.verbose_msg)
                Logs.error(str(e))
@@ -115,7 +121,7 @@ def set_main_module(file_path):
                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]:
+       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
@@ -125,11 +131,13 @@ def set_main_module(file_path):
                Context.g_module.options=Utils.nada
 def parse_options():
        Context.create_context('options').execute()
+       for var in Options.envvars:
+               (name,value)=var.split('=',1)
+               os.environ[name.strip()]=value
        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:
@@ -143,7 +151,10 @@ def run_command(cmd_name):
        ctx.log_timer=Utils.Timer()
        ctx.options=Options.options
        ctx.cmd=cmd_name
-       ctx.execute()
+       try:
+               ctx.execute()
+       finally:
+               ctx.finalize()
        return ctx
 def run_commands():
        parse_options()
@@ -162,12 +173,12 @@ 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
+                               fname=os.path.join(root,f)
                                try:
                                        os.remove(fname)
                                except OSError:
                                        Logs.warn('Could not remove %r'%fname)
-       for x in[Context.DBFILE,'config.log']:
+       for x in(Context.DBFILE,'config.log'):
                try:
                        os.remove(x)
                except OSError:
@@ -193,15 +204,16 @@ def distclean(ctx):
                                        pass
                                except OSError ,e:
                                        if e.errno!=errno.ENOENT:
-                                               Logs.warn('project %r cannot be removed'%proj[Context.OUT])
+                                               Logs.warn('Could not remove %r'%proj['out_dir'])
                        else:
                                distclean_dir(proj['out_dir'])
                        for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']):
+                               p=os.path.join(k,Options.lockfile)
                                try:
-                                       os.remove(os.path.join(k,Options.lockfile))
+                                       os.remove(p)
                                except OSError ,e:
                                        if e.errno!=errno.ENOENT:
-                                               Logs.warn('file %r cannot be removed'%f)
+                                               Logs.warn('Could not remove %r'%p)
                if not Options.commands:
                        for x in'.waf-1. waf-1. .waf3-1. waf3-1.'.split():
                                if f.startswith(x):
@@ -225,7 +237,7 @@ class Dist(Context.Context):
                node=self.base_path.make_node(arch_name)
                try:
                        node.delete()
-               except Exception:
+               except OSError:
                        pass
                files=self.get_files()
                if self.algo.startswith('tar.'):
@@ -241,7 +253,7 @@ class Dist(Context.Context):
                                zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED)
                        zip.close()
                else:
-                       self.fatal('Valid algo types are tar.bz2, tar.gz or zip')
+                       self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip')
                try:
                        from hashlib import sha1 as sha
                except ImportError:
@@ -290,10 +302,11 @@ class Dist(Context.Context):
                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)
+                       self.excl=Node.exclude_regs+' **/waf-1.8.* **/.waf-1.8* **/waf3-1.8.* **/.waf3-1.8* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*'
+                       if Context.out_dir:
+                               nd=self.root.find_node(Context.out_dir)
+                               if nd:
+                                       self.excl+=' '+nd.path_from(self.base_path)
                        return self.excl
        def get_files(self):
                try:
@@ -369,6 +382,8 @@ def autoconfigure(execute_method):
                if do_config:
                        Options.commands.insert(0,self.cmd)
                        Options.commands.insert(0,'configure')
+                       if Configure.autoconfig=='clobber':
+                               Options.options.__dict__=env.options
                        return
                return execute_method(self)
        return execute
index 8cc4cc3..3aa4489 100644 (file)
@@ -2,7 +2,7 @@
 # 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
+import os,re,sys
 from waflib import Utils,Logs,Errors
 NOT_RUN=0
 MISSING=1
@@ -37,24 +37,6 @@ def f(tsk):
        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):
@@ -67,14 +49,15 @@ class store_task_type(type):
                        if getattr(cls,'run_str',None):
                                (f,dvars)=compile_fun(cls.run_str,cls.shell)
                                cls.hcode=cls.run_str
+                               cls.orig_run_str=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)
+                       if sys.hexversion>0x3000000:
+                               cls.hcode=cls.hcode.encode('iso8859-1','xmlcharrefreplace')
                        getattr(cls,'register',classes)[name]=cls
 evil=store_task_type('evil',(object,),{})
 class TaskBase(evil):
@@ -94,10 +77,14 @@ class TaskBase(evil):
                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'
+                       return self.fun.__name__
+               return self.__class__.__name__
        def __hash__(self):
                return id(self)
+       def keyword(self):
+               if hasattr(self,'fun'):
+                       return'Function'
+               return'Processing'
        def exec_command(self,cmd,**kw):
                bld=self.generator.bld
                try:
@@ -150,7 +137,20 @@ class TaskBase(evil):
        def post_run(self):
                pass
        def log_display(self,bld):
-               bld.to_log(self.display())
+               if self.generator.bld.progress_bar==3:
+                       return
+               s=self.display()
+               if s:
+                       if bld.logger:
+                               logger=bld.logger
+                       else:
+                               logger=Logs
+                       if self.generator.bld.progress_bar==1:
+                               c1=Logs.colors.cursor_off
+                               c2=Logs.colors.cursor_on
+                               logger.info(s,extra={'stream':sys.stderr,'terminator':'','c1':c1,'c2':c2})
+                       else:
+                               logger.info(s,extra={'terminator':'','c1':'','c2':''})
        def display(self):
                col1=Logs.colors(self.color)
                col2=Logs.colors.NORMAL
@@ -178,8 +178,11 @@ class TaskBase(evil):
                        return None
                total=master.total
                n=len(str(total))
-               fs='[%%%dd/%%%dd] %%s%%s%%s'%(n,n)
-               return fs%(cur(),total,col1,s,col2)
+               fs='[%%%dd/%%%dd] %%s%%s%%s%%s\n'%(n,n)
+               kw=self.keyword()
+               if kw:
+                       kw+=' '
+               return fs%(cur(),total,kw,col1,s,col2)
        def attr(self,att,default=None):
                ret=getattr(self,att,self)
                if ret is self:return getattr(self.__class__,att,default)
@@ -207,6 +210,8 @@ class TaskBase(evil):
                        return'invalid status for task in %r: %r'%(name,self.hasrun)
        def colon(self,var1,var2):
                tmp=self.env[var1]
+               if not tmp:
+                       return[]
                if isinstance(var2,str):
                        it=self.env[var2]
                else:
@@ -214,8 +219,6 @@ class TaskBase(evil):
                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)
@@ -232,12 +235,33 @@ class Task(TaskBase):
                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])
+               name=self.__class__.__name__
+               if self.outputs:
+                       if(name.endswith('lib')or name.endswith('program'))or not self.inputs:
+                               node=self.outputs[0]
+                               return node.path_from(node.ctx.launch_node())
+               if not(self.inputs or self.outputs):
+                       return self.__class__.__name__
+               if len(self.inputs)==1:
+                       node=self.inputs[0]
+                       return node.path_from(node.ctx.launch_node())
+               src_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.inputs])
+               tgt_str=' '.join([a.path_from(a.ctx.launch_node())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)
+               return'%s: %s%s%s'%(self.__class__.__name__.replace('_task',''),src_str,sep,tgt_str)
+       def keyword(self):
+               name=self.__class__.__name__
+               if name.endswith('lib')or name.endswith('program'):
+                       return'Linking'
+               if len(self.inputs)==1 and len(self.outputs)==1:
+                       return'Compiling'
+               if not self.inputs:
+                       if self.outputs:
+                               return'Creating'
+                       else:
+                               return'Running'
+               return'Processing'
        def __repr__(self):
                try:
                        ins=",".join([x.name for x in self.inputs])
@@ -361,9 +385,11 @@ class Task(TaskBase):
                        try:
                                if prev==self.compute_sig_implicit_deps():
                                        return prev
-                       except Exception:
+                       except Errors.TaskNotReady:
+                               raise
+                       except EnvironmentError:
                                for x in bld.node_deps.get(self.uid(),[]):
-                                       if x.is_child_of(bld.srcnode):
+                                       if not x.is_bld():
                                                try:
                                                        os.stat(x.abspath())
                                                except OSError:
@@ -419,71 +445,20 @@ class Task(TaskBase):
                        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
+if sys.hexversion>0x3000000:
+       def uid(self):
                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
+                       return self.uid_
+               except AttributeError:
+                       m=Utils.md5()
+                       up=m.update
+                       up(self.__class__.__name__.encode('iso8859-1','xmlcharrefreplace'))
+                       for x in self.inputs+self.outputs:
+                               up(x.abspath().encode('iso8859-1','xmlcharrefreplace'))
+                       self.uid_=m.digest()
+                       return self.uid_
+       uid.__doc__=Task.uid.__doc__
+       Task.uid=uid
 def is_before(t1,t2):
        to_list=Utils.to_list
        for k in to_list(t2.ext_in):
@@ -578,6 +553,7 @@ def compile_fun_noshell(line):
        def repl(match):
                g=match.group
                if g('dollar'):return"$"
+               elif g('backslash'):return'\\'
                elif g('subst'):extr.append((g('var'),g('code')));return"<<|@|>>"
                return None
        line2=reg_act.sub(repl,line)
index 381bfce..e34b8be 100644 (file)
@@ -5,8 +5,9 @@
 import copy,re,os
 from waflib import Task,Utils,Logs,Errors,ConfigSet,Node
 feats=Utils.defaultdict(set)
+HEADER_EXTS=['.h','.hpp','.hxx','.hh']
 class task_gen(object):
-       mappings={}
+       mappings=Utils.ordered_iter_dict()
        prec=Utils.defaultdict(list)
        def __init__(self,*k,**kw):
                self.source=''
@@ -36,7 +37,7 @@ class task_gen(object):
        def __repr__(self):
                lst=[]
                for x in self.__dict__.keys():
-                       if x not in['env','bld','compiled_tasks','tasks']:
+                       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):
@@ -111,27 +112,29 @@ class task_gen(object):
                return True
        def get_hook(self,node):
                name=node.name
-               for k in self.mappings:
-                       if name.endswith(k):
-                               return self.mappings[k]
+               if self.mappings:
+                       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):
+               raise Errors.WafError("File %r has no mapping in %r (have you forgotten to load a waf tool?)"%(node,task_gen.mappings.keys()))
+       def create_task(self,name,src=None,tgt=None,**kw):
                task=Task.classes[name](env=self.env.derive(),generator=self)
                if src:
                        task.set_inputs(src)
                if tgt:
                        task.set_outputs(tgt)
+               task.__dict__.update(kw)
                self.tasks.append(task)
                return task
        def clone(self,env):
                newobj=self.bld()
                for x in self.__dict__:
-                       if x in['env','bld']:
+                       if x in('env','bld'):
                                continue
-                       elif x in['path','features']:
+                       elif x in('path','features'):
                                setattr(newobj,x,getattr(self,x))
                        else:
                                setattr(newobj,x,copy.copy(getattr(self,x)))
@@ -153,7 +156,7 @@ def declare_chain(name='',rule=None,reentrant=None,color='BLUE',ext_in=[],ext_ou
                        _ext_in=ext_in[0]
                tsk=self.create_task(name,node)
                cnt=0
-               keys=list(self.mappings.keys())+list(self.__class__.mappings.keys())
+               keys=set(self.mappings.keys())|set(self.__class__.mappings.keys())
                for x in ext:
                        k=node.change_ext(x,ext_in=_ext_in)
                        tsk.outputs.append(k)
@@ -212,7 +215,7 @@ def to_nodes(self,lst,path=None):
        tmp=[]
        path=path or self.path
        find=path.find_resource
-       if isinstance(lst,self.path.__class__):
+       if isinstance(lst,Node.Node):
                lst=[lst]
        for x in Utils.to_list(lst):
                if isinstance(x,str):
@@ -262,7 +265,7 @@ def process_rule(self):
                        Task.update_outputs(cls)
                if getattr(self,'always',None):
                        Task.always_run(cls)
-               for x in['after','before','ext_in','ext_out']:
+               for x in('after','before','ext_in','ext_out'):
                        setattr(cls,x,getattr(self,x,[]))
                if getattr(self,'cache_rule','True'):
                        cache[(name,self.rule)]=cls
@@ -307,11 +310,11 @@ class subst_pc(Task.Task):
                                os.chmod(self.outputs[0].abspath(),self.generator.chmod)
                        return None
                if getattr(self.generator,'fun',None):
-                       self.generator.fun(self)
+                       return self.generator.fun(self)
                code=self.inputs[0].read(encoding=getattr(self.generator,'encoding','ISO8859-1'))
                if getattr(self.generator,'subst_fun',None):
                        code=self.generator.subst_fun(self,code)
-                       if code:
+                       if code is not None:
                                self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
                        return
                code=code.replace('%','%%')
@@ -329,8 +332,12 @@ class subst_pc(Task.Task):
                except AttributeError:
                        d={}
                        for x in lst:
-                               tmp=getattr(self.generator,x,'')or self.env.get_flat(x)or self.env.get_flat(x.upper())
-                               d[x]=str(tmp)
+                               tmp=getattr(self.generator,x,'')or self.env[x]or self.env[x.upper()]
+                               try:
+                                       tmp=''.join(tmp)
+                               except TypeError:
+                                       tmp=str(tmp)
+                               d[x]=tmp
                code=code%d
                self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','ISO8859-1'))
                self.generator.bld.raw_deps[self.uid()]=self.dep_vars=lst
@@ -397,8 +404,12 @@ def process_subst(self):
                        if val:
                                has_constraints=True
                                setattr(tsk,k,val)
-               if not has_constraints and b.name.endswith('.h'):
-                       tsk.before=[k for k in('c','cxx')if k in Task.classes]
+               if not has_constraints:
+                       global HEADER_EXTS
+                       for xt in HEADER_EXTS:
+                               if b.name.endswith(xt):
+                                       tsk.before=[k for k in('c','cxx')if k in Task.classes]
+                                       break
                inst_to=getattr(self,'install_path',None)
                if inst_to:
                        self.bld.install_files(inst_to,b,chmod=getattr(self,'chmod',Utils.O644))
index 7a16dfe..9488ead 100644 (file)
@@ -8,4 +8,6 @@ def find_ar(conf):
        conf.load('ar')
 def configure(conf):
        conf.find_program('ar',var='AR')
-       conf.env.ARFLAGS='rcs'
+       conf.add_os_flags('ARFLAGS')
+       if not conf.env.ARFLAGS:
+               conf.env.ARFLAGS=['rcs']
index b9ed5f4..c1991fd 100644 (file)
@@ -9,7 +9,7 @@ from waflib.Tools.ccroot import link_task,stlink_task
 from waflib.TaskGen import extension,feature
 class asm(Task.Task):
        color='BLUE'
-       run_str='${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}'
+       run_str='${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}'
 @extension('.s','.S','.asm','.ASM','.spp','.SPP')
 def asm_hook(self,node):
        return self.create_compiled_task('asm',node)
index 4d8cbd5..2252e5e 100644 (file)
@@ -7,9 +7,11 @@ from waflib.Tools import c_preproc
 from waflib.Tools.ccroot import link_task,stlink_task
 @TaskGen.extension('.c')
 def c_hook(self,node):
+       if not self.env.CC and self.env.CXX:
+               return self.create_compiled_task('cxx',node)
        return self.create_compiled_task('c',node)
 class c(Task.Task):
-       run_str='${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT}'
+       run_str='${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath()}'
        vars=['CCDEPS']
        ext_in=['.h']
        scan=c_preproc.scan
index a3a2bb9..34e1a9a 100644 (file)
@@ -29,9 +29,9 @@ def sniff_features(**kw):
                feats.append('java')
        if'java'in exts:
                return'java'
-       if type in['program','shlib','stlib']:
+       if type in('program','shlib','stlib'):
                for x in feats:
-                       if x in['cxx','d','c']:
+                       if x in('cxx','d','c'):
                                feats.append(x+type)
        return feats
 def set_features(kw,_type):
index eb615d8..3282122 100755 (executable)
@@ -43,15 +43,19 @@ int main(int argc, char **argv) {
 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):
+def parse_flags(self,line,uselib_store,env=None,force_static=False,posix=None):
        assert(isinstance(line,str))
        env=env or self.env
-       app=env.append_value
-       appu=env.append_unique
-       lex=shlex.shlex(line,posix=False)
+       if posix is None:
+               posix=True
+               if'\\'in line:
+                       posix=('\\ 'in line)or('\\\\'in line)
+       lex=shlex.shlex(line,posix=posix)
        lex.whitespace_split=True
        lex.commenters=''
        lst=list(lex)
+       app=env.append_value
+       appu=env.append_unique
        uselib=uselib_store
        while lst:
                x=lst.pop(0)
@@ -60,7 +64,7 @@ def parse_flags(self,line,uselib_store,env=None,force_static=False):
                if st=='-I'or st=='/I':
                        if not ot:ot=lst.pop(0)
                        appu('INCLUDES_'+uselib,[ot])
-               elif st=='-include':
+               elif st=='-i':
                        tmp=[x,lst.pop(0)]
                        app('CFLAGS',tmp)
                        app('CXXFLAGS',tmp)
@@ -84,6 +88,12 @@ def parse_flags(self,line,uselib_store,env=None,force_static=False):
                        appu('FRAMEWORK_'+uselib,[lst.pop(0)])
                elif x.startswith('-F'):
                        appu('FRAMEWORKPATH_'+uselib,[x[2:]])
+               elif x=='-Wl,-rpath':
+                       app('RPATH_'+uselib,lst.pop(0))
+               elif x.startswith('-Wl,-R'):
+                       app('RPATH_'+uselib,x[6:])
+               elif x.startswith('-Wl,-rpath,'):
+                       app('RPATH_'+uselib,x[11:])
                elif x.startswith('-Wl'):
                        app('LINKFLAGS_'+uselib,[x])
                elif x.startswith('-m')or x.startswith('-f')or x.startswith('-dynamic'):
@@ -91,7 +101,7 @@ def parse_flags(self,line,uselib_store,env=None,force_static=False):
                        app('CXXFLAGS_'+uselib,[x])
                elif x.startswith('-bundle'):
                        app('LINKFLAGS_'+uselib,[x])
-               elif x.startswith('-undefined'):
+               elif x.startswith('-undefined')or x.startswith('-Xlinker'):
                        arg=lst.pop(0)
                        app('LINKFLAGS_'+uselib,[x,arg])
                elif x.startswith('-arch')or x.startswith('-isysroot'):
@@ -102,11 +112,6 @@ def parse_flags(self,line,uselib_store,env=None,force_static=False):
                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:
@@ -132,14 +137,25 @@ def validate_cfg(self,kw):
                        if not'msg'in kw:
                                kw['msg']='Checking for %r %s %s'%(kw['package'],cfg_ver[x],kw[y])
                        return
+       if not'define_name'in kw:
+               pkgname=kw.get('uselib_store',kw['package'].upper())
+               kw['define_name']=self.have_define(pkgname)
+       if not'uselib_store'in kw:
+               self.undefine(kw['define_name'])
        if not'msg'in kw:
                kw['msg']='Checking for %r'%(kw['package']or kw['path'])
 @conf
 def exec_cfg(self,kw):
+       path=Utils.to_list(kw['path'])
        def define_it():
-               self.define(self.have_define(kw.get('uselib_store',kw['package'])),1,0)
+               pkgname=kw.get('uselib_store',kw['package'].upper())
+               if kw.get('global_define'):
+                       self.define(self.have_define(kw['package']),1,False)
+               else:
+                       self.env.append_unique('DEFINES_%s'%pkgname,"%s=1"%self.have_define(pkgname))
+               self.env[self.have_define(pkgname)]=1
        if'atleast_pkgconfig_version'in kw:
-               cmd=[kw['path'],'--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']]
+               cmd=path+['--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']]
                self.cmd_and_log(cmd)
                if not'okmsg'in kw:
                        kw['okmsg']='yes'
@@ -147,22 +163,22 @@ def exec_cfg(self,kw):
        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']])
+                       self.cmd_and_log(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()
+               version=self.cmd_and_log(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']]
+       lst=[]+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))
-       static=False
+       static=kw.get('force_static',False)
        if'args'in kw:
                args=Utils.to_list(kw['args'])
                if'--static'in args or'--static-libs'in args:
@@ -184,7 +200,7 @@ def exec_cfg(self,kw):
        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)
+       self.parse_flags(ret,kw.get('uselib_store',kw['package'].upper()),kw.get('env',self.env),force_static=static,posix=kw.get('posix',None))
        return ret
 @conf
 def check_cfg(self,*k,**kw):
@@ -194,24 +210,37 @@ def check_cfg(self,*k,**kw):
                kw['args']=' '.join(lst[1:])
        self.validate_cfg(kw)
        if'msg'in kw:
-               self.start_msg(kw['msg'])
+               self.start_msg(kw['msg'],**kw)
        ret=None
        try:
                ret=self.exec_cfg(kw)
        except self.errors.WafError:
                if'errmsg'in kw:
-                       self.end_msg(kw['errmsg'],'YELLOW')
+                       self.end_msg(kw['errmsg'],'YELLOW',**kw)
                if Logs.verbose>1:
                        raise
                else:
                        self.fatal('The configuration failed')
        else:
+               if not ret:
+                       ret=True
                kw['success']=ret
                if'okmsg'in kw:
-                       self.end_msg(self.ret_msg(kw['okmsg'],kw))
+                       self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
        return ret
+def build_fun(bld):
+       if bld.kw['compile_filename']:
+               node=bld.srcnode.make_node(bld.kw['compile_filename'])
+               node.write(bld.kw['code'])
+       o=bld(features=bld.kw['features'],source=bld.kw['compile_filename'],target='testprog')
+       for k,v in bld.kw.items():
+               setattr(o,k,v)
+       if not bld.kw.get('quiet',None):
+               bld.conf.to_log("==>\n%s\n<=="%bld.kw['code'])
 @conf
 def validate_c(self,kw):
+       if not'build_fun'in kw:
+               kw['build_fun']=build_fun
        if not'env'in kw:
                kw['env']=self.env.derive()
        env=kw['env']
@@ -306,7 +335,7 @@ def validate_c(self,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')]:
+       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])
@@ -368,12 +397,12 @@ def post_check(self,*k,**kw):
 @conf
 def check(self,*k,**kw):
        self.validate_c(kw)
-       self.start_msg(kw['msg'])
+       self.start_msg(kw['msg'],**kw)
        ret=None
        try:
-               ret=self.run_c_code(*k,**kw)
+               ret=self.run_build(*k,**kw)
        except self.errors.ConfigurationError:
-               self.end_msg(kw['errmsg'],'YELLOW')
+               self.end_msg(kw['errmsg'],'YELLOW',**kw)
                if Logs.verbose>1:
                        raise
                else:
@@ -382,10 +411,10 @@ def check(self,*k,**kw):
                kw['success']=ret
        ret=self.post_check(*k,**kw)
        if not ret:
-               self.end_msg(kw['errmsg'],'YELLOW')
+               self.end_msg(kw['errmsg'],'YELLOW',**kw)
                self.fatal('The configuration failed %r'%ret)
        else:
-               self.end_msg(self.ret_msg(kw['okmsg'],kw))
+               self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw)
        return ret
 class test_exec(Task.Task):
        color='PINK'
@@ -408,64 +437,6 @@ class test_exec(Task.Task):
 @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'
@@ -529,9 +500,7 @@ def get_define(self,key):
 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')
+def write_config_header(self,configfile='',guard='',top=False,defines=True,headers=False,remove=True,define_prefix=''):
        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()
@@ -554,12 +523,16 @@ def get_config_header(self,defines=True,headers=False,define_prefix=''):
                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))
+               tbl={}
+               for k in self.env['DEFINES']:
+                       a,_,b=k.partition('=')
+                       tbl[a]=b
+               for k in self.env[DEFKEYS]:
+                       try:
+                               txt='#define %s%s %s'%(define_prefix,k,tbl[k])
+                       except KeyError:
+                               txt='/* #undef %s%s */'%(define_prefix,k)
+                       lst.append(txt)
        return"\n".join(lst)
 @conf
 def cc_add_flags(conf):
@@ -584,7 +557,7 @@ def cxx_load_tools(conf):
                conf.env.DEST_OS=Utils.unversioned_sys_platform()
        conf.load('cxx')
 @conf
-def get_cc_version(conf,cc,gcc=False,icc=False):
+def get_cc_version(conf,cc,gcc=False,icc=False,clang=False):
        cmd=cc+['-dM','-E','-']
        env=conf.env.env or None
        try:
@@ -602,8 +575,12 @@ def get_cc_version(conf,cc,gcc=False,icc=False):
                        conf.fatal('Could not determine the compiler type')
        if icc and out.find('__INTEL_COMPILER')<0:
                conf.fatal('Not icc/icpc')
+       if clang and out.find('__clang__')<0:
+               conf.fatal('Not clang/clang++')
+       if not clang and out.find('__clang__')>=0:
+               conf.fatal('Could not find g++, if renamed try eg: CXX=g++48 waf configure')
        k={}
-       if icc or gcc:
+       if icc or gcc or clang:
                out=out.splitlines()
                for line in out:
                        lst=shlex.split(line)
@@ -645,9 +622,15 @@ def get_cc_version(conf,cc,gcc=False,icc=False):
                        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__'])
+                               try:
+                                       conf.env['CC_VERSION']=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__'])
+                               except KeyError:
+                                       conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__'])
                        else:
-                               conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__'])
+                               try:
+                                       conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__'])
+                               except KeyError:
+                                       conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],0)
        return k
 @conf
 def get_xlc_version(conf,cc):
@@ -687,7 +670,7 @@ def get_suncc_version(conf,cc):
 @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')
+               self.env.append_unique('LINKFLAGS','-Wl,--as-needed')
 class cfgtask(Task.TaskBase):
        def display(self):
                return''
@@ -708,12 +691,10 @@ class cfgtask(Task.TaskBase):
                        return 1
 @conf
 def multicheck(self,*k,**kw):
-       self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)))
+       self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)),**kw)
        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):
@@ -741,6 +722,6 @@ def multicheck(self,*k,**kw):
                x.logger.memhandler.flush()
        for x in tasks:
                if x.hasrun!=Task.SUCCESS:
-                       self.end_msg(kw.get('errmsg','no'),color='YELLOW')
+                       self.end_msg(kw.get('errmsg','no'),color='YELLOW',**kw)
                        self.fatal(kw.get('fatalmsg',None)or'One of the tests has failed, see the config.log for more information')
-       self.end_msg('ok')
+       self.end_msg('ok',**kw)
index 1f99cd3..79f8c9c 100644 (file)
@@ -15,7 +15,7 @@ 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':'~',}
+g_optrans={'not':'!','not_eq':'!','and':'&&','and_eq':'&=','or':'||','or_eq':'|=','xor':'^','xor_eq':'^=','bitand':'&','bitor':'|','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_]*[(]')
@@ -71,17 +71,17 @@ def reduce_nums(val_1,val_2,val_op):
        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=='|'or d=='bitor':c=a|b
+       elif d=='||'or d=='or':c=int(a or b)
+       elif d=='&'or d=='bitand':c=a&b
+       elif d=='&&'or d=='and':c=int(a and b)
+       elif d=='!='or d=='not_eq':c=int(a!=b)
+       elif d=='^'or d=='xor':c=int(a^b)
        elif d=='<=':c=int(a<=b)
        elif d=='<':c=int(a<b)
        elif d=='>':c=int(a>b)
        elif d=='>=':c=int(a>=b)
-       elif d=='^':c=int(a^b)
        elif d=='<<':c=a<<b
        elif d=='>>':c=a>>b
        else:c=0
@@ -381,7 +381,8 @@ def extract_include(txt,defs):
                        return'"',toks[0][1]
        else:
                if toks[0][1]=='<'and toks[-1][1]=='>':
-                       return stringize(toks).lstrip('<').rstrip('>')
+                       ret='<',stringize(toks).lstrip('<').rstrip('>')
+                       return ret
        raise PreprocError("could not parse include %s."%txt)
 def parse_char(txt):
        if not txt:raise PreprocError("attempted to parse a null char")
@@ -410,7 +411,9 @@ def tokenize_private(s):
                        v=m(name)
                        if v:
                                if name==IDENT:
-                                       try:v=g_optrans[v];name=OP
+                                       try:
+                                               g_optrans[v];
+                                               name=OP
                                        except KeyError:
                                                if v.lower()=="true":
                                                        v=1
@@ -472,6 +475,9 @@ class c_parser(object):
                        nd[tup]=ret
                        return ret
        def tryfind(self,filename):
+               if filename.endswith('.moc'):
+                       self.names.append(filename)
+                       return None
                self.curfile=filename
                found=self.cached_find_resource(self.currentnode_stack[-1],filename)
                for n in self.nodepaths:
@@ -480,8 +486,7 @@ class c_parser(object):
                        found=self.cached_find_resource(n,filename)
                if found and not found in self.ban_includes:
                        self.nodes.append(found)
-                       if filename[-4:]!='.moc':
-                               self.addlines(found)
+                       self.addlines(found)
                else:
                        if not filename in self.names:
                                self.names.append(filename)
@@ -519,8 +524,7 @@ class c_parser(object):
                try:
                        self.parse_cache=bld.parse_cache
                except AttributeError:
-                       bld.parse_cache={}
-                       self.parse_cache=bld.parse_cache
+                       self.parse_cache=bld.parse_cache={}
                self.current_file=node
                self.addlines(node)
                if env['DEFINES']:
index 6a94573..b90b6e1 100644 (file)
@@ -75,12 +75,15 @@ class link_task(Task.Task):
                                if self.env.DEST_BINFMT=='pe':
                                        name=name+'-'+nums[0]
                                elif self.env.DEST_OS=='openbsd':
-                                       pattern='%s.%s.%s'%(pattern,nums[0],nums[1])
+                                       pattern='%s.%s'%(pattern,nums[0])
+                                       if len(nums)>=2:
+                                               pattern+='.%s'%nums[1]
                        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}'
+       chmod=Utils.O644
 def rm_tgt(cls):
        old=cls.run
        def wrap(self):
@@ -111,7 +114,7 @@ def apply_link(self):
        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)
+               self.install_task=self.bld.install_files(inst_to,self.link_task.outputs[:],env=self.env,chmod=self.link_task.chmod,task=self.link_task)
 @taskgen_method
 def use_rec(self,name,**kw):
        if name in self.tmp_use_not or name in self.tmp_use_seen:
@@ -139,6 +142,8 @@ def use_rec(self,name,**kw):
                        y.tmp_use_var='STLIB'
        p=self.tmp_use_prec
        for x in self.to_list(getattr(y,'use',[])):
+               if self.env["STLIB_"+x]:
+                       continue
                try:
                        p[x].append(name)
                except KeyError:
@@ -190,11 +195,11 @@ def process_use(self):
                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:
+                       if var=='LIB'or y.tmp_use_stlib or x in names:
                                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])
+                               self.env.append_unique(var+'PATH',[tmp_path])
                else:
                        if y.tmp_use_objects:
                                self.add_objects_from_tgen(y)
@@ -205,11 +210,11 @@ def process_use(self):
        for x in names:
                try:
                        y=self.bld.get_tgen_by_name(x)
-               except Exception:
+               except Errors.WafError:
                        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',[])):
+                       for k in self.to_list(getattr(y,'use',[])):
                                if not self.env['STLIB_'+k]and not k in self.uselib:
                                        self.uselib.append(k)
 @taskgen_method
@@ -238,16 +243,17 @@ def get_uselib_vars(self):
 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])
+       app=env.append_value
+       feature_uselib=self.features+self.to_list(getattr(self,'uselib',[]))
+       for var in _vars:
+               y=var.lower()
+               val=getattr(self,y,[])
+               if val:
+                       app(var,self.to_list(val))
+               for x in feature_uselib:
+                       val=env['%s_%s'%(var,x)]
+                       if val:
+                               app(var,val)
 @feature('cshlib','cxxshlib','fcshlib')
 @after_method('apply_link')
 def apply_implib(self):
@@ -271,14 +277,19 @@ def apply_implib(self):
                        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)
-re_vnum=re.compile('^([1-9]\\d*|0)[.]([1-9]\\d*|0)[.]([1-9]\\d*|0)$')
+       if getattr(self,'install_task',None):
+               try:
+                       inst_to=self.install_path_implib
+               except AttributeError:
+                       try:
+                               inst_to=self.install_path
+                       except AttributeError:
+                               inst_to='${IMPLIBDIR}'
+                               self.install_task.dest='${BINDIR}'
+                               if not self.env.IMPLIBDIR:
+                                       self.env.IMPLIBDIR=self.env.LIBDIR
+               self.implib_install_task=self.bld.install_files(inst_to,implib,env=self.env,chmod=self.link_task.chmod,task=self.link_task)
+re_vnum=re.compile('^([1-9]\\d*|0)([.]([1-9]\\d*|0)[.]([1-9]\\d*|0))?$')
 @feature('cshlib','cxxshlib','dshlib','fcshlib','vnum')
 @after_method('apply_link','propagate_uselib_vars')
 def apply_vnum(self):
@@ -300,7 +311,10 @@ def apply_vnum(self):
                v=self.env.SONAME_ST%name2
                self.env.append_value('LINKFLAGS',v.split())
        if self.env.DEST_OS!='openbsd':
-               self.create_task('vnum',node,[node.parent.find_or_declare(name2),node.parent.find_or_declare(name3)])
+               outs=[node.parent.find_or_declare(name3)]
+               if name2!=name3:
+                       outs.append(node.parent.find_or_declare(name2))
+               self.create_task('vnum',node,outs)
        if getattr(self,'install_task',None):
                self.install_task.hasrun=Task.SKIP_ME
                bld=self.bld
@@ -311,9 +325,12 @@ def apply_vnum(self):
                        self.vnum_install_task=(t1,)
                else:
                        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 name2!=name3:
+                               t2=bld.symlink_as(path+os.sep+name2,name3)
+                               self.vnum_install_task=(t1,t2,t3)
+                       else:
+                               self.vnum_install_task=(t1,t3)
        if'-dynamiclib'in self.env['LINKFLAGS']:
                try:
                        inst_to=self.install_path
@@ -327,6 +344,8 @@ class vnum(Task.Task):
        color='CYAN'
        quient=True
        ext_in=['.bin']
+       def keyword(self):
+               return'Symlinking'
        def run(self):
                for x in self.outputs:
                        path=x.abspath()
diff --git a/waflib/Tools/clang.py b/waflib/Tools/clang.py
new file mode 100644 (file)
index 0000000..1693256
--- /dev/null
@@ -0,0 +1,20 @@
+#! /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.Tools import ccroot,ar,gcc
+from waflib.Configure import conf
+@conf
+def find_clang(conf):
+       cc=conf.find_program('clang',var='CC')
+       conf.get_cc_version(cc,clang=True)
+       conf.env.CC_NAME='clang'
+def configure(conf):
+       conf.find_clang()
+       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/clangxx.py b/waflib/Tools/clangxx.py
new file mode 100644 (file)
index 0000000..7407af9
--- /dev/null
@@ -0,0 +1,20 @@
+#! /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.Tools import ccroot,ar,gxx
+from waflib.Configure import conf
+@conf
+def find_clangxx(conf):
+       cxx=conf.find_program('clang++',var='CXX')
+       conf.get_cc_version(cxx,clang=True)
+       conf.env.CXX_NAME='clang'
+def configure(conf):
+       conf.find_clangxx()
+       conf.find_ar()
+       conf.gxx_common_flags()
+       conf.gxx_modifier_platform()
+       conf.cxx_load_tools()
+       conf.cxx_add_flags()
+       conf.link_add_flags()
index 04504fa..eed826b 100644 (file)
@@ -2,17 +2,21 @@
 # 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
+import os,sys,imp,types,re
 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'],}
+c_compiler={'win32':['msvc','gcc','clang'],'cygwin':['gcc'],'darwin':['clang','gcc'],'aix':['xlc','gcc','clang'],'linux':['gcc','clang','icc'],'sunos':['suncc','gcc'],'irix':['gcc','irixcc'],'hpux':['gcc'],'gnu':['gcc','clang'],'java':['gcc','msvc','clang','icc'],'default':['gcc','clang'],}
+def default_compilers():
+       build_platform=Utils.unversioned_sys_platform()
+       possible_compiler_list=c_compiler.get(build_platform,c_compiler['default'])
+       return' '.join(possible_compiler_list)
 def configure(conf):
-       try:test_for_compiler=conf.options.check_c_compiler
+       try:test_for_compiler=conf.options.check_c_compiler or default_compilers()
        except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_c')")
-       for compiler in test_for_compiler.split():
+       for compiler in re.split('[ ,]+',test_for_compiler):
                conf.env.stash()
-               conf.start_msg('Checking for %r (c compiler)'%compiler)
+               conf.start_msg('Checking for %r (C compiler)'%compiler)
                try:
                        conf.load(compiler)
                except conf.errors.ConfigurationError ,e:
@@ -26,14 +30,11 @@ def configure(conf):
                                break
                        conf.end_msg(False)
        else:
-               conf.fatal('could not configure a c compiler!')
+               conf.fatal('could not configure a C compiler!')
 def options(opt):
+       test_for_compiler=default_compilers()
        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")
+       cc_compiler_opts=opt.add_option_group('Configuration options')
+       cc_compiler_opts.add_option('--check-c-compiler',default=None,help='list of C compilers to try [%s]'%test_for_compiler,dest="check_c_compiler")
        for x in test_for_compiler.split():
                opt.load('%s'%x)
index 14b7c7d..1990fb5 100644 (file)
@@ -2,17 +2,21 @@
 # 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
+import os,sys,imp,types,re
 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++']}
+cxx_compiler={'win32':['msvc','g++','clang++'],'cygwin':['g++'],'darwin':['clang++','g++'],'aix':['xlc++','g++','clang++'],'linux':['g++','clang++','icpc'],'sunos':['sunc++','g++'],'irix':['g++'],'hpux':['g++'],'gnu':['g++','clang++'],'java':['g++','msvc','clang++','icpc'],'default':['g++','clang++']}
+def default_compilers():
+       build_platform=Utils.unversioned_sys_platform()
+       possible_compiler_list=cxx_compiler.get(build_platform,cxx_compiler['default'])
+       return' '.join(possible_compiler_list)
 def configure(conf):
-       try:test_for_compiler=conf.options.check_cxx_compiler
+       try:test_for_compiler=conf.options.check_cxx_compiler or default_compilers()
        except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_cxx')")
-       for compiler in test_for_compiler.split():
+       for compiler in re.split('[ ,]+',test_for_compiler):
                conf.env.stash()
-               conf.start_msg('Checking for %r (c++ compiler)'%compiler)
+               conf.start_msg('Checking for %r (C++ compiler)'%compiler)
                try:
                        conf.load(compiler)
                except conf.errors.ConfigurationError ,e:
@@ -26,14 +30,11 @@ def configure(conf):
                                break
                        conf.end_msg(False)
        else:
-               conf.fatal('could not configure a c++ compiler!')
+               conf.fatal('could not configure a C++ compiler!')
 def options(opt):
+       test_for_compiler=default_compilers()
        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")
+       cxx_compiler_opts=opt.add_option_group('Configuration options')
+       cxx_compiler_opts.add_option('--check-cxx-compiler',default=None,help='list of C++ compilers to try [%s]'%test_for_compiler,dest="check_cxx_compiler")
        for x in test_for_compiler.split():
                opt.load('%s'%x)
index ee173e1..3bc1999 100644 (file)
@@ -2,12 +2,19 @@
 # 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
+import os,sys,imp,types,re
 from waflib import Utils,Configure,Options,Logs
+d_compiler={'default':['gdc','dmd','ldc2']}
+def default_compilers():
+       build_platform=Utils.unversioned_sys_platform()
+       possible_compiler_list=d_compiler.get(build_platform,d_compiler['default'])
+       return' '.join(possible_compiler_list)
 def configure(conf):
-       for compiler in conf.options.dcheck.split(','):
+       try:test_for_compiler=conf.options.check_d_compiler or default_compilers()
+       except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_d')")
+       for compiler in re.split('[ ,]+',test_for_compiler):
                conf.env.stash()
-               conf.start_msg('Checking for %r (d compiler)'%compiler)
+               conf.start_msg('Checking for %r (D compiler)'%compiler)
                try:
                        conf.load(compiler)
                except conf.errors.ConfigurationError ,e:
@@ -21,9 +28,10 @@ def configure(conf):
                                break
                        conf.end_msg(False)
        else:
-               conf.fatal('no suitable d compiler was found')
+               conf.fatal('could not configure a D compiler!')
 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)
+       test_for_compiler=default_compilers()
+       d_compiler_opts=opt.add_option_group('Configuration options')
+       d_compiler_opts.add_option('--check-d-compiler',default=None,help='list of D compilers to try [%s]'%test_for_compiler,dest='check_d_compiler')
+       for x in test_for_compiler.split():
+               opt.load('%s'%x)
index ec5d2ea..77f8481 100644 (file)
@@ -2,21 +2,20 @@
 # 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
+import os,sys,imp,types,re
 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 default_compilers():
+       build_platform=Utils.unversioned_sys_platform()
+       possible_compiler_list=fc_compiler.get(build_platform,fc_compiler['default'])
+       return' '.join(possible_compiler_list)
 def configure(conf):
-       try:test_for_compiler=conf.options.check_fc
+       try:test_for_compiler=conf.options.check_fortran_compiler or default_compilers()
        except AttributeError:conf.fatal("Add options(opt): opt.load('compiler_fc')")
-       for compiler in test_for_compiler.split():
+       for compiler in re.split('[ ,]+',test_for_compiler):
                conf.env.stash()
-               conf.start_msg('Checking for %r (fortran compiler)'%compiler)
+               conf.start_msg('Checking for %r (Fortran compiler)'%compiler)
                try:
                        conf.load(compiler)
                except conf.errors.ConfigurationError ,e:
@@ -30,14 +29,11 @@ def configure(conf):
                                break
                        conf.end_msg(False)
        else:
-               conf.fatal('could not configure a fortran compiler!')
+               conf.fatal('could not configure a Fortran compiler!')
 def options(opt):
+       test_for_compiler=default_compilers()
        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)
+       fortran_compiler_opts=opt.add_option_group('Configuration options')
+       fortran_compiler_opts.add_option('--check-fortran-compiler',default=None,help='list of Fortran compiler to try [%s]'%test_for_compiler,dest="check_fortran_compiler")
+       for x in test_for_compiler.split():
+               opt.load('%s'%x)
index b744a8d..8702739 100644 (file)
@@ -11,7 +11,7 @@ def cxx_hook(self,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}'
+       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[0].abspath()}'
        vars=['CXXDEPS']
        ext_in=['.h']
        scan=c_preproc.scan
index b6e3303..fb0999e 100644 (file)
@@ -8,9 +8,9 @@ from waflib.Configure import conf
 @conf
 def find_dmd(conf):
        conf.find_program(['dmd','dmd2','ldc'],var='D')
-       out=conf.cmd_and_log([conf.env.D,'--help'])
+       out=conf.cmd_and_log(conf.env.D+['--help'])
        if out.find("D Compiler v")==-1:
-               out=conf.cmd_and_log([conf.env.D,'-version'])
+               out=conf.cmd_and_log(conf.env.D+['-version'])
                if out.find("based on DMD v1.")==-1:
                        conf.fatal("detected compiler is not dmd/ldc")
 @conf
@@ -40,7 +40,7 @@ def common_flags_dmd(conf):
 def configure(conf):
        conf.find_dmd()
        if sys.platform=='win32':
-               out=conf.cmd_and_log([conf.env.D,'--help'])
+               out=conf.cmd_and_log(conf.env.D+['--help'])
                if out.find("D Compiler v2.")>-1:
                        conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead')
        conf.load('ar')
index 3589799..12785ab 100644 (file)
@@ -89,8 +89,6 @@ class fcprogram(ccroot.link_task):
 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:
index 580eac7..4b22879 100644 (file)
@@ -2,10 +2,10 @@
 # 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
+import re,os,sys,shlex
 from waflib.Configure import conf
-from waflib.TaskGen import feature,after_method,before_method
-from waflib import Build,Utils
+from waflib.TaskGen import feature,before_method
+from waflib import Utils
 FC_FRAGMENT='        program main\n        end     program main\n'
 FC_FRAGMENT2='        PROGRAM MAIN\n        END\n'
 @conf
@@ -115,7 +115,7 @@ def is_link_verbose(self,txt):
 @conf
 def check_fortran_verbose_flag(self,*k,**kw):
        self.start_msg('fortran link verbose flag')
-       for x in['-v','--verbose','-verbose','-V']:
+       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:
@@ -148,32 +148,32 @@ def parse_fortran_link(lines):
        return final_flags
 SPACE_OPTS=re.compile('^-[LRuYz]$')
 NOSPACE_OPTS=re.compile('^-[RL]')
+def _parse_flink_token(lexer,token,tmp_flags):
+       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
 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)
+               t=_parse_flink_token(lexer,t,tmp_flags)
        final_flags.extend(tmp_flags)
        return final_flags
 @conf
@@ -240,9 +240,9 @@ def link_main_routines_tg_method(self):
        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"]:
+       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'')
@@ -274,7 +274,7 @@ 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']:
+       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:
index 13f6207..838b2fc 100644 (file)
@@ -28,5 +28,5 @@ waflib.TaskGen.declare_chain(name='flex',rule=flexfun,ext_in='.l',decider=decide
 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):
+       if re.search(r"\\msys\\[0-9.]+\\bin\\flex.exe$",conf.env.FLEX[0]):
                conf.env.FLEX_MSYS=True
index 9bc331a..abc9ec1 100644 (file)
@@ -9,7 +9,6 @@ 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
index aca49ca..dfdbca2 100644 (file)
@@ -2,15 +2,15 @@
 # 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
index da966ec..8519ce4 100644 (file)
@@ -8,8 +8,8 @@ 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:
+       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):
index 854a93d..ce173b3 100644 (file)
@@ -9,7 +9,6 @@ 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
index 1d75510..eeca335 100644 (file)
@@ -3,8 +3,9 @@
 # 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
+from waflib import Context,Task,Utils,Options,Errors,Logs
+from waflib.TaskGen import taskgen_method,before_method,after_method,feature,extension
+from waflib.Configure import conf
 @taskgen_method
 def add_marshal_file(self,filename,prefix):
        if not hasattr(self,'marshal_list'):
@@ -98,14 +99,6 @@ def add_settings_enums(self,namespace,filename_list):
        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=[]
@@ -136,7 +129,7 @@ def process_settings(self):
                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')
+               target_node=schema_node.change_ext('.xml.valid')
                schema_task.set_outputs(target_node)
                schema_task.env['GLIB_VALIDATE_SCHEMA_OUTPUT']=target_node.abspath()
        def compile_schemas_callback(bld):
@@ -155,10 +148,69 @@ def process_settings(self):
 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):
+@extension('.gresource.xml')
+def process_gresource_source(self,node):
+       if not self.env['GLIB_COMPILE_RESOURCES']:
+               raise Errors.WafError("Unable to process GResource file - glib-compile-resources was not found during configure")
+       if'gresource'in self.features:
+               return
+       h_node=node.change_ext('_xml.h')
+       c_node=node.change_ext('_xml.c')
+       self.create_task('glib_gresource_source',node,[h_node,c_node])
+       self.source.append(c_node)
+@feature('gresource')
+def process_gresource_bundle(self):
+       for i in self.to_list(self.source):
+               node=self.path.find_resource(i)
+               task=self.create_task('glib_gresource_bundle',node,node.change_ext(''))
+               inst_to=getattr(self,'install_path',None)
+               if inst_to:
+                       self.bld.install_files(inst_to,task.outputs)
+class glib_gresource_base(Task.Task):
+       color='BLUE'
+       base_cmd='${GLIB_COMPILE_RESOURCES} --sourcedir=${SRC[0].parent.srcpath()} --sourcedir=${SRC[0].bld_dir()}'
+       def scan(self):
+               bld=self.generator.bld
+               kw={}
+               try:
+                       if not kw.get('cwd',None):
+                               kw['cwd']=bld.cwd
+               except AttributeError:
+                       bld.cwd=kw['cwd']=bld.variant_dir
+               kw['quiet']=Context.BOTH
+               cmd=Utils.subst_vars('${GLIB_COMPILE_RESOURCES} --sourcedir=%s --sourcedir=%s --generate-dependencies %s'%(self.inputs[0].parent.srcpath(),self.inputs[0].bld_dir(),self.inputs[0].bldpath()),self.env)
+               output=bld.cmd_and_log(cmd,**kw)
+               nodes=[]
+               names=[]
+               for dep in output.splitlines():
+                       if dep:
+                               node=bld.bldnode.find_node(dep)
+                               if node:
+                                       nodes.append(node)
+                               else:
+                                       names.append(dep)
+               return(nodes,names)
+class glib_gresource_source(glib_gresource_base):
+       vars=['GLIB_COMPILE_RESOURCES']
+       fun_h=Task.compile_fun_shell(glib_gresource_base.base_cmd+' --target=${TGT[0].abspath()} --generate-header ${SRC}')
+       fun_c=Task.compile_fun_shell(glib_gresource_base.base_cmd+' --target=${TGT[1].abspath()} --generate-source ${SRC}')
+       ext_out=['.h']
+       def run(self):
+               return self.fun_h[0](self)or self.fun_c[0](self)
+class glib_gresource_bundle(glib_gresource_base):
+       run_str=glib_gresource_base.base_cmd+' --target=${TGT} ${SRC}'
+       shell=True
+@conf
+def find_glib_genmarshal(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)
+@conf
+def find_glib_mkenums(conf):
+       if not conf.env.PERL:
+               conf.find_program('perl',var='PERL')
+       conf.find_program('glib-mkenums',interpreter='PERL',var='GLIB_MKENUMS')
+@conf
+def find_glib_compile_schemas(conf):
+       conf.find_program('glib-compile-schemas',var='GLIB_COMPILE_SCHEMAS')
        def getstr(varname):
                return getattr(Options.options,varname,getattr(conf.env,varname,''))
        gsettingsschemadir=getstr('GSETTINGSSCHEMADIR')
@@ -169,5 +221,14 @@ def configure(conf):
                        datadir=os.path.join(prefix,'share')
                gsettingsschemadir=os.path.join(datadir,'glib-2.0','schemas')
        conf.env['GSETTINGSSCHEMADIR']=gsettingsschemadir
+@conf
+def find_glib_compile_resources(conf):
+       conf.find_program('glib-compile-resources',var='GLIB_COMPILE_RESOURCES')
+def configure(conf):
+       conf.find_glib_genmarshal()
+       conf.find_glib_mkenums()
+       conf.find_glib_compile_schemas(mandatory=False)
+       conf.find_glib_compile_resources(mandatory=False)
 def options(opt):
-       opt.add_option('--gsettingsschemadir',help='GSettings schema location [Default: ${datadir}/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR')
+       gr=opt.add_option_group('Installation directories')
+       gr.add_option('--gsettingsschemadir',help='GSettings schema location [DATADIR/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR')
index 9c8a304..08eafd4 100644 (file)
@@ -2,29 +2,30 @@
 # encoding: utf-8
 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
 
-import os
+import os,re
 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, 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
+gnuopts='''
+bindir, user commands, ${EXEC_PREFIX}/bin
+sbindir, system binaries, ${EXEC_PREFIX}/sbin
+libexecdir, program-specific binaries, ${EXEC_PREFIX}/libexec
+sysconfdir, host-specific configuration, ${PREFIX}/etc
+sharedstatedir, architecture-independent variable data, ${PREFIX}/com
+localstatedir, variable data, ${PREFIX}/var
+libdir, object code libraries, ${EXEC_PREFIX}/lib%s
+includedir, header files, ${PREFIX}/include
+oldincludedir, header files for non-GCC compilers, /usr/include
+datarootdir, architecture-independent data root, ${PREFIX}/share
+datadir, architecture-independent data, ${DATAROOTDIR}
+infodir, GNU "info" documentation, ${DATAROOTDIR}/info
 localedir, locale-dependent data, ${DATAROOTDIR}/locale
-mandir, man documentation, ${DATAROOTDIR}/man
+mandir, manual pages, ${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]
+htmldir, HTML documentation, ${DOCDIR}
+dvidir, DVI documentation, ${DOCDIR}
+pdfdir, PDF documentation, ${DOCDIR}
+psdir, PostScript documentation, ${DOCDIR}
+'''%Utils.lib64()
+_options=[x.split(', ')for x in gnuopts.splitlines()if x]
 def configure(conf):
        def get_param(varname,default):
                return getattr(Options.options,varname,'')or default
@@ -45,10 +46,10 @@ def configure(conf):
                                except TypeError:
                                        complete=False
        if not complete:
-               lst=[name for name,_,_ in _options if not env[name.upper()]]
+               lst=[x for x,_,_ in _options if not env[x.upper()]]
                raise conf.errors.WafError('Variable substitution failure %r'%lst)
 def options(opt):
-       inst_dir=opt.add_option_group('Installation directories','By default, "waf install" will put the files in\
+       inst_dir=opt.add_option_group('Installation prefix','By default, "waf install" will put the files in\
  "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\
  than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"')
        for k in('--prefix','--destdir'):
@@ -56,10 +57,10 @@ def options(opt):
                if option:
                        opt.parser.remove_option(k)
                        inst_dir.add_option(option)
-       inst_dir.add_option('--exec-prefix',help='installation prefix [Default: ${PREFIX}]',default='',dest='EXEC_PREFIX')
-       dirs_options=opt.add_option_group('Pre-defined installation directories','')
+       inst_dir.add_option('--exec-prefix',help='installation prefix for binaries [PREFIX]',default='',dest='EXEC_PREFIX')
+       dirs_options=opt.add_option_group('Installation directories')
        for name,help,default in _options:
                option_name='--'+name
                str_default=default
-               str_help='%s [Default: %s]'%(help,str_default)
+               str_help='%s [%s]'%(help,re.sub(r'\$\{([^}]+)\}',r'\1',str_default))
                dirs_options.add_option(option_name,help=str_help,default='',dest=name.upper())
index 475f7fd..375c9d2 100644 (file)
@@ -2,15 +2,15 @@
 # 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_gxx(conf):
        cxx=conf.find_program(['g++','c++'],var='CXX')
-       cxx=conf.cmd_to_list(cxx)
        conf.get_cc_version(cxx,gcc=True)
        conf.env.CXX_NAME='gcc'
-       conf.env.CXX=cxx
 @conf
 def gxx_common_flags(conf):
        v=conf.env
index 7c75e18..d08c7f4 100644 (file)
@@ -9,17 +9,9 @@ from waflib.Configure import conf
 def find_icc(conf):
        if sys.platform=='cygwin':
                conf.fatal('The Intel compiler does not work on Cygwin')
-       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('icc',var='CC')
-       if not cc:cc=conf.find_program('ICL',var='CC')
-       if not cc:conf.fatal('Intel C Compiler (icc) was not found')
-       cc=conf.cmd_to_list(cc)
+       cc=conf.find_program(['icc','ICL'],var='CC')
        conf.get_cc_version(cc,icc=True)
-       v['CC']=cc
-       v['CC_NAME']='icc'
+       conf.env.CC_NAME='icc'
 def configure(conf):
        conf.find_icc()
        conf.find_ar()
index 14a5325..e071e40 100644 (file)
@@ -9,16 +9,9 @@ from waflib.Configure import conf
 def find_icpc(conf):
        if sys.platform=='cygwin':
                conf.fatal('The Intel compiler does not work on Cygwin')
-       v=conf.env
-       cxx=None
-       if v['CXX']:cxx=v['CXX']
-       elif'CXX'in conf.environ:cxx=conf.environ['CXX']
-       if not cxx:cxx=conf.find_program('icpc',var='CXX')
-       if not cxx:conf.fatal('Intel C++ Compiler (icpc) was not found')
-       cxx=conf.cmd_to_list(cxx)
+       cxx=conf.find_program('icpc',var='CXX')
        conf.get_cc_version(cxx,icc=True)
-       v['CXX']=cxx
-       v['CXX_NAME']='icc'
+       conf.env.CXX_NAME='icc'
 def configure(conf):
        conf.find_icpc()
        conf.find_ar()
index a9f2528..b0bbf28 100644 (file)
@@ -9,7 +9,6 @@ from waflib.Configure import conf
 @conf
 def find_ifort(conf):
        fc=conf.find_program('ifort',var='FC')
-       fc=conf.cmd_to_list(fc)
        conf.get_ifort_version(fc)
        conf.env.FC_NAME='IFORT'
 @conf
@@ -29,8 +28,11 @@ def ifort_modifier_platform(conf):
                ifort_modifier_func()
 @conf
 def get_ifort_version(conf,fc):
-       version_re=re.compile(r"ifort\s*\(IFORT\)\s*(?P<major>\d*)\.(?P<minor>\d*)",re.I).search
-       cmd=fc+['--version']
+       version_re=re.compile(r"Intel[\sa-zA-Z()0-9,-]*Version\s*(?P<major>\d*)\.(?P<minor>\d*)",re.I).search
+       if Utils.is_win32:
+               cmd=fc
+       else:
+               cmd=fc+['-logo']
        out,err=fc_config.getoutput(conf,cmd,stdin=False)
        if out:
                match=version_re(out)
index d558674..b8a6318 100644 (file)
@@ -3,40 +3,56 @@
 # 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
+from waflib import Configure,Context,TaskGen,Task,Utils,Runner,Options,Build,Logs
 import waflib.Tools.ccroot
-from waflib.TaskGen import feature,before_method
+from waflib.TaskGen import feature,before_method,taskgen_method
 from waflib.Logs import error
+from waflib.Configure import conf
+_style_flags={'ba':'-b','desktop':'-d','keys':'-k','quoted':'--quoted-style','quotedxml':'--quotedxml-style','rfc822deb':'-r','schemas':'-s','xml':'-x',}
+@taskgen_method
+def ensure_localedir(self):
+       if not self.env.LOCALEDIR:
+               if self.env.DATAROOTDIR:
+                       self.env.LOCALEDIR=os.path.join(self.env.DATAROOTDIR,'locale')
+               else:
+                       self.env.LOCALEDIR=os.path.join(self.env.PREFIX,'share','locale')
 @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'
+       self.ensure_localedir()
+       podir=getattr(self,'podir','.')
+       podirnode=self.path.find_dir(podir)
+       if not podirnode:
+               error("could not find the podir %r"%podir)
+               return
+       cache=getattr(self,'intlcache','.intlcache')
+       self.env.INTLCACHE=[os.path.join(str(self.path.get_bld()),podir,cache)]
+       self.env.INTLPODIR=podirnode.bldpath()
+       self.env.append_value('INTLFLAGS',getattr(self,'flags',self.env.INTLFLAGS_DEFAULT))
+       if'-c'in self.env.INTLFLAGS:
+               self.bld.fatal('Redundant -c flag in intltool task %r'%self)
+       style=getattr(self,'style',None)
+       if style:
+               try:
+                       style_flag=_style_flags[style]
+               except KeyError:
+                       self.bld.fatal('intltool_in style "%s" is not valid'%style)
+               self.env.append_unique('INTLFLAGS',[style_flag])
        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}')
+               inst=getattr(self,'install_path',None)
                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','')
+       self.ensure_localedir()
+       appname=getattr(self,'appname',getattr(Context.g_module,Context.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:
@@ -62,16 +78,20 @@ class po(Task.Task):
        run_str='${MSGFMT} -o ${TGT} ${SRC}'
        color='BLUE'
 class intltool(Task.Task):
-       run_str='${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}'
+       run_str='${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}'
        color='BLUE'
-def configure(conf):
+@conf
+def find_msgfmt(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('\\','\\\\'))
+@conf
+def find_intltool_merge(conf):
+       if not conf.env.PERL:
+               conf.find_program('perl',var='PERL')
+       conf.env.INTLCACHE_ST='--cache=%s'
+       conf.env.INTLFLAGS_DEFAULT=['-q','-u']
+       conf.find_program('intltool-merge',interpreter='PERL',var='INTLTOOL')
+def configure(conf):
+       conf.find_msgfmt()
+       conf.find_intltool_merge()
        if conf.env.CC or conf.env.CXX:
                conf.check(header_name='locale.h')
index 8dbdfca..24e9822 100644 (file)
@@ -14,7 +14,6 @@ def find_irixcc(conf):
        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:
index 15f128c..44c2b60 100644 (file)
@@ -157,7 +157,6 @@ class jar_create(Task.Task):
                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:
@@ -253,7 +252,6 @@ def configure(self):
                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')
index cd51f5f..ee8ce48 100644 (file)
@@ -19,7 +19,7 @@ class msgfmt(Task.Task):
        run_str='${MSGFMT} ${SRC} -o ${TGT}'
 def configure(self):
        kdeconfig=self.find_program('kde4-config')
-       prefix=self.cmd_and_log('%s --prefix'%kdeconfig).strip()
+       prefix=self.cmd_and_log(kdeconfig+['--prefix']).strip()
        fname='%s/share/apps/cmake/modules/KDELibsDependencies.cmake'%prefix
        try:os.stat(fname)
        except OSError:
@@ -28,7 +28,7 @@ def configure(self):
                except OSError:self.fatal('could not open %s'%fname)
        try:
                txt=Utils.readf(fname)
-       except(OSError,IOError):
+       except EnvironmentError:
                self.fatal('could not read %s'%fname)
        txt=txt.replace('\\\n','\n')
        fu=re.compile('#(.*)\n')
index 25b99e5..d98f26e 100644 (file)
@@ -8,7 +8,7 @@ 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'])
+       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
index dd62e40..82d7d56 100644 (file)
@@ -59,7 +59,11 @@ def setup_msvc(conf,versions,arch=False):
 @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')
+       try:
+               conf.msvc_cnt+=1
+       except AttributeError:
+               conf.msvc_cnt=1
+       batfile=conf.bldnode.make_node('waf-print-msvc-%d.bat'%conf.msvc_cnt)
        batfile.write("""@echo off
 set INCLUDE=
 set LIB=
@@ -68,7 +72,7 @@ echo PATH=%%PATH%%
 echo INCLUDE=%%INCLUDE%%
 echo LIB=%%LIB%%;%%LIBPATH%%
 """%(vcvars,target))
-       sout=conf.cmd_and_log(['cmd','/E:on','/V:on','/C',batfile.abspath()])
+       sout=conf.cmd_and_log(['cmd.exe','/E:on','/V:on','/C',batfile.abspath()])
        lines=sout.splitlines()
        if not lines[0]:
                lines.pop(0)
@@ -87,7 +91,6 @@ echo LIB=%%LIB%%;%%LIBPATH%%
        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:
@@ -175,7 +178,7 @@ def gather_wince_supported_platforms():
 def gather_msvc_detected_versions():
        version_pattern=re.compile('^(\d\d?\.\d\d?)(Exp)?$')
        detected_versions=[]
-       for vcver,vcvar in[('VCExpress','Exp'),('VisualStudio','')]:
+       for vcver,vcvar in(('VCExpress','Exp'),('VisualStudio','')):
                try:
                        prefix='SOFTWARE\\Wow6432node\\Microsoft\\'+vcver
                        all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix)
@@ -372,7 +375,7 @@ def gather_intel_composer_versions(conf,versions):
                                        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')
-                                       for vscomntool in['VS110COMNTOOLS','VS100COMNTOOLS']:
+                                       for vscomntool in('VS110COMNTOOLS','VS100COMNTOOLS'):
                                                if vscomntool in os.environ:
                                                        vs_express_path=os.environ[vscomntool]+r'..\IDE\VSWinExpress.exe'
                                                        dev_env_path=os.environ[vscomntool]+r'..\IDE\devenv.exe'
@@ -528,7 +531,6 @@ def find_msvc(conf):
        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):
@@ -618,10 +620,8 @@ def apply_flags_msvc(self):
                        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
+                               if getattr(self,'install_task',None):
+                                       self.pdb_install_task=self.bld.install_files(self.install_task.dest,pdbnode,env=self.env)
                                break
 @feature('cprogram','cshlib','cxxprogram','cxxshlib')
 @after_method('apply_link')
@@ -651,13 +651,11 @@ def exec_mf(self):
        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=[]+mtool
        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)
+       return self.exec_command(lst)
 def quote_response_command(self,flag):
        if flag.find(' ')>-1:
                for x in('/LIBPATH:','/IMPLIB:','/OUT:','/I'):
@@ -725,6 +723,8 @@ def wrap_class(class_name):
        derived_class.quote_response_command=quote_response_command
        derived_class.exec_command_msvc=exec_command_msvc
        derived_class.exec_mf=exec_mf
+       if hasattr(cls,'hcode'):
+               derived_class.hcode=cls.hcode
        return derived_class
 for k in'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split():
        wrap_class(k)
index 8b6c2f8..87b6d93 100644 (file)
@@ -36,7 +36,7 @@ def check_perl_version(self,minver=None):
                self.end_msg("Perl not found",color="YELLOW")
                return False
        self.env['PERL']=perl
-       version=self.cmd_and_log([perl,"-e",'printf \"%vd\", $^V'])
+       version=self.cmd_and_log(self.env.PERL+["-e",'printf \"%vd\", $^V'])
        if not version:
                res=False
                version="Unknown"
@@ -48,7 +48,7 @@ def check_perl_version(self,minver=None):
        return res
 @conf
 def check_perl_module(self,module):
-       cmd=[self.env['PERL'],'-e','use %s'%module]
+       cmd=self.env.PERL+['-e','use %s'%module]
        self.start_msg('perl module %s'%module)
        try:
                r=self.cmd_and_log(cmd)
@@ -63,18 +63,22 @@ def check_perl_ext_devel(self):
        perl=env.PERL
        if not perl:
                self.fatal('find perl first')
-       def read_out(cmd):
-               return Utils.to_list(self.cmd_and_log(perl+cmd))
-       env['LINKFLAGS_PERLEXT']=read_out(" -MConfig -e'print $Config{lddlflags}'")
-       env['INCLUDES_PERLEXT']=read_out(" -MConfig -e'print \"$Config{archlib}/CORE\"'")
-       env['CFLAGS_PERLEXT']=read_out(" -MConfig -e'print \"$Config{ccflags} $Config{cccdlflags}\"'")
-       env['XSUBPP']=read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}\"'")
-       env['EXTUTILS_TYPEMAP']=read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/typemap\"'")
+       def cmd_perl_config(s):
+               return perl+['-MConfig','-e','print \"%s\"'%s]
+       def cfg_str(cfg):
+               return self.cmd_and_log(cmd_perl_config(cfg))
+       def cfg_lst(cfg):
+               return Utils.to_list(cfg_str(cfg))
+       env['LINKFLAGS_PERLEXT']=cfg_lst('$Config{lddlflags}')
+       env['INCLUDES_PERLEXT']=cfg_lst('$Config{archlib}/CORE')
+       env['CFLAGS_PERLEXT']=cfg_lst('$Config{ccflags} $Config{cccdlflags}')
+       env['XSUBPP']=cfg_lst('$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}')
+       env['EXTUTILS_TYPEMAP']=cfg_lst('$Config{privlib}/ExtUtils/typemap')
        if not getattr(Options.options,'perlarchdir',None):
-               env['ARCHDIR_PERL']=self.cmd_and_log(perl+" -MConfig -e'print $Config{sitearch}'")
+               env['ARCHDIR_PERL']=cfg_str('$Config{sitearch}')
        else:
                env['ARCHDIR_PERL']=getattr(Options.options,'perlarchdir')
-       env['perlext_PATTERN']='%s.'+self.cmd_and_log(perl+" -MConfig -e'print $Config{dlext}'")
+       env['perlext_PATTERN']='%s.'+cfg_str('$Config{dlext}')
 def options(opt):
        opt.add_option('--with-perl-binary',type='string',dest='perlbinary',help='Specify alternate perl binary',default=None)
        opt.add_option('--with-perl-archdir',type='string',dest='perlarchdir',help='Specify directory where to install arch specific files',default=None)
index 56c0d7d..3cbaca1 100644 (file)
@@ -3,7 +3,7 @@
 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
 
 import os,sys
-from waflib import Utils,Options,Errors,Logs
+from waflib import Utils,Options,Errors,Logs,Task,Node
 from waflib.TaskGen import extension,before_method,after_method,feature
 from waflib.Configure import conf
 FRAG='''
@@ -26,64 +26,66 @@ int main(int argc, char **argv)
 '''
 INST='''
 import sys, py_compile
-py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3])
+py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True)
 '''
 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))
+@before_method('process_source')
 @feature('py')
 def feature_py(self):
-       pass
+       self.install_path=getattr(self,'install_path','${PYTHONDIR}')
+       install_from=getattr(self,'install_from',None)
+       if install_from and not isinstance(install_from,Node.Node):
+               install_from=self.path.find_dir(install_from)
+       self.install_from=install_from
+       ver=self.env.PYTHON_VERSION
+       if not ver:
+               self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version')
+       if int(ver.replace('.',''))>31:
+               self.install_32=True
+@extension('.py')
+def process_py(self,node):
+       assert(node.get_bld_sig())
+       assert(getattr(self,'install_path')),'add features="py"'
+       if self.install_path:
+               if self.install_from:
+                       self.bld.install_files(self.install_path,[node],cwd=self.install_from,relative_trick=True)
+               else:
+                       self.bld.install_files(self.install_path,[node],relative_trick=True)
+       lst=[]
+       if self.env.PYC:
+               lst.append('pyc')
+       if self.env.PYO:
+               lst.append('pyo')
+       if self.install_path:
+               if self.install_from:
+                       pyd=Utils.subst_vars("%s/%s"%(self.install_path,node.path_from(self.install_from)),self.env)
+               else:
+                       pyd=Utils.subst_vars("%s/%s"%(self.install_path,node.path_from(self.path)),self.env)
+       else:
+               pyd=node.abspath()
+       for ext in lst:
+               if self.env.PYTAG:
+                       name=node.name[:-3]
+                       pyobj=node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s"%(name,self.env.PYTAG,ext))
+                       pyobj.parent.mkdir()
+               else:
+                       pyobj=node.change_ext(".%s"%ext)
+               tsk=self.create_task(ext,node,pyobj)
+               tsk.pyd=pyd
+               if self.install_path:
+                       self.bld.install_files(os.path.dirname(pyd),pyobj,cwd=node.parent.get_bld(),relative_trick=True)
+class pyc(Task.Task):
+       color='PINK'
+       def run(self):
+               cmd=[Utils.subst_vars('${PYTHON}',self.env),'-c',INST,self.inputs[0].abspath(),self.outputs[0].abspath(),self.pyd]
+               ret=self.generator.bld.exec_command(cmd)
+               return ret
+class pyo(Task.Task):
+       color='PINK'
+       def run(self):
+               cmd=[Utils.subst_vars('${PYTHON}',self.env),Utils.subst_vars('${PYFLAGS_OPT}',self.env),'-c',INST,self.inputs[0].abspath(),self.outputs[0].abspath(),self.pyd]
+               ret=self.generator.bld.exec_command(cmd)
+               return ret
 @feature('pyext')
 @before_method('propagate_uselib_vars','apply_link')
 @after_method('apply_bundle')
@@ -131,7 +133,7 @@ def get_python_variables(self,variables,imports=None):
                self.fatal('The distutils module is unusable: install "python-devel"?')
        self.to_log(out)
        return_values=[]
-       for s in out.split('\n'):
+       for s in out.splitlines():
                s=s.strip()
                if not s:
                        continue
@@ -144,33 +146,82 @@ def get_python_variables(self,variables,imports=None):
                else:break
        return return_values
 @conf
-def check_python_headers(conf):
+def python_cross_compile(self,features='pyembed pyext'):
+       features=Utils.to_list(features)
+       if not('PYTHON_LDFLAGS'in self.environ or'PYTHON_PYEXT_LDFLAGS'in self.environ or'PYTHON_PYEMBED_LDFLAGS'in self.environ):
+               return False
+       for x in'PYTHON_VERSION PYTAG pyext_PATTERN'.split():
+               if not x in self.environ:
+                       self.fatal('Please set %s in the os environment'%x)
+               else:
+                       self.env[x]=self.environ[x]
+       xx=self.env.CXX_NAME and'cxx'or'c'
+       if'pyext'in features:
+               flags=self.environ.get('PYTHON_PYEXT_LDFLAGS',self.environ.get('PYTHON_LDFLAGS',None))
+               if flags is None:
+                       self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required')
+               else:
+                       self.parse_flags(flags,'PYEXT')
+               self.check(header_name='Python.h',define_name='HAVE_PYEXT',msg='Testing pyext configuration',features='%s %sshlib pyext'%(xx,xx),fragment=FRAG,errmsg='Could not build python extensions')
+       if'pyembed'in features:
+               flags=self.environ.get('PYTHON_PYEMBED_LDFLAGS',self.environ.get('PYTHON_LDFLAGS',None))
+               if flags is None:
+                       self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required')
+               else:
+                       self.parse_flags(flags,'PYEMBED')
+               self.check(header_name='Python.h',define_name='HAVE_PYEMBED',msg='Testing pyembed configuration',fragment=FRAG,errmsg='Could not build a python embedded interpreter',features='%s %sprogram pyembed'%(xx,xx))
+       return True
+@conf
+def check_python_headers(conf,features='pyembed pyext'):
+       features=Utils.to_list(features)
+       assert('pyembed'in features)or('pyext'in features),"check_python_headers features must include 'pyembed' and/or 'pyext'"
        env=conf.env
        if not env['CC_NAME']and not env['CXX_NAME']:
                conf.fatal('load a compiler first (gcc, g++, ..)')
+       if conf.python_cross_compile(features):
+               return
        if not env['PYTHON_VERSION']:
                conf.check_python_version()
-       pybin=conf.env.PYTHON
+       pybin=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()
+       v='prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.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)))
+       conf.to_log("Configuration returned from %r:\n%s\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[x]=conf.environ[x]=dct[x]
        env['pyext_PATTERN']='%s'+dct['SO']
+       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',msg="python-config",mandatory=False)
+       if env.PYTHON_CONFIG:
+               all_flags=[['--cflags','--libs','--ldflags']]
+               if sys.hexversion<0x2070000:
+                       all_flags=[[k]for k in all_flags[0]]
+               xx=env.CXX_NAME and'cxx'or'c'
+               if'pyembed'in features:
+                       for flags in all_flags:
+                               conf.check_cfg(msg='Asking python-config for pyembed %r flags'%' '.join(flags),path=env.PYTHON_CONFIG,package='',uselib_store='PYEMBED',args=flags)
+                       conf.check(header_name='Python.h',define_name='HAVE_PYEMBED',msg='Getting pyembed flags from python-config',fragment=FRAG,errmsg='Could not build a python embedded interpreter',features='%s %sprogram pyembed'%(xx,xx))
+               if'pyext'in features:
+                       for flags in all_flags:
+                               conf.check_cfg(msg='Asking python-config for pyext %r flags'%' '.join(flags),path=env.PYTHON_CONFIG,package='',uselib_store='PYEXT',args=flags)
+                       conf.check(header_name='Python.h',define_name='HAVE_PYEXT',msg='Getting pyext flags from python-config',features='%s %sshlib pyext'%(xx,xx),fragment=FRAG,errmsg='Could not build python extensions')
+               conf.define('HAVE_PYTHON_H',1)
+               return
        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']+'m','python'+env['PYTHON_VERSION'].replace('.','')):
+       if not dct["LDVERSION"]:
+               dct["LDVERSION"]=env['PYTHON_VERSION']
+       for name in('python'+dct['LDVERSION'],'python'+env['PYTHON_VERSION']+'m','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)
@@ -194,25 +245,12 @@ def check_python_headers(conf):
                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']):
+       if Utils.is_win32 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']]
+       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'])
@@ -226,17 +264,7 @@ def check_python_headers(conf):
                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'
-               flags=['--cflags','--libs','--ldflags']
-               for f in flags:
-                       conf.check_cfg(msg='Asking python-config for pyembed %s flags'%f,path=conf.env.PYTHON_CONFIG,package='',uselib_store='PYEMBED',args=[f])
-               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))
-               for f in flags:
-                       conf.check_cfg(msg='Asking python-config for pyext %s flags'%f,path=conf.env.PYTHON_CONFIG,package='',uselib_store='PYEXT',args=[f])
-               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.check(header_name='Python.h',define_name='HAVE_PYTHON_H',uselib='PYEMBED',fragment=FRAG,errmsg='Distutils not installed? Broken python installation? Get python-config now!')
 @conf
 def check_python_version(conf,minver=None):
        assert minver is None or isinstance(minver,tuple)
@@ -252,23 +280,27 @@ def check_python_version(conf,minver=None):
        if result:
                pyver='.'.join([str(x)for x in pyver_tuple[:2]])
                conf.env['PYTHON_VERSION']=pyver
-               if'PYTHONDIR'in conf.environ:
+               if'PYTHONDIR'in conf.env:
+                       pydir=conf.env['PYTHONDIR']
+               elif'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']])
+                               (python_LIBDEST,pydir)=conf.get_python_variables(["get_config_var('LIBDEST') or ''","get_python_lib(standard_lib=0) or ''"])
                        else:
                                python_LIBDEST=None
-                               (pydir,)=conf.get_python_variables(["get_python_lib(standard_lib=0, prefix=%r) or ''"%conf.env['PREFIX']])
+                               (pydir,)=conf.get_python_variables(["get_python_lib(standard_lib=0) or ''"])
                        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:
+               if'PYTHONARCHDIR'in conf.env:
+                       pyarchdir=conf.env['PYTHONARCHDIR']
+               elif'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']])
+                       (pyarchdir,)=conf.get_python_variables(["get_python_lib(plat_specific=1, standard_lib=0) or ''"])
                        if not pyarchdir:
                                pyarchdir=pydir
                if hasattr(conf,'define'):
@@ -288,13 +320,13 @@ PYTHON_MODULE_TEMPLATE='''
 import %s as current_module
 version = getattr(current_module, '__version__', None)
 if version is not None:
-    print(str(version))
+       print(str(version))
 else:
-    print('unknown version')
+       print('unknown version')
 '''
 @conf
 def check_python_module(conf,module_name,condition=''):
-       msg='Python module %s'%module_name
+       msg="Checking for python module '%s'"%module_name
        if condition:
                msg='%s (%s)'%(msg,condition)
        conf.start_msg(msg)
@@ -324,20 +356,25 @@ def check_python_module(conf,module_name,condition=''):
                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['PYTHON']=Options.options.python or os.environ.get('PYTHON',sys.executable)
+       if Options.options.pythondir:
+               v['PYTHONDIR']=Options.options.pythondir
+       if Options.options.pythonarchdir:
+               v['PYTHONARCHDIR']=Options.options.pythonarchdir
+       conf.find_program('python',var='PYTHON')
        v['PYFLAGS']=''
        v['PYFLAGS_OPT']='-O'
        v['PYC']=getattr(Options.options,'pyc',1)
        v['PYO']=getattr(Options.options,'pyo',1)
+       try:
+               v.PYTAG=conf.cmd_and_log(conf.env.PYTHON+['-c',"import imp;print(imp.get_tag())"]).strip()
+       except Errors.WafError:
+               pass
 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')
+       pyopt=opt.add_option_group("Python Options")
+       pyopt.add_option('--nopyc',dest='pyc',action='store_false',default=1,help='Do not install bytecode compiled .pyc files (configuration) [Default:install]')
+       pyopt.add_option('--nopyo',dest='pyo',action='store_false',default=1,help='Do not install optimised compiled .pyo files (configuration) [Default:install]')
+       pyopt.add_option('--python',dest="python",help='python binary to be used [Default: %s]'%sys.executable)
+       pyopt.add_option('--pythondir',dest='pythondir',help='Installation path for python modules (py, platform-independent .py and .pyc files)')
+       pyopt.add_option('--pythonarchdir',dest='pythonarchdir',help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)')
index b4328e7..49cdf93 100644 (file)
@@ -11,8 +11,8 @@ except ImportError:
 else:
        has_xml=True
 import os,sys
-from waflib.Tools import c_preproc,cxx
-from waflib import Task,Utils,Options,Errors
+from waflib.Tools import cxx
+from waflib import Task,Utils,Options,Errors,Context
 from waflib.TaskGen import feature,after_method,extension
 from waflib.Configure import conf
 from waflib import Logs
@@ -25,17 +25,6 @@ class qxx(Task.classes['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)
-               lst=[]
-               for x in nodes:
-                       if x.name.endswith('.moc'):
-                               s=x.path_from(self.inputs[0].parent.get_bld())
-                               if s not in names:
-                                       names.append(s)
-                       else:
-                               lst.append(x)
-               return(lst,names)
        def runnable_status(self):
                if self.moc_done:
                        return Task.Task.runnable_status(self)
@@ -56,10 +45,20 @@ class qxx(Task.classes['cxx']):
                        tsk=moc_cache[h_node]=Task.classes['moc'](env=self.env,generator=self.generator)
                        tsk.set_inputs(h_node)
                        tsk.set_outputs(m_node)
+                       if self.generator:
+                               self.generator.tasks.append(tsk)
                        gen=self.generator.bld.producer
                        gen.outstanding.insert(0,tsk)
                        gen.total+=1
                        return tsk
+       def moc_h_ext(self):
+               try:
+                       ext=Options.options.qt_header_ext.split()
+               except AttributeError:
+                       pass
+               if not ext:
+                       ext=MOC_H
+               return ext
        def add_moc_tasks(self):
                node=self.inputs[0]
                bld=self.generator.bld
@@ -69,27 +68,19 @@ class qxx(Task.classes['cxx']):
                        pass
                else:
                        delattr(self,'cache_sig')
+               include_nodes=[node.parent]+self.generator.includes_nodes
                moctasks=[]
-               mocfiles=[]
-               try:
-                       tmp_lst=bld.raw_deps[self.uid()]
-                       bld.raw_deps[self.uid()]=[]
-               except KeyError:
-                       tmp_lst=[]
-               for d in tmp_lst:
+               mocfiles=set([])
+               for d in bld.raw_deps.get(self.uid(),[]):
                        if not d.endswith('.moc'):
                                continue
                        if d in mocfiles:
-                               Logs.error("paranoia owns")
                                continue
-                       mocfiles.append(d)
+                       mocfiles.add(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:
+                       for x in include_nodes:
+                               for e in self.moc_h_ext():
                                        h_node=x.find_node(base2+e)
                                        if h_node:
                                                break
@@ -99,28 +90,19 @@ class qxx(Task.classes['cxx']):
                        else:
                                for k in EXT_QT4:
                                        if base2.endswith(k):
-                                               for x in[node.parent]+self.generator.includes_nodes:
+                                               for x in include_nodes:
                                                        h_node=x.find_node(base2)
                                                        if h_node:
                                                                break
-                                       if h_node:
-                                               m_node=h_node.change_ext(k+'.moc')
-                                               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
+                               raise Errors.WafError('No source found for %r which is a moc file'%d)
                        task=self.create_moc_task(h_node,m_node)
                        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=self.create_moc_task(bld.node_deps[(self.inputs[0].parent.abspath(),name)],d)
-                               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'
@@ -140,7 +122,7 @@ class XMLHandler(ContentHandler):
 @extension(*EXT_RCC)
 def create_rcc_task(self,node):
        rcnode=node.change_ext('_rc.cpp')
-       rcctask=self.create_task('rcc',node,rcnode)
+       self.create_task('rcc',node,rcnode)
        cpptask=self.create_task('cxx',rcnode,rcnode.change_ext('.o'))
        try:
                self.compiled_tasks.append(cpptask)
@@ -179,7 +161,7 @@ def apply_qt4(self):
        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 in('-D','-I','/D','/I'):
                        if(f[0]=='/'):
                                lst.append('-'+flag[1:])
                        else:
@@ -190,10 +172,11 @@ 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}'
+       run_str='${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}'
        ext_out=['.h']
+       def rcname(self):
+               return os.path.splitext(self.inputs[0].name)[0]
        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([],[])
@@ -216,6 +199,10 @@ class rcc(Task.Task):
 class moc(Task.Task):
        color='BLUE'
        run_str='${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}'
+       def keyword(self):
+               return"Creating"
+       def __str__(self):
+               return self.outputs[0].path_from(self.generator.bld.launch_node())
 class ui4(Task.Task):
        color='BLUE'
        run_str='${QT_UIC} ${SRC} -o ${TGT}'
@@ -267,14 +254,14 @@ def find_qt4_binaries(self):
                                paths.append(qtbin)
        cand=None
        prev_ver=['4','0','0']
-       for qmk in['qmake-qt4','qmake4','qmake']:
+       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()
+                               version=self.cmd_and_log(qmake+['-query','QT_VERSION']).strip()
                        except self.errors.WafError:
                                pass
                        else:
@@ -287,7 +274,7 @@ def find_qt4_binaries(self):
                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
+       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
@@ -301,18 +288,17 @@ def find_qt4_binaries(self):
                                break
        find_bin(['uic-qt3','uic3'],'QT_UIC3')
        find_bin(['uic-qt4','uic'],'QT_UIC')
-       if not env['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')
+       self.start_msg('Checking for uic version')
+       uicver=self.cmd_and_log(env.QT_UIC+["-version"],output=Context.BOTH)
+       uicver=''.join(uicver).strip()
        uicver=uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt','')
-       self.msg('Checking for uic version','%s'%uicver)
+       self.end_msg(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(['rcc-qt4','rcc'],'QT_RCC')
        find_bin(['lrelease-qt4','lrelease'],'QT_LRELEASE')
        find_bin(['lupdate-qt4','lupdate'],'QT_LUPDATE')
        env['UIC3_ST']='%s -o %s'
@@ -327,12 +313,12 @@ 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()
+                       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
+                       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()
+       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)
diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py
new file mode 100644 (file)
index 0000000..8213b8d
--- /dev/null
@@ -0,0 +1,488 @@
+#! /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 cxx
+from waflib import Task,Utils,Options,Errors,Context
+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_QT5=['.cpp','.cc','.cxx','.C']
+QT5_LIBS='''
+qtmain
+Qt5Bluetooth
+Qt5CLucene
+Qt5Concurrent
+Qt5Core
+Qt5DBus
+Qt5Declarative
+Qt5DesignerComponents
+Qt5Designer
+Qt5Gui
+Qt5Help
+Qt5MultimediaQuick_p
+Qt5Multimedia
+Qt5MultimediaWidgets
+Qt5Network
+Qt5Nfc
+Qt5OpenGL
+Qt5Positioning
+Qt5PrintSupport
+Qt5Qml
+Qt5QuickParticles
+Qt5Quick
+Qt5QuickTest
+Qt5Script
+Qt5ScriptTools
+Qt5Sensors
+Qt5SerialPort
+Qt5Sql
+Qt5Svg
+Qt5Test
+Qt5WebKit
+Qt5WebKitWidgets
+Qt5Widgets
+Qt5WinExtras
+Qt5X11Extras
+Qt5XmlPatterns
+Qt5Xml'''
+class qxx(Task.classes['cxx']):
+       def __init__(self,*k,**kw):
+               Task.Task.__init__(self,*k,**kw)
+               self.moc_done=0
+       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 create_moc_task(self,h_node,m_node):
+               try:
+                       moc_cache=self.generator.bld.moc_cache
+               except AttributeError:
+                       moc_cache=self.generator.bld.moc_cache={}
+               try:
+                       return moc_cache[h_node]
+               except KeyError:
+                       tsk=moc_cache[h_node]=Task.classes['moc'](env=self.env,generator=self.generator)
+                       tsk.set_inputs(h_node)
+                       tsk.set_outputs(m_node)
+                       if self.generator:
+                               self.generator.tasks.append(tsk)
+                       gen=self.generator.bld.producer
+                       gen.outstanding.insert(0,tsk)
+                       gen.total+=1
+                       return tsk
+               else:
+                       delattr(self,'cache_sig')
+       def moc_h_ext(self):
+               try:
+                       ext=Options.options.qt_header_ext.split()
+               except AttributeError:
+                       pass
+               if not ext:
+                       ext=MOC_H
+               return ext
+       def add_moc_tasks(self):
+               node=self.inputs[0]
+               bld=self.generator.bld
+               try:
+                       self.signature()
+               except KeyError:
+                       pass
+               else:
+                       delattr(self,'cache_sig')
+               include_nodes=[node.parent]+self.generator.includes_nodes
+               moctasks=[]
+               mocfiles=set([])
+               for d in bld.raw_deps.get(self.uid(),[]):
+                       if not d.endswith('.moc'):
+                               continue
+                       if d in mocfiles:
+                               continue
+                       mocfiles.add(d)
+                       h_node=None
+                       base2=d[:-4]
+                       for x in include_nodes:
+                               for e in self.moc_h_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_QT5:
+                                       if base2.endswith(k):
+                                               for x in include_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 source found for %r which is a moc file'%d)
+                       task=self.create_moc_task(h_node,m_node)
+                       moctasks.append(task)
+               self.run_after.update(set(moctasks))
+               self.moc_done=1
+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')
+       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('ui5',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('qt5')
+@after_method('apply_link')
+def apply_qt5(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_qt5:
+                       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.append_value('MOC_FLAGS',lst)
+@extension(*EXT_QT5)
+def cxx_hook(self,node):
+       return self.create_compiled_task('qxx',node)
+class rcc(Task.Task):
+       color='BLUE'
+       run_str='${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}'
+       ext_out=['.h']
+       def rcname(self):
+               return os.path.splitext(self.inputs[0].name)[0]
+       def scan(self):
+               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 ui5(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(['<file>%s</file>'%k.path_from(self.outputs[0].parent)for k in self.inputs])
+               code='<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n%s\n</qresource>\n</RCC>'%txt
+               self.outputs[0].write(code)
+def configure(self):
+       self.find_qt5_binaries()
+       self.set_qt5_libs_to_check()
+       self.set_qt5_defines()
+       self.find_qt5_libraries()
+       self.add_qt5_rpath()
+       self.simplify_qt5_libs()
+@conf
+def find_qt5_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('QT5_ROOT','')
+               qtbin=os.environ.get('QT5_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/qt5/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=['5','0','0']
+       for qmk in('qmake-qt5','qmake5','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 not cand:
+               try:
+                       self.find_program('qtchooser')
+               except self.errors.ConfigurationError:
+                       pass
+               else:
+                       cmd=self.env.QTCHOOSER+['-qt=5','-run-tool=qmake']
+                       try:
+                               version=self.cmd_and_log(cmd+['-query','QT_VERSION'])
+                       except self.errors.WafError:
+                               pass
+                       else:
+                               cand=cmd
+       if cand:
+               self.env.QMAKE=cand
+       else:
+               self.fatal('Could not find qmake for qt5')
+       self.env.QT_INSTALL_BINS=qtbin=self.cmd_and_log(self.env.QMAKE+['-query','QT_INSTALL_BINS']).strip()+os.sep
+       paths.insert(0,qtbin)
+       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-qt5','uic'],'QT_UIC')
+       if not env.QT_UIC:
+               self.fatal('cannot find the uic compiler for qt5')
+       self.start_msg('Checking for uic version')
+       uicver=self.cmd_and_log(env.QT_UIC+['-version'],output=Context.BOTH)
+       uicver=''.join(uicver).strip()
+       uicver=uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt','')
+       self.end_msg(uicver)
+       if uicver.find(' 3.')!=-1 or uicver.find(' 4.')!=-1:
+               self.fatal('this uic compiler is for qt3 or qt5, add uic for qt5 to your path')
+       find_bin(['moc-qt5','moc'],'QT_MOC')
+       find_bin(['rcc-qt5','rcc'],'QT_RCC')
+       find_bin(['lrelease-qt5','lrelease'],'QT_LRELEASE')
+       find_bin(['lupdate-qt5','lupdate'],'QT_LUPDATE')
+       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_qt5_libraries(self):
+       qtlibs=getattr(Options.options,'qtlibs',None)or os.environ.get("QT5_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 Qt5 libraries in',qtlibs)
+       qtincludes=os.environ.get("QT5_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/qt5/lib/pkgconfig:/opt/qt5/lib/pkgconfig:/usr/lib/qt5/lib:/opt/qt5/lib'%(qtlibs,qtlibs)
+       try:
+               if os.environ.get("QT5_XCOMPILE",None):
+                       raise self.errors.ConfigurationError()
+               self.check_cfg(atleast_pkgconfig_version='0.1')
+       except self.errors.ConfigurationError:
+               for i in self.qt5_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%s5.a","%s.lib","%s5.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%sd5.a","%sd.lib","%sd5.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.qt5_vars_debug+self.qt5_vars:
+                       self.check_cfg(package=i,args='--cflags --libs',mandatory=False)
+@conf
+def simplify_qt5_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.qt5_vars,'LIBPATH_QTCORE')
+       process_lib(self.qt5_vars_debug,'LIBPATH_QTCORE_DEBUG')
+@conf
+def add_qt5_rpath(self):
+       env=self.env
+       if getattr(Options.options,'want_rpath',False):
+               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.qt5_vars,'LIBPATH_QTCORE')
+               process_rpath(self.qt5_vars_debug,'LIBPATH_QTCORE_DEBUG')
+@conf
+def set_qt5_libs_to_check(self):
+       if not hasattr(self,'qt5_vars'):
+               self.qt5_vars=QT5_LIBS
+       self.qt5_vars=Utils.to_list(self.qt5_vars)
+       if not hasattr(self,'qt5_vars_debug'):
+               self.qt5_vars_debug=[a+'_debug'for a in self.qt5_vars]
+       self.qt5_vars_debug=Utils.to_list(self.qt5_vars_debug)
+@conf
+def set_qt5_defines(self):
+       if sys.platform!='win32':
+               return
+       for x in self.qt5_vars:
+               y=x[2:].upper()
+               self.env.append_unique('DEFINES_%s'%x.upper(),'QT_%s_LIB'%y)
+               self.env.append_unique('DEFINES_%s_DEBUG'%x.upper(),'QT_%s_LIB'%y)
+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_qt5",default=False)
index 04cddfb..32a36bd 100644 (file)
@@ -27,7 +27,7 @@ def check_ruby_version(self,minver=()):
                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()
+               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
@@ -51,9 +51,9 @@ def check_ruby_ext_devel(self):
                self.fatal('load a c/c++ compiler first')
        version=tuple(map(int,self.env.RUBY_VERSION.split(".")))
        def read_out(cmd):
-               return Utils.to_list(self.cmd_and_log([self.env.RUBY,'-rrbconfig','-e',cmd]))
+               return Utils.to_list(self.cmd_and_log(self.env.RUBY+['-rrbconfig','-e',cmd]))
        def read_config(key):
-               return read_out('puts Config::CONFIG[%r]'%key)
+               return read_out('puts RbConfig::CONFIG[%r]'%key)
        ruby=self.env['RUBY']
        archdir=read_config('archdir')
        cpppath=archdir
@@ -87,7 +87,7 @@ def check_ruby_ext_devel(self):
 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])
+               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)
index 48f4943..6b7bb60 100644 (file)
@@ -2,25 +2,18 @@
 # 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)
+       cc=conf.find_program('cc',var='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'
+       v.CC_NAME='sun'
        conf.get_suncc_version(cc)
 @conf
 def scc_common_flags(conf):
index 1736c2d..721180c 100644 (file)
@@ -2,26 +2,18 @@
 # 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)
+       cc=conf.find_program(['CC','c++'],var='CXX')
        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'
+       v.CXX_NAME='sun'
        conf.get_suncc_version(cc)
 @conf
 def sxx_common_flags(conf):
index 6813022..c58c040 100644 (file)
@@ -3,7 +3,7 @@
 # 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 import Utils,Task,Errors,Logs,Node
 from waflib.TaskGen import feature,before_method
 re_bibunit=re.compile(r'\\(?P<type>putbib)\[(?P<file>[^\[\]]*)\]',re.M)
 def bibunitscan(self):
@@ -14,7 +14,7 @@ def bibunitscan(self):
        for match in re_bibunit.finditer(code):
                path=match.group('file')
                if path:
-                       for k in['','.bib']:
+                       for k in('','.bib'):
                                Logs.debug('tex: trying %s%s'%(path,k))
                                fi=node.parent.find_resource(path+k)
                                if fi:
@@ -23,10 +23,11 @@ def bibunitscan(self):
                                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_deps_tex=['','.ltx','.tex','.bib','.pdf','.png','.eps','.ps','.sty']
 exts_tex=['.ltx','.tex']
-re_tex=re.compile(r'\\(?P<type>include|bibliography|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P<file>[^{}]*)}',re.M)
+re_tex=re.compile(r'\\(?P<type>usepackage|RequirePackage|include|bibliography([^\[\]{}]*)|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P<file>[^{}]*)}',re.M)
 g_bibtex_re=re.compile('bibdata',re.M)
+g_glossaries_re=re.compile('\\@newglossary',re.M)
 class tex(Task.Task):
        bibtex_fun,_=Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}',shell=False)
        bibtex_fun.__doc__="""
@@ -36,8 +37,13 @@ class tex(Task.Task):
        makeindex_fun.__doc__="""
        Execute the program **makeindex**
        """
+       makeglossaries_fun,_=Task.compile_fun('${MAKEGLOSSARIES} ${SRCFILE}',shell=False)
+       makeglossaries_fun.__doc__="""
+       Execute the program **makeglossaries**
+       """
        def exec_command(self,cmd,**kw):
                bld=self.generator.bld
+               Logs.info('runner: %r'%cmd)
                try:
                        if not kw.get('cwd',None):
                                kw['cwd']=bld.cwd
@@ -71,13 +77,23 @@ class tex(Task.Task):
                        code=node.read()
                        global re_tex
                        for match in re_tex.finditer(code):
+                               multibib=match.group('type')
+                               if multibib and multibib.startswith('bibliography'):
+                                       multibib=multibib[len('bibliography'):]
+                                       if multibib.startswith('style'):
+                                               continue
+                               else:
+                                       multibib=None
                                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)
+                                                       for up in self.texinputs_nodes:
+                                                               Logs.debug('tex: trying %s%s'%(path,k))
+                                                               found=up.find_resource(path+k)
+                                                               if found:
+                                                                       break
                                                        for tsk in self.generator.tasks:
                                                                if not found or found in tsk.outputs:
                                                                        break
@@ -88,6 +104,11 @@ class tex(Task.Task):
                                                                        if found.name.endswith(ext):
                                                                                parse_node(found)
                                                                                break
+                                                       if found and multibib and found.name.endswith('.bib'):
+                                                               try:
+                                                                       self.multibibs.append(found)
+                                                               except AttributeError:
+                                                                       self.multibibs=[found]
                                                if add_name:
                                                        names.append(path)
                parse_node(node)
@@ -102,16 +123,22 @@ class tex(Task.Task):
                for aux_node in self.aux_nodes:
                        try:
                                ct=aux_node.read()
-                       except(OSError,IOError):
+                       except EnvironmentError:
                                Logs.error('Error reading %s: %r'%aux_node.abspath())
                                continue
                        if g_bibtex_re.findall(ct):
-                               Logs.warn('calling bibtex')
+                               Logs.info('calling bibtex')
                                self.env.env={}
                                self.env.env.update(os.environ)
-                               self.env.env.update({'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS})
+                               self.env.env.update({'BIBINPUTS':self.texinputs(),'BSTINPUTS':self.texinputs()})
                                self.env.SRCFILE=aux_node.name[:-4]
                                self.check_status('error when calling bibtex',self.bibtex_fun())
+               for node in getattr(self,'multibibs',[]):
+                       self.env.env={}
+                       self.env.env.update(os.environ)
+                       self.env.env.update({'BIBINPUTS':self.texinputs(),'BSTINPUTS':self.texinputs()})
+                       self.env.SRCFILE=node.name[:-4]
+                       self.check_status('error when calling bibtex',self.bibtex_fun())
        def bibunits(self):
                try:
                        bibunits=bibunitscan(self)
@@ -119,21 +146,22 @@ class tex(Task.Task):
                        Logs.error('error bibunitscan')
                else:
                        if bibunits:
-                               fn=['bu'+str(i)for i in xrange(1,len(bibunits)+1)]
+                               fn=['bu'+str(i)for i in range(1,len(bibunits)+1)]
                                if fn:
-                                       Logs.warn('calling bibtex on bibunits')
+                                       Logs.info('calling bibtex on bibunits')
                                for f in fn:
-                                       self.env.env={'BIBINPUTS':self.TEXINPUTS,'BSTINPUTS':self.TEXINPUTS}
+                                       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):
+               self.idx_node=self.inputs[0].change_ext('.idx')
                try:
                        idx_path=self.idx_node.abspath()
                        os.stat(idx_path)
                except OSError:
-                       Logs.warn('index file %s absent, not calling makeindex'%idx_path)
+                       Logs.info('index file %s absent, not calling makeindex'%idx_path)
                else:
-                       Logs.warn('calling makeindex')
+                       Logs.info('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())
@@ -141,47 +169,65 @@ class tex(Task.Task):
                p=self.inputs[0].parent.get_bld()
                if os.path.exists(os.path.join(p.abspath(),'btaux.aux')):
                        self.aux_nodes+=p.ant_glob('*[0-9].aux')
+       def makeglossaries(self):
+               src_file=self.inputs[0].abspath()
+               base_file=os.path.basename(src_file)
+               base,_=os.path.splitext(base_file)
+               for aux_node in self.aux_nodes:
+                       try:
+                               ct=aux_node.read()
+                       except EnvironmentError:
+                               Logs.error('Error reading %s: %r'%aux_node.abspath())
+                               continue
+                       if g_glossaries_re.findall(ct):
+                               if not self.env.MAKEGLOSSARIES:
+                                       raise Errors.WafError("The program 'makeglossaries' is missing!")
+                               Logs.warn('calling makeglossaries')
+                               self.env.SRCFILE=base
+                               self.check_status('error when calling makeglossaries %s'%base,self.makeglossaries_fun())
+                               return
+       def texinputs(self):
+               return os.pathsep.join([k.abspath()for k in self.texinputs_nodes])+os.pathsep
        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')
+               Logs.info('first pass on %s'%self.__class__.__name__)
+               cur_hash=self.hash_aux_nodes()
+               self.call_latex()
+               self.hash_aux_nodes()
                self.bibtopic()
                self.bibfile()
                self.bibunits()
                self.makeindex()
-               hash=''
+               self.makeglossaries()
                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:
+                       prev_hash=cur_hash
+                       cur_hash=self.hash_aux_nodes()
+                       if not cur_hash:
+                               Logs.error('No aux.h to process')
+                       if cur_hash and cur_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())
+                       Logs.info('calling %s'%self.__class__.__name__)
+                       self.call_latex()
+       def hash_aux_nodes(self):
+               try:
+                       nodes=self.aux_nodes
+               except AttributeError:
+                       try:
+                               self.aux_nodes=self.scan_aux(self.inputs[0].change_ext('.aux'))
+                       except IOError:
+                               return None
+               return Utils.h_list([Utils.h_file(x.abspath())for x in self.aux_nodes])
+       def call_latex(self):
+               self.env.env={}
+               self.env.env.update(os.environ)
+               self.env.env.update({'TEXINPUTS':self.texinputs()})
+               self.env.SRCFILE=self.inputs[0].abspath()
+               self.check_status('error when calling latex',self.texfun())
 class latex(tex):
        texfun,vars=Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}',shell=False)
 class pdflatex(tex):
@@ -203,7 +249,7 @@ class pdf2ps(Task.Task):
 @feature('tex')
 @before_method('process_source')
 def apply_tex(self):
-       if not getattr(self,'type',None)in['latex','pdflatex','xelatex']:
+       if not getattr(self,'type',None)in('latex','pdflatex','xelatex'):
                self.type='pdflatex'
        tree=self.bld
        outs=Utils.to_list(getattr(self,'outs',[]))
@@ -211,12 +257,15 @@ def apply_tex(self):
        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 dep in deps:
+                       if isinstance(dep,str):
+                               n=self.path.find_resource(dep)
+                               if not n:
+                                       self.bld.fatal('Could not find %r for %r'%(dep,self))
+                               if not n in deps_lst:
+                                       deps_lst.append(n)
+                       elif isinstance(dep,Node.Node):
+                               deps_lst.append(dep)
        for node in self.to_nodes(self.source):
                if self.type=='latex':
                        task=self.create_task('latex',node,node.change_ext('.dvi'))
@@ -226,30 +275,42 @@ def apply_tex(self):
                        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
-               v=dict(os.environ)
-               p=node.parent.abspath()+os.pathsep+self.path.abspath()+os.pathsep+self.path.get_bld().abspath()+os.pathsep+v.get('TEXINPUTS','')+os.pathsep
-               v['TEXINPUTS']=p
+                       for n in deps_lst:
+                               if not n in task.dep_nodes:
+                                       task.dep_nodes.append(n)
+               if hasattr(self,'texinputs_nodes'):
+                       task.texinputs_nodes=self.texinputs_nodes
+               else:
+                       task.texinputs_nodes=[node.parent,node.parent.get_bld(),self.path,self.path.get_bld()]
+                       lst=os.environ.get('TEXINPUTS','')
+                       if self.env.TEXINPUTS:
+                               lst+=os.pathsep+self.env.TEXINPUTS
+                       if lst:
+                               lst=lst.split(os.pathsep)
+                       for x in lst:
+                               if x:
+                                       if os.path.isabs(x):
+                                               p=self.bld.root.find_node(x)
+                                               if p:
+                                                       task.texinputs_nodes.append(p)
+                                               else:
+                                                       Logs.error('Invalid TEXINPUTS folder %s'%x)
+                                       else:
+                                               Logs.error('Cannot resolve relative paths in TEXINPUTS %s'%x)
                if self.type=='latex':
                        if'ps'in outs:
                                tsk=self.create_task('dvips',task.outputs,node.change_ext('.ps'))
-                               tsk.env.env=dict(v)
+                               tsk.env.env=dict(os.environ)
                        if'pdf'in outs:
                                tsk=self.create_task('dvipdf',task.outputs,node.change_ext('.pdf'))
-                               tsk.env.env=dict(v)
+                               tsk.env.env=dict(os.environ)
                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():
+       for p in'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps makeglossaries'.split():
                try:
                        self.find_program(p,var=p.upper())
                except self.errors.ConfigurationError:
index 96248c1..e50eb86 100644 (file)
@@ -10,7 +10,7 @@ class valac(Task.Task):
        vars=["VALAC","VALAC_VERSION","VALAFLAGS"]
        ext_out=['.h']
        def run(self):
-               cmd=[self.env['VALAC']]+self.env['VALAFLAGS']
+               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:
@@ -159,7 +159,7 @@ def vala_file(self,node):
 def find_valac(self,valac_name,min_version):
        valac=self.find_program(valac_name,var='VALAC')
        try:
-               output=self.cmd_and_log(valac+' --version')
+               output=self.cmd_and_log(valac+['--version'])
        except Exception:
                valac_version=None
        else:
index 3363172..5278b20 100644 (file)
@@ -2,8 +2,8 @@
 # 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
+import os
+from waflib.TaskGen import feature,after_method,taskgen_method
 from waflib import Utils,Task,Logs,Options
 testlock=Utils.threading.Lock()
 @feature('test')
@@ -11,6 +11,14 @@ testlock=Utils.threading.Lock()
 def make_test(self):
        if getattr(self,'link_task',None):
                self.create_task('utest',self.link_task.outputs)
+@taskgen_method
+def add_test_results(self,tup):
+       Logs.debug("ut: %r",tup)
+       self.utest_result=tup
+       try:
+               self.bld.utest_results.append(tup)
+       except AttributeError:
+               self.bld.utest_results=[tup]
 class utest(Task.Task):
        color='PINK'
        after=['vnum','inst']
@@ -23,11 +31,9 @@ class utest(Task.Task):
                        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)
+       def add_path(self,dct,path,var):
+               dct[var]=os.pathsep.join(Utils.to_list(path)+[os.environ.get(var,'')])
+       def get_test_env(self):
                try:
                        fu=getattr(self.generator.bld,'all_test_paths')
                except AttributeError:
@@ -39,32 +45,30 @@ class utest(Task.Task):
                                                s=tg.link_task.outputs[0].parent.abspath()
                                                if s not in lst:
                                                        lst.append(s)
-                       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')
+                               self.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')
+                               self.add_path(fu,lst,'DYLD_LIBRARY_PATH')
+                               self.add_path(fu,lst,'LD_LIBRARY_PATH')
                        else:
-                               add_path(fu,lst,'LD_LIBRARY_PATH')
+                               self.add_path(fu,lst,'LD_LIBRARY_PATH')
                        self.generator.bld.all_test_paths=fu
+               return fu
+       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)
                cwd=getattr(self.generator,'ut_cwd','')or self.inputs[0].parent.abspath()
-               testcmd=getattr(Options.options,'testcmd',False)
+               testcmd=getattr(self.generator,'ut_cmd',False)or 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)
+               proc=Utils.subprocess.Popen(self.ut_exec,cwd=cwd,env=self.get_test_env(),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]
+                       return self.generator.add_test_results(tup)
                finally:
                        testlock.release()
 def summary(bld):
index fbf0fcf..829617d 100644 (file)
@@ -7,10 +7,8 @@ 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
index b7efb23..e1b98b2 100644 (file)
@@ -7,10 +7,8 @@ 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
index 92cfd81..d1a59f9 100644 (file)
@@ -2,14 +2,9 @@
 # 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 os,sys,errno,traceback,inspect,re,shutil,datetime,gc,platform
 import subprocess
-try:
-       from collections import deque
-except ImportError:
-       class deque(list):
-               def popleft(self):
-                       return self.pop(0)
+from collections import deque,defaultdict
 try:
        import _winreg as winreg
 except ImportError:
@@ -32,6 +27,8 @@ except ImportError:
 try:
        import threading
 except ImportError:
+       if not'JOBS'in os.environ:
+               os.environ['JOBS']='1'
        class threading(object):
                pass
        class Lock(object):
@@ -56,23 +53,34 @@ O755=493
 rot_chr=['\\','|','/','-']
 rot_idx=0
 try:
-       from collections import defaultdict
+       from collections import OrderedDict as ordered_iter_dict
 except ImportError:
-       class defaultdict(dict):
-               def __init__(self,default_factory):
-                       super(defaultdict,self).__init__()
-                       self.default_factory=default_factory
-               def __getitem__(self,key):
+       class ordered_iter_dict(dict):
+               def __init__(self,*k,**kw):
+                       self.lst=[]
+                       dict.__init__(self,*k,**kw)
+               def clear(self):
+                       dict.clear(self)
+                       self.lst=[]
+               def __setitem__(self,key,value):
+                       dict.__setitem__(self,key,value)
+                       try:
+                               self.lst.remove(key)
+                       except ValueError:
+                               pass
+                       self.lst.append(key)
+               def __delitem__(self,key):
+                       dict.__delitem__(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'
+                               self.lst.remove(key)
+                       except ValueError:
+                               pass
+               def __iter__(self):
+                       for x in self.lst:
+                               yield x
+               def keys(self):
+                       return self.lst
+is_win32=sys.platform in('win32','cli','os2')
 def readf(fname,m='r',encoding='ISO8859-1'):
        if sys.hexversion>0x3000000 and not'b'in m:
                m+='b'
@@ -81,7 +89,10 @@ def readf(fname,m='r',encoding='ISO8859-1'):
                        txt=f.read()
                finally:
                        f.close()
-               txt=txt.decode(encoding)
+               if encoding:
+                       txt=txt.decode(encoding)
+               else:
+                       txt=txt.decode()
        else:
                f=open(fname,m)
                try:
@@ -108,67 +119,70 @@ def h_file(fname):
        finally:
                f.close()
        return m.digest()
-if hasattr(os,'O_NOINHERIT')and sys.hexversion<0x3040000:
-       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)
+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:
-                       f.write(data)
+                       txt=f.read()
                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()
+               if encoding:
+                       txt=txt.decode(encoding)
+               else:
+                       txt=txt.decode()
+       else:
+               f=os.fdopen(fd,m)
                try:
-                       while fname:
-                               fname=f.read(200000)
-                               m.update(fname)
+                       txt=f.read()
                finally:
                        f.close()
-               return m.digest()
-       readf_old=readf
-       writef_old=writef
-       h_file_old=h_file
+       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_unix=readf
+writef_unix=writef
+h_file_unix=h_file
+if hasattr(os,'O_NOINHERIT')and sys.hexversion<0x3040000:
        readf=readf_win32
        writef=writef_win32
        h_file=h_file_win32
@@ -190,27 +204,27 @@ Return the hexadecimal representation of a string
 :param s: string to convert
 :type s: string
 """
+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=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):
@@ -231,18 +245,7 @@ def to_list(sth):
                return sth.split()
        else:
                return sth
-re_nl=re.compile('\r*\n',re.M)
-def str_to_dict(txt):
-       tbl={}
-       lines=re_nl.split(txt)
-       for x in lines:
-               x=x.strip()
-               if not x or x.startswith('#')or x.find('=')<0:
-                       continue
-               tmp=x.split('=')
-               tbl[tmp[0].strip()]='='.join(tmp[1:]).strip()
-       return tbl
-def split_path(path):
+def split_path_unix(path):
        return path.split('/')
 def split_path_cygwin(path):
        if path.startswith('//'):
@@ -261,6 +264,8 @@ if sys.platform=='cygwin':
        split_path=split_path_cygwin
 elif is_win32:
        split_path=split_path_win32
+else:
+       split_path=split_path_unix
 split_path.__doc__="""
 Split a path by / or \\. This function is not like os.path.split
 
@@ -275,12 +280,29 @@ def check_dir(path):
                except OSError ,e:
                        if not os.path.isdir(path):
                                raise Errors.WafError('Cannot create the folder %r'%path,ex=e)
+def check_exe(name,env=None):
+       if not name:
+               raise ValueError('Cannot execute an empty string!')
+       def is_exe(fpath):
+               return os.path.isfile(fpath)and os.access(fpath,os.X_OK)
+       fpath,fname=os.path.split(name)
+       if fpath and is_exe(name):
+               return os.path.abspath(name)
+       else:
+               env=env or os.environ
+               for path in env["PATH"].split(os.pathsep):
+                       path=path.strip('"')
+                       exe_file=os.path.join(path,name)
+                       if is_exe(exe_file):
+                               return os.path.abspath(exe_file)
+       return None
 def def_attrs(cls,**kw):
        for k,v in kw.items():
                if not hasattr(cls,k):
                        setattr(cls,k,v)
 def quote_define_name(s):
-       fu=re.compile("[^a-zA-Z0-9]").sub("_",s)
+       fu=re.sub('[^a-zA-Z0-9]','_',s)
+       fu=re.sub('_+','_',fu)
        fu=fu.upper()
        return fu
 def h_list(lst):
@@ -336,7 +358,8 @@ def unversioned_sys_platform():
                else:s=s.lower()
        if s=='powerpc':
                return'darwin'
-       if s=='win32'or s.endswith('os2')and s!='sunos2':return s
+       if s=='win32'or s=='os2':
+               return s
        return re.split('\d+$',s)[0]
 def nada(*k,**kw):
        pass
@@ -345,10 +368,10 @@ class Timer(object):
                self.start_time=datetime.datetime.utcnow()
        def __str__(self):
                delta=datetime.datetime.utcnow()-self.start_time
-               days=int(delta.days)
-               hours=delta.seconds//3600
-               minutes=(delta.seconds-hours*3600)//60
-               seconds=delta.seconds-hours*3600-minutes*60+float(delta.microseconds)/1000/1000
+               days=delta.days
+               hours,rem=divmod(delta.seconds,3600)
+               minutes,seconds=divmod(rem,60)
+               seconds+=delta.microseconds*1e-6
                result=''
                if days:
                        result+='%dd'%days
@@ -410,3 +433,11 @@ def get_registry_app_path(key,filename):
        else:
                if os.path.isfile(result):
                        return result
+def lib64():
+       if os.sep=='/':
+               is_64=platform.architecture()[0]=='64bit'
+               if os.path.exists('/usr/lib64')and not os.path.exists('/usr/lib32'):
+                       return'64'if is_64 else''
+               else:
+                       return''if is_64 else'32'
+       return''
index def27e4..68cf26f 100644 (file)
@@ -2,65 +2,83 @@
 # encoding: utf-8
 # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file
 
-import sys,os
+import os,re,sys
+from waflib.Utils import threading
+wlock=threading.Lock()
 try:
-       if not(sys.stderr.isatty()and sys.stdout.isatty()):
-               raise ValueError('not a tty')
-       from ctypes import Structure,windll,c_short,c_ushort,c_ulong,c_int,byref,POINTER,c_long,c_char
+       from ctypes import Structure,windll,c_short,c_ushort,c_ulong,c_int,byref,c_wchar,POINTER,c_long
+except ImportError:
+       class AnsiTerm(object):
+               def __init__(self,stream):
+                       self.stream=stream
+                       try:
+                               self.errors=self.stream.errors
+                       except AttributeError:
+                               pass
+                       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()
+else:
        class COORD(Structure):
                _fields_=[("X",c_short),("Y",c_short)]
        class SMALL_RECT(Structure):
                _fields_=[("Left",c_short),("Top",c_short),("Right",c_short),("Bottom",c_short)]
        class CONSOLE_SCREEN_BUFFER_INFO(Structure):
-               _fields_=[("Size",COORD),("CursorPosition",COORD),("Attributes",c_short),("Window",SMALL_RECT),("MaximumWindowSize",COORD)]
+               _fields_=[("Size",COORD),("CursorPosition",COORD),("Attributes",c_ushort),("Window",SMALL_RECT),("MaximumWindowSize",COORD)]
        class CONSOLE_CURSOR_INFO(Structure):
                _fields_=[('dwSize',c_ulong),('bVisible',c_int)]
+       try:
+               _type=unicode
+       except NameError:
+               _type=str
+       to_int=lambda number,default:number and int(number)or default
+       STD_OUTPUT_HANDLE=-11
+       STD_ERROR_HANDLE=-12
        windll.kernel32.GetStdHandle.argtypes=[c_ulong]
        windll.kernel32.GetStdHandle.restype=c_ulong
        windll.kernel32.GetConsoleScreenBufferInfo.argtypes=[c_ulong,POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
        windll.kernel32.GetConsoleScreenBufferInfo.restype=c_long
        windll.kernel32.SetConsoleTextAttribute.argtypes=[c_ulong,c_ushort]
        windll.kernel32.SetConsoleTextAttribute.restype=c_long
-       windll.kernel32.FillConsoleOutputCharacterA.argtypes=[c_ulong,c_char,c_ulong,POINTER(COORD),POINTER(c_ulong)]
-       windll.kernel32.FillConsoleOutputCharacterA.restype=c_long
+       windll.kernel32.FillConsoleOutputCharacterW.argtypes=[c_ulong,c_wchar,c_ulong,POINTER(COORD),POINTER(c_ulong)]
+       windll.kernel32.FillConsoleOutputCharacterW.restype=c_long
        windll.kernel32.FillConsoleOutputAttribute.argtypes=[c_ulong,c_ushort,c_ulong,POINTER(COORD),POINTER(c_ulong)]
        windll.kernel32.FillConsoleOutputAttribute.restype=c_long
        windll.kernel32.SetConsoleCursorPosition.argtypes=[c_ulong,POINTER(COORD)]
        windll.kernel32.SetConsoleCursorPosition.restype=c_long
        windll.kernel32.SetConsoleCursorInfo.argtypes=[c_ulong,POINTER(CONSOLE_CURSOR_INFO)]
        windll.kernel32.SetConsoleCursorInfo.restype=c_long
-       sbinfo=CONSOLE_SCREEN_BUFFER_INFO()
-       csinfo=CONSOLE_CURSOR_INFO()
-       hconsole=windll.kernel32.GetStdHandle(-11)
-       windll.kernel32.GetConsoleScreenBufferInfo(hconsole,byref(sbinfo))
-       if sbinfo.Size.X<9 or sbinfo.Size.Y<9:raise ValueError('small console')
-       windll.kernel32.GetConsoleCursorInfo(hconsole,byref(csinfo))
-except Exception:
-       pass
-else:
-       import re,threading
-       is_vista=getattr(sys,"getwindowsversion",None)and sys.getwindowsversion()[0]>=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)
+               def __init__(self,s):
+                       self.stream=s
+                       try:
+                               self.errors=s.errors
+                       except AttributeError:
+                               pass
+                       self.encoding=s.encoding
                        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))
+                       handle=(s.fileno()==2)and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE
+                       self.hconsole=windll.kernel32.GetStdHandle(handle)
+                       self._sbinfo=CONSOLE_SCREEN_BUFFER_INFO()
+                       self._csinfo=CONSOLE_CURSOR_INFO()
+                       windll.kernel32.GetConsoleCursorInfo(self.hconsole,byref(self._csinfo))
+                       self._orig_sbinfo=CONSOLE_SCREEN_BUFFER_INFO()
+                       r=windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(self._orig_sbinfo))
+                       self._isatty=r==1
                def screen_buffer_info(self):
-                       sbinfo=CONSOLE_SCREEN_BUFFER_INFO()
-                       windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(sbinfo))
-                       return sbinfo
+                       windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(self._sbinfo))
+                       return self._sbinfo
                def clear_line(self,param):
                        mode=param and int(param)or 0
                        sbinfo=self.screen_buffer_info()
@@ -74,7 +92,7 @@ else:
                                line_start=sbinfo.CursorPosition
                                line_length=sbinfo.Size.X-sbinfo.CursorPosition.X
                        chars_written=c_ulong()
-                       windll.kernel32.FillConsoleOutputCharacterA(self.hconsole,c_char(' '),line_length,line_start,byref(chars_written))
+                       windll.kernel32.FillConsoleOutputCharacterW(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)
@@ -90,7 +108,7 @@ 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_ulong()
-                       windll.kernel32.FillConsoleOutputCharacterA(self.hconsole,c_char(' '),clear_length,clear_start,byref(chars_written))
+                       windll.kernel32.FillConsoleOutputCharacterW(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()
@@ -133,20 +151,16 @@ else:
                        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))
+                       sbinfo=self.screen_buffer_info()
                        attr=sbinfo.Attributes
                        for c in cols:
-                               if is_vista:
-                                       c=int(c)
-                               else:
-                                       c=to_int(c,0)
+                               c=to_int(c,0)
                                if 29<c<38:
                                        attr=(attr&0xfff0)|self.rgb2bgr(c-30)
                                elif 39<c<48:
                                        attr=(attr&0xff0f)|(self.rgb2bgr(c-40)<<4)
                                elif c==0:
-                                       attr=self.orig_sbinfo.Attributes
+                                       attr=self._orig_sbinfo.Attributes
                                elif c==1:
                                        attr|=0x08
                                elif c==4:
@@ -155,23 +169,26 @@ else:
                                        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))
+                       self._csinfo.bVisible=1
+                       windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(self._csinfo))
                def hide_cursor(self,param):
-                       csinfo.bVisible=0
-                       windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(csinfo))
+                       self._csinfo.bVisible=0
+                       windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(self._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)
+                               if self._isatty:
+                                       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)
+                               else:
+                                       self.stream.write(text)
                        finally:
                                wlock.release()
                def writeconsole(self,txt):
@@ -179,13 +196,43 @@ else:
                        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)
+                       done=0
+                       todo=len(txt)
+                       chunk=32<<10
+                       while todo!=0:
+                               doing=min(chunk,todo)
+                               buf=txt[done:done+doing]
+                               r=writeconsole(self.hconsole,buf,doing,byref(chars_written),None)
+                               if r==0:
+                                       chunk>>=1
+                                       continue
+                               done+=doing
+                               todo-=doing
+               def fileno(self):
+                       return self.stream.fileno()
                def flush(self):
                        pass
                def isatty(self):
-                       return True
-       sys.stderr=sys.stdout=AnsiTerm()
-       os.environ['TERM']='vt100'
+                       return self._isatty
+       if sys.stdout.isatty()or sys.stderr.isatty():
+               handle=sys.stdout.isatty()and STD_OUTPUT_HANDLE or STD_ERROR_HANDLE
+               console=windll.kernel32.GetStdHandle(handle)
+               sbinfo=CONSOLE_SCREEN_BUFFER_INFO()
+               def get_term_cols():
+                       windll.kernel32.GetConsoleScreenBufferInfo(console,byref(sbinfo))
+                       return sbinfo.Size.X-1
+try:
+       import struct,fcntl,termios
+except ImportError:
+       pass
+else:
+       if(sys.stdout.isatty()or sys.stderr.isatty())and os.environ.get('TERM','')not in('dumb','emacs'):
+               FD=sys.stdout.isatty()and sys.stdout.fileno()or sys.stderr.fileno()
+               def fun():
+                       return struct.unpack("HHHH",fcntl.ioctl(FD,termios.TIOCGWINSZ,struct.pack("HHHH",0,0,0,0)))[1]
+               try:
+                       fun()
+               except Exception ,e:
+                       pass
+               else:
+                       get_term_cols=fun
index 3343afc..8a69dbf 100644 (file)
@@ -26,8 +26,36 @@ 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
+Utils.pproc=Utils.subprocess
+Utils.get_term_cols=Logs.get_term_cols
+def cmd_output(cmd,**kw):
+       silent=False
+       if'silent'in kw:
+               silent=kw['silent']
+               del(kw['silent'])
+       if'e'in kw:
+               tmp=kw['e']
+               del(kw['e'])
+               kw['env']=tmp
+       kw['shell']=isinstance(cmd,str)
+       kw['stdout']=Utils.subprocess.PIPE
+       if silent:
+               kw['stderr']=Utils.subprocess.PIPE
+       try:
+               p=Utils.subprocess.Popen(cmd,**kw)
+               output=p.communicate()[0]
+       except OSError ,e:
+               raise ValueError(str(e))
+       if p.returncode:
+               if not silent:
+                       msg="command execution failed: %s -> %r"%(cmd,str(output))
+                       raise ValueError(msg)
+               output=''
+       return output
+Utils.cmd_output=cmd_output
 def name_to_obj(self,s,env=None):
-       Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"')
+       if Logs.verbose:
+               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):
@@ -49,13 +77,15 @@ def retrieve(self,name,fromenv=None):
                self.prepare_env(env)
                self.all_envs[name]=env
        else:
-               if fromenv:Logs.warn("The environment %s may have been configured already"%name)
+               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
+Utils.WafError=Errors.WafError
 Options.OptionsContext.sub_options=Options.OptionsContext.recurse
 Options.OptionsContext.tool_options=Context.Context.load
 Options.Handler=Options.OptionsContext
@@ -76,24 +106,32 @@ 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')
+               if Logs.verbose:
+                       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"')
+               if Logs.verbose:
+                       Logs.warn('compat: rename "detect" to "configure"')
                ret.configure=ret.detect
        return ret
 Context.load_tool=load_tool
+def get_curdir(self):
+       return self.path.abspath()
+Context.Context.curdir=property(get_curdir,Utils.nada)
 rev=Context.load_module
-def load_module(path):
-       ret=rev(path)
+def load_module(path,encoding=None):
+       ret=rev(path,encoding)
        if'set_options'in ret.__dict__:
-               Logs.warn('compat: rename "set_options" to "options" (%r)'%path)
+               if Logs.verbose:
+                       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)
+               if Logs.verbose:
+                       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)
+               if Logs.verbose:
+                       Logs.warn('compat: rename "blddir" to "out" (%r)'%path)
                ret.out=ret.blddir
        return ret
 Context.load_module=load_module
@@ -101,15 +139,18 @@ 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")')
+               if Logs.verbose:
+                       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")')
+               if Logs.verbose:
+                       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"')
+               if Logs.verbose:
+                       Logs.warn('compat: "ccflags" was renamed to "cflags"')
                self.cflags=self.ccflags
        return old_post(self)
 TaskGen.task_gen.post=post
@@ -128,9 +169,11 @@ def apply_uselib_local(self):
        names=self.to_list(getattr(self,'uselib_local',[]))
        get=self.bld.get_tgen_by_name
        seen=set([])
+       seen_uselib=set([])
        tmp=Utils.deque(names)
        if tmp:
-               Logs.warn('compat: "uselib_local" is deprecated, replace by "use"')
+               if Logs.verbose:
+                       Logs.warn('compat: "uselib_local" is deprecated, replace by "use"')
        while tmp:
                lib_name=tmp.popleft()
                if lib_name in seen:
@@ -157,9 +200,11 @@ def apply_uselib_local(self):
                        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 v not in seen_uselib:
+                               seen_uselib.add(v)
+                               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')
@@ -218,3 +263,17 @@ 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)
+def install_dir(self,path):
+       if not path:
+               return[]
+       destpath=Utils.subst_vars(path,self.env)
+       if self.is_install>0:
+               Logs.info('* creating %s'%destpath)
+               Utils.check_dir(destpath)
+       elif self.is_install<0:
+               Logs.info('* removing %s'%destpath)
+               try:
+                       os.remove(destpath)
+               except OSError:
+                       pass
+Build.BuildContext.install_dir=install_dir