mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2024-05-14 01:59:38 -04:00
497 lines
21 KiB
Python
Executable file
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()
|