midori/waf-modules/wafadmin/Tools/ccroot.py
2013-10-23 20:26:27 -07:00

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)