Lenard Lindstrom avatar Lenard Lindstrom committed 859ceb5

Updated Windows build process so works better with MSYS.
Library searches are more elaborate.
setup.py is now VC/MinGW agnostic.

Comments (0)

Files changed (47)

 PNG = -lpng
 JPEG = -ljpeg
 SCRAP = -lX11
+DLL_SDL = -Lprebuilt/lib/SDL.dll
+DLL_FONT = -Lprebuilt/lib/SDL_ttf.dll
+DLL_IMAGE = -Lprebuilt/lib/SDL_image.dll
+DLL_MIXER = -Lprebuilt/lib/SDL_mixer.dll
+DLL_SMPEG = -Lprebuilt/lib/smpeg.dll
+DLL_TIFF = -Lprebuilt/lib/libtiff.dll
+DLL_PNG = -Lprebuilt/lib/libpng13.dll
+DLL_JPEG = -Lprebuilt/lib/jpeg.dll
+DLL_Z = -Lprebuilt/lib/zlib1.dll
+DLL_VORBISFILE = -Lprebuilt/lib/libvorbisfile-3.dll
+DLL_VORBIS = -Lprebuilt/lib/libvorbis-0.dll
+DLL_OGG = -Lprebuilt/lib/libogg-0.dll
 #--EndConfig
 
 #DEBUG = -C-W -C-Wall
 #auto-copy needed DLLs into the pygame installation folder.
 #you can simply ignore these lines under non-windows, no need to
 #comment out.
-COPYLIB_smpeg $(SDL) $(SMPEG) $(DEBUG)
+COPYLIB__SDL $(DLL_SDL)
+COPYLIB__SDL_ttf $(DLL_FONT)
+COPYLIB__SDL_image $(DLL_IMAGE)
+COPYLIB__SDL_mixer $(DLL_MIXER)
+COPYLIB__smpeg $(DLL_SMPEG)
+COPYLIB__tiff $(DLL_TIFF)
+COPYLIB__png $(DLL_PNG)
+COPYLIB__jpeg $(DLL_JPEG)
+COPYLIB__z $(DLL_Z)
+COPYLIB__vorbisfile $(DLL_VORBISFILE)
+COPYLIB__vorbis $(DLL_VORBIS)
+COPYLIB__ogg $(DLL_OGG)
 # BUG	= fixed a bug that was (or could have been) crashing
 #
 #
+Jan 24, 2008
+    Updated the configuration and build process under Windows. In config_msys.py
+       and config.py os.popen is replaced with the newer subprocess.Popen so
+       the MSYS will run. Calls to raw_input now show the prompt on an MSYS
+       console. In an MSYS build paths written to Setup are now Windows paths
+       for distutils. The hard coded DLL file paths have been removed from setup.py.
+       In now gets the paths from Setup. Consequently, setup.py is now VC/MinGW
+       agnostic.
+
 Jan 8, 2008
     pygame.surfarray now can change between Numeric and numpy using the
        new methods pygame.surfarray.use_array () and
 
 def confirm(message):
     "ask a yes/no question, return result"
-    reply = raw_input('\n' + message + ' [y/N]:')
-    if reply and string.lower(reply[0]) == 'y':
-        return 1
-    return 0
+    #The output must be flushed for the prompt to be visible on MSYS bash
+    sys.stdout.write("\n%s [Y/n]:" % message)
+    sys.stdout.flush()
+    reply = raw_input()
+    if reply and string.lower(reply[0]) == 'n':
+        return 0
+    return 1
 
 def prepdep(dep, basepath):
     "add some vars to a dep"
 """Config on Msys mingw"""
 
+import dll
 import os, sys, string
+import subprocess
+import re
 from glob import glob
 from distutils.sysconfig import get_python_inc
+import itertools
 
 configcommand = os.environ.get('SDL_CONFIG', 'sdl-config',)
 configcommand = configcommand + ' --version --cflags --libs'
 localbase = os.environ.get('LOCALBASE', '')
 
-#these get prefixes with '/usr' and '/usr/local' or the $LOCALBASE
+#these get prefixes with '/usr/local' and /mingw or the $LOCALBASE
 origincdirs = ['/include', '/include/SDL', '/include/SDL11',
-               'include/smpeg' ]
+               '/include/smpeg' ]
 origlibdirs = ['/lib']
 
+
+class ConfigError(Exception):
+    pass
+
+msys_root = os.path.split(os.path.split(os.environ['SHELL'])[0])[0]  # Get msys root directory
+try:
+    mingw_root = os.environ['MINGW_ROOT_DIRECTORY']
+except KeyError:
+    pass
+check_for_drive = re.compile('/[A-Z]/', re.I).match
+def has_drive(path):
+    return check_for_drive(path) is not None
+
+class ConvertionError(ConfigError):
+    pass
+
+def msys_to_windows(path):
+    """Return a Windows translation of an MSYS path
+
+    The Unix path separator is uses as it survives the distutils setup file read process.
+    """
+    if path.startswith('/usr'):
+        path =  msys_root + path[4:]
+    elif path.startswith('/mingw'):
+        try:
+            path =  mingw_root + path[6:]
+        except NameError:
+            raise ConversionError('MINGW_ROOT_DIRECTORY environment variable undefined')
+    elif has_drive(path):
+        path =  path[1] + ":" + path[2:]
+    elif path == '/':
+        path = msys_root
+    elif path.startswith('/'):
+        path =  msys_root + path
+    return path.replace(os.sep, '/')
+
+def path_join(a, *p):
+    return os.path.join(a, *p).replace(os.sep, '/')
+path_split = os.path.split
+
 def confirm(message):
     "ask a yes/no question, return result"
-    reply = raw_input('\n' + message + ' [Y/n]:')
+    #The output must be flushed for the prompt to be visible on MSYS bash
+    sys.stdout.write("\n%s [Y/n]:" % message)
+    sys.stdout.flush()
+    reply = raw_input()
     if reply and string.lower(reply[0]) == 'n':
         return 0
     return 1
 
 class DependencyProg:
+    needs_dll = True
     def __init__(self, name, envname, exename, minver, defaultlibs):
         self.name = name
         command = os.environ.get(envname, exename)
+        drv, pth = os.path.splitdrive(command)
+        if drv:
+            command = '/' + drv[0] + pth
+        shell = os.environ['SHELL']
         self.lib_dir = ''
         self.inc_dir = ''
         self.libs = []
         self.cflags = ''
         try:
-            config = os.popen(command + ' --version --cflags --libs').readlines()
-            flags = string.split(string.join(config[1:], ' '))
-            self.ver = string.strip(config[0])
+            config = subprocess.Popen([shell, command, '--version', '--cflags', '--libs'],
+                                      stdout=subprocess.PIPE
+                                      ).communicate()[0]
+            ver, flags = config.split('\n', 1)
+            self.ver = ver.strip()
+            flags = flags.split()
             if minver and self.ver < minver:
                 err= 'WARNING: requires %s version %s (%s found)' % (self.name, self.ver, minver)
                 raise ValueError, err
             self.found = 1
             self.cflags = ''
             for f in flags:
-                if f[:2] in ('-l', '-D', '-I', '-L'):
+                if f[:2] in ('-I', '-L'):
+                    self.cflags += f[:2] + msys_to_windows(f[2:]) + ' '
+                elif f[:2] in ('-l', '-D'):
                     self.cflags += f + ' '
                 elif f[:3] == '-Wl':
                     self.cflags += '-Xlinker ' + f + ' '
             print self.name + '        '[len(self.name):] + ': not found'
 
 class Dependency:
+    needs_dll = True
     def __init__(self, name, checkhead, checklib, libs):
         self.name = name
         self.inc_dir = None
         self.cflags = ''
     
     def configure(self, incdirs, libdirs):
-        incname = self.checkhead
-        libnames = self.checklib, string.lower(self.name)
+        self.find_inc_dir(incdirs)
+        self.find_lib_dir(libdirs)
         
-        for dir in incdirs:
-            path = os.path.join(dir, incname)
-            if os.path.isfile(path):
-                self.inc_dir = dir
-        for dir in libdirs:
-            for name in libnames:
-                path = os.path.join(dir, name)
-                if filter(os.path.isfile, glob(path+'*')):
-                    self.lib_dir = dir
-                
         if self.lib_dir and self.inc_dir:
             print self.name + '        '[len(self.name):] + ': found'
             self.found = 1
         else:
             print self.name + '        '[len(self.name):] + ': not found'
 
+    def find_inc_dir(self, incdirs):
+        incname = self.checkhead
+        for dir in incdirs:
+            path = path_join(dir, incname)
+            if os.path.isfile(path):
+                self.inc_dir = dir
+                return
+
+    def find_lib_dir(self, libdirs):
+        libname = self.checklib
+        for dir in libdirs:
+            path = path_join(dir, libname)
+            if filter(os.path.isfile, glob(path+'*')):
+                self.lib_dir = dir
+                return
+
+        
 class DependencyPython:
+    needs_dll = False
     def __init__(self, name, module, header):
         self.name = name
         self.lib_dir = ''
             except ImportError:
                 self.found = 0
         if self.found and self.header:
-            fullpath = os.path.join(get_python_inc(0), self.header)
+            fullpath = path_join(get_python_inc(0), self.header)
             if not os.path.isfile(fullpath):
                 self.found = 0
             else:
         else:
             print self.name + '        '[len(self.name):] + ': not found'
 
-sdl_lib_name = 'SDL'
-if sys.platform.find('bsd') != -1:
-    sdl_lib_name = 'SDL-1.1'
+class DependencyWin:
+    needs_dll = False
+    def __init__(self, name, libs):
+        self.name = name
+        self.inc_dir = None
+        self.lib_dir = None
+        self.libs = libs
+        self.found = 1
+        self.cflags = ''
+        
+    def configure(self, incdirs, libdirs):
+        pass
+
+class DependencyDLL:
+    needs_dll = False
+    def __init__(self, name):
+        self.name = 'DLL_' + name
+        self.inc_dir = None
+        self.lib_dir = '_'
+        self.libs = []
+        self.found = 1  # Alway found to make its COPYLIB work
+        self.cflags = ''
+        self.lib_name = name
+        self.file_name_test = dll.tester(name)
+
+    def configure(self, incdirs, libdirs, start=None):
+        omit = []
+        if start is not None:
+            if self.set_path(start):
+                return
+            omit.append(start)
+            p, f = path_split(start)
+            if f == 'lib' and self.set_path(path_join(p, 'bin')):
+                return
+            omit.append(start)
+        # Search other directories
+        for dir in libdirs:
+            if dir not in omit:
+                if self.set_path(dir):
+                    return
+                p, f = path_split(dir)
+                if f == 'lib' and self.set_path(path_join(p, 'bin')):  # cond. and
+                    return
+
+    def set_path(self, wdir):
+        test = self.file_name_test
+        try:
+            files = os.listdir(wdir)
+        except:
+            pass
+        else:
+            for f in files:
+                if test(f) and os.path.isfile(path_join(wdir, f)):
+                    # Found
+                    self.lib_dir = path_join(wdir, f)
+                    return True
+        # Not found
+        return False
+
 
 def main():
     print '\nHunting dependencies...'
     DEPS = [
-        DependencyProg('SDL', 'SDL_CONFIG', 'sdl-config', '1.2', ['sdl']),
-        Dependency('FONT', 'SDL_ttf.h', 'libSDL_ttf.so', ['SDL_ttf']),
-        Dependency('IMAGE', 'SDL_image.h', 'libSDL_image.so', ['SDL_image']),
-        Dependency('MIXER', 'SDL_mixer.h', 'libSDL_mixer.so', ['SDL_mixer']),
+        DependencyProg('SDL', 'SDL_CONFIG', 'sdl-config', '1.2', ['SDL']),
+        Dependency('FONT', 'SDL_ttf.h', 'libSDL_ttf.dll.a', ['SDL_ttf']),
+        Dependency('IMAGE', 'SDL_image.h', 'libSDL_image.dll.a', ['SDL_image']),
+        Dependency('MIXER', 'SDL_mixer.h', 'libSDL_mixer.dll.a', ['SDL_mixer']),
         DependencyProg('SMPEG', 'SMPEG_CONFIG', 'smpeg-config', '0.4.3', ['smpeg']),
+        Dependency('PNG', 'png.h', 'libpng.dll.a', ['png']),
+        Dependency('JPEG', 'jpeglib.h', 'libjpeg.dll.a', ['jpeg']),
+        DependencyWin('SCRAP', ['user32', 'gdi32']),
+        DependencyDLL('TIFF'),
+        DependencyDLL('VORBISFILE'),
+        DependencyDLL('VORBIS'),
+        DependencyDLL('OGG'),
+        DependencyDLL('Z'),
     ]
 
     if not DEPS[0].found:
     if localbase:
         incdirs = [localbase+d for d in origincdirs]
         libdirs = [localbase+d for d in origlibdirs]
-    incdirs = ["/usr"+d for d in origincdirs]
-    libdirs = ["/usr"+d for d in origlibdirs]
-    incdirs += ["/usr/local"+d for d in origincdirs]
-    libdirs += ["/usr/local"+d for d in origlibdirs]
+    else:
+        incdirs = []
+        libdirs = []
+    incdirs += [msys_to_windows("/usr/local"+d) for d in origincdirs]
+    libdirs += [msys_to_windows("/usr/local"+d) for d in origlibdirs]
+    incdirs += [msys_to_windows("/mingw"+d) for d in origincdirs]
+    libdirs += [msys_to_windows("/mingw"+d) for d in origlibdirs]
     for arg in string.split(DEPS[0].cflags):
         if arg[:2] == '-I':
             incdirs.append(arg[2:])
         elif arg[:2] == '-L':
             libdirs.append(arg[2:])
+    dll_deps = []
     for d in DEPS:
         d.configure(incdirs, libdirs)
+        if d.needs_dll:
+            dll_dep = DependencyDLL(d.name)
+            dll_dep.configure(incdirs, libdirs, d.lib_dir)
+            dll_deps.append(dll_dep)
 
-
+    DEPS += dll_deps
+    for d in DEPS:
+        if isinstance(d, DependencyDLL):
+            if d.lib_dir == '':
+                print "DLL for %-12s: not found" % d.lib_name
+            else:
+                print "DLL for %-12s: %s" % (d.lib_name, d.lib_dir)
+    
     for d in DEPS[1:]:
         if not d.found:
             if not confirm("""
 Warning, some of the pygame dependencies were not found. Pygame can still
 compile and install, but games that depend on those missing dependencies
 will not run. Would you like to continue the configuration?"""):
-                raise SystemExit
+                raise SystemExit()
             break
 
     return DEPS
 
 if __name__ == '__main__':
-    print """This is the configuration subscript for Unix.
+    print """This is the configuration subscript for MSYS.
 Please run "config.py" for full configuration."""
 
 """Config on Windows"""
 
+import dll
 import os, sys
 from glob import glob
 from distutils.sysconfig import get_python_inc
 
 huntpaths = ['..', '..\\..', '..\\*', '..\\..\\*']
 
+
 class Dependency:
     inc_hunt = ['include']
     lib_hunt = ['VisualC\\SDL\\Release', 'VisualC\\Release', 'Release', 'lib']
             self.inc_dir = self.findhunt(self.path, Dependency.inc_hunt)
             self.lib_dir = self.findhunt(self.path, Dependency.lib_hunt)
 
+
 class DependencyPython:
     def __init__(self, name, module, header):
         self.name = name
         else:
             print self.name + '        '[len(self.name):] + ': not found'
 
+
+class DependencyDLL(Dependency):
+    def __init__(self, name, wildcards=None, link=None):
+        Dependency.__init__(self, 'DLL_' + name, wildcards, [])
+        self.lib_name = name
+        self.test = dll.tester(name)
+        self.lib_dir = '_'
+        self.found = 1
+        self.link = link
+
+    def configure(self):
+        if self.link is None and self.wildcards:
+            self.hunt()
+            self.choosepath()
+        else:
+            self.path = self.link.path
+        if self.path is not None:
+            self.hunt_dll()
+
+    def hunt_dll(self):
+        for dir in self.lib_hunt:
+            path = os.path.join(self.path, dir)
+            try:
+                entries = os.listdir(path)
+            except:
+                pass
+            else:
+                for e in entries:
+                    if self.test(e) and os.path.isfile(os.path.join(path, e)):
+                        # Found
+                        self.lib_dir = os.path.join(path, e).replace('\\', '/')
+                        print "DLL for %s is %s" % (self.lib_name, self.lib_dir)
+                        return
+        print "DLL for %s not found" % self.lib_name
+
+                    
+class DependencyWin:
+    def __init__(self, name, libs):
+        self.name = name
+        self.inc_dir = None
+        self.lib_dir = None
+        self.libs = libs
+        self.found = 1
+        self.cflags = ''
+        
+    def configure(self):
+        pass
+
+
 DEPS = [
-    Dependency('SDL', ['SDL-[0-9].*'], ['SDL'], 1),
-    Dependency('FONT', ['SDL_ttf-[0-9].*'], ['SDL_ttf']),
-    Dependency('IMAGE', ['SDL_image-[0-9].*'], ['SDL_image']),
-    Dependency('MIXER', ['SDL_mixer-[0-9].*'], ['SDL_mixer']),
-    Dependency('SMPEG', ['smpeg-[0-9].*'], ['smpeg']),
-    Dependency('SCRAP', ['user32.*', 'gdi32.*'], ['user32', 'gdi32']),
+    Dependency('SDL', ['SDL-[1-9].*'], ['SDL'], 1),
+    Dependency('FONT', ['SDL_ttf-[2-9].*'], ['SDL_ttf']),
+    Dependency('IMAGE', ['SDL_image-[1-9].*'], ['SDL_image']),
+    Dependency('MIXER', ['SDL_mixer-[1-9].*'], ['SDL_mixer']),
+    Dependency('SMPEG', ['smpeg-[0-9].*', 'smpeg'], ['smpeg']),
+    DependencyWin('SCRAP', ['user32', 'gdi32']),
+    Dependency('JPEG', ['jpeg-[6-9]*'], ['jpeg']),
+    Dependency('PNG', ['libpng-[1-9].*'], ['png']),
+    DependencyDLL('TIFF', ['tiff-[3-9].*']),
+    DependencyDLL('VORBIS', ['libvorbis-[1-9].*']),
+    DependencyDLL('OGG', ['libogg-[1-9].*']),
+    DependencyDLL('Z', ['zlib-[1-9].*']),
+]
+
+DEPS += [
+    DependencyDLL('SDL', link=DEPS[0]),
+    DependencyDLL('FONT', link=DEPS[1]),
+    DependencyDLL('IMAGE', link=DEPS[2]),
+    DependencyDLL('MIXER', link=DEPS[3]),
+    DependencyDLL('SMPEG', link=DEPS[4]),
+    DependencyDLL('JPEG', link=DEPS[6]),
+    DependencyDLL('PNG', link=DEPS[7]),
+    DependencyDLL('VORBISFILE', link=DEPS[9]),
 ]
 
 def setup_prebuilt():
     if os.path.isdir('prebuilt'):
         reply = raw_input('\nUse the SDL libraries in "prebuilt"? [Y/n]')
         if not reply or reply[0].lower() != 'n':
-            return setup_prebuilt()
-            raise SystemExit
+            setup_prebuilt()
+            raise SystemExit()
 
     global DEPS
     for d in DEPS:
         d.configure()
-
-    return DEPS    
+    
+    return DEPS
 
 if __name__ == '__main__':
     print """This is the configuration subscript for Windows.

configtest/readme.txt

+The unit tests for the Windows configuration scripts.
+
+These must be run from their containing directory. That directory
+must be a subdirectory of the python scripts they test.
+
+test_congif_msys.py:
+    Test dependency search. Requires testdir directory. Must
+    be run from the MSYS console.
+
+test_config_msys_i.py:
+    Internals test. Check MSYS to path conversion.
+
+test_config_win.py
+    Test dependency search. Requires testdir directroy.
+
+test_dll.py
+    Test the shared DLL information.
+
+

configtest/test_config_msys.py

+# program test_config_msys.py
+
+"""Test config_msys.py for against a dummy directory structure.
+
+This test must be performed on an MSYS console.
+"""
+
+import os
+import os.path
+import sys
+
+# Ensure the execution environment is correct
+if not ("MSYSTEM" in os.environ and os.environ["MSYSTEM"] == "MINGW32"):  # cond. and
+    print "This test must be run from an MSYS console."
+    sys.exit(1)
+
+test_dir = './testdir'
+if not os.path.isdir(test_dir):
+    print "Test directory %s not found." % test_dir
+
+os.environ['LOCALBASE'] = test_dir
+sys.path.append('..')
+
+import config_msys
+
+import unittest
+    
+dependencies = dict([(dep.name, dep) for dep in config_msys.main()])
+
+
+class RunConfigTestCase(unittest.TestCase):
+    """Test dependencies returned by config_msys.main()"""
+
+    class Dependency(object):
+        # Holds dependency info
+        def __init__(self, libs=None, inc_dir_rel=None, lib_dir_rel=None):
+            if libs is None:
+                libs = []
+            self.libs = libs
+            self.inc_dir = None
+            self.lib_dir = None
+            if inc_dir_rel is not None:
+                self.inc_dir = '%s/%s' % (test_dir, inc_dir_rel)
+            if lib_dir_rel is not None:
+                self.lib_dir = '%s/%s' % (test_dir, lib_dir_rel)
+
+    # Pygame dependencies
+    expectations = {
+        'SDL': Dependency(['SDL'], 'include/sdl', 'lib'),  # ? uses sdl-config script
+        'FONT': Dependency(['SDL_ttf'], 'include/sdl', 'lib'),
+        'IMAGE': Dependency(['SDL_image'], 'include/sdl', 'lib'),
+        'MIXER': Dependency(['SDL_mixer'], 'include', 'lib'),  # A deviant include dir
+        'SMPEG': Dependency(['smpeg'], 'include', 'lib'),  # ? uses smpeg-config script
+        'PNG': Dependency(['png'], 'include', 'lib'),
+        'JPEG': Dependency(['jpeg'], 'include/sdl', 'lib'),  # A deviant include dir
+        'SCRAP': Dependency(['user32', 'gdi32']),
+        'DLL_SDL': Dependency(lib_dir_rel='bin/sdl.dll'),
+        'DLL_FONT': Dependency(lib_dir_rel='bin/sdl_ttf.dll'),  # Where DLLs likely are
+        'DLL_IMAGE': Dependency(lib_dir_rel='bin/sdl_image.dll'),
+        'DLL_MIXER': Dependency(lib_dir_rel='lib/sdl_mixer.dll'),  # Where the search starts
+        'DLL_SMPEG': Dependency(lib_dir_rel='bin/smpeg.dll'),
+        'DLL_TIFF': Dependency(lib_dir_rel='bin/libtiff.dll'),
+        'DLL_PNG': Dependency(lib_dir_rel='bin/libpng13.dll'),
+        'DLL_JPEG': Dependency(lib_dir_rel='bin/jpeg.dll'),
+        'DLL_Z': Dependency(lib_dir_rel='bin/zlib1.dll'),
+        'DLL_VORBISFILE': Dependency(lib_dir_rel='bin/libvorbisfile-3.dll'),
+        'DLL_VORBIS': Dependency(lib_dir_rel='bin/libvorbis-0.dll'),
+        'DLL_OGG': Dependency(lib_dir_rel='bin/libogg-0.dll'),
+        }
+
+    def test_dependencies(self):
+        """Ensure all dependencies are present"""
+        self.failUnlessEqual(len(dependencies), len(self.expectations))
+        for name in self.expectations:
+            self.failUnless(name in dependencies, name)
+
+    def test_dll_match(self):
+        """Ensure DLLs match with dll.py."""
+        import dll
+        
+        for name in dll.regexs:
+            self.failUnless('DLL_' + name in dependencies, name)
+
+    def test_found(self):
+        """Ensure all dependencies were found"""
+        for dep in dependencies.values():
+            self.failUnless(dep.found, dep.name)
+
+    # def test_not_found(self):
+    # No easy way to test the case where something is missing
+
+    def test_libs(self):
+        """Ensure each dependency has the proper libraries"""
+        from config_msys import DependencyProg
+        
+        for name, dep in dependencies.items():
+            if isinstance(dep, DependencyProg):
+                # Do not know how to test this one.
+                continue
+            dlibs = dep.libs
+            elibs = self.expectations[name].libs
+            self.failUnlessEqual(dlibs, elibs, "%s: %s != %s" % (name, dlibs, elibs))
+
+    def test_proper_include_paths(self):
+        """Ensure each dependency has found its include directory"""
+        from config_msys import DependencyProg
+        
+        for name, dep in dependencies.items():
+            if isinstance(dep, DependencyProg):
+                # Do not know how to test this one.
+                continue
+            dinc_dir = dep.inc_dir
+            if dinc_dir is not None:
+                dinc_dir = dinc_dir.lower()
+            einc_dir = self.expectations[name].inc_dir
+            self.failUnlessEqual(dinc_dir, einc_dir, "%s: %s != %s" % (name, dinc_dir, einc_dir))
+
+    def test_proper_library_path(self):
+        """Ensure each dependency has found its library directory/DLL file"""
+        from config_msys import DependencyProg
+        
+        for name, dep in dependencies.items():
+            if isinstance(dep, DependencyProg):
+                # Do not know how to test this one.
+                continue
+            dlib_dir = dep.lib_dir
+            if dlib_dir is not None:
+                dlib_dir = dlib_dir.lower()
+            elib_dir = self.expectations[name].lib_dir
+            self.failUnlessEqual(dlib_dir, elib_dir, "%s: %s != %s" % (name, dlib_dir, elib_dir))
+
+if __name__ == '__main__':
+    unittest.main()

configtest/test_config_msys_i.py

+# test_config_msys_i.py program
+
+"""Unit test of config_msys.py internals
+
+This test need not be run from an MSYS console.
+"""
+
+import os
+import sys
+
+msys_root_directory = 'C:/_msys_/1.0'
+mingw_root_directory = 'C:/_mingw_'
+os.environ['SHELL'] = os.path.join(msys_root_directory, 'bin', 'sh.exe')
+os.environ['MINGW_ROOT_DIRECTORY'] = mingw_root_directory
+
+sys.path.append('..')
+
+import config_msys
+
+import unittest
+
+def join_path(b, *p):
+    return os.path.join(b, *p).replace(os.sep, '/')
+
+class PathsTestCase(unittest.TestCase):
+    """Test congif_msys.msys_to_windows"""
+    some_file_name = 'foo.txt'
+
+    def test_path_usr(self):
+        """Ensure /usr translates"""
+        self.failUnlessEqual(config_msys.msys_to_windows('/usr'), msys_root_directory)
+
+    def test_path_usr_somefile(self):
+        """Ensure /usr/..... translates"""
+        msys_path = '/usr/%s' % self.some_file_name
+        win_path = join_path(msys_root_directory, self.some_file_name)
+        self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+    def test_path_mingw(self):
+        """Ensure /mingw translates"""
+        self.failUnlessEqual(config_msys.msys_to_windows('/mingw'), mingw_root_directory)
+
+    def test_path_mingw_something(self):
+        """Ensure /mingw/.... translates"""
+        msys_path = '/mingw/%s' % self.some_file_name
+        win_path = join_path(mingw_root_directory, self.some_file_name)
+        self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+    def test_path_root(self):
+        """Ensure / translates"""
+        self.failUnlessEqual(config_msys.msys_to_windows('/'), msys_root_directory)
+
+    def test_path_root_something(self):
+        """Ensure /.... translates"""
+        msys_path = '/%s' % self.some_file_name
+        win_path = join_path(msys_root_directory, self.some_file_name)
+        self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+    def test_drive_letter_absolute(self):
+        """Ensure x:/.... translates"""
+        for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
+            msys_path = '/%s/%s' % (d, self.some_file_name)
+            win_path = '%s:/%s' % (d, self.some_file_name)
+            self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+    def test_drive_letter_relative(self):
+        """Ensure x:.... translates"""
+        for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
+            msys_path = '%s:dir/%s' % (d, self.some_file_name)
+            win_path = join_path('%s:' % d, 'dir', self.some_file_name)
+            self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+    def test_path_relative(self):
+        """Ensure relative paths translate"""
+        msys_path = './dir/%s' % self.some_file_name
+        win_path = join_path('.', 'dir', self.some_file_name)
+        self.failUnlessEqual(config_msys.msys_to_windows(msys_path), win_path)
+
+if __name__ == '__main__':
+    unittest.main()

configtest/test_config_win.py

+# program test_config_msys.py
+
+"""Test config_msys.py for against a dummy directory structure.
+
+This test must be performed on an MSYS console.
+"""
+
+import sys
+sys.path.append('..')
+import config_win
+
+import unittest
+import os
+
+test_dir = 'testdir'
+if not os.path.isdir(test_dir):
+    print "Test directory %s not found." % test_dir
+os.chdir(os.path.join(test_dir, 'include'))
+
+dependencies = dict([(dep.name, dep) for dep in config_win.main()])
+
+
+class RunConfigTestCase(unittest.TestCase):
+    """Test dependencies returned by config_win.main()"""
+
+    class Dependency(object):
+        # Holds dependency info
+        def __init__(self, libs=None, inc_dir_rel=None, lib_dir_rel=None):
+            if libs is None:
+                libs = []
+            self.libs = libs
+            self.inc_dir = None
+            self.lib_dir = None
+            if inc_dir_rel is not None:
+                self.inc_dir = '%s/%s' % ('..', inc_dir_rel)
+            if lib_dir_rel is not None:
+                self.lib_dir = '%s/%s' % ('..', lib_dir_rel)
+
+    # Pygame dependencies
+    expectations = {
+        'SDL': Dependency(['SDL'], 'sdl-1.2.12/include', 'sdl-1.2.12/visualc/sdl/release'),
+        'FONT': Dependency(['SDL_ttf'], 'sdl_ttf-2.0.9', 'sdl_ttf-2.0.9/release'),
+        'IMAGE': Dependency(['SDL_image'], 'sdl_image-1.2.6', 'sdl_image-1.2.6/visualc/release'),
+        'MIXER': Dependency(['SDL_mixer'], 'sdl_mixer-1.2.8', 'sdl_mixer-1.2.8/release'),
+        'SMPEG': Dependency(['smpeg'], 'smpeg', 'smpeg/release'),
+        'PNG': Dependency(['png'], 'libpng-1.2.19', 'libpng-1.2.19/lib'),
+        'JPEG': Dependency(['jpeg'], 'jpeg-6b', 'jpeg-6b/release'),
+        'SCRAP': Dependency(['user32', 'gdi32']),
+        'DLL_SDL': Dependency(lib_dir_rel='sdl-1.2.12/visualc/sdl/release/sdl.dll'),
+        'DLL_FONT': Dependency(lib_dir_rel='sdl_ttf-2.0.9/release/sdl_ttf.dll'),
+        'DLL_IMAGE': Dependency(lib_dir_rel='sdl_image-1.2.6/visualc/release/sdl_image.dll'),
+        'DLL_MIXER': Dependency(lib_dir_rel='sdl_mixer-1.2.8/release/sdl_mixer.dll'),
+        'DLL_SMPEG': Dependency(lib_dir_rel='smpeg/release/smpeg.dll'),
+        'DLL_TIFF': Dependency(lib_dir_rel='tiff-3.8.2/release/libtiff.dll'),
+        'DLL_PNG': Dependency(lib_dir_rel='libpng-1.2.19/lib/libpng13.dll'),
+        'DLL_JPEG': Dependency(lib_dir_rel='jpeg-6b/release/jpeg.dll'),
+        'DLL_Z': Dependency(lib_dir_rel='zlib-1.2.3/release/zlib1.dll'),
+        'DLL_VORBISFILE': Dependency(lib_dir_rel='libvorbis-1.2.0/release/libvorbisfile-3.dll'),
+        'DLL_VORBIS': Dependency(lib_dir_rel='libvorbis-1.2.0/release/libvorbis-0.dll'),
+        'DLL_OGG': Dependency(lib_dir_rel='libogg-1.1.3/release/libogg-0.dll'),
+        }
+
+    def test_dependencies(self):
+        """Ensure all dependencies are present"""
+        self.failUnlessEqual(len(dependencies), len(self.expectations))
+        for name in self.expectations:
+            self.failUnless(name in dependencies, name)
+
+    def test_dll_match(self):
+        """Ensure DLLs match with dll.py."""
+        import dll
+        
+        for name in dll.regexs:
+            self.failUnless('DLL_' + name in dependencies, name)
+
+    def test_found(self):
+        """Ensure all dependencies were found"""
+        for dep in dependencies.values():
+            self.failUnless(dep.found, dep.name)
+
+    # def test_not_found(self):
+    # No easy way to test the case where something is missing
+
+    def test_libs(self):
+        """Ensure each dependency has the proper libraries"""
+        for name, dep in dependencies.items():
+            dlibs = dep.libs
+            elibs = self.expectations[name].libs
+            self.failUnlessEqual(dlibs, elibs, "%s: %s != %s" % (name, dlibs, elibs))
+
+    def test_proper_include_paths(self):
+        """Ensure each dependency has found its include directory"""
+        for name, dep in dependencies.items():
+            dinc_dir = dep.inc_dir
+            if dinc_dir is not None:
+                dinc_dir = dinc_dir.lower()
+            einc_dir = self.expectations[name].inc_dir
+            self.failUnlessEqual(dinc_dir, einc_dir, "%s: %s != %s" % (name, dinc_dir, einc_dir))
+
+    def test_proper_library_path(self):
+        """Ensure each dependency has found its library directory/DLL file"""
+        for name, dep in dependencies.items():
+            dlib_dir = dep.lib_dir
+            if dlib_dir is not None:
+                dlib_dir = dlib_dir.lower()
+            elib_dir = self.expectations[name].lib_dir
+            self.failUnlessEqual(dlib_dir, elib_dir, "%s: %s != %s" % (name, dlib_dir, elib_dir))
+
+if __name__ == '__main__':
+    unittest.main()

configtest/test_dll.py

+# program test_dll.py
+
+"""A unit test on the dll.py module that confirms file matching patterns"""
+
+import sys
+
+sys.path.append('..')
+
+import dll
+
+import unittest
+
+class MatchTestCase(unittest.TestCase):
+
+    test_cases = [
+        ('SDL', ['SDL.dll', 'sdl.DLL', 'libsdl.dll'], ['sdl.dll.a']),
+        ('MIXER', ['SDL_mixer.dll', 'sdl_MIXER.DLL', 'libsdl_mixer.dll'], ['sdl_mixer.dll.a']),
+        ('IMAGE', ['SDL_image.dll', 'sdl_IMAGE.DLL', 'libsdl_image.dll'], ['sdl_image.dll.a']),
+        ('FONT', ['SDL_ttf.dll', 'sdl_TTF.DLL', 'libsdl_ttf.dll'], ['sdl_ttf.dll.a']),
+        ('SMPEG', ['smpeg.dll', 'SMPEG.DLL', 'libsmpeg.dll'], ['smpeg.dll.a']),
+        ('TIFF', ['tiff.dll', 'TIFF.DLL', 'libtiff.dll'], ['tiff.dll.a']),
+        ('JPEG', ['jpeg.dll', 'JPEG.DLL', 'libjpeg.dll'], ['jpeg.dll.a']),
+        ('PNG', ['libpng13.dll', 'LIBPNG13.DLL', 'libpng12.dll', 'png12.dll', 'png13.dll'],
+                ['libpng.dll', 'libpng13.dll.a']),
+        ('Z', ['zlib1.dll', 'ZLIB1.DLL'], ['z.dll', 'libzlib1.dll', 'zlib1.dll.a']),
+        ('VORBIS', ['vorbis.dll', 'VORBIS.DLL', 'libvorbis-0.dll'], ['libvorbis-1.dll', 'libvorbis-0.dll.a']),
+        ('VORBISFILE', ['vorbisfile.dll', 'VORBISFILE.DLL', 'libvorbisfile-3.dll'],
+                       ['libvorbisfile-0.dll', 'libvorbisfile-3.dll.a']),
+        ('OGG', ['ogg.dll', 'OGG.DLL', 'libogg-0.dll'], ['libogg-1.dll', 'libogg-0.dll.a']),
+        ]
+
+    def test_compat(self):
+        """Validate the test cases"""
+        self.failUnlessEqual(len(self.test_cases), len(dll.regexs))
+        for name, valid_files, invalid_files in self.test_cases:
+            self.failUnless(name in  dll.regexs, name)
+
+    def test_match(self):
+        """Ensure certain file names match"""
+        for name, valid_files, invalid_files in self.test_cases:
+            test = dll.tester(name)
+            for f in valid_files:
+                self.failUnless(test(f), f)
+
+    def test_failed_match(self):
+        """Ensure certain file names do not match"""
+        for name, valid_files, invalid_files in self.test_cases:
+            test = dll.tester(name)
+            for f in invalid_files:
+                self.failUnless(not test(f), f)
+
+class DependencyLookupTestCase(unittest.TestCase):
+    def test_no_dependencies(self):
+        """Ensure no dependencies are returned for a library with non"""
+        self.failUnlessEqual(list(dll.dependencies(['SDL'])), ['SDL'])
+
+    def test_not_found(self):
+        """Ensure an empty dependency list is returned for an unrecognized library"""
+        self.failUnless(not dll.dependencies(['?']))
+
+    def test_multiple_dependencies(self):
+        """Ensure dependencies are recursively traced"""
+        expected_libs = ['vorbisfile', 'vorbis', 'ogg']
+        libs = dll.dependencies(['vorbisfile'])
+        self.failUnlessEqual(len(libs), len(expected_libs))
+        for lib in expected_libs:
+            self.failUnless(lib in libs)
+
+    def test_multiple_libs(self):
+        """Ensure mutliple libraries in a list are handled"""
+        expected_libs = ['SDL', 'z']  # Chosen for not having dependencies
+        libs = dll.dependencies(expected_libs)
+        self.failUnlessEqual(len(libs), len(expected_libs))
+        for lib in expected_libs:
+            self.failUnless(lib in libs)
+
+    def test_no_libs(self):
+        """Check special case of an empty library list"""
+        self.failUnless(not dll.dependencies([]))
+
+if __name__ == '__main__':
+    unittest.main()

configtest/testdir/SDL-1.2.12/VisualC/SDL/Release/SDL.dll

+A bogus DLL

configtest/testdir/SDL-1.2.12/include/SDL.h

+/* Just a bogus header file */

configtest/testdir/SDL_image-1.2.6/VisualC/Release/SDL_image.dll

+A bogus DLL

configtest/testdir/SDL_mixer-1.2.8/Release/SDL_mixer.dll

+A bogus DLL

configtest/testdir/SDL_ttf-2.0.9/Release/SDL_ttf.dll

+A bogus DLL

configtest/testdir/bin/SDL.dll

+A bogus DLL

configtest/testdir/bin/SDL_image.dll

+A bogus DLL

configtest/testdir/bin/SDL_ttf.dll

+A bogus DLL

configtest/testdir/bin/jpeg.dll

+A bogus DLL

configtest/testdir/bin/libogg-0.dll

+A bogus DLL

configtest/testdir/bin/libpng13.dll

+A bogus DLL

configtest/testdir/bin/libtiff.dll

+A bogus DLL

configtest/testdir/bin/libvorbis-0.dll

+A bogus DLL

configtest/testdir/bin/libvorbisfile-3.dll

+A bogus DLL

configtest/testdir/bin/smpeg.dll

+A bogus DLL

configtest/testdir/bin/zlib1.dll

+A bogus DLL

configtest/testdir/include/SDL/SDL_image.h

+/* Just a bogus header file */

configtest/testdir/include/SDL/SDL_ttf.h

+/* Just a bogus header file */

configtest/testdir/include/SDL/jpeglib.h

+/* Just a bogus header file */

configtest/testdir/include/SDL_mixer.h

+/* Just a bogus header file */

configtest/testdir/include/png.h

+/* Just a bogus header file */

configtest/testdir/jpeg-6b/Release/jpeg.dll

+A bogus DLL

configtest/testdir/lib/SDL_mixer.dll

+A bogus DLL

configtest/testdir/lib/libSDL_image.dll.a

+A bogus DLL

configtest/testdir/lib/libSDL_mixer.dll.a

+A bogus DLL

configtest/testdir/lib/libSDL_ttf.dll.a

+A bogus DLL

configtest/testdir/lib/libjpeg.dll.a

+A bogus DLL

configtest/testdir/lib/libpng.dll.a

+A bogus DLL

configtest/testdir/libogg-1.1.3/Release/libogg-0.dll

+A bogus DLL

configtest/testdir/libpng-1.2.19/lib/libpng13.dll

+A bogus DLL

configtest/testdir/libvorbis-1.2.0/Release/libvorbis-0.dll

+A bogus DLL

configtest/testdir/libvorbis-1.2.0/Release/libvorbisfile-3.dll

+A bogus DLL

configtest/testdir/smpeg/Release/smpeg.dll

+A bogus DLL

configtest/testdir/tiff-3.8.2/Release/libtiff.dll

+A bogus DLL

configtest/testdir/zlib-1.2.3/Release/zlib1.dll

+A bogus DLL
+# dll.py module
+
+"""DLL specifics"""
+
+import re
+
+#re file patterns and dependencies of Pygame DLL dependencies
+regexs = {
+    'MIXER': r'(lib){0,1}SDL_mixer\.dll$',
+    'VORBISFILE': r'(lib){0,1}vorbisfile(-3){0,1}\.dll$',
+    'VORBIS': r'(lib){0,1}vorbis(-0){0,1}\.dll$',
+    'OGG': r'(lib){0,1}ogg(-0){0,1}\.dll$',
+    'SMPEG': r'(lib){0,1}smpeg\.dll$',
+    'IMAGE': r'(lib){0,1}SDL_image\.dll$',
+    'TIFF': r'(lib){0,1}tiff\.dll$',
+    'JPEG': r'(lib){0,1}jpeg\.dll$',
+    'PNG': r'(lib){0,1}png(1[23])\.dll$',
+    'FONT': r'(lib){0,1}SDL_ttf\.dll$',
+    'Z': r'zlib1\.dll$',
+    'SDL': r'(lib){0,1}SDL\.dll$',
+    }
+
+lib_dependencies = {
+    'SDL_mixer': ['SDL', 'vorbisfile', 'smpeg'],
+    'vorbisfile': ['vorbis'],
+    'vorbis': ['ogg'],
+    'ogg': [],
+    'smpeg': ['SDL'],
+    'SDL_image': ['SDL', 'jpeg', 'png', 'tiff'],
+    'tiff': ['jpeg', 'z'],
+    'jpeg': [],
+    'png': ['z'],
+    'SDL_ttf': ['SDL', 'z'],
+    'z': [],
+    'SDL': [],
+    }
+
+def tester(name):
+    def test(f):
+        return match(f) is not None
+    match =  re.compile(regexs[name], re.I).match
+    return test
+
+def dependencies(libs):
+    r = {}
+    for lib in libs:
+        try:
+            deps = lib_dependencies[lib]
+        except KeyError:
+            pass
+        else:
+            r[lib] = 1
+            r.update(dependencies(deps))
+    return r
         'setup_requires': ['bdist_mpkg>=0.4.2'],
     })
 
-
 import config
 # a separate method for finding dlls with mingw.
 if config.is_msys_mingw():
 
 #headers to install
 headers = glob.glob(os.path.join('src', '*.h'))
-headers.remove (os.path.join ('src', 'numeric_arrayobject.h'))
+headers.remove(os.path.join('src', 'numeric_arrayobject.h'))
 
 #sanity check for any arguments
 if len(sys.argv) == 1:
 
 #try to find DLLs and copy them too  (only on windows)
 if sys.platform == 'win32':
-    
-    # check to see if we are using mingw.
-    import config
-    # a separate method for finding dlls with mingw.
-    if config.is_msys_mingw():
 
-        print data_files
-        # FIXME: hardcoding the dll paths for the moment.
-        the_dlls = ["C:\\msys\\1.0\\local\\bin\\SDL.dll",
-                    "C:\\msys\\1.0\\local\\bin\\SDL_image.dll",
-                    "C:\\msys\\1.0\\local\\bin\\SDL_ttf.dll",
-                    "C:\\msys\\1.0\\local\\bin\\SDL_mixer.dll",
-                    "C:\\msys\\1.0\\local\\bin\\jpeg.dll",
-                    "C:\\msys\\1.0\\local\\bin\\libpng13.dll",
-                    "C:\\msys\\1.0\\local\\bin\\libtiff.dll",
-                   ]
+    #add dependency DLLs to the project
+    import dll
 
-        the_dlls = ["C:\\MingW\\bin\\SDL.dll",
-                    "C:\\MingW\\bin\\SDL_image.dll",
-                    "C:\\MingW\\bin\\SDL_ttf.dll",
-                    "C:\\MingW\\bin\\SDL_mixer.dll",
-                    "C:\\MingW\\bin\\jpeg.dll",
-                    "C:\\MingW\\bin\\libpng13.dll",
-                    "C:\\MingW\\bin\\libtiff.dll",
-                   ]
-
-
-                   # no smpeg.
-                    #"C:\\msys\\1.0\\local\\bin\\smpeg.dll"]
-
-        data_files.extend(the_dlls)
-
-
-        
-        ext = "dll"
-        for e in extensions:
-            paths = []
-            print e.library_dirs
-            for d in e.library_dirs:
-                 for l in e.libraries:
-                        #name = tempcompiler.shared_lib_format%(l, ext)
-                        name = "%s.%s" %(l, ext)
-                        paths.append(os.path.join(d, name))
-            #print paths
-            for p in paths:
-                if os.path.isfile(p) and p not in data_files:
-                    data_files.append(p)
-
-
-    else:
-
-        tempcompiler = new_compiler()
-        ext = tempcompiler.shared_lib_extension
-        for e in extensions:
-            paths = []
-            print e.library_dirs
-            for d in e.library_dirs:
-                 for l in e.libraries:
-                        name = tempcompiler.shared_lib_format%(l, ext)
-                        paths.append(os.path.join(d, name))
-            for p in paths:
-                if os.path.isfile(p) and p not in data_files:
-                    data_files.append(p)
-
+    the_dlls = {}
+    required_dlls = {}
+    for e in extensions:
+        if e.name.startswith('COPYLIB__'):
+            the_dlls[e.name[9:]] = e.library_dirs[0]
+        else:
+            required_dlls.update(dll.dependencies(e.libraries))
+    for lib in required_dlls:
+        #next DLL; a distutils bug requires the paths to have Windows separators
+        f = the_dlls[lib].replace('/', os.sep)
+        if f == '_':
+            print "WARNING, DLL for %s library not found." % lib
+        else:
+            data_files.append(f)
 
 
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.