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

316 lines
8.9 KiB
Python

#! /usr/bin/env python
# encoding: utf-8
import os,shlex,sys,time
try:import cPickle
except ImportError:import pickle as cPickle
import Environment,Utils,Options,Logs
from Logs import warn
from Constants import*
try:
from urllib import request
except:
from urllib import urlopen
else:
urlopen=request.urlopen
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
#
'''
class ConfigurationError(Utils.WscriptError):
pass
autoconfig=False
def find_file(filename,path_list):
for directory in Utils.to_list(path_list):
if os.path.exists(os.path.join(directory,filename)):
return directory
return''
def find_program_impl(env,filename,path_list=[],var=None,environ=None):
if not environ:
environ=os.environ
try:path_list=path_list.split()
except AttributeError:pass
if var:
if env[var]:return env[var]
if var in environ:env[var]=environ[var]
if not path_list:path_list=environ.get('PATH','').split(os.pathsep)
ext=(Options.platform=='win32')and'.exe,.com,.bat,.cmd'or''
for y in[filename+x for x in ext.split(',')]:
for directory in path_list:
x=os.path.join(directory,y)
if os.path.isfile(x):
if var:env[var]=x
return x
return''
class ConfigurationContext(Utils.Context):
tests={}
error_handlers=[]
def __init__(self,env=None,blddir='',srcdir=''):
self.env=None
self.envname=''
self.environ=dict(os.environ)
self.line_just=40
self.blddir=blddir
self.srcdir=srcdir
self.all_envs={}
self.cwd=self.curdir=os.getcwd()
self.tools=[]
self.setenv(DEFAULT)
self.lastprog=''
self.hash=0
self.files=[]
self.tool_cache=[]
if self.blddir:
self.post_init()
def post_init(self):
self.cachedir=os.path.join(self.blddir,CACHE_DIR)
path=os.path.join(self.blddir,WAF_CONFIG_LOG)
try:os.unlink(path)
except(OSError,IOError):pass
try:
self.log=open(path,'w')
except(OSError,IOError):
self.fatal('could not open %r for writing'%path)
app=Utils.g_module.APPNAME
if app:
ver=getattr(Utils.g_module,'VERSION','')
if ver:
app="%s (%s)"%(app,ver)
now=time.ctime()
pyver=sys.hexversion
systype=sys.platform
args=" ".join(sys.argv)
wafver=WAFVERSION
abi=ABI
self.log.write(conf_template%vars())
def __del__(self):
if hasattr(self,'log')and self.log:
self.log.close()
def fatal(self,msg):
raise ConfigurationError(msg)
def check_tool(self,input,tooldir=None,funs=None):
tools=Utils.to_list(input)
if tooldir:tooldir=Utils.to_list(tooldir)
for tool in tools:
tool=tool.replace('++','xx')
if tool=='java':tool='javaw'
if tool.lower()=='unittest':tool='unittestw'
mag=(tool,id(self.env),funs)
if mag in self.tool_cache:
continue
self.tool_cache.append(mag)
module=None
try:
module=Utils.load_tool(tool,tooldir)
except Exception,e:
ex=e
if Options.options.download:
_3rdparty=os.path.normpath(Options.tooldir[0]+os.sep+'..'+os.sep+'3rdparty')
for x in Utils.to_list(Options.remote_repo):
for sub in['branches/waf-%s/wafadmin/3rdparty'%WAFVERSION,'trunk/wafadmin/3rdparty']:
url='/'.join((x,sub,tool+'.py'))
try:
web=urlopen(url)
if web.getcode()!=200:
continue
except Exception,e:
continue
else:
loc=None
try:
loc=open(_3rdparty+os.sep+tool+'.py','wb')
loc.write(web.read())
web.close()
finally:
if loc:
loc.close()
Logs.warn('downloaded %s from %s'%(tool,url))
try:
module=Utils.load_tool(tool,tooldir)
except:
Logs.warn('module %s from %s is unusable'%(tool,url))
try:
os.unlink(_3rdparty+os.sep+tool+'.py')
except:
pass
continue
else:
break
if not module:
Logs.error('Could not load the tool %r or download a suitable replacement from the repository (sys.path %r)\n%s'%(tool,sys.path,e))
raise ex
else:
Logs.error('Could not load the tool %r in %r (try the --download option?):\n%s'%(tool,sys.path,e))
raise ex
if funs is not None:
self.eval_rules(funs)
else:
func=getattr(module,'detect',None)
if func:
if type(func)is type(find_file):func(self)
else:self.eval_rules(func)
self.tools.append({'tool':tool,'tooldir':tooldir,'funs':funs})
def sub_config(self,k):
self.recurse(k,name='configure')
def pre_recurse(self,name_or_mod,path,nexdir):
return{'conf':self,'ctx':self}
def post_recurse(self,name_or_mod,path,nexdir):
if not autoconfig:
return
self.hash=hash((self.hash,getattr(name_or_mod,'waf_hash_val',name_or_mod)))
self.files.append(path)
def store(self,file=''):
if not os.path.isdir(self.cachedir):
os.makedirs(self.cachedir)
if not file:
file=open(os.path.join(self.cachedir,'build.config.py'),'w')
file.write('version = 0x%x\n'%HEXVERSION)
file.write('tools = %r\n'%self.tools)
file.close()
if not self.all_envs:
self.fatal('nothing to store in the configuration context!')
for key in self.all_envs:
tmpenv=self.all_envs[key]
tmpenv.store(os.path.join(self.cachedir,key+CACHE_SUFFIX))
def set_env_name(self,name,env):
self.all_envs[name]=env
return env
def retrieve(self,name,fromenv=None):
try:
env=self.all_envs[name]
except KeyError:
env=Environment.Environment()
env['PREFIX']=os.path.abspath(os.path.expanduser(Options.options.prefix))
self.all_envs[name]=env
else:
if fromenv:warn("The environment %s may have been configured already"%name)
return env
def setenv(self,name):
self.env=self.retrieve(name)
self.envname=name
def add_os_flags(self,var,dest=None):
try:self.env.append_value(dest or var,Utils.to_list(self.environ[var]))
except KeyError:pass
def check_message_1(self,sr):
self.line_just=max(self.line_just,len(sr))
for x in('\n',self.line_just*'-','\n',sr,'\n'):
self.log.write(x)
Utils.pprint('NORMAL',"%s :"%sr.ljust(self.line_just),sep='')
def check_message_2(self,sr,color='GREEN'):
self.log.write(sr)
self.log.write('\n')
Utils.pprint(color,sr)
def check_message(self,th,msg,state,option=''):
sr='Checking for %s %s'%(th,msg)
self.check_message_1(sr)
p=self.check_message_2
if state:p('ok '+str(option))
else:p('not found','YELLOW')
def check_message_custom(self,th,msg,custom,option='',color='PINK'):
sr='Checking for %s %s'%(th,msg)
self.check_message_1(sr)
self.check_message_2(custom,color)
def msg(self,msg,result,color=None):
self.start_msg('Checking for '+msg)
if not isinstance(color,str):
color=result and'GREEN'or'YELLOW'
self.end_msg(result,color)
def start_msg(self,msg):
try:
if self.in_msg:
return
except:
self.in_msg=0
self.in_msg+=1
self.line_just=max(self.line_just,len(msg))
for x in('\n',self.line_just*'-','\n',msg,'\n'):
self.log.write(x)
Utils.pprint('NORMAL',"%s :"%msg.ljust(self.line_just),sep='')
def end_msg(self,result,color):
self.in_msg-=1
if self.in_msg:
return
if not color:
color='GREEN'
if result==True:
msg='ok'
elif result==False:
msg='not found'
color='YELLOW'
else:
msg=str(result)
self.log.write(msg)
self.log.write('\n')
Utils.pprint(color,msg)
def find_program(self,filename,path_list=[],var=None,mandatory=False):
ret=None
if var:
if self.env[var]:
ret=self.env[var]
elif var in os.environ:
ret=os.environ[var]
if not isinstance(filename,list):filename=[filename]
if not ret:
for x in filename:
ret=find_program_impl(self.env,x,path_list,var,environ=self.environ)
if ret:break
self.check_message_1('Checking for program %s'%' or '.join(filename))
self.log.write(' find program=%r paths=%r var=%r\n -> %r\n'%(filename,path_list,var,ret))
if ret:
Utils.pprint('GREEN',str(ret))
else:
Utils.pprint('YELLOW','not found')
if mandatory:
self.fatal('The program %r is required'%filename)
if var:
self.env[var]=ret
return ret
def cmd_to_list(self,cmd):
if isinstance(cmd,str)and cmd.find(' '):
try:
os.stat(cmd)
except OSError:
return shlex.split(cmd)
else:
return[cmd]
return cmd
def __getattr__(self,name):
r=self.__class__.__dict__.get(name,None)
if r:return r
if name and name.startswith('require_'):
for k in['check_','find_']:
n=name.replace('require_',k)
ret=self.__class__.__dict__.get(n,None)
if ret:
def run(*k,**kw):
r=ret(self,*k,**kw)
if not r:
self.fatal('requirement failure')
return r
return run
self.fatal('No such method %r'%name)
def eval_rules(self,rules):
self.rules=Utils.to_list(rules)
for x in self.rules:
f=getattr(self,x)
if not f:self.fatal("No such method '%s'."%x)
try:
f()
except Exception,e:
ret=self.err_handler(x,e)
if ret==BREAK:
break
elif ret==CONTINUE:
continue
else:
self.fatal(e)
def err_handler(self,fun,error):
pass
def conf(f):
setattr(ConfigurationContext,f.__name__,f)
return f
def conftest(f):
ConfigurationContext.tests[f.__name__]=f
return conf(f)