|
@@ -0,0 +1,248 @@
|
|
|
+# ----------------------------------------------------------------------------
|
|
|
+# Copyright (c) 2008 David James
|
|
|
+# Copyright (c) 2006-2008 Alex Holkner
|
|
|
+# All rights reserved.
|
|
|
+#
|
|
|
+# Redistribution and use in source and binary forms, with or without
|
|
|
+# modification, are permitted provided that the following conditions
|
|
|
+# are met:
|
|
|
+#
|
|
|
+# * Redistributions of source code must retain the above copyright
|
|
|
+# notice, this list of conditions and the following disclaimer.
|
|
|
+# * Redistributions in binary form must reproduce the above copyright
|
|
|
+# notice, this list of conditions and the following disclaimer in
|
|
|
+# the documentation and/or other materials provided with the
|
|
|
+# distribution.
|
|
|
+# * Neither the name of pyglet nor the names of its
|
|
|
+# contributors may be used to endorse or promote products
|
|
|
+# derived from this software without specific prior written
|
|
|
+# permission.
|
|
|
+#
|
|
|
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
|
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
+# POSSIBILITY OF SUCH DAMAGE.
|
|
|
+# ----------------------------------------------------------------------------
|
|
|
+
|
|
|
+import os.path, re, sys, glob
|
|
|
+import ctypes
|
|
|
+import ctypes.util
|
|
|
+
|
|
|
+def _environ_path(name):
|
|
|
+ if name in os.environ:
|
|
|
+ return os.environ[name].split(":")
|
|
|
+ else:
|
|
|
+ return []
|
|
|
+
|
|
|
+class LibraryLoader(object):
|
|
|
+ def __init__(self):
|
|
|
+ self.other_dirs=[]
|
|
|
+
|
|
|
+ def load_library(self,libname):
|
|
|
+ """Given the name of a library, load it."""
|
|
|
+ paths = self.getpaths(libname)
|
|
|
+
|
|
|
+ for path in paths:
|
|
|
+ if os.path.exists(path):
|
|
|
+ return self.load(path)
|
|
|
+
|
|
|
+ raise ImportError,"%s not found." % libname
|
|
|
+
|
|
|
+ def load(self,path):
|
|
|
+ """Given a path to a library, load it."""
|
|
|
+ try:
|
|
|
+ # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead
|
|
|
+ # of the default RTLD_LOCAL. Without this, you end up with
|
|
|
+ # libraries not being loadable, resulting in "Symbol not found"
|
|
|
+ # errors
|
|
|
+ if sys.platform == 'darwin':
|
|
|
+ return ctypes.CDLL(path, ctypes.RTLD_GLOBAL)
|
|
|
+ else:
|
|
|
+ return ctypes.cdll.LoadLibrary(path)
|
|
|
+ except OSError,e:
|
|
|
+ raise ImportError,e
|
|
|
+
|
|
|
+ def getpaths(self,libname):
|
|
|
+ """Return a list of paths where the library might be found."""
|
|
|
+ if os.path.isabs(libname):
|
|
|
+ yield libname
|
|
|
+
|
|
|
+ else:
|
|
|
+ for path in self.getplatformpaths(libname):
|
|
|
+ yield path
|
|
|
+
|
|
|
+ path = ctypes.util.find_library(libname)
|
|
|
+ if path: yield path
|
|
|
+
|
|
|
+ def getplatformpaths(self, libname):
|
|
|
+ return []
|
|
|
+
|
|
|
+# Darwin (Mac OS X)
|
|
|
+
|
|
|
+class DarwinLibraryLoader(LibraryLoader):
|
|
|
+ name_formats = ["lib%s.dylib", "lib%s.so", "lib%s.bundle", "%s.dylib",
|
|
|
+ "%s.so", "%s.bundle", "%s"]
|
|
|
+
|
|
|
+ def getplatformpaths(self,libname):
|
|
|
+ if os.path.pathsep in libname:
|
|
|
+ names = [libname]
|
|
|
+ else:
|
|
|
+ names = [format % libname for format in self.name_formats]
|
|
|
+
|
|
|
+ for dir in self.getdirs(libname):
|
|
|
+ for name in names:
|
|
|
+ yield os.path.join(dir,name)
|
|
|
+
|
|
|
+ def getdirs(self,libname):
|
|
|
+ '''Implements the dylib search as specified in Apple documentation:
|
|
|
+
|
|
|
+ http://developer.apple.com/documentation/DeveloperTools/Conceptual/
|
|
|
+ DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html
|
|
|
+
|
|
|
+ Before commencing the standard search, the method first checks
|
|
|
+ the bundle's ``Frameworks`` directory if the application is running
|
|
|
+ within a bundle (OS X .app).
|
|
|
+ '''
|
|
|
+
|
|
|
+ dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH")
|
|
|
+ if not dyld_fallback_library_path:
|
|
|
+ dyld_fallback_library_path = [os.path.expanduser('~/lib'),
|
|
|
+ '/usr/local/lib', '/usr/lib']
|
|
|
+
|
|
|
+ dirs = []
|
|
|
+
|
|
|
+ if '/' in libname:
|
|
|
+ dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
|
|
|
+ else:
|
|
|
+ dirs.extend(_environ_path("LD_LIBRARY_PATH"))
|
|
|
+ dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
|
|
|
+
|
|
|
+ dirs.extend(self.other_dirs)
|
|
|
+ dirs.append(".")
|
|
|
+
|
|
|
+ if hasattr(sys, 'frozen') and sys.frozen == 'macosx_app':
|
|
|
+ dirs.append(os.path.join(
|
|
|
+ os.environ['RESOURCEPATH'],
|
|
|
+ '..',
|
|
|
+ 'Frameworks'))
|
|
|
+
|
|
|
+ dirs.extend(dyld_fallback_library_path)
|
|
|
+
|
|
|
+ return dirs
|
|
|
+
|
|
|
+# Posix
|
|
|
+
|
|
|
+class PosixLibraryLoader(LibraryLoader):
|
|
|
+ _ld_so_cache = None
|
|
|
+
|
|
|
+ def _create_ld_so_cache(self):
|
|
|
+ # Recreate search path followed by ld.so. This is going to be
|
|
|
+ # slow to build, and incorrect (ld.so uses ld.so.cache, which may
|
|
|
+ # not be up-to-date). Used only as fallback for distros without
|
|
|
+ # /sbin/ldconfig.
|
|
|
+ #
|
|
|
+ # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted.
|
|
|
+
|
|
|
+ directories = []
|
|
|
+ for name in ("LD_LIBRARY_PATH",
|
|
|
+ "SHLIB_PATH", # HPUX
|
|
|
+ "LIBPATH", # OS/2, AIX
|
|
|
+ "LIBRARY_PATH", # BE/OS
|
|
|
+ ):
|
|
|
+ if name in os.environ:
|
|
|
+ directories.extend(os.environ[name].split(os.pathsep))
|
|
|
+ directories.extend(self.other_dirs)
|
|
|
+ directories.append(".")
|
|
|
+
|
|
|
+ try: directories.extend([dir.strip() for dir in open('/etc/ld.so.conf')])
|
|
|
+ except IOError: pass
|
|
|
+
|
|
|
+ directories.extend(['/lib', '/usr/lib', '/lib64', '/usr/lib64'])
|
|
|
+
|
|
|
+ cache = {}
|
|
|
+ lib_re = re.compile(r'lib(.*)\.s[ol]')
|
|
|
+ ext_re = re.compile(r'\.s[ol]$')
|
|
|
+ for dir in directories:
|
|
|
+ try:
|
|
|
+ for path in glob.glob("%s/*.s[ol]*" % dir):
|
|
|
+ file = os.path.basename(path)
|
|
|
+
|
|
|
+ # Index by filename
|
|
|
+ if file not in cache:
|
|
|
+ cache[file] = path
|
|
|
+
|
|
|
+ # Index by library name
|
|
|
+ match = lib_re.match(file)
|
|
|
+ if match:
|
|
|
+ library = match.group(1)
|
|
|
+ if library not in cache:
|
|
|
+ cache[library] = path
|
|
|
+ except OSError:
|
|
|
+ pass
|
|
|
+
|
|
|
+ self._ld_so_cache = cache
|
|
|
+
|
|
|
+ def getplatformpaths(self, libname):
|
|
|
+ if self._ld_so_cache is None:
|
|
|
+ self._create_ld_so_cache()
|
|
|
+
|
|
|
+ result = self._ld_so_cache.get(libname)
|
|
|
+ if result: yield result
|
|
|
+
|
|
|
+ path = ctypes.util.find_library(libname)
|
|
|
+ if path: yield os.path.join("/lib",path)
|
|
|
+
|
|
|
+# Windows
|
|
|
+
|
|
|
+class _WindowsLibrary(object):
|
|
|
+ def __init__(self, path):
|
|
|
+ self.cdll = ctypes.cdll.LoadLibrary(path)
|
|
|
+ self.windll = ctypes.windll.LoadLibrary(path)
|
|
|
+
|
|
|
+ def __getattr__(self, name):
|
|
|
+ try: return getattr(self.cdll,name)
|
|
|
+ except AttributeError:
|
|
|
+ try: return getattr(self.windll,name)
|
|
|
+ except AttributeError:
|
|
|
+ raise
|
|
|
+
|
|
|
+class WindowsLibraryLoader(LibraryLoader):
|
|
|
+ name_formats = ["%s.dll", "lib%s.dll"]
|
|
|
+
|
|
|
+ def load(self, path):
|
|
|
+ return _WindowsLibrary(path)
|
|
|
+
|
|
|
+ def getplatformpaths(self, libname):
|
|
|
+ if os.path.sep not in libname:
|
|
|
+ for name in self.name_formats:
|
|
|
+ path = ctypes.util.find_library(name % libname)
|
|
|
+ if path:
|
|
|
+ yield path
|
|
|
+
|
|
|
+# Platform switching
|
|
|
+
|
|
|
+# If your value of sys.platform does not appear in this dict, please contact
|
|
|
+# the Ctypesgen maintainers.
|
|
|
+
|
|
|
+loaderclass = {
|
|
|
+ "darwin": DarwinLibraryLoader,
|
|
|
+ "cygwin": WindowsLibraryLoader,
|
|
|
+ "win32": WindowsLibraryLoader
|
|
|
+}
|
|
|
+
|
|
|
+loader = loaderclass.get(sys.platform, PosixLibraryLoader)()
|
|
|
+
|
|
|
+def add_library_search_dirs(other_dirs):
|
|
|
+ loader.other_dirs = other_dirs
|
|
|
+
|
|
|
+load_library = loader.load_library
|
|
|
+
|
|
|
+del loaderclass
|