diff options
Diffstat (limited to 'waflib/Tools/c_config.py')
-rw-r--r-- | waflib/Tools/c_config.py | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py new file mode 100644 index 0000000..6347171 --- /dev/null +++ b/waflib/Tools/c_config.py @@ -0,0 +1,805 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file + +from __future__ import with_statement +import os,re,shlex +from waflib import Build,Utils,Task,Options,Logs,Errors,Runner +from waflib.TaskGen import after_method,feature +from waflib.Configure import conf +WAF_CONFIG_H='config.h' +DEFKEYS='define_key' +INCKEYS='include_key' +SNIP_EMPTY_PROGRAM=''' +int main(int argc, char **argv) { + (void)argc; (void)argv; + return 0; +} +''' +MACRO_TO_DESTOS={'__linux__':'linux','__GNU__':'gnu','__FreeBSD__':'freebsd','__NetBSD__':'netbsd','__OpenBSD__':'openbsd','__sun':'sunos','__hpux':'hpux','__sgi':'irix','_AIX':'aix','__CYGWIN__':'cygwin','__MSYS__':'cygwin','_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','__xtensa__':'xtensa',} +@conf +def parse_flags(self,line,uselib_store,env=None,force_static=False,posix=None): + assert(isinstance(line,str)) + env=env or self.env + 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) + uselib=uselib_store + def app(var,val): + env.append_value('%s_%s'%(var,uselib),val) + def appu(var,val): + env.append_unique('%s_%s'%(var,uselib),val) + static=False + while lst: + x=lst.pop(0) + st=x[:2] + ot=x[2:] + if st=='-I'or st=='/I': + if not ot: + ot=lst.pop(0) + appu('INCLUDES',ot) + elif st=='-i': + tmp=[x,lst.pop(0)] + app('CFLAGS',tmp) + app('CXXFLAGS',tmp) + elif st=='-D'or(env.CXX_NAME=='msvc'and st=='/D'): + if not ot: + ot=lst.pop(0) + app('DEFINES',ot) + elif st=='-l': + if not ot: + ot=lst.pop(0) + prefix='STLIB'if(force_static or static)else'LIB' + app(prefix,ot) + elif st=='-L': + if not ot: + ot=lst.pop(0) + prefix='STLIBPATH'if(force_static or static)else'LIBPATH' + appu(prefix,ot) + elif x.startswith('/LIBPATH:'): + prefix='STLIBPATH'if(force_static or static)else'LIBPATH' + appu(prefix,x.replace('/LIBPATH:','')) + elif x.startswith('-std='): + prefix='CXXFLAGS'if'++'in x else'CFLAGS' + app(prefix,x) + elif x.startswith('+')or x in('-pthread','-fPIC','-fpic','-fPIE','-fpie'): + app('CFLAGS',x) + app('CXXFLAGS',x) + app('LINKFLAGS',x) + elif x=='-framework': + appu('FRAMEWORK',lst.pop(0)) + elif x.startswith('-F'): + appu('FRAMEWORKPATH',x[2:]) + elif x=='-Wl,-rpath'or x=='-Wl,-R': + app('RPATH',lst.pop(0).lstrip('-Wl,')) + elif x.startswith('-Wl,-R,'): + app('RPATH',x[7:]) + elif x.startswith('-Wl,-R'): + app('RPATH',x[6:]) + elif x.startswith('-Wl,-rpath,'): + app('RPATH',x[11:]) + elif x=='-Wl,-Bstatic'or x=='-Bstatic': + static=True + elif x=='-Wl,-Bdynamic'or x=='-Bdynamic': + static=False + elif x.startswith('-Wl')or x in('-rdynamic','-pie'): + app('LINKFLAGS',x) + elif x.startswith(('-m','-f','-dynamic','-O','-g')): + app('CFLAGS',x) + app('CXXFLAGS',x) + elif x.startswith('-bundle'): + app('LINKFLAGS',x) + elif x.startswith(('-undefined','-Xlinker')): + arg=lst.pop(0) + app('LINKFLAGS',[x,arg]) + elif x.startswith(('-arch','-isysroot')): + tmp=[x,lst.pop(0)] + app('CFLAGS',tmp) + app('CXXFLAGS',tmp) + app('LINKFLAGS',tmp) + elif x.endswith(('.a','.so','.dylib','.lib')): + appu('LINKFLAGS',x) + else: + self.to_log('Unhandled flag %r'%x) +@conf +def validate_cfg(self,kw): + if not'path'in kw: + if not self.env.PKGCONFIG: + self.find_program('pkg-config',var='PKGCONFIG') + kw['path']=self.env.PKGCONFIG + s=('atleast_pkgconfig_version'in kw)+('modversion'in kw)+('package'in kw) + if s!=1: + raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') + if not'msg'in kw: + if'atleast_pkgconfig_version'in kw: + kw['msg']='Checking for pkg-config version >= %r'%kw['atleast_pkgconfig_version'] + elif'modversion'in kw: + kw['msg']='Checking for %r version'%kw['modversion'] + else: + kw['msg']='Checking for %r'%(kw['package']) + if not'okmsg'in kw and not'modversion'in kw: + kw['okmsg']='yes' + if not'errmsg'in kw: + kw['errmsg']='not found' + if'atleast_pkgconfig_version'in kw: + pass + elif'modversion'in kw: + if not'uselib_store'in kw: + kw['uselib_store']=kw['modversion'] + if not'define_name'in kw: + kw['define_name']='%s_VERSION'%Utils.quote_define_name(kw['uselib_store']) + else: + if not'uselib_store'in kw: + kw['uselib_store']=Utils.to_list(kw['package'])[0].upper() + if not'define_name'in kw: + kw['define_name']=self.have_define(kw['uselib_store']) +@conf +def exec_cfg(self,kw): + path=Utils.to_list(kw['path']) + env=self.env.env or None + if kw.get('pkg_config_path'): + if not env: + env=dict(self.environ) + env['PKG_CONFIG_PATH']=kw['pkg_config_path'] + def define_it(): + define_name=kw['define_name'] + if kw.get('global_define',1): + self.define(define_name,1,False) + else: + self.env.append_unique('DEFINES_%s'%kw['uselib_store'],"%s=1"%define_name) + if kw.get('add_have_to_env',1): + self.env[define_name]=1 + if'atleast_pkgconfig_version'in kw: + cmd=path+['--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']] + self.cmd_and_log(cmd,env=env) + return + if'modversion'in kw: + version=self.cmd_and_log(path+['--modversion',kw['modversion']],env=env).strip() + if not'okmsg'in kw: + kw['okmsg']=version + self.define(kw['define_name'],version) + return version + lst=[]+path + defi=kw.get('define_variable') + 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=kw.get('force_static',False) + if'args'in kw: + args=Utils.to_list(kw['args']) + if'--static'in args or'--static-libs'in args: + static=True + lst+=args + lst.extend(Utils.to_list(kw['package'])) + if'variables'in kw: + v_env=kw.get('env',self.env) + vars=Utils.to_list(kw['variables']) + for v in vars: + val=self.cmd_and_log(lst+['--variable='+v],env=env).strip() + var='%s_%s'%(kw['uselib_store'],v) + v_env[var]=val + return + ret=self.cmd_and_log(lst,env=env) + define_it() + self.parse_flags(ret,kw['uselib_store'],kw.get('env',self.env),force_static=static,posix=kw.get('posix')) + return ret +@conf +def check_cfg(self,*k,**kw): + self.validate_cfg(kw) + if'msg'in kw: + 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',**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),**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'): + bld.conf.to_log("==>\n%s\n<=="%bld.kw['code']) +@conf +def validate_c(self,kw): + for x in('type_name','field_name','function_name'): + if x in kw: + Logs.warn('Invalid argument %r in test'%x) + if not'build_fun'in kw: + kw['build_fun']=build_fun + if not'env'in kw: + kw['env']=self.env.derive() + env=kw['env'] + if not'compiler'in kw and not'features'in kw: + kw['compiler']='c' + if env.CXX_NAME and Task.classes.get('cxx'): + kw['compiler']='cxx' + if not self.env.CXX: + self.fatal('a c++ compiler is required') + else: + if not self.env.CC: + self.fatal('a c compiler is required') + if not'compile_mode'in kw: + kw['compile_mode']='c' + if'cxx'in Utils.to_list(kw.get('features',[]))or kw.get('compiler')=='cxx': + kw['compile_mode']='cxx' + if not'type'in kw: + kw['type']='cprogram' + if not'features'in kw: + if not'header_name'in kw or kw.get('link_header_test',True): + kw['features']=[kw['compile_mode'],kw['type']] + else: + kw['features']=[kw['compile_mode']] + else: + kw['features']=Utils.to_list(kw['features']) + if not'compile_filename'in kw: + kw['compile_filename']='test.c'+((kw['compile_mode']=='cxx')and'pp'or'') + def to_header(dct): + if'header_name'in dct: + dct=Utils.to_list(dct['header_name']) + return''.join(['#include <%s>\n'%x for x in dct]) + return'' + if'framework_name'in kw: + fwkname=kw['framework_name'] + if not'uselib_store'in kw: + kw['uselib_store']=fwkname.upper() + if not kw.get('no_header'): + fwk='%s/%s.h'%(fwkname,fwkname) + if kw.get('remove_dot_h'): + fwk=fwk[:-2] + val=kw.get('header_name',[]) + kw['header_name']=Utils.to_list(val)+[fwk] + kw['msg']='Checking for framework %s'%fwkname + kw['framework']=fwkname + elif'header_name'in kw: + if not'msg'in kw: + kw['msg']='Checking for header %s'%kw['header_name'] + l=Utils.to_list(kw['header_name']) + assert len(l),'list of headers in header_name is empty' + kw['code']=to_header(kw)+SNIP_EMPTY_PROGRAM + if not'uselib_store'in kw: + kw['uselib_store']=l[0].upper() + if not'define_name'in kw: + kw['define_name']=self.have_define(l[0]) + if'lib'in kw: + if not'msg'in kw: + kw['msg']='Checking for library %s'%kw['lib'] + if not'uselib_store'in kw: + kw['uselib_store']=kw['lib'].upper() + if'stlib'in kw: + if not'msg'in kw: + kw['msg']='Checking for static library %s'%kw['stlib'] + if not'uselib_store'in kw: + kw['uselib_store']=kw['stlib'].upper() + if'fragment'in kw: + kw['code']=kw['fragment'] + if not'msg'in kw: + kw['msg']='Checking for code snippet' + if not'errmsg'in kw: + kw['errmsg']='no' + for(flagsname,flagstype)in(('cxxflags','compiler'),('cflags','compiler'),('linkflags','linker')): + if flagsname in kw: + if not'msg'in kw: + kw['msg']='Checking for %s flags %s'%(flagstype,kw[flagsname]) + if not'errmsg'in kw: + kw['errmsg']='no' + if not'execute'in kw: + kw['execute']=False + if kw['execute']: + kw['features'].append('test_exec') + kw['chmod']=Utils.O755 + if not'errmsg'in kw: + kw['errmsg']='not found' + if not'okmsg'in kw: + kw['okmsg']='yes' + if not'code'in kw: + kw['code']=SNIP_EMPTY_PROGRAM + if self.env[INCKEYS]: + kw['code']='\n'.join(['#include <%s>'%x for x in self.env[INCKEYS]])+'\n'+kw['code'] + if kw.get('merge_config_header')or env.merge_config_header: + kw['code']='%s\n\n%s'%(self.get_config_header(),kw['code']) + env.DEFINES=[] + if not kw.get('success'): + kw['success']=None + if'define_name'in kw: + self.undefine(kw['define_name']) + if not'msg'in kw: + self.fatal('missing "msg" in conf.check(...)') +@conf +def post_check(self,*k,**kw): + is_success=0 + if kw['execute']: + if kw['success']is not None: + if kw.get('define_ret'): + is_success=kw['success'] + else: + is_success=(kw['success']==0) + else: + is_success=(kw['success']==0) + if kw.get('define_name'): + comment=kw.get('comment','') + define_name=kw['define_name'] + if kw['execute']and kw.get('define_ret')and isinstance(is_success,str): + if kw.get('global_define',1): + self.define(define_name,is_success,quote=kw.get('quote',1),comment=comment) + else: + if kw.get('quote',1): + succ='"%s"'%is_success + else: + succ=int(is_success) + val='%s=%s'%(define_name,succ) + var='DEFINES_%s'%kw['uselib_store'] + self.env.append_value(var,val) + else: + if kw.get('global_define',1): + self.define_cond(define_name,is_success,comment=comment) + else: + var='DEFINES_%s'%kw['uselib_store'] + self.env.append_value(var,'%s=%s'%(define_name,int(is_success))) + if kw.get('add_have_to_env',1): + if kw.get('uselib_store'): + self.env[self.have_define(kw['uselib_store'])]=1 + elif kw['execute']and kw.get('define_ret'): + self.env[define_name]=is_success + else: + self.env[define_name]=int(is_success) + if'header_name'in kw: + if kw.get('auto_add_header_name'): + self.env.append_value(INCKEYS,Utils.to_list(kw['header_name'])) + if is_success and'uselib_store'in kw: + from waflib.Tools import ccroot + _vars=set() + for x in kw['features']: + if x in ccroot.USELIB_VARS: + _vars|=ccroot.USELIB_VARS[x] + for k in _vars: + x=k.lower() + if x in kw: + self.env.append_value(k+'_'+kw['uselib_store'],kw[x]) + return is_success +@conf +def check(self,*k,**kw): + self.validate_c(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 + else: + self.fatal('The configuration failed') + else: + kw['success']=ret + ret=self.post_check(*k,**kw) + if not ret: + self.end_msg(kw['errmsg'],'YELLOW',**kw) + self.fatal('The configuration failed %r'%ret) + else: + self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw) + return ret +class test_exec(Task.Task): + color='PINK' + def run(self): + if getattr(self.generator,'rpath',None): + if getattr(self.generator,'define_ret',False): + self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) + else: + self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()]) + else: + env=self.env.env or{} + env.update(dict(os.environ)) + for var in('LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','PATH'): + env[var]=self.inputs[0].parent.abspath()+os.path.pathsep+env.get(var,'') + if getattr(self.generator,'define_ret',False): + self.generator.bld.retval=self.generator.bld.cmd_and_log([self.inputs[0].abspath()],env=env) + else: + self.generator.bld.retval=self.generator.bld.exec_command([self.inputs[0].abspath()],env=env) +@feature('test_exec') +@after_method('apply_link') +def test_exec_fun(self): + self.create_task('test_exec',self.link_task.outputs[0]) +@conf +def check_cxx(self,*k,**kw): + kw['compiler']='cxx' + return self.check(*k,**kw) +@conf +def check_cc(self,*k,**kw): + kw['compiler']='c' + return self.check(*k,**kw) +@conf +def set_define_comment(self,key,comment): + coms=self.env.DEFINE_COMMENTS + if not coms: + coms=self.env.DEFINE_COMMENTS={} + coms[key]=comment or'' +@conf +def get_define_comment(self,key): + coms=self.env.DEFINE_COMMENTS or{} + return coms.get(key,'') +@conf +def define(self,key,val,quote=True,comment=''): + assert isinstance(key,str) + if not key: + return + if val is True: + val=1 + elif val in(False,None): + val=0 + if isinstance(val,int)or isinstance(val,float): + s='%s=%s' + else: + s=quote and'%s="%s"'or'%s=%s' + app=s%(key,str(val)) + ban=key+'=' + lst=self.env.DEFINES + for x in lst: + if x.startswith(ban): + lst[lst.index(x)]=app + break + else: + self.env.append_value('DEFINES',app) + self.env.append_unique(DEFKEYS,key) + self.set_define_comment(key,comment) +@conf +def undefine(self,key,comment=''): + assert isinstance(key,str) + if not key: + return + ban=key+'=' + lst=[x for x in self.env.DEFINES if not x.startswith(ban)] + self.env.DEFINES=lst + self.env.append_unique(DEFKEYS,key) + self.set_define_comment(key,comment) +@conf +def define_cond(self,key,val,comment=''): + assert isinstance(key,str) + if not key: + return + if val: + self.define(key,1,comment=comment) + else: + self.undefine(key,comment=comment) +@conf +def is_defined(self,key): + assert key and isinstance(key,str) + ban=key+'=' + for x in self.env.DEFINES: + if x.startswith(ban): + return True + return False +@conf +def get_define(self,key): + assert key and isinstance(key,str) + ban=key+'=' + for x in self.env.DEFINES: + if x.startswith(ban): + return x[len(ban):] + return None +@conf +def have_define(self,key): + return(self.env.HAVE_PAT or'HAVE_%s')%Utils.quote_define_name(key) +@conf +def write_config_header(self,configfile='',guard='',top=False,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() + node=node.make_node(configfile) + node.parent.mkdir() + lst=['/* WARNING! All changes made to this file will be lost! */\n'] + lst.append('#ifndef %s\n#define %s\n'%(waf_guard,waf_guard)) + lst.append(self.get_config_header(defines,headers,define_prefix=define_prefix)) + lst.append('\n#endif /* %s */\n'%waf_guard) + node.write('\n'.join(lst)) + self.env.append_unique(Build.CFG_FILES,[node.abspath()]) + if remove: + for key in self.env[DEFKEYS]: + self.undefine(key) + self.env[DEFKEYS]=[] +@conf +def get_config_header(self,defines=True,headers=False,define_prefix=''): + lst=[] + if self.env.WAF_CONFIG_H_PRELUDE: + lst.append(self.env.WAF_CONFIG_H_PRELUDE) + if headers: + for x in self.env[INCKEYS]: + lst.append('#include <%s>'%x) + if defines: + tbl={} + for k in self.env.DEFINES: + a,_,b=k.partition('=') + tbl[a]=b + for k in self.env[DEFKEYS]: + caption=self.get_define_comment(k) + if caption: + caption=' /* %s */'%caption + try: + txt='#define %s%s %s%s'%(define_prefix,k,tbl[k],caption) + except KeyError: + txt='/* #undef %s%s */%s'%(define_prefix,k,caption) + lst.append(txt) + return"\n".join(lst) +@conf +def cc_add_flags(conf): + conf.add_os_flags('CPPFLAGS',dup=False) + conf.add_os_flags('CFLAGS',dup=False) +@conf +def cxx_add_flags(conf): + conf.add_os_flags('CPPFLAGS',dup=False) + conf.add_os_flags('CXXFLAGS',dup=False) +@conf +def link_add_flags(conf): + conf.add_os_flags('LINKFLAGS',dup=False) + conf.add_os_flags('LDFLAGS',dup=False) +@conf +def cc_load_tools(conf): + if not conf.env.DEST_OS: + conf.env.DEST_OS=Utils.unversioned_sys_platform() + conf.load('c') +@conf +def cxx_load_tools(conf): + if not conf.env.DEST_OS: + conf.env.DEST_OS=Utils.unversioned_sys_platform() + conf.load('cxx') +@conf +def get_cc_version(conf,cc,gcc=False,icc=False,clang=False): + cmd=cc+['-dM','-E','-'] + env=conf.env.env or None + try: + out,err=conf.cmd_and_log(cmd,output=0,input='\n'.encode(),env=env) + except Errors.WafError: + conf.fatal('Could not determine the compiler version %r'%cmd) + if gcc: + if out.find('__INTEL_COMPILER')>=0: + conf.fatal('The intel compiler pretends to be gcc') + if out.find('__GNUC__')<0 and out.find('__clang__')<0: + 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 gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure') + k={} + if icc or gcc or clang: + out=out.splitlines() + for line in out: + lst=shlex.split(line) + if len(lst)>2: + key=lst[1] + val=lst[2] + k[key]=val + def isD(var): + return var in k + if not conf.env.DEST_OS: + conf.env.DEST_OS='' + for i in MACRO_TO_DESTOS: + if isD(i): + conf.env.DEST_OS=MACRO_TO_DESTOS[i] + break + else: + if isD('__APPLE__')and isD('__MACH__'): + conf.env.DEST_OS='darwin' + elif isD('__unix__'): + conf.env.DEST_OS='generic' + if isD('__ELF__'): + conf.env.DEST_BINFMT='elf' + elif isD('__WINNT__')or isD('__CYGWIN__')or isD('_WIN32'): + conf.env.DEST_BINFMT='pe' + if not conf.env.IMPLIBDIR: + conf.env.IMPLIBDIR=conf.env.LIBDIR + conf.env.LIBDIR=conf.env.BINDIR + elif isD('__APPLE__'): + conf.env.DEST_BINFMT='mac-o' + if not conf.env.DEST_BINFMT: + conf.env.DEST_BINFMT=Utils.destos_to_binfmt(conf.env.DEST_OS) + for i in MACRO_TO_DEST_CPU: + if isD(i): + conf.env.DEST_CPU=MACRO_TO_DEST_CPU[i] + break + Logs.debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')])) + if icc: + ver=k['__INTEL_COMPILER'] + conf.env.CC_VERSION=(ver[:-2],ver[-2],ver[-1]) + else: + if isD('__clang__')and isD('__clang_major__'): + conf.env.CC_VERSION=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__']) + else: + conf.env.CC_VERSION=(k['__GNUC__'],k['__GNUC_MINOR__'],k.get('__GNUC_PATCHLEVEL__','0')) + return k +@conf +def get_xlc_version(conf,cc): + cmd=cc+['-qversion'] + try: + out,err=conf.cmd_and_log(cmd,output=0) + except Errors.WafError: + conf.fatal('Could not find xlc %r'%cmd) + for v in(r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",): + version_re=re.compile(v,re.I).search + match=version_re(out or err) + if match: + k=match.groupdict() + conf.env.CC_VERSION=(k['major'],k['minor']) + break + else: + conf.fatal('Could not determine the XLC version.') +@conf +def get_suncc_version(conf,cc): + cmd=cc+['-V'] + try: + out,err=conf.cmd_and_log(cmd,output=0) + except Errors.WafError as e: + if not(hasattr(e,'returncode')and hasattr(e,'stdout')and hasattr(e,'stderr')): + conf.fatal('Could not find suncc %r'%cmd) + out=e.stdout + err=e.stderr + version=(out or err) + version=version.splitlines()[0] + version_re=re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P<major>\d*)\.(?P<minor>\d*)',re.I).search + match=version_re(version) + if match: + k=match.groupdict() + conf.env.CC_VERSION=(k['major'],k['minor']) + else: + conf.fatal('Could not determine the suncc version.') +@conf +def add_as_needed(self): + if self.env.DEST_BINFMT=='elf'and'gcc'in(self.env.CXX_NAME,self.env.CC_NAME): + self.env.append_unique('LINKFLAGS','-Wl,--as-needed') +class cfgtask(Task.Task): + def __init__(self,*k,**kw): + Task.Task.__init__(self,*k,**kw) + self.run_after=set() + def display(self): + return'' + def runnable_status(self): + for x in self.run_after: + if not x.hasrun: + return Task.ASK_LATER + return Task.RUN_ME + def uid(self): + return Utils.SIG_NIL + def signature(self): + return Utils.SIG_NIL + def run(self): + conf=self.conf + bld=Build.BuildContext(top_dir=conf.srcnode.abspath(),out_dir=conf.bldnode.abspath()) + bld.env=conf.env + bld.init_dirs() + bld.in_msg=1 + bld.logger=self.logger + bld.multicheck_task=self + args=self.args + try: + if'func'in args: + bld.test(build_fun=args['func'],msg=args.get('msg',''),okmsg=args.get('okmsg',''),errmsg=args.get('errmsg',''),) + else: + args['multicheck_mandatory']=args.get('mandatory',True) + args['mandatory']=True + try: + bld.check(**args) + finally: + args['mandatory']=args['multicheck_mandatory'] + except Exception: + return 1 + def process(self): + Task.Task.process(self) + if'msg'in self.args: + with self.generator.bld.multicheck_lock: + self.conf.start_msg(self.args['msg']) + if self.hasrun==Task.NOT_RUN: + self.conf.end_msg('test cancelled','YELLOW') + elif self.hasrun!=Task.SUCCESS: + self.conf.end_msg(self.args.get('errmsg','no'),'YELLOW') + else: + self.conf.end_msg(self.args.get('okmsg','yes'),'GREEN') +@conf +def multicheck(self,*k,**kw): + self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)),**kw) + for var in('DEFINES',DEFKEYS): + self.env.append_value(var,[]) + self.env.DEFINE_COMMENTS=self.env.DEFINE_COMMENTS or{} + class par(object): + def __init__(self): + self.keep=False + self.task_sigs={} + self.progress_bar=0 + def total(self): + return len(tasks) + def to_log(self,*k,**kw): + return + bld=par() + bld.keep=kw.get('run_all_tests',True) + bld.imp_sigs={} + tasks=[] + id_to_task={} + for dct in k: + x=Task.classes['cfgtask'](bld=bld,env=None) + tasks.append(x) + x.args=dct + x.bld=bld + x.conf=self + x.args=dct + x.logger=Logs.make_mem_logger(str(id(x)),self.logger) + if'id'in dct: + id_to_task[dct['id']]=x + for x in tasks: + for key in Utils.to_list(x.args.get('before_tests',[])): + tsk=id_to_task[key] + if not tsk: + raise ValueError('No test named %r'%key) + tsk.run_after.add(x) + for key in Utils.to_list(x.args.get('after_tests',[])): + tsk=id_to_task[key] + if not tsk: + raise ValueError('No test named %r'%key) + x.run_after.add(tsk) + def it(): + yield tasks + while 1: + yield[] + bld.producer=p=Runner.Parallel(bld,Options.options.jobs) + bld.multicheck_lock=Utils.threading.Lock() + p.biter=it() + self.end_msg('started') + p.start() + for x in tasks: + x.logger.memhandler.flush() + self.start_msg('-> processing test results') + if p.error: + for x in p.error: + if getattr(x,'err_msg',None): + self.to_log(x.err_msg) + self.end_msg('fail',color='RED') + raise Errors.WafError('There is an error in the library, read config.log for more information') + failure_count=0 + for x in tasks: + if x.hasrun not in(Task.SUCCESS,Task.NOT_RUN): + failure_count+=1 + if failure_count: + self.end_msg(kw.get('errmsg','%s test failed'%failure_count),color='YELLOW',**kw) + else: + self.end_msg('all ok',**kw) + for x in tasks: + if x.hasrun!=Task.SUCCESS: + if x.args.get('mandatory',True): + self.fatal(kw.get('fatalmsg')or'One of the tests has failed, read config.log for more information') +@conf +def check_gcc_o_space(self,mode='c'): + if int(self.env.CC_VERSION[0])>4: + return + self.env.stash() + if mode=='c': + self.env.CCLNK_TGT_F=['-o',''] + elif mode=='cxx': + self.env.CXXLNK_TGT_F=['-o',''] + features='%s %sshlib'%(mode,mode) + try: + self.check(msg='Checking if the -o link must be split from arguments',fragment=SNIP_EMPTY_PROGRAM,features=features) + except self.errors.ConfigurationError: + self.env.revert() + else: + self.env.commit() |