397 lines
14 KiB
Python
397 lines
14 KiB
Python
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
import sys
|
|
if sys.hexversion < 0x020400f0: from sets import Set as set
|
|
import os,sys,re
|
|
import TaskGen,Task,Utils,preproc,Logs,Build,Options
|
|
from Logs import error,debug,warn
|
|
from Utils import md5
|
|
from TaskGen import taskgen,after,before,feature
|
|
from Constants import*
|
|
from Configure import conftest
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
from io import StringIO
|
|
import config_c
|
|
USE_TOP_LEVEL=False
|
|
def get_cc_version(conf,cc,gcc=False,icc=False):
|
|
cmd=cc+['-dM','-E','-']
|
|
try:
|
|
p=Utils.pproc.Popen(cmd,stdin=Utils.pproc.PIPE,stdout=Utils.pproc.PIPE,stderr=Utils.pproc.PIPE)
|
|
p.stdin.write('\n')
|
|
out=p.communicate()[0]
|
|
except:
|
|
conf.fatal('could not determine the compiler version %r'%cmd)
|
|
out=str(out)
|
|
if gcc:
|
|
if out.find('__INTEL_COMPILER')>=0:
|
|
conf.fatal('The intel compiler pretends to be gcc')
|
|
if out.find('__GNUC__')<0:
|
|
conf.fatal('Could not determine the compiler type')
|
|
if icc and out.find('__INTEL_COMPILER')<0:
|
|
conf.fatal('Not icc/icpc')
|
|
k={}
|
|
if icc or gcc:
|
|
out=out.split('\n')
|
|
import shlex
|
|
for line in out:
|
|
lst=shlex.split(line)
|
|
if len(lst)>2:
|
|
key=lst[1]
|
|
val=lst[2]
|
|
k[key]=val
|
|
def isD(var):
|
|
return var in k
|
|
def isT(var):
|
|
return var in k and k[var]!='0'
|
|
mp1={'__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','__POWERPC__':'powerpc',}
|
|
for i in mp1:
|
|
if isD(i):
|
|
conf.env.DEST_OS=mp1[i]
|
|
break
|
|
else:
|
|
if isD('__APPLE__')and isD('__MACH__'):
|
|
conf.env.DEST_OS='darwin'
|
|
elif isD('__unix__'):
|
|
conf.env.DEST_OS='generic'
|
|
if isD('__ELF__'):
|
|
conf.env.DEST_BINFMT='elf'
|
|
elif isD('__WINNT__')or isD('__CYGWIN__'):
|
|
conf.env.DEST_BINFMT='pe'
|
|
elif isD('__APPLE__'):
|
|
conf.env.DEST_BINFMT='mac-o'
|
|
mp2={'__x86_64__':'x86_64','__i386__':'x86','__ia64__':'ia','__mips__':'mips','__sparc__':'sparc','__alpha__':'alpha','__arm__':'arm','__hppa__':'hppa','__powerpc__':'powerpc',}
|
|
for i in mp2:
|
|
if isD(i):
|
|
conf.env.DEST_CPU=mp2[i]
|
|
break
|
|
debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')]))
|
|
conf.env['CC_VERSION']=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__'])
|
|
return k
|
|
class DEBUG_LEVELS:
|
|
ULTRADEBUG="ultradebug"
|
|
DEBUG="debug"
|
|
RELEASE="release"
|
|
OPTIMIZED="optimized"
|
|
CUSTOM="custom"
|
|
ALL=[ULTRADEBUG,DEBUG,RELEASE,OPTIMIZED,CUSTOM]
|
|
def scan(self):
|
|
debug('ccroot: _scan_preprocessor(self, node, env, path_lst)')
|
|
if len(self.inputs)==1:
|
|
node=self.inputs[0]
|
|
(nodes,names)=preproc.get_deps(node,self.env,nodepaths=self.env['INC_PATHS'])
|
|
if Logs.verbose:
|
|
debug('deps: deps for %s: %r; unresolved %r',str(node),nodes,names)
|
|
return(nodes,names)
|
|
all_nodes=[]
|
|
all_names=[]
|
|
seen=set()
|
|
for node in self.inputs:
|
|
(nodes,names)=preproc.get_deps(node,self.env,nodepaths=self.env['INC_PATHS'])
|
|
if Logs.verbose:
|
|
debug('deps: deps for %s: %r; unresolved %r',str(node),nodes,names)
|
|
for x in nodes:
|
|
if id(x)in seen:continue
|
|
seen.add(id(x))
|
|
all_nodes.append(x)
|
|
for x in names:
|
|
if not x in all_names:
|
|
all_names.append(x)
|
|
return(all_nodes,all_names)
|
|
class ccroot_abstract(TaskGen.task_gen):
|
|
def __init__(self,*k,**kw):
|
|
if len(k)>1:
|
|
k=list(k)
|
|
if k[1][0]!='c':
|
|
k[1]='c'+k[1]
|
|
TaskGen.task_gen.__init__(self,*k,**kw)
|
|
def get_target_name(self):
|
|
tp='program'
|
|
for x in self.features:
|
|
if x in['cshlib','cstaticlib']:
|
|
tp=x.lstrip('c')
|
|
pattern=self.env[tp+'_PATTERN']
|
|
if not pattern:pattern='%s'
|
|
dir,name=os.path.split(self.target)
|
|
if self.env.DEST_BINFMT=='pe'and getattr(self,'vnum',None)and'cshlib'in self.features:
|
|
name=name+'-'+self.vnum.split('.')[0]
|
|
return os.path.join(dir,pattern%name)
|
|
def default_cc(self):
|
|
Utils.def_attrs(self,includes='',defines='',rpaths='',uselib='',uselib_local='',add_objects='',p_flag_vars=[],p_type_vars=[],compiled_tasks=[],link_task=None)
|
|
if not self.env.DEST_BINFMT:
|
|
self.env.DEST_BINFMT=Utils.unversioned_sys_platform_to_binary_format(self.env.DEST_OS or Utils.unversioned_sys_platform())
|
|
if not self.env.BINDIR:self.env.BINDIR=Utils.subst_vars('${PREFIX}/bin',self.env)
|
|
if not self.env.LIBDIR:self.env.LIBDIR=Utils.subst_vars('${PREFIX}/lib${LIB_EXT}',self.env)
|
|
def apply_verif(self):
|
|
if not(self.source or getattr(self,'add_objects',None)or getattr(self,'uselib_local',None)or getattr(self,'obj_files',None)):
|
|
raise Utils.WafError('no source files specified for %s'%self)
|
|
if not self.target:
|
|
raise Utils.WafError('no target for %s'%self)
|
|
def vars_target_cprogram(self):
|
|
self.default_install_path=self.env.BINDIR
|
|
self.default_chmod=O755
|
|
def vars_target_cshlib(self):
|
|
if self.env.DEST_BINFMT=='pe':
|
|
self.default_chmod=O755
|
|
self.default_install_path=self.env.BINDIR
|
|
else:
|
|
self.default_install_path=self.env.LIBDIR
|
|
def default_link_install(self):
|
|
if self.install_path:
|
|
self.bld.install_files(self.install_path,self.link_task.outputs[0],env=self.env,chmod=self.chmod)
|
|
def apply_incpaths(self):
|
|
lst=[]
|
|
for lib in self.to_list(self.uselib):
|
|
for path in self.env['CPPPATH_'+lib]:
|
|
if not path in lst:
|
|
lst.append(path)
|
|
if preproc.go_absolute:
|
|
for path in preproc.standard_includes:
|
|
if not path in lst:
|
|
lst.append(path)
|
|
for path in self.to_list(self.includes):
|
|
if not path in lst:
|
|
if preproc.go_absolute or not os.path.isabs(path):
|
|
lst.append(path)
|
|
else:
|
|
self.env.prepend_value('CPPPATH',path)
|
|
for path in lst:
|
|
node=None
|
|
if os.path.isabs(path):
|
|
if preproc.go_absolute:
|
|
node=self.bld.root.find_dir(path)
|
|
elif path[0]=='#':
|
|
node=self.bld.srcnode
|
|
if len(path)>1:
|
|
node=node.find_dir(path[1:])
|
|
else:
|
|
node=self.path.find_dir(path)
|
|
if node:
|
|
self.env.append_value('INC_PATHS',node)
|
|
if USE_TOP_LEVEL:
|
|
self.env.append_value('INC_PATHS',self.bld.srcnode)
|
|
def apply_type_vars(self):
|
|
for x in self.features:
|
|
if not x in['cprogram','cstaticlib','cshlib']:
|
|
continue
|
|
x=x.lstrip('c')
|
|
st=self.env[x+'_USELIB']
|
|
if st:self.uselib=self.uselib+' '+st
|
|
for var in self.p_type_vars:
|
|
compvar='%s_%s'%(x,var)
|
|
value=self.env[compvar]
|
|
if value:self.env.append_value(var,value)
|
|
def apply_link(self):
|
|
link=getattr(self,'link',None)
|
|
if not link:
|
|
if'cstaticlib'in self.features:link='static_link'
|
|
elif'cxx'in self.features:link='cxx_link'
|
|
else:link='cc_link'
|
|
tsk=self.create_task(link)
|
|
outputs=[t.outputs[0]for t in self.compiled_tasks]
|
|
tsk.set_inputs(outputs)
|
|
tsk.set_outputs(self.path.find_or_declare(get_target_name(self)))
|
|
self.link_task=tsk
|
|
def apply_lib_vars(self):
|
|
env=self.env
|
|
self.uselib=self.to_list(self.uselib)
|
|
names=self.to_list(self.uselib_local)
|
|
seen=set([])
|
|
tmp=Utils.deque(names)
|
|
while tmp:
|
|
lib_name=tmp.popleft()
|
|
if lib_name in seen:
|
|
continue
|
|
y=self.name_to_obj(lib_name)
|
|
if not y:
|
|
raise Utils.WafError('object %r was not found in uselib_local (required by %r)'%(lib_name,self.name))
|
|
y.post()
|
|
seen.add(lib_name)
|
|
if getattr(y,'uselib_local',None):
|
|
lst=y.to_list(y.uselib_local)
|
|
if'cshlib'in y.features or'cprogram'in y.features:
|
|
lst=[x for x in lst if not'cstaticlib'in self.name_to_obj(x).features]
|
|
tmp.extend(lst)
|
|
if getattr(y,'link_task',None):
|
|
link_name=y.target[y.target.rfind(os.sep)+1:]
|
|
if'cstaticlib'in y.features:
|
|
env.append_value('STATICLIB',link_name)
|
|
elif'cshlib'in y.features or'cprogram'in y.features:
|
|
env.append_value('LIB',link_name)
|
|
self.link_task.set_run_after(y.link_task)
|
|
dep_nodes=getattr(self.link_task,'dep_nodes',[])
|
|
self.link_task.dep_nodes=dep_nodes+y.link_task.outputs
|
|
tmp_path=y.link_task.outputs[0].parent.bldpath(self.env)
|
|
if not tmp_path in env['LIBPATH']:env.prepend_value('LIBPATH',tmp_path)
|
|
for v in self.to_list(y.uselib):
|
|
if not env['STATICLIB_'+v]:
|
|
if not v in self.uselib:
|
|
self.uselib.insert(0,v)
|
|
if getattr(y,'export_incdirs',None):
|
|
for x in self.to_list(y.export_incdirs):
|
|
node=y.path.find_dir(x)
|
|
if not node:
|
|
raise Utils.WafError('object %r: invalid folder %r in export_incdirs'%(y.target,x))
|
|
self.env.append_unique('INC_PATHS',node)
|
|
for x in self.uselib:
|
|
for v in self.p_flag_vars:
|
|
val=self.env[v+'_'+x]
|
|
if val:self.env.append_value(v,val)
|
|
def apply_objdeps(self):
|
|
if not getattr(self,'add_objects',None):return
|
|
seen=[]
|
|
names=self.to_list(self.add_objects)
|
|
while names:
|
|
x=names[0]
|
|
if x in seen:
|
|
names=names[1:]
|
|
continue
|
|
y=self.name_to_obj(x)
|
|
if not y:
|
|
raise Utils.WafError('object %r was not found in uselib_local (required by add_objects %r)'%(x,self.name))
|
|
if getattr(y,'add_objects',None):
|
|
added=0
|
|
lst=y.to_list(y.add_objects)
|
|
lst.reverse()
|
|
for u in lst:
|
|
if u in seen:continue
|
|
added=1
|
|
names=[u]+names
|
|
if added:continue
|
|
y.post()
|
|
seen.append(x)
|
|
for t in y.compiled_tasks:
|
|
self.link_task.inputs.extend(t.outputs)
|
|
def apply_obj_vars(self):
|
|
v=self.env
|
|
lib_st=v['LIB_ST']
|
|
staticlib_st=v['STATICLIB_ST']
|
|
libpath_st=v['LIBPATH_ST']
|
|
staticlibpath_st=v['STATICLIBPATH_ST']
|
|
rpath_st=v['RPATH_ST']
|
|
app=v.append_unique
|
|
if v['FULLSTATIC']:
|
|
v.append_value('LINKFLAGS',v['FULLSTATIC_MARKER'])
|
|
for i in v['RPATH']:
|
|
if i and rpath_st:
|
|
app('LINKFLAGS',rpath_st%i)
|
|
for i in v['LIBPATH']:
|
|
app('LINKFLAGS',libpath_st%i)
|
|
app('LINKFLAGS',staticlibpath_st%i)
|
|
if v['STATICLIB']:
|
|
v.append_value('LINKFLAGS',v['STATICLIB_MARKER'])
|
|
k=[(staticlib_st%i)for i in v['STATICLIB']]
|
|
app('LINKFLAGS',k)
|
|
if not v['FULLSTATIC']:
|
|
if v['STATICLIB']or v['LIB']:
|
|
v.append_value('LINKFLAGS',v['SHLIB_MARKER'])
|
|
app('LINKFLAGS',[lib_st%i for i in v['LIB']])
|
|
def process_obj_files(self):
|
|
if not hasattr(self,'obj_files'):return
|
|
for x in self.obj_files:
|
|
node=self.path.find_resource(x)
|
|
self.link_task.inputs.append(node)
|
|
def add_obj_file(self,file):
|
|
if not hasattr(self,'obj_files'):self.obj_files=[]
|
|
if not'process_obj_files'in self.meths:self.meths.append('process_obj_files')
|
|
self.obj_files.append(file)
|
|
c_attrs={'cxxflag':'CXXFLAGS','cflag':'CCFLAGS','ccflag':'CCFLAGS','linkflag':'LINKFLAGS','ldflag':'LINKFLAGS','lib':'LIB','libpath':'LIBPATH','staticlib':'STATICLIB','staticlibpath':'STATICLIBPATH','rpath':'RPATH','framework':'FRAMEWORK','frameworkpath':'FRAMEWORKPATH'}
|
|
def add_extra_flags(self):
|
|
for x in self.__dict__.keys():
|
|
y=x.lower()
|
|
if y[-1]=='s':
|
|
y=y[:-1]
|
|
if c_attrs.get(y,None):
|
|
self.env.append_unique(c_attrs[y],getattr(self,x))
|
|
def apply_implib(self):
|
|
if not self.env.DEST_BINFMT=='pe':
|
|
return
|
|
self.meths.remove('default_link_install')
|
|
bindir=self.install_path
|
|
if not bindir:return
|
|
dll=self.link_task.outputs[0]
|
|
self.bld.install_files(bindir,dll,self.env,self.chmod)
|
|
implib=self.env['implib_PATTERN']%os.path.split(self.target)[1]
|
|
implib=dll.parent.find_or_declare(implib)
|
|
self.link_task.outputs.append(implib)
|
|
self.bld.install_as('${LIBDIR}/%s'%implib.name,implib,self.env)
|
|
self.env.append_value('LINKFLAGS',(self.env['IMPLIB_ST']%implib.bldpath(self.env)).split())
|
|
def apply_vnum(self):
|
|
if not getattr(self,'vnum','')or not'cshlib'in self.features or os.name!='posix'or self.env.DEST_BINFMT not in('elf','mac-o'):
|
|
return
|
|
self.meths.remove('default_link_install')
|
|
link=self.link_task
|
|
nums=self.vnum.split('.')
|
|
node=link.outputs[0]
|
|
libname=node.name
|
|
if libname.endswith('.dylib'):
|
|
name3=libname.replace('.dylib','.%s.dylib'%self.vnum)
|
|
name2=libname.replace('.dylib','.%s.dylib'%nums[0])
|
|
else:
|
|
name3=libname+'.'+self.vnum
|
|
name2=libname+'.'+nums[0]
|
|
if self.env.SONAME_ST:
|
|
v=self.env.SONAME_ST%name2
|
|
self.env.append_value('LINKFLAGS',v.split())
|
|
bld=self.bld
|
|
nums=self.vnum.split('.')
|
|
path=self.install_path
|
|
if not path:return
|
|
bld.install_as(path+os.sep+name3,node,env=self.env)
|
|
bld.symlink_as(path+os.sep+name2,name3)
|
|
bld.symlink_as(path+os.sep+libname,name3)
|
|
self.create_task('vnum',node,[node.parent.find_or_declare(name2),node.parent.find_or_declare(name3)])
|
|
def exec_vnum_link(self):
|
|
for x in self.outputs:
|
|
path=x.abspath(self.env)
|
|
try:
|
|
os.remove(path)
|
|
except OSError:
|
|
pass
|
|
try:
|
|
os.symlink(self.inputs[0].name,path)
|
|
except OSError:
|
|
return 1
|
|
cls=Task.task_type_from_func('vnum',func=exec_vnum_link,ext_in='.bin',color='CYAN')
|
|
cls.quiet=1
|
|
def add_as_needed(conf):
|
|
if conf.env.DEST_BINFMT=='elf'and'gcc'in(conf.env.CXX_NAME,conf.env.CC_NAME):
|
|
conf.env.append_unique('LINKFLAGS','--as-needed')
|
|
|
|
feature('cc','cxx')(default_cc)
|
|
before('apply_core')(default_cc)
|
|
feature('cprogram','dprogram','cstaticlib','dstaticlib','cshlib','dshlib')(apply_verif)
|
|
feature('cprogram','dprogram')(vars_target_cprogram)
|
|
after('default_cc')(vars_target_cprogram)
|
|
before('apply_core')(vars_target_cprogram)
|
|
after('default_cc')(vars_target_cshlib)
|
|
feature('cshlib','dshlib')(vars_target_cshlib)
|
|
before('apply_core')(vars_target_cshlib)
|
|
feature('cprogram','dprogram','cstaticlib','dstaticlib','cshlib','dshlib')(default_link_install)
|
|
after('apply_link','vars_target_cprogram','vars_target_cshlib')(default_link_install)
|
|
feature('cc','cxx')(apply_incpaths)
|
|
after('apply_type_vars','apply_lib_vars','apply_core')(apply_incpaths)
|
|
feature('cc','cxx')(apply_type_vars)
|
|
after('init_cc','init_cxx')(apply_type_vars)
|
|
before('apply_lib_vars')(apply_type_vars)
|
|
feature('cprogram','cshlib','cstaticlib')(apply_link)
|
|
after('apply_core')(apply_link)
|
|
feature('cc','cxx')(apply_lib_vars)
|
|
after('apply_link','init_cc','init_cxx','apply_core')(apply_lib_vars)
|
|
feature('cprogram','cstaticlib','cshlib')(apply_objdeps)
|
|
after('init_cc','init_cxx','apply_link')(apply_objdeps)
|
|
feature('cprogram','cshlib','cstaticlib')(apply_obj_vars)
|
|
after('apply_lib_vars')(apply_obj_vars)
|
|
after('apply_link')(process_obj_files)
|
|
taskgen(add_obj_file)
|
|
feature('cc','cxx')(add_extra_flags)
|
|
before('init_cxx','init_cc')(add_extra_flags)
|
|
before('apply_lib_vars','apply_obj_vars','apply_incpaths','init_cc')(add_extra_flags)
|
|
feature('cshlib')(apply_implib)
|
|
after('apply_link','default_cc')(apply_implib)
|
|
before('apply_lib_vars','apply_objdeps','default_link_install')(apply_implib)
|
|
feature('cshlib')(apply_vnum)
|
|
after('apply_link')(apply_vnum)
|
|
before('apply_lib_vars','default_link_install')(apply_vnum)
|
|
conftest(add_as_needed)
|