Commits

Anonymous committed 0b36150

Updated build system to be more modular and configurable (Vicent Marti).
Added Darwin build support from Vicent Marti.

Comments (0)

Files changed (13)

 
 import sys
 
+build = {}
+
 if sys.version_info[0] >= 3:
     unicode = str
 
 
 # SDL support.
 # This MUST be enabled for the other SDL related modules.
-WITH_SDL = istrue (os.getenv ("WITH_SDL", True))
+build['SDL'] = istrue (os.getenv ("WITH_SDL", True))
 
 # SDL_mixer support
-WITH_SDL_MIXER = istrue (os.getenv ("WITH_SDL_MIXER", True)) and WITH_SDL
+build['SDL_MIXER'] = istrue (os.getenv ("WITH_SDL_MIXER", True)) and build['SDL']
 
 # SDL_image support
-WITH_SDL_IMAGE = istrue (os.getenv ("WITH_SDL_IMAGE", True)) and WITH_SDL
+build['SDL_IMAGE'] = istrue (os.getenv ("WITH_SDL_IMAGE", True)) and build['SDL']
 
 # SDL_ttf support
-WITH_SDL_TTF = istrue (os.getenv ("WITH_SDL_TTF", True)) and WITH_SDL
+build['SDL_TTF'] = istrue (os.getenv ("WITH_SDL_TTF", True)) and build['SDL']
 
 # SDL_gfx support
-WITH_SDL_GFX = istrue (os.getenv ("WITH_SDL_GFX", True)) and WITH_SDL
+build['SDL_GFX'] = istrue (os.getenv ("WITH_SDL_GFX", True)) and build['SDL']
 
 # libpng support
 # This is used by Surface.save() to enable PNG saving.
-WITH_PNG = istrue (os.getenv ("WITH_PNG", True))
+build['PNG'] = istrue (os.getenv ("WITH_PNG", True))
 
 # libjpeg support
 # This is used by Surface.save() to enable JPEG saving.
-WITH_JPEG = istrue (os.getenv ("WITH_JPEG", True))
+build['JPEG'] = istrue (os.getenv ("WITH_JPEG", True))

config/config_darwin.py

+import os, sys
+from config import config_generic, config_unix
+
+# Plistlib is always available on Mac OS X, but it is only
+# available on Windows/Unix from 2.6
+try: import plistlib
+except: pass
+
+
+def _get_framework_path(library):
+    """
+        Returns a tuple containing the path to the
+        'Frameworks' folder of the OS and the path to
+        the specific Framework for the given library.
+    """
+    for path in ('/', os.path.expanduser('~/'), '/System/'):
+        path = os.path.join(path, 'Library/Frameworks/')
+        framework = os.path.join(path,
+                library + '.framework/Versions/Current/')
+
+        framework_lib = os.path.join(framework, library)
+        if os.path.isfile(framework_lib):
+            return path, framework
+
+    return (None, None)
+
+def get_sys_libs(module):
+    return []
+
+def get_install_libs(cfg):
+    return []
+
+def sdl_get_version():
+    """
+        Returns the installed SDL version.
+        In Mac OS, we first check for the version of the installed 
+        SDL Framework bundle. If it's not available, we fallback to
+        the version detection for all Unix systems.
+    """
+    path, framework = _get_framework_path('SDL')
+    if framework:
+        plist = plistlib.readPlist(os.path.join(framework, 'Resources', 'Info.plist'))
+        return plist['CFBundleVersion'] + " (SDL.framework)"
+
+    return config_unix.sdl_get_version()
+
+class Dependency (config_unix.Dependency):
+    """
+        Mac OS X Library Dependency.
+
+        Dependencies are handled exactly in the same manner as
+        any other Unix system, except because we have to look in
+        some additional system folders for libraries (the places
+        where MacPorts and Fink install their stuff)
+    """
+    _searchdirs = ['/usr', '/usr/local', '/opt/local']
+    _incdirs = ['include']
+    _libdirs = ['lib']
+
+class DependencySDL (config_unix.DependencySDL, Dependency):
+    """
+        Mac OS X SDL Library Dependency.
+
+        The SDL library under Mac OS is mainly distributed via
+        Framework bundles, so we have to handle this case.
+    """
+
+    def _configure_frameworks(self):
+        """
+            Configuration callback which looks for installed SDL
+            framework bundles.
+        """
+        path, framework = _get_framework_path(self.library_id)
+
+        if not framework:
+            return False
+
+        self.incdirs.append(os.path.join(framework, 'Headers'))
+        self.cflags.append('-Xlinker "-framework"')
+        self.cflags.append('-Xlinker "%s"' % self.library_id)
+        self.cflags.append('-Xlinker "-F%s"' % path)
+        self.libs.remove(self.library_id)
+        return True
+
+    _configure_frameworks.priority = 4
+

config/config_generic.py

+import os
+
+class Dependency (object):
+    """
+        Generic Dependency class.
+
+        This class represents a generic library dependency of a PyGame
+        module, i.e. the required compiler and linker flags for building
+        a module which depends on this library.
+
+        This class is instantiated with the 'linker id' (for example, a
+        library which is linked with '-lpng' has 'png' as its linker id)
+        of the library it represents and the name of a representative
+        header file.
+
+        It must be then configured with the configure() method; if the
+        configuration is successful, the setup_module() method may be
+        used to update a Module object with the compiler flags which are
+        needed to build it.
+
+        The process of 'configuring' this Dependency implies setting the
+        following lists with the information relevant to the library:
+            
+            self.incdirs (all the directories which contain the include files)
+            self.libdirs (the directory(s) which contain the library itself)
+            self.libs    (the name of the library files which must be linked)
+            self.cflags  (all the flags which must be passed to the C compiler)
+            self.lflags  (all the flags which must be passed to the C linker)
+
+        Configuration is done by executing 'configuration callbacks'
+        (each one implementing a different configuration method) until
+        the required information has been collected.
+
+        A configuration callback is simply a class method starting by
+        '_configure_' which is automatically executed by the
+        Dependency.configure() method and returns True if the library's
+        information was found.
+
+        By default, this generic class implements the configuration
+        method which is common to all platforms:
+        Dependency._configure_guess() tries to guess the location of the
+        library by looking in system folders for the required files.
+
+        However, all platforms inherit this class to implement their
+        custom configuration callbacks; for instance, Unix systems also
+        try to use the 'pkgconfig' tool to automatically locate
+        installed libraries, and Mac OS X tries to locate installed
+        Framework Bundles containing the libraries.
+
+        See the other configuration callbacks in their respective modules:
+
+            config.config_unix
+            config.config_darwin
+            config.config_msys
+            config.config_win
+    """
+
+    def __init__(self, header_file, library_link_id):
+        self.header_file = header_file
+        self.library_name = 'lib' + library_link_id
+        self.library_id = library_link_id
+
+        self.incdirs = []
+        self.libdirs = []
+        self.libs = [self.library_id]
+        self.cflags = []
+        self.lflags = []
+
+        self.configured = False
+
+    def _canbuild(self, cfg):
+        """
+            Returns if this library has been manually disabled
+            by the user on the 'cfg.py' module, and hence cannot be built.
+        """
+        cfg_entry = self.library_id.upper()
+
+        if cfg_entry in cfg.build:
+            return cfg.build[cfg_entry]
+
+        # if the library doesn't show up on cfg.py, we assume that the user
+        # wants to actually compile it.
+        return True
+
+    def _configure_guess(self):
+        """
+            Configuration callback which automatically looks for
+            the required headers and libraries in some default
+            system folders.
+        """
+        directory = self._find_incdir(self.header_file)
+
+        if directory is None:
+            return False
+
+        self.incdirs.append(directory)
+        self.libdirs.append(self._find_libdir(self.library_name))
+        self.cflags.append("-DHAVE_" + self.library_id.upper())
+        return True
+
+    _configure_guess.priority = 0
+
+    def configure(self, cfg):
+        """
+            Finds the compiler/linker information needed
+            to configure this library.
+        """
+        print ("Configuring library '%s':" % self.library_id)
+
+        if not self._canbuild(cfg):
+            print ("\tLibrary '%s' has been manually disabled.\n" % self.library_id)
+            return
+
+        # find all configuration callbacks
+        configure_callbacks = [ getattr(self, attr)
+                                for attr in dir(self)
+                                if attr.startswith('_configure_') ]
+
+        # helper method for sort
+        def _get_priority(cb):
+            if hasattr(cb, 'priority'):
+                return cb.priority
+            return 0
+
+        # sort them by priority; callbacks without a priority attribute
+        # default to 0
+        configure_callbacks.sort(reverse = True, key = _get_priority)
+
+        for callback in configure_callbacks:
+            callback_name = callback.__name__[11:].title()
+
+            if callback():
+                print (("Attempting to configure with %s..." % callback_name).ljust(50) + "Success!")
+                self.configured = True
+
+                self.cflags = list(set(self.cflags))
+                self.lflags = list(set(self.lflags))
+                self.incdirs = list(set(self.incdirs))
+                self.libdirs = list(set(self.libdirs))
+                self.libs = list(set(self.libs))
+
+                print ("")
+                print ("\tCFlags : " + repr(self.cflags))
+                print ("\tLFlags : " + repr(self.lflags))
+                print ("\tIncDirs: " + repr(self.incdirs))
+                print ("\tLibDirs: " + repr(self.libdirs))
+                print ("\tLibs   : " + repr(self.libs))
+                print ("")
+
+                # once the library has been configured with one configuration
+                # callback, stop trying to configure it again
+                return
+                
+            print (("Attempting to configure with %s..." % callback_name).ljust(50) + "Failure.")
+
+        print ("\tFailed to configure library %s.\n" % self.library_id)
+
+    def setup_module(self, module, optional = False):
+        """
+            Updates a modules.Module object with all the compiler
+            and linker flags required to build it with this library.
+
+            module - modules.Module object
+            optional - whether the module requires the library to build
+        """
+
+        # if the building for this module is disabled already, it means
+        # one of the other library prerequisites couldn't be configured
+        # and the module won't be built no matter what
+        if not module.canbuild:
+            return
+
+        # if this library hasn't been able to be configured, and it's
+        # required for the module to build, we have to disable the building
+        # of such module
+        if not self.configured:
+            module.canbuild = optional
+            return
+        
+        # update compiler/linker args for the module
+        module.cflags += list(self.cflags)
+        module.lflags += list(self.lflags)
+        module.incdirs += list(self.incdirs)
+        module.libdirs += list(self.libdirs)
+        module.libs += list(self.libs)
+
+
+class DependencySDL (Dependency):
+    """
+        Generic SDL Dependency class.
+
+        This class represents a SDL-based library which must be linked with
+        a module. The main difference between a normal dependency and a SDL
+        dependency is that the later must always contain our custom 'src/sdl'
+        include dir.
+
+        Additionally, some platforms implement custom SDL configuration callbacks: 
+            Unix and Msys use the 'sdl-config' utility and Windows uses some special
+            handling when linking SDL libraries.
+
+        See: 
+            config.config_unix.DependencySDL._configure_sdlconfig
+            config.config_win.DependencySDL._configure_guess
+    """
+
+    def __init__(self, header_file, library_id):
+        Dependency.__init__(self, header_file, library_id)
+
+        # custom SDL include directory
+        self.incdirs.append(os.path.join ("src", "sdl"))
+

config/config_modules.py

 import os, sys
 from config import sdlconfig, pkgconfig, helpers
-from config import config_msys, config_unix, config_win
+from config import config_msys, config_unix, config_win, config_darwin
+from config.config_generic import Dependency, DependencySDL
 
-def get_install_libs (buildsystem, cfg):
-    # Gets the libraries to install for the target platform.
-    if buildsystem == "unix":
-        return config_unix.get_install_libs (cfg)
-    elif buildsystem == "msys":
-        return config_msys.get_install_libs (cfg)
-    elif buildsystem == "win":
-        return config_win.get_install_libs (cfg)
+OS_MODULES = {
+    'win'   : config_win,
+    'msys'  : config_msys,
+    'unix'  : config_unix,
+    'darwin': config_darwin
+}
 
-def find_incdir (buildsystem, header):
-    # Gets the include directory for the specified header file.
-    if buildsystem == "msys":
-        return config_msys.find_incdir (header)
-    elif buildsystem == "unix":
-        return config_unix.find_incdir (header)
-    elif buildsystem == "win":
-        return config_win.find_incdir (header)
+def get_dependencies(buildsystem, cfg):
+    """
+        Returns a dict with all the configured libraries which 
+        will be used when linking PyGame modules.
 
-def find_libdir (buildsystem, lib):
-    # Gets the library directory for the specified library file.
-    if buildsystem == "msys":
-        return config_msys.find_libdir (lib)
-    elif buildsystem == "unix":
-        return config_unix.find_libdir (lib)
-    elif buildsystem == "win":
-        return config_win.find_libdir (lib)
+        Configuring a library implies finding its location
+        and storing the compiler/linker arguments which
+        will be passed to all the modules which rely on such
+        library.
+    """
+    os_module = OS_MODULES[buildsystem]
 
-def get_sys_libs (buildsystem, module):
-    # Gets a list of system libraries to link the module against.
-    if buildsystem == "msys":
-        return config_msys.get_sys_libs (module) or []
-    elif buildsystem == "unix":
-        return config_unix.get_sys_libs (module) or []
-    elif buildsystem == "win":
-        return config_win.get_sys_libs (module) or []
-    
-def sdl_get_version (buildsystem):
-    # Gets the SDL version.
-    if buildsystem == "msys":
-        return config_msys.sdl_get_version ()
-    elif buildsystem == "unix":
-        return config_unix.sdl_get_version ()
-    elif buildsystem == "win":
-        return config_win.sdl_get_version ()
+    DEPENDENCIES = {
+    #   extern_name : dep_class               (header,            lib_ids       ),
+        'sdl'       : os_module.DependencySDL ('SDL.h',           'SDL'         ),
+        'sdl_mixer' : os_module.DependencySDL ('SDL_mixer.h',     'SDL_mixer',  ),
+        'sdl_ttf'   : os_module.DependencySDL ('SDL_ttf.h',       'SDL_ttf',    ),
+        'sdl_gfx'   : os_module.DependencySDL ('SDL_framerate.h', 'SDL_gfx',    ),
+        'sdl_image' : os_module.DependencySDL ('SDL_image.h',     'SDL_image',  ),
+        'png'       : os_module.Dependency    ('png.h',           'png'         ),
+        'jpeg'      : os_module.Dependency    ('jpeglib.h',       'jpeg'        ),
+    }
 
-def prepare_modules (buildsystem, modules, cfg):
-    # Prepares all passed modules, setting up their compile and linkage flags,
-    # the necessary includes and the inter-module dependencies.
-    haspkgconfig = hassdlconfig = False
-    if buildsystem in ("unix", "msys"):
-        haspkgconfig = pkgconfig.has_pkgconfig ()
-        hassdlconfig = sdlconfig.has_sdlconfig ()
+    for (dep_name, dep) in DEPENDENCIES.items():
+        dep.configure(cfg)
 
-    sdlincpath = os.path.join ("src", "sdl")
-    sdlincdirs = []
-    sdllibdirs = []
-    sdllibs = None
-    sdlcflags = None
-    sdllflags = None
-    hassdl = sdl_get_version (buildsystem) != None
+    return DEPENDENCIES
 
-    pngincdirs = []
-    pnglibdirs = []
-    pnglibs = None
-    pngcflags = None
-    pnglflags = None
-    haspng = False
+def sdl_get_version(buildsystem):
+    """
+        Returns the version of the installed SDL library
+    """
+    return OS_MODULES[buildsystem].sdl_get_version()
 
-    jpgincdirs = []
-    jpglibdirs = []
-    jpglibs = None
-    jpgcflags = None
-    jpglflags = None
-    hasjpg = False
+def get_sys_libs(buildsystem, module):
+    """
+        Return a list with any system-specific libraries
+        which must be linked together with a module
+    """
+    return OS_MODULES[buildsystem].get_sys_libs(module)
 
-    if haspkgconfig:
-        sdlincdirs = pkgconfig.get_incdirs ("sdl") + [ sdlincpath ]
-        sdllibdirs = pkgconfig.get_libdirs ("sdl")
-        sdllibs = pkgconfig.get_libs ("sdl")
-        sdlcflags = pkgconfig.get_cflags ("sdl")
-        sdllflags = pkgconfig.get_lflags ("sdl")
-        if cfg.WITH_PNG and pkgconfig.exists ("libpng"):
-            pngincdirs = pkgconfig.get_incdirs ("libpng")
-            pnglibdirs = pkgconfig.get_libdirs ("libpng")
-            pngcflags = pkgconfig.get_cflags ("libpng") + [ "-DHAVE_PNG" ]
-            pnglflags = pkgconfig.get_lflags ("libpng")
-            pnglibs = pkgconfig.get_libs ("libpng")
-            haspng = True
-    elif hassdlconfig:
-        sdlincdirs = sdlconfig.get_incdirs () + [ sdlincpath ]
-        sdllibdirs = sdlconfig.get_libdirs ()
-        sdllibs = sdlconfig.get_libs ()
-        sdlcflags = sdlconfig.get_cflags ()
-        sdllflags = sdlconfig.get_lflags ()
-    else:
-        d = find_incdir (buildsystem, "SDL.h")
-        if d != None:
-            sdlincdirs = [ d, sdlincpath ]
-            sdllibs = [ "SDL" ]
-            if buildsystem in ("win", "msys"):
-                sdllibs.append ("SDLmain")    
-                sdllibdirs = [ find_libdir (buildsystem, "SDL") ]
-            else:
-                sdllibdirs = [ find_libdir (buildsystem, "libSDL") ]
-            
-            sdlcflags = []
-            sdllflags = []
+def get_install_libs(buildsystem, cfg):
+    """
+        Return a list with the libraries which must be bundled
+        and installed with Pygame, based on the active OS
+    """
+    return OS_MODULES[buildsystem].get_install_libs(cfg)
 
-    if cfg.WITH_PNG and not haspng:
-        d = find_incdir (buildsystem, "png.h")
-        if d != None:
-            pngincdirs = [ d ]
-            pnglibdirs = [ find_libdir (buildsystem, "libpng") ]
-            pnglibs = [ "png" ]
-            pngcflags = [ "-DHAVE_PNG" ]
-            pnglflags = []
-            haspng = True
+def prepare_modules(buildsystem, modules, cfg):
+    """
+        Updates all the modules that must be built by adding
+        compiler/link information for the libraries on which
+        they depend.
 
-    if cfg.WITH_JPEG:
-        d = find_incdir (buildsystem, "jpeglib.h")
-        if d != None:
-            jpgincdirs = [ d ]
-            jpglibdirs = [ find_libdir (buildsystem, "libjpeg") ]
-            jpglibs = [ "jpeg" ]
-            jpgcflags = [ "-DHAVE_JPEG" ]
-            jpglflags = []
-            hasjpg = True
+        buildsystem - The active build system
+        modules - List of module.Module objects
+        cfg - The currently loaded 'cfg' module
+    """
 
-    if buildsystem == "msys":
-        # Msys has to treat the paths differently.
-        sdlincdirs = [ config_msys.msys_to_windows (d) for d in sdlincdirs ]
-        sdllibdirs = [ config_msys.msys_to_windows (d) for d in sdllibdirs ]
-        jpgincdirs = [ config_msys.msys_to_windows (d) for d in jpgincdirs ]
-        jpglibdirs = [ config_msys.msys_to_windows (d) for d in jpglibdirs ]
-        pngincdirs = [ config_msys.msys_to_windows (d) for d in pngincdirs ]
-        pnglibdirs = [ config_msys.msys_to_windows (d) for d in pnglibdirs ]
-    
+    os_config = OS_MODULES[buildsystem]
+
+    # configure our library dependencies
+    dependencies = get_dependencies(buildsystem, cfg)
+
     for mod in modules:
-        # Do not build the numericXXX modules on 3.x
-        if "numeric" in mod.name and helpers.getversion() >= (3, 0, 0):
-            mod.canbuild = False
-            continue
-        
-        # Get module-specific system libraries.
-        mod.libs = []
-        mod.libs += get_sys_libs (buildsystem, mod.name)
-        
-        # SDL based module
-        if mod.name.startswith ("sdl"):
-            mod.canbuild = cfg.WITH_SDL
-            mod.incdirs = list (sdlincdirs)
-            mod.libdirs = list (sdllibdirs)
-            mod.libs += list (sdllibs)
-            mod.cflags = list (sdlcflags)
-            mod.lflags = list (sdllflags)
+        mod.canbuild = True
 
-            # SDL Mixer linkage
-            if mod.name.startswith ("sdlmixer"):
-                mod.canbuild = cfg.WITH_SDL and cfg.WITH_SDL_MIXER
-                mod.libs += [ "SDL_mixer" ]
+        # add build/link information for the library dependencies 
+        # on which mod relies.
+        # if one of the required libraries cannot be found,
+        # the module will be disabled (cannot be built)
+        for dep_name in mod.depends:
+            dep_name = dep_name.lower()
 
-            # SDL TTF linkage
-            if mod.name.startswith ("sdlttf"):
-                mod.canbuild = cfg.WITH_SDL and cfg.WITH_SDL_TTF
-                mod.libs += [ "SDL_ttf" ]
+            if dep_name not in dependencies:
+                raise Exception("Invalid library dependency: '%s'" % dep_name)
 
-            # SDL Image linkage
-            if mod.name.startswith ("sdlimage"):
-                mod.canbuild = cfg.WITH_SDL and cfg.WITH_SDL_IMAGE
-                mod.libs += [ "SDL_image" ]
+            dep = dependencies[dep_name]
+            dep.setup_module(mod, False)
 
-            # SDL GFX linkage
-            if mod.name.startswith ("sdlgfx"):
-                mod.canbuild = cfg.WITH_SDL and cfg.WITH_SDL_GFX
-                mod.libs += [ "SDL_gfx" ]
+        # add build/link information for optional libraries
+        # our module might rely on.
+        # if one of the optional libraries cannot be found,
+        # nothing bad happens. The module will be built but may
+        # lack some of its functionality
+        for dep_name in mod.optional_dep:
+            dep_name = dep_name.lower()
 
-            # PNG and JPEG support for Surface.save
-            if mod.name == "sdl.video":
-                if haspng:
-                    mod.cflags += list (pngcflags)
-                    mod.lflags += list (pnglflags)
-                    mod.incdirs += list (pngincdirs)
-                    mod.libdirs += list (pnglibdirs)
-                    mod.libs += list (pnglibs)
-                if hasjpg:
-                    mod.cflags += list (jpgcflags)
-                    mod.lflags += list (jpglflags)
-                    mod.incdirs += list (jpgincdirs)
-                    mod.libdirs += list (jpglibdirs)
-                    mod.libs += list (jpglibs)
+            if dep_name in dependencies:
+                dep = dependencies[dep_name]
+                dep.setup_module(mod, True)
 
-        # SDL linkage for pygame.mask
-        elif mod.name == "mask" and hassdl:
-            mod.incdirs = list (sdlincdirs)
-            mod.libdirs = list (sdllibdirs)
-            mod.libs += list (sdllibs)
-            mod.cflags = list (sdlcflags)
-            mod.lflags = list (sdllflags)
+        # add any OS-specific libraries
+        mod.libs += os_config.get_sys_libs(mod.name) or []

config/config_msys.py

 import os, glob
 from config import sdlconfig, pkgconfig, msys, helpers, dll
+from config import config_unix, config_generic
 
 try:
     msys_obj = msys.Msys (require_mingw=False)
 except:
     msys_obj = None
 
-_searchdirs = [ "/usr", "/usr/local", "/mingw" ]
-_incdirs = [ "include", "X11/include" ]
-_libdirs = [ "lib", "X11/lib" ]
+def sdl_get_version ():
+    return config_unix.sdl_get_version()
+
+def get_sys_libs (module):
+    # Gets a list of system libraries to link the module against.
+    if module == "sdlext.scrap":
+        return [ "user32", "gdi32" ]
+
+
 
 def _hunt_libs (name, dirs):
     # Used by get_install_libs(). It resolves the dependency libraries
                     libs[filename] = 1
     return libs
 
-def find_incdir (name):
-    # Gets the include directory for the specified header file.
-    for d in _searchdirs:
-        for g in _incdirs:
-            p = msys_obj.msys_to_windows (os.path.join (d, g))
-            f = os.path.join (p, name)
-            if os.path.isfile (f):
-                return p
-
-def find_libdir (name):
-    # Gets the library directory for the specified library file.
-    for d in _searchdirs:
-        for g in _libdirs:
-            p = msys_obj.msys_to_windows (os.path.join (d, g))
-            f = os.path.join (p, name)
-            if filter (os.path.isfile, glob.glob (f + '*')):
-                return p
-
-def sdl_get_version ():
-    # Gets the SDL version.
-    if pkgconfig.has_pkgconfig ():
-        return pkgconfig.get_version ("sdl")[0]
-    elif sdlconfig.has_sdlconfig ():
-        return sdlconfig.get_version ()[0]
-    return None
-
-def msys_to_windows (path):
-    # Converts a msys path to a Windows path.
-    return msys_obj.msys_to_windows (path)
-
-def get_sys_libs (module):
-    # Gets a list of system libraries to link the module against.
-    if module == "sdlext.scrap":
-        return [ "user32", "gdi32" ]
-
 def get_install_libs (cfg):
     # Gets the libraries to install for the target platform.
     libraries = {}
     dirs += [ msys_obj.msys_to_windows ("/mingw/" + d) for d in _libdirs]
     dirs += [ msys_obj.msys_to_windows ("/mingw/bin") ]
     
-    if cfg.WITH_SDL:
+    if cfg.build['SDL']:
         libraries.update (_hunt_libs ("SDL", dirs))
-    if cfg.WITH_SDL_MIXER:
+    if cfg.build['SDL_MIXER']:
         libraries.update (_hunt_libs ("SDL_mixer", dirs))
-    if cfg.WITH_SDL_IMAGE:
+    if cfg.build['SDL_IMAGE']:
         libraries.update (_hunt_libs ("SDL_image", dirs))
-    if cfg.WITH_SDL_TTF:
+    if cfg.build['SDL_TTF']:
         libraries.update (_hunt_libs ("SDL_ttf", dirs))
-    if cfg.WITH_SDL_GFX:
+    if cfg.build['SDL_GFX']:
         libraries.update (_hunt_libs ("SDL_gfx", dirs))
-    if cfg.WITH_PNG:
+    if cfg.build['PNG']:
         libraries.update (_hunt_libs ("png", dirs))
-    if cfg.WITH_JPEG:
+    if cfg.build['JPEG']:
         libraries.update (_hunt_libs ("jpeg", dirs))
+
     return [ k.replace ("/", os.sep) for k in libraries.keys() ]
 
+
+class Dependency (config_unix.Dependency):
+    _searchdirs = [ "/usr", "/usr/local", "/mingw" ]
+    _incdirs = [ "include", "X11/include" ]
+    _libdirs = [ "lib", "X11/lib" ]
+
+    def _find_incdir (self, name):
+        # Gets the include directory for the specified header file.
+        for d in self._searchdirs:
+            for g in self._incdirs:
+                p = msys_obj.msys_to_windows (os.path.join (d, g))
+                f = os.path.join (p, name)
+                if os.path.isfile (f):
+                    return p
+
+    def _find_libdir (self, name):
+        # Gets the library directory for the specified library file.
+        for d in self._searchdirs:
+            for g in self._libdirs:
+                p = msys_obj.msys_to_windows (os.path.join (d, g))
+                f = os.path.join (p, name)
+                if filter (os.path.isfile, glob.glob (f + '*')):
+                    return p
+
+    def configure(self, cfg):
+        """
+            Override the generic module configuration to make sure
+            that all the found paths are converted from MSYS to full
+            Windows path.
+        """
+        super(Dependency, self).configure(cfg)
+
+        if self.configured:
+            self.incdirs = [ msys_obj.msys_to_windows (d) for d in self.incdirs ]
+            self.libdirs = [ msys_obj.msys_to_windows (d) for d in self.libdirs ]
+
+class DependencySDL(config_unix.DependencySDL, Dependency):
+    def _configure_guess(self):
+        if super(Dependency, self)._configure_guess():
+            self.libs.append('SDLmain')
+            self.libdirs.append(self._find_libdir('SDL'))
+            return True
+
+        return False
+
+    # Always attempt to configure first
+    _configure_guess.priority = 5
+

config/config_unix.py

 import os, glob
-from config import sdlconfig, pkgconfig, helpers
-
-_searchdirs = [ "/usr", "/usr/local" ]
-_incdirs = [ "include", "X11/include" ]
-_libdirs = [ "lib", "X11/lib" ]
-
-def find_incdir (name):
-    # Gets the include directory for the specified header file.
-    for d in _searchdirs:
-        for g in _incdirs:
-            p = os.path.join (d, g)
-            f = os.path.join (p, name)
-            if os.path.isfile (f):
-                return p
-
-def find_libdir (name):
-    # Gets the library directory for the specified library file.
-    for d in _searchdirs:
-        for g in _libdirs:
-            p = os.path.join (d, g)
-            f = os.path.join (p, name)
-            if filter (os.path.isfile, glob.glob (f + '*')):
-                return p
-
-def sdl_get_version ():
-    # Gets the SDL version.
-    if pkgconfig.has_pkgconfig ():
-        return pkgconfig.get_version ("sdl")[0]
-    elif sdlconfig.has_sdlconfig ():
-        return sdlconfig.get_version ()[0]
-    return None
+from config import config_generic, sdlconfig, pkgconfig, helpers
 
 def get_sys_libs (module):
     # Gets a list of system libraries to link the module against.
     if module == "sdlext.scrap":
         return [ "X11" ]
 
-def get_install_libs (cfg):
-    # Gets the libraries to install for the target platform.
-    #
-    # Assume plain shared libraries - do not add anything.
+def sdl_get_version():
+    """
+        Returns the installed SDL library version.
+        By default, we obtain the version using either
+        'pkgconfig' or the 'sdl-config' tool.
+    """
+    if pkgconfig.has_pkgconfig ():
+        return pkgconfig.get_version ("sdl")[0]
+    elif sdlconfig.has_sdlconfig ():
+        return sdlconfig.get_version ()[0]
+
+    # TODO: SDL may be installed manually (i.e. compiled from
+    # source). any way to find the version?
+    return None
+
+def get_install_libs(cfg):
     return []
+
+
+class Dependency (config_generic.Dependency):
+    _searchdirs = [ "/usr", "/usr/local" ]
+    _incdirs = [ "include", "X11/include" ]
+    _libdirs = [ "lib", "X11/lib" ]
+
+    def _find_incdir(self, name):
+        # Gets the include directory for the specified header file.
+        for d in self._searchdirs:
+            for g in self._incdirs:
+                p = os.path.join (d, g)
+                f = os.path.join (p, name)
+                if os.path.isfile (f):
+                    return p
+
+    def _find_libdir(self, name):
+        # Gets the library directory for the specified library file.
+        for d in self._searchdirs:
+            for g in self._libdirs:
+                p = os.path.join (d, g)
+                f = os.path.join (p, name)
+                if filter (os.path.isfile, glob.glob (f + '*')):
+                    return p
+
+    def _configure_pkgconfig(self):
+        """
+            Configuration callback using the 'pkgconfig' tool
+        """
+        if (not pkgconfig.has_pkgconfig() or 
+            not pkgconfig.exists(self.library_name)):
+            return False
+
+        self.incdirs += pkgconfig.get_incdirs(self.library_name)
+        self.libdirs += pkgconfig.get_libdirs(self.library_name)
+        self.libs += pkgconfig.get_libs(self.library_name)
+        self.cflags += pkgconfig.get_cflags(self.library_name)
+        self.lflags += pkgconfig.get_lflags(self.library_name)
+        return True
+
+    _configure_pkgconfig.priority = 1
+
+class DependencySDL (config_generic.DependencySDL, Dependency):
+    # look in the SDL subdir for headers
+    _incdirs = [ "include", "X11/include", "include/SDL", "X11/include/SDL" ]
+
+    def _configure_pkgconfig(self):
+        """
+            Configuration callback using the 'pkgconfig' tool.
+            Note that all the SDL-based libraries don't show up
+            as such under pkgconfig, hence we need to always look
+            for SDL.
+        """
+        if (not pkgconfig.has_pkgconfig() or 
+            not pkgconfig.exists('sdl')):
+            return False
+
+        if not self._find_incdir(self.header_file):
+            return False
+
+        self.incdirs += pkgconfig.get_incdirs('sdl')
+        self.libdirs += pkgconfig.get_libdirs('sdl')
+        self.libs += pkgconfig.get_libs('sdl')
+        self.cflags += pkgconfig.get_cflags('sdl')
+        self.lflags += pkgconfig.get_lflags('sdl')
+        return True
+
+    _configure_pkgconfig.priority = 1
+
+    def _configure_sdlconfig(self):
+        """
+            Configuration callback using the 'sdl-config' tool
+        """
+        if not sdlconfig.has_sdlconfig():
+            return False
+
+        # SDL-config returns valid values for all the sdl-based
+        # libraries (sdl_ttf, sdl_mixer, etc) even if the library
+        # is not installed. Make sure at least that its header
+        # exists!
+        if not self._find_incdir(self.header_file):
+            return False
+
+        self.incdirs += sdlconfig.get_incdirs ()
+        self.libdirs += sdlconfig.get_libdirs ()
+        self.libs += sdlconfig.get_libs ()
+        self.cflags += sdlconfig.get_cflags ()
+        self.lflags += sdlconfig.get_lflags ()
+        return True
+
+    _configure_sdlconfig.priority = 2
+

config/config_win.py

 import os, glob
 from config import sdlconfig, pkgconfig, helpers, dll
+from config import config_generic
 
-_searchdirs = [ "prebuilt", "..", "..\\.." ]
-_incdirs = [ "", "include" ]
-_libdirs = [ "", "VisualC\\SDL\\Release", "VisualC\\Release", "Release", "lib"]
+def sdl_get_version ():
+    # Gets the SDL version.
+    # TODO: Is there some way to detect the correct version?
+    return "Unknown"
+
+def get_sys_libs (module):
+    # Gets a list of system libraries to link the module against.
+    if module == "sdlext.scrap":
+        return [ "user32", "gdi32" ]
 
 def _hunt_libs (name, dirs):
     # Used by get_install_libs(). It resolves the dependency libraries
                     libs[filename] = 1
     return libs
 
-
-def find_incdir (name):
-    # Gets the include directory for the specified header file.
-    for d in _searchdirs:
-        for g in _incdirs:
-            p = os.path.join (d, g)
-            f = os.path.join (p, name)
-            if os.path.isfile (f):
-                return p
-
-def find_libdir (name):
-    # Gets the library directory for the specified library file.
-    for d in _searchdirs:
-        for g in _libdirs:
-            p = os.path.join (d, g)
-            f = os.path.join (p, name)
-            if len (list (filter (os.path.isfile, glob.glob (f + '*')))) > 0:
-                return p
-
-def sdl_get_version ():
-    # Gets the SDL version.
-    # TODO: Is there some way to detect the correct version?
-    return "Unknown"
-
-def get_sys_libs (module):
-    # Gets a list of system libraries to link the module against.
-    if module == "sdlext.scrap":
-        return [ "user32", "gdi32" ]
-
 def get_install_libs (cfg):
     # Gets the libraries to install for the target platform.
+    _libdirs = [ "", "VisualC\\SDL\\Release", "VisualC\\Release", "Release",
+                 "lib"]
+    _searchdirs = [ "prebuilt", "..", "..\\.." ]
+
     libraries = {}
     values = {}
     dirs = []
         for g in _libdirs:
             dirs.append (os.path.join (d, g))
     
-    if cfg.WITH_SDL:
+    if cfg.build['SDL']:
         libraries.update (_hunt_libs ("SDL", dirs))
-    if cfg.WITH_SDL_MIXER:
+    if cfg.build['SDL_MIXER']:
         libraries.update (_hunt_libs ("SDL_mixer", dirs))
-    if cfg.WITH_SDL_IMAGE:
+    if cfg.build['SDL_IMAGE']:
         libraries.update (_hunt_libs ("SDL_image", dirs))
-    if cfg.WITH_SDL_TTF:
+    if cfg.build['SDL_TTF']:
         libraries.update (_hunt_libs ("SDL_ttf", dirs))
-    if cfg.WITH_SDL_GFX:
+    if cfg.build['SDL_GFX']:
         libraries.update (_hunt_libs ("SDL_gfx", dirs))
-    if cfg.WITH_PNG:
+    if cfg.build['PNG']:
         libraries.update (_hunt_libs ("png", dirs))
-    if cfg.WITH_JPEG:
+    if cfg.build['JPEG']:
         libraries.update (_hunt_libs ("jpeg", dirs))
+
     return libraries.keys ()
+
+
+class Dependency (config_generic.Dependency):
+    _searchdirs = [ "prebuilt", "..", "..\\.." ]
+    _incdirs = [ "", "include" ]
+    _libdirs = [ "", "VisualC\\SDL\\Release", "VisualC\\Release", "Release",
+                 "lib"]
+
+    def _find_incdir(self, name):
+        # Gets the include directory for the specified header file.
+        for d in self._searchdirs:
+            for g in self._incdirs:
+                p = os.path.join (d, g)
+                f = os.path.join (p, name)
+                if os.path.isfile (f):
+                    return p
+
+    def _find_libdir(self, name):
+        # Gets the library directory for the specified library file.
+        for d in self._searchdirs:
+            for g in self._libdirs:
+                p = os.path.join (d, g)
+                f = os.path.join (p, name)
+                if len (list (filter (os.path.isfile, glob.glob (f + '*')))) > 0:
+                    return p
+
+class DependencySDL(config_generic.DependencySDL, Dependency):
+    def _configure_guess(self):
+        if super(DependencySDL, self)._configure_guess():
+            self.libs.append('SDLmain')
+            self.libdirs = [ self._find_libdir('SDL') ]
+            return True
+
+        return False
+
+    # Under windows, always guess the library position
+    _configure_guess.priority = 5
+

config/pkgconfig.py

 def exists (package):
     pipe = os.popen ("pkg-config --exists %s" % package, "r")
     ret = pipe.close ()
-    return ret == None
+    return ret in (None, 0)
 
 def has_pkgconfig ():
     if msys.is_msys():
 entry looks like this: ::
 
   Module ("MODULENAME", [ "SOURCEFILE.c", "SOURCEFILE.c", ... ],
-          [ "pgCAPIHEADER.h", "pgCAPIHEADER.h", ...], "DOCFILE.xml")
+          [ "pgCAPIHEADER.h", "pgCAPIHEADER.h", ...], "DOCFILE.xml",
+          ['DEPENDENCY1', 'DEPENDENCY2', ...])
 
 In case you have submodules, you would split anything according to your
 needs. You can see how submodules are added by looking at the various
 install.
 DOCFILE.xml is the name of the documentation file to use, which is located
 under doc/src (see below, "Documenting").
+Each entry in the DEPENDENCYx list represents an external library reference
+which must be linked with the module. The names of these libraries can be
+found/modified in the config.config_modules file.
 
 Example: ::
 
   Module ("myownlib",[ "src/myownlib/myownlibmod.c", "src/myownlib/myclass.c" ],
-                     [ "src/myownlib/pgmyownlib.h" ], "myownlib.xml")
+                     [ "src/myownlib/pgmyownlib.h" ], "myownlib.xml", ['SDL'])
 
-If the module has external dependencies, which cannot be guaranteed to
-be available on each platform, add a ::
 
-  WITH_MOD = istrue (os.getenv ("WITH_MOD", True))
+If you need to define a new library reference, you may do so in the dependencies
+dictionary in config.config_modules ::
 
-to the cfg.py configuration file so that users can enable/disable the
-module on demand using the build and environment settings.
+    'dependency_name' : 
+        os_module.Dependency('header.h', 'library_id'),
 
-Adjust the various config/config_XXX.py files to check for needed dependencies
-of your module and such. As this can vary from platform to platform,
-it is recommended to look at the existing code within the files and add your
-own checks as necessary. If the module features a WITH_MOD = ... entry
-within cfg.py, it MUST check for WITH_MOD and has to be enabled or disabled
-according to that entry.
+When defining a new dependency, 'dependency_name' is its full name (as
+referenced when instantiating a new Module object), 'header.h' is a
+representative header for the library, and 'library_id' is the linking
+id for the library: For example, a library that is linked with the
+'-ljpeg' has 'jpeg' as its id.
 
-Example: ::
-  
-  if WITH_MYOWNLIB:
-      # Module should be build. MyOwnLib is available according to the
-      # user.
-      mod.canbuild = check_for_myownlib_needs()
-      mod.incdirs = ...
-      ...  
-  else:
-      # Disable the module.
-      mod.canbuild = False
+All the modules which depend on such library will be automatically
+configured and built using it.
+
+Additionally, you may disable/enable the compilation of such library
+(and hence of all the modules which rely on it) by adding an entry to
+the 'build' dictionary in the cfg.py module ::
+
+    build['dependency_name'] = False
+
 
 C Module Dependencies
 ---------------------
 environment, you can check for the build system flags, which are automatically
 added at compile time. Currently, the following flags are available:
 
-  IS_WIN32 - Win32 build with Visual C++
-  IS_MSYS  - (Win32) Msys build with GCC
-  IS_UNIX  - Any other build plattform that successfully passes the preparations
-
-You can easily check for those flags in the C code using the usualy preprocessor
-magic: ::
+  +-----------+----------------------------------------+
+  | IS_WIN32  | Win32 build with Visual C++            |
+  +-----------+----------------------------------------+
+  | IS_MSYS   | (Win32) Msys build with GCC            |
+  +-----------+----------------------------------------+
+  | IS_DARWIN | MacOS X and Darin-based platforms      |
+  +-----------+----------------------------------------+
+  | IS_UNIX   | Any other build platform that          |
+  |           | successfully passes the preparations   |
+  +-----------+----------------------------------------+
+  
+You can easily check for those flags in the C code using the usualy
+preprocessor magic: ::
 
   #ifdef IS_WIN32 
     /* Visual C++ specific Win32 instructions */
     /* GCC/Msys specific Win32 instructions */
   #elif defined(IS_UNIX)
    /* Unix specific instructions */
+  #elif defined(IS_DARWIN)
+   /* Darwin specific instructions */
   #endif
 
 Python Modules
 
 Documenting
 -----------
-As written above (see "C module build system"), the documentation files reside
-in doc/src/. They are all XML files and must have a ".xml" suffix in order to
-be recognized by the documentation build system.
+As written above (see "C module build system"), the documentation files
+reside in doc/src/. They are all XML files and must have a ".xml" suffix
+in order to be recognized by the documentation build system.
 
 Python Modules
 ^^^^^^^^^^^^^^
  
   python create_doc.py pygame2.myownlib myownlib.xml
 
-This will create a XML documentation file including the documentation you
-already wrote for the module. A second step now will require you to remove the
-documentation from the code and use the API constants which will be generated
-by the documentation system.
-Include the "DOCFILE_doc.h" header file, then use the proper constants for all
+This will create a XML documentation file including the documentation
+you already wrote for the module. A second step now will require you to
+remove the documentation from the code and use the API constants which
+will be generated by the documentation system. Include the
+"DOCFILE_doc.h" header file, then use the proper constants for all
 things to document.
 
 C Documentation Constants
 The C constants are generated using the DOC_MODULENAME_CLASSNAME_NAME scheme.
 The following constants are used:
 
-  +---------------------------+-------------------------------------------+
-  | DOC_MODULENAME            | The documentation for the module.         |
-  +---------------------------+-------------------------------------------+
-  | DOC_MODULENAME_FUNCNAME   | The documentation for a module function.  |
-  +---------------------------+-------------------------------------------+
-  | DOC_MODULENAME_CLASSNAME  | The documentation for a class.            |
-  +---------------------------+-------------------------------------------+
-  |DOC_MODULENAME_CLASSNAME_X | The documentation for a class method or   |
-  |                           | attribute.                                |
-  +---------------------------+-------------------------------------------+
+  +----------------------------+-------------------------------------------+
+  | DOC_MODULENAME             | The documentation for the module.         |
+  +----------------------------+-------------------------------------------+
+  | DOC_MODULENAME_FUNCNAME    | The documentation for a module function.  |
+  +----------------------------+-------------------------------------------+
+  | DOC_MODULENAME_CLASSNAME   | The documentation for a class.            |
+  +----------------------------+-------------------------------------------+
+  | DOC_MODULENAME_CLASSNAME_X | The documentation for a class method or   |
+  |                            | attribute.                                |
+  +----------------------------+-------------------------------------------+
 
 Take a look at the src/base code to learn more about it.

doc/MODULE_FAQ.txt

 added at compile time. Currently, the following flags and macros are available:
 
   +-----------+----------------------------------------+
-  |  IS_WIN32 | Win32 build with Visual C++            |
+  | IS_WIN32  | Win32 build with Visual C++            |
   +-----------+----------------------------------------+
   | IS_MSYS   | (Win32) Msys build with GCC            |
   +-----------+----------------------------------------+
+  | IS_DARWIN | MacOS X and Darin-based platforms      |
+  +-----------+----------------------------------------+
   | IS_UNIX   | Any other build platform that          |
   |           | successfully passes the preparations   |
   +-----------+----------------------------------------+
 	@echo "  linkcheck to check all external links for integrity"
 
 clean:
-	-rm -rf sphinx/build *~ *.pyc ref html
+	-rm -rf sphinx/build *~ *.pyc *.orig ref html
 	-rm -f buildmingw.rst buildunix.rst buildvc.rst
 	-rm -f newmodules.rst module_faq.rst
 
 from distutils.extension import Extension
 import sys, os
 import config, cfg
+from config import helpers
 
 # For create_cref.py
 sys.path.append ("doc")
 import create_cref
 
 class Module:
-    def __init__ (self, name, sources=None, instheaders=[], docfile=None):
+    def __init__ (self, name, sources=None, instheaders=[], docfile=None, depends=None, optional_dep=None):
+        """
+            Initializes the Module object.
+
+            name -  Name of this module
+            sources - List of all the C sources which make the module
+            instheaders - Additional C headers
+            docfile - XML file containing the documentation for the module
+            depends -   List of all the external libraries on which this 
+                        module depends.
+                        These libraries must be declared beforehand in 
+                        config.config_modules.DEPENDENCIES
+            optional_dep - List of optional libraries with which this module can be built.
+        """
+
         self.name = name
         self.sources = sources
         self.installheaders = instheaders
         nn = name.upper ().replace (".", "_")
         self.cflags_avail = "-DHAVE_PYGAME_" + nn
 
+        self.depends = list (depends or [])
+        self.optional_dep = list(optional_dep or [])
+
 modules = [
-    Module ("base", [ "src/base/basemod.c",
-                      "src/base/bufferproxy.c",
-                      "src/base/color.c",
-                      "src/base/floatrect.c",
-                      "src/base/rect.c",
-                      "src/base/surface.c" ],
-            [ "src/pgcompat.h",
-              "src/base/pgbase.h",
-              "src/base/pgdefines.h",
-              "src/base/pgtypes.h" ], "base.xml"),
 
-    Module ("mask", [ "src/mask/bitmask.c",
-                      "src/mask/mask.c",
-                      "src/mask/maskmod.c" ],
-            [ "src/mask/bitmask.h",
-              "src/mask/pgmask.h" ], "mask.xml"),
+    Module ("base",
+        sources = [
+            "src/base/basemod.c",
+            "src/base/bufferproxy.c",
+            "src/base/color.c",
+            "src/base/floatrect.c",
+            "src/base/rect.c",
+            "src/base/surface.c" ],
 
-    Module ("physics", [ "src/physics/aabbox.c",
-                         "src/physics/body.c",
-                         "src/physics/collision.c",
-                         "src/physics/contact.c",
-                         "src/physics/joint.c",
-                         "src/physics/physicsmod.c",
-                         "src/physics/rectshape.c",
-                         "src/physics/shape.c",
-                         "src/physics/vector.c",
-                         "src/physics/world.c" ],
-           [ "src/physics/pgphysics.h" ], "physics.xml"),
+        instheaders = [
+            "src/pgcompat.h",
+            "src/base/pgbase.h",
+            "src/base/pgdefines.h",
+            "src/base/pgtypes.h" ],
+        
+        docfile = "base.xml"),
 
-    Module ("sdl.base", [ "src/sdl/sdlmod.c" ], [ "src/sdl/pgsdl.h" ],
-            "sdlbase.xml"),
-    Module ("sdl.audio", [ "src/sdl/audiomod.c" ], docfile="sdlaudio.xml"),
-    Module ("sdl.cdrom", [ "src/sdl/cdrommod.c",
-                           "src/sdl/cdrom.c",
-                           "src/sdl/cdtrack.c" ], docfile="sdlcdrom.xml"),
-    Module ("sdl.constants", [ "src/sdl/constantsmod.c" ]),
-    Module ("sdl.event", [ "src/sdl/eventmod.c",
-                           "src/sdl/event.c" ], docfile="sdlevent.xml"),
-    Module ("sdl.gl", [ "src/sdl/glmod.c" ], docfile="sdlgl.xml"),
-    Module ("sdl.image", [ "src/sdl/imagemod.c" ], docfile="sdlimage.xml"),
-    Module ("sdl.joystick", [ "src/sdl/joystickmod.c",
-                              "src/sdl/joystick.c" ],
-            docfile="sdljoystick.xml"),
-    Module ("sdl.keyboard", [ "src/sdl/keyboardmod.c" ],
-            docfile="sdlkeyboard.xml"),
-    Module ("sdl.mouse", [ "src/sdl/cursor.c",
-                           "src/sdl/mousemod.c" ], docfile="sdlmouse.xml"),
-    Module ("sdl.rwops", [ "src/sdl/rwopsmod.c" ], docfile="sdlrwops.xml"),
-    Module ("sdl.time", [ "src/sdl/timemod.c" ], docfile="sdltime.xml"),
-    Module ("sdl.video", [ "src/sdl/pixelformat.c",
-                           "src/sdl/surface_blit.c",
-                           "src/sdl/surface_fill.c",
-                           "src/sdl/surface_save.c",
-                           "src/sdl/surface.c",
-                           "src/sdl/tga.c",
-                           "src/sdl/png.c",
-                           "src/sdl/jpg.c",
-                           "src/sdl/overlay.c",
-                           "src/sdl/videomod.c" ], docfile="sdlvideo.xml"),
-    Module ("sdl.wm", [ "src/sdl/wmmod.c" ], docfile="sdlwm.xml"),
+    Module ("mask",
+        sources = [
+            "src/mask/bitmask.c",
+            "src/mask/mask.c",
+            "src/mask/maskmod.c" ],
 
-    Module ("sdlext.base", [ "src/sdlext/pixelarray.c",
-                             "src/sdlext/sdlextmod.c" ],
-            [ "src/sdlext/pgsdlext.h" ], "sdlextbase.xml"),
-    Module ("sdlext.constants", [ "src/sdlext/constantsmod.c" ]),
-    Module ("sdlext.draw", [ "src/sdlext/draw.c",
-                             "src/sdlext/drawmod.c" ],
-            docfile="sdlextdraw.xml"),
-    Module ("sdlext.fastevent", [ "src/sdlext/fasteventmod.c",
-                                  "src/sdlext/fastevents.c" ],
-            docfile="sdlextfastevent.xml"),
-    Module ("sdlext.numericsurfarray", [ "src/sdlext/numericsurfarraymod.c" ],
-            docfile="sdlextnumericsurfarray.xml"),
-    Module ("sdlext.scrap", [ "src/sdlext/scrapmod.c",
-                              "src/sdlext/scrap.c",
-                              "src/sdlext/scrap_x11.c",
-                              "src/sdlext/scrap_win.c" ],
-            docfile="sdlextscrap.xml"),
-    Module ("sdlext.transform", [ "src/sdlext/transform.c",
-                                  "src/sdlext/filters.c",
-                                  "src/sdlext/transformmod.c" ],
-            docfile="sdlexttransform.xml"),
+        instheaders = [
+            "src/mask/bitmask.h",
+            "src/mask/pgmask.h" ],
+        
+        docfile = "mask.xml",
+        optional_dep = ['SDL']),
 
-    Module ("sdlmixer.base", [ "src/sdlmixer/mixermod.c",
-                               "src/sdlmixer/chunk.c",
-                               "src/sdlmixer/channel.c",
-                               "src/sdlmixer/music.c" ],
-            [ "src/sdlmixer/pgmixer.h" ], "sdlmixerbase.xml"),
-    Module ("sdlmixer.constants", [ "src/sdlmixer/constantsmod.c" ]),
-    Module ("sdlmixer.channel", [ "src/sdlmixer/channelmod.c" ],
-            docfile="sdlmixerchannel.xml"),
-    Module ("sdlmixer.music", [ "src/sdlmixer/musicmod.c" ],
-            docfile="sdlmixermusic.xml"),
-    Module ("sdlmixer.numericsndarray",
-            [ "src/sdlmixer/numericsndarraymod.c" ],
-            docfile="sdlmixernumericsndarray.xml"),
+    Module ("physics",
+        sources = [
+            "src/physics/aabbox.c",
+            "src/physics/body.c",
+            "src/physics/collision.c",
+            "src/physics/contact.c",
+            "src/physics/joint.c",
+            "src/physics/physicsmod.c",
+            "src/physics/rectshape.c",
+            "src/physics/shape.c",
+            "src/physics/vector.c",
+            "src/physics/world.c" ],
 
-    Module ("sdlttf.base", [ "src/sdlttf/ttfmod.c",
-                             "src/sdlttf/font.c" ],
-            [ "src/sdlttf/pgttf.h" ], "sdlttfbase.xml"),
-    Module ("sdlttf.constants", [ "src/sdlttf/constantsmod.c" ]),
+        instheaders = [ "src/physics/pgphysics.h" ],
+        docfile = "physics.xml"),
 
-    Module ("sdlimage.base", [ "src/sdlimage/imagemod.c" ],
-            docfile="sdlimagebase.xml"),
+    Module ("sdl.base",
+        sources = [ "src/sdl/sdlmod.c" ],
+        instheaders = [ "src/sdl/pgsdl.h" ],
+        docfile = "sdlbase.xml",
+        depends = ['SDL']),
 
-    Module ("sdlgfx.base", [ "src/sdlgfx/fpsmanager.c",
-                             "src/sdlgfx/gfxmod.c" ],
-            [ "src/sdlgfx/pggfx.h" ], "sdlgfxbase.xml"),
-    Module ("sdlgfx.constants", [ "src/sdlgfx/constantsmod.c" ]),
-    Module ("sdlgfx.primitives", [ "src/sdlgfx/primitivesmod.c" ],
-            docfile="sdlgfxprimitives.xml"),
-    Module ("sdlgfx.rotozoom", [ "src/sdlgfx/rotozoommod.c" ],
-            docfile="sdlgfxrotozoom.xml"),
+    Module ("sdl.audio",
+        sources = [ "src/sdl/audiomod.c" ],
+        docfile = "sdlaudio.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.cdrom",
+        sources = [
+            "src/sdl/cdrommod.c",
+            "src/sdl/cdrom.c",
+            "src/sdl/cdtrack.c" ],
+
+        docfile="sdlcdrom.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.constants",
+        sources = [ "src/sdl/constantsmod.c" ],
+        depends = ['SDL']),
+
+    Module ("sdl.event",
+        sources = [
+            "src/sdl/eventmod.c",
+            "src/sdl/event.c" ],
+
+        docfile = "sdlevent.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.gl",
+        sources = [ "src/sdl/glmod.c" ],
+        docfile = "sdlgl.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.image",
+        sources = [ "src/sdl/imagemod.c" ],
+        docfile = "sdlimage.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.joystick",
+        sources = [
+            "src/sdl/joystickmod.c",
+            "src/sdl/joystick.c" ],
+
+        docfile="sdljoystick.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.keyboard",
+        sources = [ "src/sdl/keyboardmod.c" ],
+        docfile = "sdlkeyboard.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.mouse",
+        sources = [
+            "src/sdl/cursor.c",
+            "src/sdl/mousemod.c" ],
+        docfile = "sdlmouse.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.rwops",
+        sources = [ "src/sdl/rwopsmod.c" ],
+        docfile = "sdlrwops.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.time",
+        sources = [ "src/sdl/timemod.c" ],
+        docfile = "sdltime.xml",
+        depends = ['SDL']),
+
+    Module ("sdl.video",
+        sources = [
+            "src/sdl/pixelformat.c",
+            "src/sdl/surface_blit.c",
+            "src/sdl/surface_fill.c",
+            "src/sdl/surface_save.c",
+            "src/sdl/surface.c",
+            "src/sdl/tga.c",
+            "src/sdl/png.c",
+            "src/sdl/jpg.c",
+            "src/sdl/overlay.c",
+            "src/sdl/videomod.c" ],
+        
+        docfile = "sdlvideo.xml",
+        depends = ['SDL'],
+        optional_dep = ['jpeg', 'png']),
+
+    Module ("sdl.wm",
+        sources = [ "src/sdl/wmmod.c" ],
+        docfile = "sdlwm.xml",
+        depends = ['SDL']),
+
+    Module ("sdlext.base",
+        sources = [
+            "src/sdlext/pixelarray.c",
+            "src/sdlext/sdlextmod.c" ],
+        instheaders = [ "src/sdlext/pgsdlext.h" ],
+        docfile = "sdlextbase.xml",
+        depends = ['SDL']),
+
+    Module ("sdlext.constants",
+        sources = [ "src/sdlext/constantsmod.c" ],
+        depends = ['SDL']),
+
+    Module ("sdlext.draw",
+        sources = [
+            "src/sdlext/draw.c",
+            "src/sdlext/drawmod.c" ],
+
+        docfile = "sdlextdraw.xml",
+        depends = ['SDL']),
+
+    Module ("sdlext.fastevent",
+        sources = [
+            "src/sdlext/fasteventmod.c",
+            "src/sdlext/fastevents.c" ],
+
+        docfile = "sdlextfastevent.xml",
+        depends = ['SDL']),
+
+    Module ("sdlext.scrap",
+        sources = [
+            "src/sdlext/scrapmod.c",
+            "src/sdlext/scrap.c",
+            "src/sdlext/scrap_x11.c",
+            "src/sdlext/scrap_win.c" ],
+
+        docfile = "sdlextscrap.xml",
+        depends = ['SDL']),
+
+    Module ("sdlext.transform",
+        sources = [
+            "src/sdlext/transform.c",
+            "src/sdlext/filters.c",
+            "src/sdlext/transformmod.c" ],
+
+        docfile = "sdlexttransform.xml",
+        depends = ['SDL']),
+
+    Module ("sdlmixer.base",
+        sources = [
+            "src/sdlmixer/mixermod.c",
+            "src/sdlmixer/chunk.c",
+            "src/sdlmixer/channel.c",
+            "src/sdlmixer/music.c" ],
+
+        instheaders = [ "src/sdlmixer/pgmixer.h" ],
+        docfile = "sdlmixerbase.xml",
+        depends = ['SDL', 'SDL_mixer']),
+
+    Module ("sdlmixer.constants",
+        sources = [ "src/sdlmixer/constantsmod.c" ],
+        depends = ['SDL', 'SDL_mixer']),
+
+    Module ("sdlmixer.channel",
+        sources = [ "src/sdlmixer/channelmod.c" ],
+        docfile = "sdlmixerchannel.xml",
+        depends = ['SDL', 'SDL_mixer']),
+
+    Module ("sdlmixer.music",
+        sources = [ "src/sdlmixer/musicmod.c" ],
+        docfile = "sdlmixermusic.xml",
+        depends = ['SDL', 'SDL_mixer']),
+
+
+    Module ("sdlttf.base",
+        sources = [
+            "src/sdlttf/ttfmod.c",
+            "src/sdlttf/font.c" ],
+
+        instheaders = [ "src/sdlttf/pgttf.h" ],
+        docfile = "sdlttfbase.xml",
+        depends = ['SDL', 'SDL_ttf']),
+
+    Module ("sdlttf.constants",
+        sources = [ "src/sdlttf/constantsmod.c" ],
+        depends = ['SDL', 'SDL_ttf']),
+
+    Module ("sdlimage.base",
+        sources = [ "src/sdlimage/imagemod.c" ],
+        docfile = "sdlimagebase.xml",
+        depends = ['SDL', 'SDL_image']),
+
+    Module ("sdlgfx.base",
+        sources = [
+            "src/sdlgfx/fpsmanager.c",
+            "src/sdlgfx/gfxmod.c" ],
+
+        instheaders = [ "src/sdlgfx/pggfx.h" ],
+        docfile = "sdlgfxbase.xml",
+        depends = ['SDL', 'SDL_gfx']),
+
+    Module ("sdlgfx.constants",
+        sources = [ "src/sdlgfx/constantsmod.c" ],
+        depends = ['SDL', 'SDL_gfx']),
+
+    Module ("sdlgfx.primitives",
+        sources = [ "src/sdlgfx/primitivesmod.c" ],
+        docfile = "sdlgfxprimitives.xml",
+        depends = ['SDL', 'SDL_gfx']),
+
+    Module ("sdlgfx.rotozoom",
+        sources = [ "src/sdlgfx/rotozoommod.c" ],
+        docfile = "sdlgfxrotozoom.xml",
+        depends = ['SDL', 'SDL_gfx']),
+
     ]
 
+if helpers.getversion() < (3, 0, 0):
+    modules.append(
+        Module ("sdlmixer.numericsndarray",
+            sources = [ "src/sdlmixer/numericsndarraymod.c" ],
+            docfile = "sdlmixernumericsndarray.xml",
+            depends = ['SDL', 'SDL_mixer']))
+
+    modules.append(
+        Module ("sdlext.numericsurfarray",
+            sources = [ "src/sdlext/numericsurfarraymod.c" ],
+            docfile = "sdlextnumericsurfarray.xml",
+            depends = ['SDL']))
+
 def get_extensions (buildsystem):
     extensions = []
 
                                  os.path.join (docincpath, incfile))
 
 def update_packages (cfg, packages, package_dir, package_data):
-    if cfg.WITH_SDL:
+    if cfg.build['SDL']:
         packages += [ "pygame2.sdl", "pygame2.sdlext" ]
         package_dir["pygame2.sdl"] = "lib/sdl"
         package_dir["pygame2.sdlext"] = "lib/sdlext"
         
-        if cfg.WITH_SDL_MIXER:
+        if cfg.build['SDL_MIXER']:
             packages += [ "pygame2.sdlmixer" ]
             package_dir["pygame2.sdlmixer"] = "lib/sdlmixer"
-        if cfg.WITH_SDL_TTF:
+        if cfg.build['SDL_TTF']:
             packages += [ "pygame2.sdlttf" ]
             package_dir["pygame2.sdlttf"] = "lib/sdlttf"
-        if cfg.WITH_SDL_IMAGE:
+        if cfg.build['SDL_IMAGE']:
             packages += [ "pygame2.sdlimage" ]
             package_dir["pygame2.sdlimage"] = "lib/sdlimage"
-        if cfg.WITH_SDL_GFX:
+        if cfg.build['SDL_GFX']:
             packages += [ "pygame2.sdlgfx" ]
             package_dir["pygame2.sdlgfx"] = "lib/sdlgfx"
 from config import *
 
 VERSION = "2.0.0"
-DEBUG= True
+DEBUG = True
 
 # Minimum requirements.
 PYTHON_MINIMUM = (2, 4)
         else:
             buildsystem = "win"
             buildcflags = "-DIS_WIN32"
+    elif sys.platform == "darwin":
+        buildsystem = "darwin"
+        buildcflags = "-DIS_DARWIN"
     else:
         buildsystem = "unix"
         buildcflags = "-DIS_UNIX"
 
-    if cfg.WITH_SDL:
+    if cfg.build['SDL']:
         sdlversion = config_modules.sdl_get_version (buildsystem)
 
     print ("\nThe following information will be used to build Pygame:")
     print ("\t System: %s" % buildsystem)
     print ("\t Python: %d.%d.%d" % helpers.getversion ())
-    if cfg.WITH_SDL:
+    if cfg.build['SDL']:
         print ("\t SDL:    %s" % sdlversion)
     return buildsystem, buildcflags
 
         print (helpers.geterror ())
         sys.exit (1)
 
-    if buildsystem in ("msys", "unix") and DEBUG:
-        os.environ["CFLAGS"] = "-W -Wall -Wimplicit-int " + \
+    os.environ["CFLAGS"] = ""
+
+    if buildsystem in ("msys", "unix", "darwin") and DEBUG:
+        os.environ["CFLAGS"] += " -W -Wall -Wimplicit-int " + \
                         "-Wimplicit-function-declaration " + \
                         "-Wimplicit -Wmain -Wreturn-type -Wunused " + \
                         "-Wswitch -Wcomment -Wtrigraphs -Wformat " + \
                         "-Wmissing-prototypes -Wmissing-declarations " + \
                         "-Wnested-externs -Wshadow -Wredundant-decls -g -pg"
 
+    # When building in Mac OS, we must make sure that all
+    # modules are built as universal binaries.
+    # FIXME: Find a better place for this?
+    if buildsystem == "darwin":
+        os.environ["CFLAGS"] += " -arch i386 -arch ppc"
+
     packages = [ "pygame2",
                  "pygame2.examples",
                  "pygame2.examples.physics",
     dllfiles = [ os.path.join ("pygame2", "dll"),
                  config_modules.get_install_libs (buildsystem, cfg) ]
     ext_modules = modules.get_extensions (buildsystem)
+
     headerfiles = []
     print ("The following modules will be built:")
     for ext in ext_modules: