From 20ef0fb0f751af27dad5d1662aa9635fe38a1d02 Mon Sep 17 00:00:00 2001 From: Stephen George Date: Mon, 13 Sep 2010 12:56:59 +0000 Subject: [PATCH] svn: r15890 --- windows/builder/check_gtk_install.py | 372 +++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 windows/builder/check_gtk_install.py diff --git a/windows/builder/check_gtk_install.py b/windows/builder/check_gtk_install.py new file mode 100644 index 000000000..fd01f0d87 --- /dev/null +++ b/windows/builder/check_gtk_install.py @@ -0,0 +1,372 @@ +import sys +import os +import _winreg +from ctypes.util import find_library +import getopt +import string + + +#==== Set up logging system +# need to also set up a logger for when run as a module. + +# change to set up a console logger in module global space. +# then add the file logger later once I know the path + + +import logging +logging.basicConfig(level=logging.DEBUG, + format='%(message)s', + datefmt='%H:%M', + filename= 'gtkcheck.log', + filemode='w') +#create a Handler for the console +console = logging.StreamHandler() +console.setLevel(logging.INFO) +#Set a simple format for console +formatter = logging.Formatter('%(levelname)-8s %(message)s') +console.setFormatter(formatter) +#add the console handler to the root handler +log = logging.getLogger('CheckGtkApp') +log.addHandler(console) + + +NOT_FOUND_STR ='Not Found' +#small selection of DLL's to test +testdlls = ['libgdk-win32-2.0-0.dll', 'libglib-2.0-0.dll', 'libgobject-2.0-0.dll', 'libcairo-2.dll', ] + +explain_exposed = ''' *********************************************************** + * It seems that other installations are exposing GTK DLL's + * to the operating system as they are in the environment + * path variable BEFORE the runtime directory. + * You should reorder the path variable to put your GTK + * runtime path before these other installations on the path''' + +explain_safe = ''' *************************************************************** + * While there are other installations of GTK DLL's on the path, + * it should be safe as they are on the path AFTER the runtime + * directory. ''' + +def RunExeCommand( app, args ): + cmd = app + ' ' + args + #print "Running: ", cmd + stdin, stdout, stderr = os.popen3( cmd ) + output = string.strip(stdout.read()) + #print output + err = stderr.read() + if err: + print err + return output + +def CheckGtkInReg(): + global gtkPathInRegistry, gtkVersionInRegistry, dllPathInRegistry, dllPathShort + log.info( '\n==== Checking Registry for GTK =====' ) + try: + with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\GTK\\2.0') as key: + gtkVersionInRegistry = _winreg.QueryValueEx(key, 'Version')[0] + gtkPathInRegistry = _winreg.QueryValueEx(key, 'Path')[0] + dllPathInRegistry = _winreg.QueryValueEx(key, 'DllPath')[0] + log.info( ' Version : %s'% gtkVersionInRegistry ) + log.info( ' Path : %s'% gtkPathInRegistry ) + log.info( ' DllPath : %s'% dllPathInRegistry ) + + except WindowsError, e: + log.info( '\n GTK registry key not found in registry' ) + log.info( ''' ******************************************************************** + * This might not be an error, but means I don't know the directory to + * your preferred GTK installation. + * - try passing in your GTK installation path.\n''' ) + log.info( '-' * 60 ) + log.info( usage ) + sys.exit(0) + +def WorkOutShortDosPath(): + global dllPathShort + log.info( '\n==== Use win32Api to query short path name for GTK =====' ) + try: + import win32api + dllPathShort = win32api.GetShortPathName(dllPathInRegistry) + log.info( ' DllPath8.3: %s' % dllPathShort ) + except ImportError: + log.info( ' **Cant query short path name, Win32Api not installed' ) + log.info( ' install from http://python.net/crew/mhammond/win32/' ) + log.info( ' if you want this function to work' ) + +def FindLibsWithCtypes(): + # use ctypes to check where windows finds it's DLL's + log.info( '\n==== Use ctypes to find dlls ====' ) + other_paths = [] + for dll in testdlls: + dllpathvalid = False + cpath = find_library(dll) + if cpath: + #print cpath + if cpath == os.path.join(dllPathInRegistry, dll) \ + or cpath == os.path.join(dllPathShort, dll): + dllpathvalid = True + + if not dllpathvalid: + pp = os.path.dirname(cpath) + if pp not in other_paths: + other_paths.append(pp) + else: + log.info( " ERROR:... ctypes failed to find %s" % dll) + if other_paths: + for pth in other_paths: + log.info( " ERROR: ctypes loaded some gtk dll's from %s" % pth ) + else: + log.info( " OK ... ctypes found dll's in %s" % os.path.dirname(cpath) ) + +def ScanDependencyFileForErrors(fname): + fin = open(fname, 'r') + lines = fin.readlines() + fin.close() + sysroot = os.environ["SystemRoot"] + capture = False + runtimedlls = {} + for line in lines: + if line.startswith(" Module"): # work out were paths end + pthend_idx = line.find("File Time Stamp") + acceptablePaths = [ dllPathShort.lower(), + dllPathInRegistry.lower(), + os.path.join(sysroot, 'system32').lower() + ] + if line.startswith('----- ------------'): + capture = True + if capture and line.startswith('['): + filename = line[5:pthend_idx].strip() + dirname = os.path.dirname(filename).strip() + parts = line[pthend_idx:].split() + OK = False + if dirname.startswith(os.path.join(sysroot, 'winsxs').lower()) \ + or dirname.startswith(os.path.join(sys.prefix, 'lib\site-packages\gtk-2.0').lower()): + OK = True + + for pth in acceptablePaths: + if dirname == pth.lower(): + OK = True + + if 'MSVCR90.DLL' in filename: + if parts[0] == 'Error': + runtimedlls[filename] = "Error dll not found" + else: + runtimedlls[filename] = parts[16] + + if OK == False: + if parts[0] == 'Error': + log.info( " %s \tError dll not found" %( filename)) + else: + log.info( " ERROR: %s \tVersion %s" %( filename, parts[16])) + for rtdll in runtimedlls: + if runtimedlls[rtdll].startswith("Error"): + log.info( '\n ERROR: MS runtime %s not found'%rtdll ) + else: + log.info( '\n MS runtime Version %s loaded from' % runtimedlls[rtdll] ) + log.info( " %s" %rtdll ) + log.info( '') + +def CheckWithDependencyWalker(): + log.info( '\n==== Checking with Dependency Walker ====' ) + log.info( ' Please be patient takes some time' ) + exe = os.path.join(scriptpath, 'depends.exe') + fout = os.path.join(scriptpath, 'depres.txt') + f2check = [ + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gtk/_gtk.pyd' ), + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/gobject/_gobject.pyd' ), + os.path.join(sys.prefix, 'Lib/site-packages/gtk-2.0/pangocairo.pyd' ), + ] + if os.path.isfile( exe ): + for ftest in f2check: + if os.path.isfile( ftest ): + #delete the output file before running command + try: + os.remove(fout) + except WindowsError, e: + pass + log.info( ' Testing file %s' % ftest ) + out = RunExeCommand(exe, '/c /f1 /ot "%s" "%s"' % (fout, ftest) ) + if os.path.isfile(fout): + ScanDependencyFileForErrors(fout) + else: + log.info( " ERROR: file %d does not exist", ftest ) + else: + log.info( ' Cannot check with dependency walker, not installed in local directory' ) + log.info( ' get dependency walker from http://www.dependencywalker.com/' ) + log.info( ' and unzip into this directory for it to work.' ) + +def CheckPathForOtherGtkInstalls(): + log.info( '\n====Checking environment path for other gtk installations====' ) + ePath = os.environ['path'] + dirs = ePath.split(';') + gtkpth_idx = 9999 + other_paths = [] + explain_level = 0 + for i, d in enumerate(dirs): + #print '==%s==' %d + if d == gtkPathInRegistry or d == dllPathInRegistry\ + or d == dllPathShort: + gtkpth_idx = i + continue + for fname in testdlls: + f = os.path.join(d, fname) + if os.path.isfile( f ): + #print ' Found Erronous gtk DLL %s' % f + if d not in other_paths: + other_paths.append(d) + if i < gtkpth_idx: # path appears BEFORE runtime path + log.info( ' ERROR: %s should not appear before runtime path' % d ) + explain_level = 2 + else: + log.info( ' FOUND: %s, Probably OK as appears AFTER runtime path' % d ) + if explain_level <= 1: + explain_level = 1 + if gtkpth_idx == 9999: + log.info( '\n ERROR: Runtime directory not on enviroment path' ) + log.info( " ** Runtime needs to be on path to load DLL's from\n" ) + if explain_level == 2: + log.info( explain_exposed ) + elif explain_level == 1: + log.info( explain_safe ) + if len(other_paths) == 0: + log.info( ' No other gtk installatons found\n' ) + +# ==== report what python thinks it's using ===== +MIN_PYTHON_VER = (2,5,1) +UNTESTED_PYTHON_VER = (3,0,0) + +MIN_GTK_VER = (2,10,11) +UNTESTED_GTK_VER = (2,16,7) + +MIN_PYGTK_VER = (2,10,6) +UNTESTED_PYGTK_VER = (2,12,2) + +MIN_GOBJECT_VER = (2,12,3) +UNTESTED_GOBJECT_VER = (2,14,3) + +MIN_CAIRO_VER = (1,2,6) +UNTESTED_CAIRO_VER = (1,4,13) + +def PrintFailedImport(appl, minVersion, result): + log.info( '--%s version %d.%d.%d or above.....\t %s' % (appl, minVersion ,result) ) + +def PrintVersionResult(appl, minVersion, actualVersion, untestedVersion): + minStr = '%d.%d.%d' % minVersion + actStr = '%d.%d.%d' % actualVersion + if minVersion <= actualVersion < untestedVersion: + result = '...OK' + elif actualVersion >= untestedVersion: + result = '...UNTESTED VERSION' + else: + result = '...FAILED' + log.info( '%s version %s or above.....\tfound %s %s' % (appl, minStr , actStr, result) ) + +def Import_pyGtkIntoPython(): + log.info( '\n==== Test import into python ====' ) + #py_str = 'found %d.%d.%d' % sys.version_info[:3] + PrintVersionResult(' Python ', MIN_PYTHON_VER, sys.version_info[:3], UNTESTED_PYTHON_VER) + + # Test the GTK version + try: + import gtk + + PrintVersionResult(' GTK+ ', MIN_GTK_VER, gtk.gtk_version, UNTESTED_GTK_VER ) + + #test the pyGTK version (which is in the gtk namespace) + PrintVersionResult(' pyGTK ', MIN_PYGTK_VER, gtk.pygtk_version, UNTESTED_PYGTK_VER ) + + except ImportError: + PrintFailedImport(' GTK+ ', MIN_GTK_VER, NOT_FOUND_STR) + PrintFailedImport(' pyGTK ', MIN_PYGTK_VER, 'Cannot test, ...GTK+ missing') + + + #test the gobject version + try: + import gobject + PrintVersionResult(' gobject', MIN_GOBJECT_VER, gobject.pygobject_version, UNTESTED_GOBJECT_VER) + + except ImportError: + PrintFailedImport(' gobject', MIN_GOBJECT_VER, NOT_FOUND_STR) + + + #test the cairo version + try: + import cairo + PrintVersionResult(' cairo ', MIN_CAIRO_VER, cairo.version_info, UNTESTED_CAIRO_VER ) + + except ImportError: + PrintFailedImport(' cairo ', MIN_CAIRO_VER, NOT_FOUND_STR) + + #test for glade + log.info( '\n==== See if libglade installed ====') + + try: + import gtk.glade + log.info( ' Glade tesing import of libglade .......\tOK\n' ) + except ImportError, e: + log.info( ' Glade importError: %s\n' % e ) + +if __name__ == '__main__': + usage = '''Check for common problems in GTK/pyGTK installation. +Usage: + python %s [options] [gtkPath] + +Arguments: + gtkPath Path to your GTK installation directory (not the bin dir) + +Options: + None + ''' %(os.path.basename(__file__) ) + + gtkPath = None + gtkPathInRegistry = NOT_FOUND_STR + gtkVersionInRegistry = NOT_FOUND_STR + dllPathInRegistry = NOT_FOUND_STR + dllPathShort = 'NoShortPath' + scriptpath = os.path.dirname(sys.argv[0]) + try: + opts, args = getopt.getopt(sys.argv[1:], "", + []) + + for o, a in opts: + if o in ("-h", "--help"): + log.info( usage ) + sys.exit(0) + + if len(args) > 1: + raise getopt.GetoptError, '\nERROR: Too many arguments' + for arg in args: + if os.path.isdir(arg): + gtkPath = arg + else: + raise getopt.GetoptError, '\nERROR: Not a valid GTK path %s' % arg + + except getopt.GetoptError, msg: + log.info( msg ) + log.info( '\n %s' % usage ) + sys.exit(2) + + import platform + winver = platform.win32_ver() + if len(winver) == 4: + log.info( '''\n==== platform.win32_ver() reports ==== + Operating System: %s + Version : %s + Service Pack : %s + OS type : %s''' % winver) + else: + os.info( winver ) + + if gtkPath: + gtkPathInRegistry = gtkPath + dllPathInRegistry = os.path.join(gtkPath, 'bin') + os.info( ' Using %s as GTK install path' % gtkPathInRegistry ) + os.info( ' Using %s as GTK dll path' % dllPathInRegistry ) + else: + CheckGtkInReg() + + WorkOutShortDosPath() + FindLibsWithCtypes() + CheckPathForOtherGtkInstalls() + Import_pyGtkIntoPython() + + CheckWithDependencyWalker() +