mupen64plus-oldsvn/configure
2009-04-10 00:05:44 +00:00

497 lines
21 KiB
Python
Executable file

#!/usr/bin/env python
#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# * Mupen64plus - configure *
# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
# * Copyright (C) 2009 DarkJeztr *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation; either version 2 of the License, or *
# * (at your option) any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * along with this program; if not, write to the *
# * Free Software Foundation, Inc., *
# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import sys
import subprocess
import os
import commands
from optparse import OptionParser, OptionGroup, OptionValueError, SUPPRESS_HELP
defaultFile = 'configure.gen'
defaultOpts = {
'NOBLIGHT':'0','NOJTTL':'0','NO_RESAMP':'0','NODUMMY':'0','PLUGINDBG':'0',
'NOGLN64':'0','NORICE':'0','NOGLIDE':'0', 'NOHLERSP':'0','NOMINPUT':'0',
'DBG_CORE':'0', 'DBG_COUNT':'0', 'DBG_COMPARE':'0', 'DBG_PROFILE':'0',
'DBG' : '0', 'DBGSYM' : '0', 'LIRC' : '1', 'Z64' : '1' , 'GUI' : 'GTK2',
'PREFIX' : '/usr/local', 'SHAREDIR' : '$(PREFIX)/share/mupen64plus',
'BINDIR' : '$(PREFIX)/bin', 'LIBDIR':'$(SHAREDIR)/plugins',
'MANDIR' : '$(PREFIX)/man/man1','PROFILE':'0',
'CONFIGURE.GEN' : 'Included' }
defaultHeader = """# configure.gen
# File Auto-Generated by ./configure
# DO NOT MODIFY
"""
optionTable = [
# Format: ['option string','make variable','value to assign',
# 'Group Identifier','help string']
# ** 'value=None' : option takes argument
['--enable-debuggui', 'DBG','1','OPT','add core debugger'],
['--disable-debuggui','DBG','0','OPT','remove core debugger'],
['--enable-lirc', 'LIRC','1','OPT','add lirc support'],
['--disable-lirc', 'LIRC','0','OPT','remove lirc support'],
['--with-nogui', 'GUI','NONE','OPT','build without GUI'],
['--with-gtk2gui', 'GUI','GTK2','OPT','build with GTK2 GUI'],
['--with-qt4gui', 'GUI','QT4','OPT','build with QT4 GUI'],
['--with-dummy','NODUMMY','0','PLG','enable dummy plugins'],
['--without-dummy','NODUMMY','1','PLG','disable dummy plugins'],
['--with-ricevideo','NORICE','0','PLG',"enable Rice's video plugin"],
['--without-ricevideo','NORICE','1','PLG',"disable Rice's video plugin"],
['--with-gln64video','NOGLN64','0','PLG',"enable glN64 video plugin"],
['--without-gln64video','NOGLN64','1','PLG',"disable glN64 video plugin"],
['--with-glidevideo','NOGLIDE','0','PLG',"enable Glide64 video plugin"],
['--without-glidevideo','NOGLIDE','1','PLG',"disable Glide64 video plugin"],
['--with-z64', 'Z64','1','PLG',"enable Ziggy's lle rsp plugin"],
['--without-z64', 'Z64','0','PLG',"disable Ziggy's lle rsp plugin"],
['--with-azimerrsp','NOHLERSP','0','PLG',"enable Azimer's hle rsp plugin"],
['--without-azimerrsp','NOHLERSP','1','PLG',"disable Azimer's hle rsp plugin"],
['--with-blightinput', 'NOBLIGHT','0','PLG','enable Blight-Input plugin'],
['--without-blightinput', 'NOBLIGHT','1','PLG','disable Blight-Input plugin'],
['--with-mupeninput', 'NOMINPUT','0','PLG','enable Mupen64 Input plugin'],
['--without-mupeninput', 'NOMINPUT','1','PLG','disable Mupen64 Input plugin'],
['--with-jttlaudio','NOJTTL','0','PLG','enable JTTL audio plugin'],
['--without-jttlaudio','NOJTTL','1','PLG','disable JTTL audio plugin'],
['--enable-jttlresample','NO_RESAMP','0','PLG','enable JTTL SINC resampler'],
['--disable-jttlresample','NO_RESAMP','1','PLG','disable JTTL SINC resampler'],
['--enable-debug', 'DBGSYM','1','DBG','add debugging symbols'],
['--disable-debug','DBGSYM','0','DBG','remove debugging symbols'],
['--enable-gprof','PROFILE','1','DBG','enable gprof profiling'],
['--disable-gprof','PROFILE','0','DBG','disable gprof profiling'],
['--enable-dbgcore','DBG_CORE','1','DBG','print r4300 debug printfs'],
['--disable-dbgcore','DBG_CORE','0','DBG','disable r4300 debug printfs'],
['--enable-corecount','DBG_COUNT','1','DBG','print r4300 instruction count (64bit only)'],
['--disable-corecount','DBG_COUNT','0','DBG','disable r4300 instruction count (64bit only)'],
['--enable-corecomp','DBG_COMPARE','1','DBG','enable r4300 core synched debugging'],
['--disable-corecomp','DBG_COMPARE','0','DBG','disable r4300 core synched debugging'],
['--enable-profiling','DBG_PROFILE','1','DBG','dump r4300 dynarec profiling data'],
['--disable-profiling','DBG_PROFILE','0','DBG','disable r4300 dynarec profiling data'],
['--enable-plugindebug','PLUGINDBG','1','DBG','enable extra debugging output for all plugins '],
['--disable-plugindebug','PLUGINDBG','0','DBG','hide extra debugging output for all plugins '],
['--prefix-dir','PREFIX',None,'PTH','sets the prefix for install'],
['--data-dir','SHAREDIR',None,'PTH','path to install shared data'],
['--binary-dir','BINDIR',None,'PTH','path to install the binaries'],
['--plugin-dir','LIBDIR',None,'PTH','path to install the plugins'],
['--man-dir','MANDIR',None,'PTH','path to the manual page'],
]
optionHeading = { 'OPT':'Optional Features','PLG':'Plugin Options',
'DBG':'Debugging Options', 'PTH':'Path Options'}
def checkDeps(config, options):
"""Checks dependancies, and disables options requiring unmet deps"""
#first assemble the dependency trees
pkgTest = ShellTest(['which','pkg-config'],'pkg-config not installed')
gtkTest = ShellTest(['pkg-config','gtk+-2.0'],'gtk+-2.0 not installed')
gtkTest.addDep(pkgTest)
sdlTest = ShellTest(['which','sdl-config'],'SDL development libraries not installed')
glewTest = CompileTest('GL/glew.h','-lGLEW','Glew not installed')
ftglTest = ShellTest(['pkg-config','ftgl'],'Ftgl not installed')
ftglTest.addDep(pkgTest)
sdl_flags = commands.getoutput("sdl-config --cflags --libs").split()
sdlttfTest = CompileTest('SDL/SDL_ttf.h',sdl_flags+['-lSDL_ttf'],'SDL-TTF development libraries not installed')
resampTest = ShellTest(['pkg-config','samplerate'],'libsamplerate not installed')
resampTest.addDep(pkgTest)
z64Test = ShellTest()
z64Test.addDep(glewTest)
z64Test.addDep(ftglTest)
z64Test.addDep(sdlTest)
coreTest = ShellTest()
coreTest.addDep(sdlTest)
blightTest = ShellTest()
blightTest.addDep(sdlTest)
blightTest.addDep(sdlttfTest)
#The following plugins share the core's dependancy on SDL, but are not tested as
#configure aborts testing if the core's deps are not bet
# glN64, ricevideo, glide64, jttlaudio, mupen64input
dbgTest = CompileTest('dis-asm.h',message='binutils not installed')
lircTest = CompileTest('lirc/lirc_client.h','-llirc_client','LIRC not installed')
# perform checks
# note that the ENTIRE dependency tree should be assembled before any of these tests are performed
if not coreTest:
print "Cannot build mupen64plus: ", coreTest.failedDep()
return False
if(config['NOJTTL']=='0'):
if(config['NO_RESAMP']=='0') and not resampTest:
config['NO_RESAMP']='1'
if(options.verbose):
sys.stderr.write('Disabling JTTL SYNC resampling support: ')
sys.stderr.write(resampTest.failedDep())
sys.stderr.write('\n')
if(config['NOBLIGHT'] =='0') and not blightTest:
config['NOBLIGHT'] = '1'
if(options.verbose):
sys.stderr.write('Disabling Blight_Input Plugin: ')
sys.stderr.write(blightTest.failedDep())
sys.stderr.write('\n')
if(config['Z64']=='1') and not z64Test:
config['Z64'] = '0'
if(options.verbose):
sys.stderr.write('Disabling Z64 Plugin: ')
sys.stderr.write(z64Test.failedDep())
sys.stderr.write('\n')
if(config['LIRC']=='1') and not lircTest:
config['LIRC'] = '0'
if(options.verbose):
sys.stderr.write('Disabling LIRC support: ')
sys.stderr.write(lircTest.failedDep())
sys.stderr.write('\n')
if(config['DBG']=='1'):
if not dbgTest:
config['DBG'] = '0'
if(options.verbose):
sys.stderr.write('Disabling Graphical Debugger: ')
sys.stderr.write(dbgTest.failedDep())
sys.stderr.write('\n')
elif config['GUI']=='NONE':
config['DBG'] = '0'
if(options.verbose):
sys.stderr.write('Disabling Graphical Debugger: ')
sys.stderr.write('Must have a gui enabled')
sys.stderr.write('\n')
#make sure we have at least one of each plugin to proceed
#Check for video plugins
if(config['NODUMMY']=='1' and config['NOGLIDE']=='1'and
config['Z64']=='0' and config['NORICE']=='1' and
config['NOGLN64']=='1'):
print "Cannot build mupen64plus: ",
print "No video plugins selected"
return False
#Check for audio plugins
if(config['NODUMMY']=='1' and config['NOJTTL']=='1'):
print "Cannot build mupen64plus: ",
print "No audio plugins selected"
return False
#Check for input plugins
if(config['NODUMMY']=='1' and config['NOBLIGHT']=='1' and
config['NOMINPUT']=='1'):
print "Cannot build mupen64plus: ",
print "No input plugins selected"
return False
#Check for rsp plugins
if(config['Z64']=='0' and config['NOHLERSP']=='1'):
print "Cannot build mupen64plus: ",
print "No RSP plugins selected"
return False
return True
def printSettings(config):
#print "\nCurrent Settings to write to", defaultFile
print "Options:"
if config['DBG']=='1': print "\tGraphical Debugger"
if config['LIRC']=='1': print "\tLIRC Support"
if config['DBGSYM']=='1': print "\tDebug symbols"
if config['GUI']=='NONE': print "\tNo GUI"
elif config['GUI']=='GTK2': print "\tGTK2 GUI"
elif config['GUI']=='QT4': print "\tQT4 GUI"
else:
print " BAD GUI OPTION"
if config['DBG_CORE']=='1': print "\tR4300 debugging output"
if config['DBG_COUNT']=='1': print "\tR4300 instruction count output"
if config['DBG_COMPARE']=='1': print "\tR4300 core-synched debugging"
if config['DBG_PROFILE']=='1': print "\tR4300 dynarec profiling output"
if config['PLUGINDBG']=='1': print "\tPlugin debugging output"
print "Plugins:"
if config['Z64']=='1': print "\tZ64 RSP & Video"
if config['NOGLN64']=='0': print "\tglN64 Video"
if config['NORICE']=='0': print "\tRice Video"
if config['NOGLIDE']=='0': print "\tGlide64 Video"
if config['NOJTTL']=='0':
if config['NO_RESAMP']=='0': print "\tJTTL Audio with SINC resampler"
else: print "\tJTTL Audio without SINC resampler"
if config['NOHLERSP']=='0': print "\tAzimer HLE RSP"
if config['NOBLIGHT']=='0': print "\tBlight Input"
if config['NOMINPUT']=='0': print "\tMupen64 Input"
if config['NODUMMY']=='0':
print "\tDummy Video\n\tDummy Audio\n\tDummy Input"
print "Directories:"
print " Install (PREFIX): ", config['PREFIX']
print " Shared (SHAREDIR): ", config['SHAREDIR']
print " Binary (BINDIR): ", config['BINDIR']
print " Plugins (LIBDIR): ", config['LIBDIR']
print " Manual (MANDIR): ", config['MANDIR']
def constructParser(config):
parser = OptionParser()
for heading in optionHeading:
group = OptionGroup(parser, optionHeading[heading])
for entry in optionTable:
if entry[3]==heading:
if entry[2]==None: # we have an option with an arg
group.add_option(entry[0], help=entry[4], metavar="DIR",
nargs=1, type='string', action='callback',
callback=config.setOption )
else:
if entry[2]==defaultOpts[entry[1]]:
hlpstr=SUPPRESS_HELP
else: hlpstr=entry[4]
group.add_option(entry[0], help=hlpstr,
action='callback', callback=config.setOption )
parser.add_option_group(group)
option = OptionGroup(parser, 'Configure Script Options')
option.add_option('-q', '--quiet', help='suppress output',
action='store_false', dest='verbose', default=True)
option.add_option('-n', '--nosave', help='do not save changes',
action='store_false', dest='save', default=True)
option.add_option('-f', '--force', help='ignore errors during read',
action='store_true', dest='force', default=False)
option.add_option('-p', '--previous', help='load previous settings',
action='store_true', dest='previous', default=False)
option.add_option('-d', '--no-deps', help='skip dependancy checks',
action='store_false', dest='checkdeps', default=True)
parser.add_option_group(option)
return parser
class ConfigFile(dict):
"""Handler for make-compatable config files"""
def setOption(self, option, opt, value, parser):
for entry in optionTable:
if opt==entry[0]:
if entry[2]==None:
self[entry[1]]=value
else:
self[entry[1]]=entry[2]
return
#Handle option mismatches - shouldn't be possible
raise OptionValueError( ''.join(['Invalid option: ', opt]) )
def initialize(self, defaultDict=defaultOpts):
self.__loaderror = False
self.clear()
self.update( defaultDict )
def load(self, fileName=defaultFile):
FILE = None
self.__loaderror = False
try:
FILE = open(fileName,'r')
lineNum = 0
for curLine in FILE:
curLine = curLine.split('#')[0] #strip comments
lineNum=lineNum+1
if curLine.isspace() or len(curLine) < 1:
continue #increment counter and skip line if it's blank
if (curLine.count('=') == 1):
curLineChunks = curLine.split('=')
if (len(curLineChunks[0]) == 0
or curLineChunks[0].isspace()):
sys.stderr.write("ERROR: Blank key in {1} line: {0}\n"
.replace("{0}", str(lineNum)).replace('{1}',defaultFile) )
self.__loaderror = True
else:
self[curLineChunks[0].strip()]=curLineChunks[1].strip()
else:
sys.stderr.write('ERROR: Bad assignment in {1} line: {0}\n'
.replace('{0}',str(lineNum)).replace('{1}',defaultFile) )
self.__loaderror = True
finally:
if(FILE <> None):
FILE.close()
def save(self, fileName=defaultFile, header=defaultHeader):
try:
FILE = open(fileName,'w+')
FILE.writelines(header)
for key in self:
FILE.write(''.join([key ,' = ', self[key], '\n']))
finally:
if(FILE <> None):
FILE.close()
def getError(self):
return self.__loaderror
def __init__(self, fileName=defaultFile, defaultDict=defaultOpts):
self.__loaderror = False
self.initialize(defaultDict)
try:
self.load(fileName)
except IOError:
self.initialize(defaultDict)
class ShellTest:
"""Class to execute some shell command and store the results"""
def __init__(self,command='pwd',message=''):
self.message = message
self.deps = []
self.checked = False
self.value = False
self.__command = command
def result(self):
"""Process dep to see if it passes or not, and does so recursively"""
if(self.checked == False):
#print ''.join(["Checking if ",self.message])
self.checked = True
try:
self.value = (subprocess.call(self.__command,
stdout=subprocess.PIPE,stderr=subprocess.PIPE)) == 0
except OSError:
self.value = False
return self.value
def failedDep(self):
"""Returns string describing the reason this dep failed"""
for dep in self.deps:
if not dep:
return dep.failedDep()
return self.message
def findDep(self, find):
"""Returns true if the dependancy 'find' is a dependancy of this dep"""
if(self == find):
return True
for dep in self.deps:
if dep.findDep(find):
return True
return False
def addDep(self, dep):
self.deps.append(dep)
self.checked = False
assert(dep.findDep(self) == False) #avoid circular dependancy graphs
def __nonzero__(self):
for dep in self.deps:
if not dep:
return False
return self.result()
class CompileTest(ShellTest):
"""Class to build a test app and compile it with gcc"""
def __init__(self,header='stdio.h',library='-lm',message=''):
self.message = message
self.deps = []
self.checked = False
self.value = False
self.__header = header
self.__library = library
def result(self):
"""Gets result by creating tmp.c file and running gcc"""
if(self.checked == False):
#print ''.join(["Checking if ",self.message])
self.checked = True
try:
try:
srcfile = open('./tmp.c','w')
main_func = "int main(int argc, char*argv[])"
srcfile.write(''.join(['#include<',self.__header,'>\n',main_func,'{}\n']))
finally:
srcfile.close()
try:
# allow __library to be either a string or a list
if isinstance(self.__library, list):
call = ['gcc','tmp.c']+self.__library+['-o','tmp.out']
else:
call = ['gcc','tmp.c', self.__library, '-o','tmp.out']
self.value=(subprocess.call(call,
stdout=subprocess.PIPE,stderr=subprocess.PIPE) == 0)
except OSError:
assert("Could not execute gcc"==0)
finally:
try:
os.remove('./tmp.c')
except OSError:
pass
try:
os.remove('./tmp.out')
except OSError:
pass
return self.value
def main():
#get options and apply new settings to configChanges
configChanges = ConfigFile('',[])
parser = constructParser(configChanges)
(options,args) = parser.parse_args()
if len(args) > 0: #should be no extra args after parsing
parser.error('try "./configure --help"')
if(options.previous):
config = ConfigFile() #load settings from existing
else:
config = ConfigFile('') #load default settings
config.update(configChanges) #apply settings from command line
if(options.checkdeps):
if not checkDeps(config, options): #check that current settings have deps met
print "\nconfigure: error: You can skip dependancy checks with '-d'"
return
if(options.verbose):
printSettings(config)
#do not write settings if we were told not to, or if settings were loaded with errors
#unless forced to save
if(options.save and (options.force or not config.getError()) ):
if(options.verbose):
print "\nSaving settings to:", defaultFile
config.save()
elif(config.getError()):
print "NOT SAVING: Due to errors reading", defaultFile
print "Use '--force' to override"
if __name__ == '__main__':
main()