summaryrefslogtreecommitdiffstats
path: root/python/sip/siputils.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/sip/siputils.py')
-rw-r--r--python/sip/siputils.py2354
1 files changed, 0 insertions, 2354 deletions
diff --git a/python/sip/siputils.py b/python/sip/siputils.py
deleted file mode 100644
index d4e596ca..00000000
--- a/python/sip/siputils.py
+++ /dev/null
@@ -1,2354 +0,0 @@
-# This module is intended to be used by the build/installation scripts of
-# extension modules created with SIP. It provides information about file
-# locations, version numbers etc., and provides some classes and functions.
-#
-# Copyright (c) 2007
-# Riverbank Computing Limited <info@riverbankcomputing.co.uk>
-#
-# This file is part of SIP.
-#
-# This copy of SIP is licensed for use under the terms of the SIP License
-# Agreement. See the file LICENSE for more details.
-#
-# SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-
-import sys
-import os
-import string
-import types
-import stat
-import re
-
-
-# These are installation specific values created when SIP was configured.
-# @SIP_CONFIGURATION@
-
-# The stack of configuration dictionaries.
-_config_stack = []
-
-
-class Configuration(object):
- """The class that represents SIP configuration values.
- """
- def __init__(self, sub_cfg=None):
- """Initialise an instance of the class.
-
- sub_cfg is the list of sub-class configurations. It should be None
- when called normally.
- """
- # Find the build macros in the closest imported module from where this
- # was originally defined.
- self._macros = None
-
- for cls in self.__class__.__mro__:
- if cls is object:
- continue
-
- mod = sys.modules[cls.__module__]
-
- if hasattr(mod, "_default_macros"):
- self._macros = mod._default_macros
- break
-
- if sub_cfg:
- cfg = sub_cfg
- else:
- cfg = []
-
- cfg.append(_pkg_config)
-
- global _config_stack
- _config_stack = cfg
-
- def __getattr__(self, name):
- """Allow configuration values and user options to be handled as
- instance variables.
-
- name is the name of the configuration value or user option.
- """
- for cfg in _config_stack:
- try:
- return cfg[name]
- except KeyError:
- pass
-
- raise AttributeError, "\"%s\" is not a valid configuration value or user option" % name
-
- def build_macros(self):
- """Return the dictionary of platform specific build macros.
- """
- return self._macros
-
- def set_build_macros(self, macros):
- """Set the dictionary of build macros to be use when generating
- Makefiles.
-
- macros is the dictionary of platform specific build macros.
- """
- self._macros = macros
-
-
-class _UniqueList:
- """A limited list that ensures all its elements are unique.
- """
- def __init__(self, value=None):
- """Initialise the instance.
-
- value is the initial value of the list.
- """
- if value is None:
- self._list = []
- else:
- self._list = value
-
- def append(self, value):
- """Append a value to the list if it isn't already present.
-
- value is the value to append.
- """
- if value not in self._list:
- self._list.append(value)
-
- def lextend(self, value):
- """A normal list extend ignoring the uniqueness.
-
- value is the list of elements to append.
- """
- self._list.extend(value)
-
- def extend(self, value):
- """Append each element of a value to a list if it isn't already
- present.
-
- value is the list of elements to append.
- """
- for el in value:
- self.append(el)
-
- def as_list(self):
- """Return the list as a raw list.
- """
- return self._list
-
-
-class _Macro:
- """A macro that can be manipulated as a list.
- """
- def __init__(self, name, value):
- """Initialise the instance.
-
- name is the name of the macro.
- value is the initial value of the macro.
- """
- self._name = name
- self.set(value)
-
- def set(self, value):
- """Explicitly set the value of the macro.
-
- value is the new value. It may be a string, a list of strings or a
- _UniqueList instance.
- """
- self._macro = []
-
- if isinstance(value, _UniqueList):
- value = value.as_list()
-
- if type(value) == types.ListType:
- self.extend(value)
- else:
- self.append(value)
-
- def append(self, value):
- """Append a value to the macro.
-
- value is the value to append.
- """
- if value:
- self._macro.append(value)
-
- def extend(self, value):
- """Append each element of a value to the macro.
-
- value is the list of elements to append.
- """
- for el in value:
- self.append(el)
-
- def as_list(self):
- """Return the macro as a list.
- """
- return self._macro
-
-
-class Makefile:
- """The base class for the different types of Makefiles.
- """
- def __init__(self, configuration, console=0, qt=0, opengl=0, python=0,
- threaded=0, warnings=1, debug=0, dir=None,
- makefile="Makefile", installs=None, universal=''):
- """Initialise an instance of the target. All the macros are left
- unchanged allowing scripts to manipulate them at will.
-
- configuration is the current configuration.
- console is set if the target is a console (rather than windows) target.
- qt is set if the target uses Qt. For Qt v4 a list of Qt libraries may
- be specified and a simple non-zero value implies QtCore and QtGui.
- opengl is set if the target uses OpenGL.
- python is set if the target #includes Python.h.
- debug is set to generated a debugging version of the target.
- threaded is set if the target requires thread support. It is
- automatically set if the target uses Qt and Qt has thread support
- enabled.
- warnings is set if compiler warning messages are required.
- debug is set if debugging symbols should be generated.
- dir is the directory for build files and Makefiles.
- makefile is the name of the Makefile.
- installs is a list of extra install targets. Each element is a two
- part list, the first of which is the source and the second is the
- destination. If the source is another list then it is a set of source
- files and the destination is a directory.
- universal is the name of the SDK if the target is a MacOS/X universal
- binary.
- """
- if qt:
- if not hasattr(configuration, "qt_version"):
- error("The target uses Qt but pyqtconfig has not been imported.")
-
- # For Qt v4 interpret Qt support as meaning link against the core
- # and GUI libraries (which corresponds to the default qmake
- # configuration). Also allow a list of Qt v4 modules to be
- # specified.
- if configuration.qt_version >= 0x040000:
- if type(qt) != types.ListType:
- qt = ["QtCore", "QtGui"]
-
- self._threaded = configuration.qt_threaded
- else:
- self._threaded = threaded
-
- if sys.platform != "darwin":
- universal = ''
-
- self.config = configuration
- self.console = console
- self._qt = qt
- self._opengl = opengl
- self._python = python
- self._warnings = warnings
- self._debug = debug
- self._dir = dir
- self._makefile = makefile
- self._installs = installs
- self._universal = universal
-
- self._finalised = 0
-
- # Copy the macros and convert them all to instance lists.
- macros = configuration.build_macros()
-
- for m in macros.keys():
- # Allow the user to override the default.
- try:
- val = getattr(configuration, m)
- except AttributeError:
- val = macros[m]
-
- # These require special handling as they are (potentially) a set of
- # space separated values rather than a single value that might
- # contain spaces.
- if m in ("DEFINES", "CONFIG") or m[:6] in ("INCDIR", "LIBDIR"):
- val = string.split(val)
-
- # We also want to treat lists of libraries in the same way so that
- # duplicates get eliminated.
- if m[:4] == "LIBS":
- val = string.split(val)
-
- self.__dict__[m] = _Macro(m, val)
-
- # This is used to alter the configuration more significantly than can
- # be done with just configuration files.
- self.generator = self.optional_string("MAKEFILE_GENERATOR", "UNIX")
-
- # These are what configuration scripts normally only need to change.
- self.extra_cflags = []
- self.extra_cxxflags = []
- self.extra_defines = []
- self.extra_include_dirs = []
- self.extra_lflags = []
- self.extra_lib_dirs = []
- self.extra_libs = []
-
- # Get these once and make them available to sub-classes.
- if sys.platform == "win32":
- def_copy = "copy"
- def_rm = "del"
- def_mkdir = "mkdir"
- def_chk_dir_exists = "if not exist"
- else:
- def_copy = "cp -f"
- def_rm = "rm -f"
- def_mkdir = "mkdir -p"
- def_chk_dir_exists = "test -d"
-
- self.copy = self.optional_string("COPY", def_copy)
- self.rm = self.optional_string("DEL_FILE", def_rm)
- self.mkdir = self.optional_string("MKDIR", def_mkdir)
- self.chkdir = self.optional_string("CHK_DIR_EXISTS", def_chk_dir_exists)
-
-
- def finalise(self):
- """Finalise the macros by doing any consolidation that isn't specific
- to a Makefile.
- """
- # Extract the things we might need from the Windows Qt configuration.
- if self._qt:
- wcfg = string.split(self.config.qt_winconfig)
- win_shared = ("shared" in wcfg)
- win_exceptions = ("exceptions" in wcfg)
- win_rtti = ("rtti" in wcfg)
- win_stl = ("stl" in wcfg)
- else:
- win_shared = 1
- win_exceptions = 0
- win_rtti = 0
- win_stl = 0
-
- # Get what we are going to transform.
- cflags = _UniqueList()
- cflags.extend(self.extra_cflags)
- cflags.extend(self.optional_list("CFLAGS"))
-
- cxxflags = _UniqueList()
- cxxflags.extend(self.extra_cxxflags)
- cxxflags.extend(self.optional_list("CXXFLAGS"))
-
- defines = _UniqueList()
- defines.extend(self.extra_defines)
- defines.extend(self.optional_list("DEFINES"))
-
- incdir = _UniqueList(["."])
- incdir.extend(self.extra_include_dirs)
- incdir.extend(self.optional_list("INCDIR"))
-
- lflags = _UniqueList()
- lflags.extend(self.extra_lflags)
- lflags.extend(self.optional_list("LFLAGS"))
-
- libdir = _UniqueList()
- libdir.extend(self.extra_lib_dirs)
- libdir.extend(self.optional_list("LIBDIR"))
-
- # Handle MacOS/X universal binaries.
- if self._universal:
- unicflags = ('-arch ppc -arch i386 -isysroot %s' % self._universal).split()
- unilflags = ('-arch ppc -arch i386 -Wl,-syslibroot,%s' % self._universal).split()
-
- cflags.lextend(unicflags)
- cxxflags.lextend(unicflags)
- lflags.lextend(unilflags)
-
- # Don't use a unique list as libraries may need to be searched more
- # than once. Also MacOS/X uses the form "-framework lib" so we don't
- # want to lose the multiple "-framework".
- libs = []
-
- for l in self.extra_libs:
- libs.append(self.platform_lib(l))
-
- if self._qt:
- libs.extend(self._dependent_libs(l))
-
- libs.extend(self.optional_list("LIBS"))
-
- rpaths = _UniqueList()
-
- for l in self.extra_lib_dirs:
- # Ignore relative directories. This is really a hack to handle
- # SIP v3 inter-module linking.
- if os.path.dirname(l) not in ("", ".", ".."):
- rpaths.append(l)
-
- if self._python:
- incdir.append(self.config.py_inc_dir)
- incdir.append(self.config.py_conf_inc_dir)
-
- if sys.platform == "cygwin":
- libdir.append(self.config.py_lib_dir)
-
- py_lib = "python%u.%u" % ((self.config.py_version >> 16), ((self.config.py_version >> 8) & 0xff))
- libs.append(self.platform_lib(py_lib))
- elif sys.platform == "win32":
- libdir.append(self.config.py_lib_dir)
-
- py_lib = "python%u%u" % ((self.config.py_version >> 16), ((self.config.py_version >> 8) & 0xff))
-
- # For Borland use the OMF version of the Python library if it
- # exists, otherwise assume that Python was built with Borland
- # and use the normal library.
- if self.generator == "BMAKE":
- bpy_lib = py_lib + "_bcpp"
- bpy_lib_path = os.path.join(self.config.py_lib_dir, self.platform_lib(bpy_lib))
-
- if os.access(bpy_lib_path, os.F_OK):
- py_lib = bpy_lib
-
- if self._debug:
- py_lib = py_lib + "_d"
-
- if self.generator != "MINGW":
- cflags.append("/D_DEBUG")
- cxxflags.append("/D_DEBUG")
-
- libs.append(self.platform_lib(py_lib))
-
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- if win_exceptions:
- cflags_exceptions = "CFLAGS_EXCEPTIONS_ON"
- cxxflags_exceptions = "CXXFLAGS_EXCEPTIONS_ON"
- else:
- cflags_exceptions = "CFLAGS_EXCEPTIONS_OFF"
- cxxflags_exceptions = "CXXFLAGS_EXCEPTIONS_OFF"
-
- cflags.extend(self.optional_list(cflags_exceptions))
- cxxflags.extend(self.optional_list(cxxflags_exceptions))
-
- if win_rtti:
- cflags_rtti = "CFLAGS_RTTI_ON"
- cxxflags_rtti = "CXXFLAGS_RTTI_ON"
- else:
- cflags_rtti = "CFLAGS_RTTI_OFF"
- cxxflags_rtti = "CXXFLAGS_RTTI_OFF"
-
- cflags.extend(self.optional_list(cflags_rtti))
- cxxflags.extend(self.optional_list(cxxflags_rtti))
-
- if win_stl:
- cflags_stl = "CFLAGS_STL_ON"
- cxxflags_stl = "CXXFLAGS_STL_ON"
- else:
- cflags_stl = "CFLAGS_STL_OFF"
- cxxflags_stl = "CXXFLAGS_STL_OFF"
-
- cflags.extend(self.optional_list(cflags_stl))
- cxxflags.extend(self.optional_list(cxxflags_stl))
-
- if self._debug:
- if win_shared:
- cflags_mt = "CFLAGS_MT_DLLDBG"
- cxxflags_mt = "CXXFLAGS_MT_DLLDBG"
- else:
- cflags_mt = "CFLAGS_MT_DBG"
- cxxflags_mt = "CXXFLAGS_MT_DBG"
-
- cflags_debug = "CFLAGS_DEBUG"
- cxxflags_debug = "CXXFLAGS_DEBUG"
- lflags_debug = "LFLAGS_DEBUG"
- else:
- if win_shared:
- cflags_mt = "CFLAGS_MT_DLL"
- cxxflags_mt = "CXXFLAGS_MT_DLL"
- else:
- cflags_mt = "CFLAGS_MT"
- cxxflags_mt = "CXXFLAGS_MT"
-
- cflags_debug = "CFLAGS_RELEASE"
- cxxflags_debug = "CXXFLAGS_RELEASE"
- lflags_debug = "LFLAGS_RELEASE"
-
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- if self._threaded:
- cflags.extend(self.optional_list(cflags_mt))
- cxxflags.extend(self.optional_list(cxxflags_mt))
-
- if self.console:
- cflags.extend(self.optional_list("CFLAGS_CONSOLE"))
- cxxflags.extend(self.optional_list("CXXFLAGS_CONSOLE"))
-
- cflags.extend(self.optional_list(cflags_debug))
- cxxflags.extend(self.optional_list(cxxflags_debug))
- lflags.extend(self.optional_list(lflags_debug))
-
- if self._warnings:
- cflags_warn = "CFLAGS_WARN_ON"
- cxxflags_warn = "CXXFLAGS_WARN_ON"
- else:
- cflags_warn = "CFLAGS_WARN_OFF"
- cxxflags_warn = "CXXFLAGS_WARN_OFF"
-
- cflags.extend(self.optional_list(cflags_warn))
- cxxflags.extend(self.optional_list(cxxflags_warn))
-
- if self._threaded:
- cflags.extend(self.optional_list("CFLAGS_THREAD"))
- cxxflags.extend(self.optional_list("CXXFLAGS_THREAD"))
- lflags.extend(self.optional_list("LFLAGS_THREAD"))
-
- if self._qt:
- if self.generator != "UNIX" and win_shared:
- defines.append("QT_DLL")
-
- if not self._debug:
- defines.append("QT_NO_DEBUG")
-
- if self.config.qt_version >= 0x040000:
- for mod in self._qt:
- if mod == "QtCore":
- defines.append("QT_CORE_LIB")
- elif mod == "QtGui":
- defines.append("QT_GUI_LIB")
- elif mod == "QtNetwork":
- defines.append("QT_NETWORK_LIB")
- elif mod == "QtOpenGL":
- defines.append("QT_OPENGL_LIB")
- elif mod == "QtSql":
- defines.append("QT_SQL_LIB")
- elif mod == "QtTest":
- defines.append("QT_TEST_LIB")
- elif mod == "QtXml":
- defines.append("QT_XML_LIB")
- elif self._threaded:
- defines.append("QT_THREAD_SUPPORT")
-
- # Handle library directories.
- libdir_qt = self.optional_list("LIBDIR_QT")
- libdir.extend(libdir_qt)
- rpaths.extend(libdir_qt)
-
- if self.config.qt_version >= 0x040000:
- # For Windows: the macros that define the dependencies on
- # Windows libraries.
- wdepmap = {
- "QtCore": "LIBS_CORE",
- "QtGui": "LIBS_GUI",
- "QtNetwork": "LIBS_NETWORK",
- "QtOpenGL": "LIBS_OPENGL"
- }
-
- # For Windows: the dependencies between Qt libraries.
- qdepmap = {
- "QtAssistant": ("QtCore", "QtGui", "QtNetwork"),
- "QtGui": ("QtCore", ),
- "QtNetwork": ("QtCore", ),
- "QtOpenGL": ("QtCore", "QtGui"),
- "QtSql": ("QtCore", ),
- "QtSvg": ("QtCore", "QtGui", "QtXml"),
- "QtTest": ("QtCore", "QtGui"),
- "QtXml": ("QtCore", ),
- "QtDesigner": ("QtCore", "QtGui"),
- "QAxContainer": ("QtCore", "QtGui")
- }
-
- # The QtSql .prl file doesn't include QtGui as a dependency (at
- # least on Linux) so we explcitly set the dependency here for
- # everything.
- if "QtSql" in self._qt:
- if "QtGui" not in self._qt:
- self._qt.append("QtGui")
-
- # With Qt v4.2.0, the QtAssistantClient library is now a shared
- # library on UNIX. The QtAssistantClient .prl file doesn't
- # include QtGui and QtNetwork as a dependency any longer. This
- # seems to be a bug in Qt v4.2.0. We explicitly set the
- # dependencies here.
- if self.config.qt_version >= 0x040200 and "QtAssistant" in self._qt:
- if "QtGui" not in self._qt:
- self._qt.append("QtGui")
- if "QtNetwork" not in self._qt:
- self._qt.append("QtNetwork")
-
- for mod in self._qt:
- lib = self._qt4_module_to_lib(mod)
- libs.append(self.platform_lib(lib, self._is_framework(mod)))
-
- if sys.platform == "win32":
- # On Windows the dependent libraries seem to be in
- # qmake.conf rather than the .prl file and the
- # inter-dependencies between Qt libraries don't seem to
- # be anywhere.
- deps = _UniqueList()
-
- if mod in wdepmap.keys():
- deps.extend(self.optional_list(wdepmap[mod]))
-
- if mod in qdepmap.keys():
- for qdep in qdepmap[mod]:
- # Ignore the dependency if it is explicitly
- # linked.
- if qdep not in self._qt:
- libs.append(self.platform_lib(self._qt4_module_to_lib(qdep)))
-
- if qdep in wdepmap.keys():
- deps.extend(self.optional_list(wdepmap[qdep]))
-
- libs.extend(deps.as_list())
- else:
- libs.extend(self._dependent_libs(lib, self._is_framework(mod)))
- else:
- # Windows needs the version number appended if Qt is a DLL.
- qt_lib = self.config.qt_lib
-
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE") and win_shared:
- qt_lib = qt_lib + string.replace(version_to_string(self.config.qt_version), ".", "")
-
- if self.config.qt_edition == "non-commercial":
- qt_lib = qt_lib + "nc"
-
- libs.append(self.platform_lib(qt_lib, self.config.qt_framework))
- libs.extend(self._dependent_libs(self.config.qt_lib))
-
- # Handle header directories.
- try:
- specd_base = self.config.qt_data_dir
- except AttributeError:
- specd_base = self.config.qt_dir
-
- specd = os.path.join(specd_base, "mkspecs", "default")
-
- if not os.access(specd, os.F_OK):
- specd = os.path.join(specd_base, "mkspecs", self.config.platform)
-
- incdir.append(specd)
-
- qtincdir = self.optional_list("INCDIR_QT")
-
- if qtincdir:
- if self.config.qt_version >= 0x040000:
- for mod in self._qt:
- if mod == "QAxContainer":
- incdir.append(os.path.join(qtincdir[0], "ActiveQt"))
- elif self._is_framework(mod):
- if mod == "QtAssistant" and self.config.qt_version < 0x040202:
- mod = "QtAssistantClient"
-
- incdir.append(os.path.join(libdir_qt[0], mod + ".framework", "Headers"))
- else:
- incdir.append(os.path.join(qtincdir[0], mod))
-
- # This must go after the module include directories.
- incdir.extend(qtincdir)
-
- if self._opengl:
- incdir.extend(self.optional_list("INCDIR_OPENGL"))
- lflags.extend(self.optional_list("LFLAGS_OPENGL"))
- libdir.extend(self.optional_list("LIBDIR_OPENGL"))
- libs.extend(self.optional_list("LIBS_OPENGL"))
-
- if self._qt or self._opengl:
- incdir.extend(self.optional_list("INCDIR_X11"))
- libdir.extend(self.optional_list("LIBDIR_X11"))
- libs.extend(self.optional_list("LIBS_X11"))
-
- if self._threaded:
- libs.extend(self.optional_list("LIBS_THREAD"))
- libs.extend(self.optional_list("LIBS_RTMT"))
- else:
- libs.extend(self.optional_list("LIBS_RT"))
-
- if self.console:
- libs.extend(self.optional_list("LIBS_CONSOLE"))
-
- libs.extend(self.optional_list("LIBS_WINDOWS"))
-
- lflags.extend(self._platform_rpaths(rpaths.as_list()))
-
- # Save the transformed values.
- self.CFLAGS.set(cflags)
- self.CXXFLAGS.set(cxxflags)
- self.DEFINES.set(defines)
- self.INCDIR.set(incdir)
- self.LFLAGS.set(lflags)
- self.LIBDIR.set(libdir)
- self.LIBS.set(libs)
-
- # Don't do it again because it has side effects.
- self._finalised = 1
-
- def _is_framework(self, mod):
- """Return true if the given Qt module is a framework.
- """
- return (self.config.qt_framework and (self.config.qt_version >= 0x040200 or mod != "QtAssistant"))
-
- def _qt4_module_to_lib(self, mname):
- """Return the name of the Qt4 library corresponding to a module.
-
- mname is the name of the module.
- """
- if mname == "QtAssistant":
- if self.config.qt_version >= 0x040202 and sys.platform == "darwin":
- lib = mname
- else:
- lib = "QtAssistantClient"
- else:
- lib = mname
-
- if self._debug:
- if sys.platform == "win32":
- lib = lib + "d"
- elif self.config.qt_version < 0x040200 or sys.platform == "darwin":
- lib = lib + "_debug"
-
- if sys.platform == "win32":
- if (mname in ("QtCore", "QtGui", "QtNetwork", "QtOpenGL",
- "QtSql", "QtSvg", "QtTest", "QtXml", "QtDesigner") or
- (self.config.qt_version >= 0x040200 and mname == "QtAssistant")):
- lib = lib + "4"
-
- return lib
-
- def optional_list(self, name):
- """Return an optional Makefile macro as a list.
-
- name is the name of the macro.
- """
- return self.__dict__[name].as_list()
-
- def optional_string(self, name, default=""):
- """Return an optional Makefile macro as a string.
-
- name is the name of the macro.
- default is the default value
- """
- s = string.join(self.optional_list(name))
-
- if not s:
- s = default
-
- return s
-
- def required_string(self, name):
- """Return a required Makefile macro as a string.
-
- name is the name of the macro.
- """
- s = self.optional_string(name)
-
- if not s:
- raise ValueError, "\"%s\" must have a non-empty value" % name
-
- return s
-
- def _platform_rpaths(self, rpaths):
- """Return a list of platform specific rpath flags.
-
- rpaths is the cannonical list of rpaths.
- """
- flags = []
- prefix = self.optional_string("RPATH")
-
- if prefix:
- for r in rpaths:
- flags.append(_quote(prefix + r))
-
- return flags
-
- def platform_lib(self, clib, framework=0):
- """Return a library name in platform specific form.
-
- clib is the library name in cannonical form.
- framework is set of the library is implemented as a MacOS framework.
- """
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- plib = clib + ".lib"
- elif sys.platform == "darwin" and framework:
- plib = "-framework " + clib
- else:
- plib = "-l" + clib
-
- return plib
-
- def _dependent_libs(self, clib, framework=0):
- """Return a list of additional libraries (in platform specific form)
- that must be linked with a library.
-
- clib is the library name in cannonical form.
- framework is set of the library is implemented as a MacOS framework.
- """
- prl_libs = []
-
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- prl_name = os.path.join(self.config.qt_lib_dir, clib + ".prl")
- elif sys.platform == "darwin" and framework:
- prl_name = os.path.join(self.config.qt_lib_dir, clib + ".framework", clib + ".prl")
- else:
- prl_name = os.path.join(self.config.qt_lib_dir, "lib" + clib + ".prl")
-
- if os.access(prl_name, os.F_OK):
- try:
- f = open(prl_name, "r")
- except IOError, detail:
- error("Unable to open \"%s\": %s" % (prl_name, detail))
-
- line = f.readline()
- while line:
- line = string.strip(line)
- if line and line[0] != "#":
- eq = string.find(line, "=")
- if eq > 0 and string.strip(line[:eq]) == "QMAKE_PRL_LIBS":
- prl_libs = string.split(line[eq + 1:])
- break
-
- line = f.readline()
-
- f.close()
-
- return prl_libs
-
-
- def parse_build_file(self, filename):
- """
- Parse a build file and return the corresponding dictionary.
-
- filename is the name of the build file. If it is a dictionary instead
- then its contents are validated.
- """
- if type(filename) is types.DictType:
- bfname = "dictionary"
- dict = filename
- else:
- if self._dir:
- bfname = os.path.join(self._dir, filename)
- else:
- bfname = filename
-
- dict = {}
-
- try:
- f = open(bfname, "r")
- except IOError, detail:
- error("Unable to open \"%s\": %s" % (bfname, detail))
-
- line_nr = 1
- line = f.readline()
-
- while line:
- line = string.strip(line)
-
- if line and line[0] != "#":
- eq = string.find(line, "=")
-
- if eq <= 0:
- error("\"%s\" line %d: Line must be in the form 'name = value value...'." % (bfname, line_nr))
-
- dict[string.strip(line[:eq])] = string.strip(line[eq + 1:])
-
- line_nr = line_nr + 1
- line = f.readline()
-
- f.close()
-
- # Check the compulsory values.
- for i in ("target", "sources"):
- try:
- dict[i]
- except KeyError:
- error("\"%s\" is missing from \"%s\"." % (i, bfname))
-
- # Get the optional values.
- for i in ("headers", "moc_headers"):
- try:
- dict[i]
- except KeyError:
- dict[i] = ""
-
- # Generate the list of objects.
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- ext = ".obj"
- else:
- ext = ".o"
-
- olist = []
-
- for f in string.split(dict["sources"]):
- root, discard = os.path.splitext(f)
- olist.append(root + ext)
-
- for f in string.split(dict["moc_headers"]):
- if not self._qt:
- error("\"%s\" defines \"moc_headers\" for a non-Qt module." % bfname)
-
- root, discard = os.path.splitext(f)
- olist.append("moc_" + root + ext)
-
- dict["objects"] = string.join(olist)
-
- return dict
-
- def clean_build_file_objects(self, mfile, build):
- """Generate the clean target.
-
- mfile is the file object.
- build is the dictionary created from the build file.
- """
- mfile.write("\t-%s $(TARGET)\n" % self.rm)
-
- for f in string.split(build["objects"]):
- mfile.write("\t-%s %s\n" % (self.rm, f))
-
- for f in string.split(build["moc_headers"]):
- root, discard = os.path.splitext(f)
- mfile.write("\t-%s moc_%s.cpp\n" % (self.rm, root))
-
- def ready(self):
- """The Makefile is now ready to be used.
- """
- if not self._finalised:
- self.finalise()
-
- def generate(self):
- """Generate the Makefile.
- """
- self.ready()
-
- if self._dir:
- mfname = os.path.join(self._dir, self._makefile)
- else:
- mfname = self._makefile
-
- try:
- mfile = open(mfname, "w")
- except IOError, detail:
- error("Unable to create \"%s\": %s" % (mfname, detail))
-
- self.generate_macros_and_rules(mfile)
- self.generate_target_default(mfile)
- self.generate_target_install(mfile)
-
- if self._installs:
- if type(self._installs) != types.ListType:
- self._installs = [self._installs]
-
- for src, dst in self._installs:
- self.install_file(mfile, src, dst)
-
- self.generate_target_clean(mfile)
-
- mfile.close()
-
- def generate_macros_and_rules(self, mfile):
- """The default implementation of the macros and rules generation.
-
- mfile is the file object.
- """
- mfile.write("CC = %s\n" % self.required_string("CC"))
- mfile.write("CXX = %s\n" % self.required_string("CXX"))
- mfile.write("LINK = %s\n" % self.required_string("LINK"))
-
- cppflags = []
-
- for f in self.optional_list("DEFINES"):
- cppflags.append("-D" + f)
-
- for f in self.optional_list("INCDIR"):
- cppflags.append("-I" + _quote(f))
-
- libs = []
-
- if self.generator in ("MSVC", "MSVC.NET"):
- libdir_prefix = "/LIBPATH:"
- else:
- libdir_prefix = "-L"
-
- for ld in self.optional_list("LIBDIR"):
- if sys.platform == "darwin" and self.config.qt_framework:
- fflag = "-F" + _quote(ld)
- libs.append(fflag)
- cppflags.append(fflag)
-
- libs.append(libdir_prefix + _quote(ld))
-
- libs.extend(self.optional_list("LIBS"))
-
- mfile.write("CPPFLAGS = %s\n" % string.join(cppflags))
-
- mfile.write("CFLAGS = %s\n" % self.optional_string("CFLAGS"))
- mfile.write("CXXFLAGS = %s\n" % self.optional_string("CXXFLAGS"))
- mfile.write("LFLAGS = %s\n" % self.optional_string("LFLAGS"))
-
- mfile.write("LIBS = %s\n" % string.join(libs))
-
- if self._qt:
- mfile.write("MOC = %s\n" % _quote(self.required_string("MOC")))
-
- # These probably don't matter.
- if self.generator == "MINGW":
- mfile.write(".SUFFIXES: .cpp .cxx .cc .C .c\n\n")
- elif self.generator == "UNIX":
- mfile.write(".SUFFIXES: .c .o .cpp .cc .cxx .C\n\n")
- else:
- mfile.write(".SUFFIXES: .c .cpp .cc .cxx .C\n\n")
-
- if self.generator in ("MSVC", "MSVC.NET"):
- mfile.write("""
-{.}.cpp{}.obj::
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
-\t$<
-<<
-
-{.}.cc{}.obj::
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
-\t$<
-<<
-
-{.}.cxx{}.obj::
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
-\t$<
-<<
-
-{.}.C{}.obj::
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -Fo @<<
-\t$<
-<<
-
-{.}.c{}.obj::
-\t$(CC) -c $(CFLAGS) $(CPPFLAGS) -Fo @<<
-\t$<
-<<
-""")
- elif self.generator == "BMAKE":
- mfile.write("""
-.cpp.obj:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o$@ $<
-
-.cc.obj:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o$@ $<
-
-.cxx.obj:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o$@ $<
-
-.C.obj:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o$@ $<
-
-.c.obj:
-\t$(CC) -c $(CFLAGS) $(CPPFLAGS) -o$@ $<
-""")
- else:
- mfile.write("""
-.cpp.o:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
-
-.cc.o:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
-
-.cxx.o:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
-
-.C.o:
-\t$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) -o $@ $<
-
-.c.o:
-\t$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
-""")
-
- def generate_target_default(self, mfile):
- """The default implementation of the default target.
-
- mfile is the file object.
- """
- mfile.write("\nall:\n")
-
- def generate_target_install(self, mfile):
- """The default implementation of the install target.
-
- mfile is the file object.
- """
- mfile.write("\ninstall:\n")
-
- def generate_target_clean(self, mfile):
- """The default implementation of the clean target.
-
- mfile is the file object.
- """
- mfile.write("\nclean:\n")
-
- def install_file(self, mfile, src, dst, strip=0):
- """Install one or more files in a directory.
-
- mfile is the file object.
- src is the name of a single file to install, or the list of a number of
- files to install.
- dst is the name of the destination directory.
- strip is set if the files should be stripped after been installed.
- """
- # Help package builders.
- if self.generator == "UNIX":
- dst = "$(DESTDIR)" + dst
-
- mfile.write("\t@%s %s " % (self.chkdir, _quote(dst)))
-
- if self.generator == "UNIX":
- mfile.write("|| ")
-
- mfile.write("%s %s\n" % (self.mkdir, _quote(dst)))
-
- if type(src) != types.ListType:
- src = [src]
-
- # Get the strip command if needed.
- if strip:
- strip_cmd = self.optional_string("STRIP")
-
- if not strip_cmd:
- strip = 0
-
- for sf in src:
- target = _quote(os.path.join(dst, os.path.basename(sf)))
-
- mfile.write("\t%s %s %s\n" % (self.copy, _quote(sf), target))
-
- if strip:
- mfile.write("\t%s %s\n" % (strip_cmd, target))
-
-
-class ParentMakefile(Makefile):
- """The class that represents a parent Makefile.
- """
- def __init__(self, configuration, subdirs, dir=None, makefile="Makefile",
- installs=None):
- """Initialise an instance of a parent Makefile.
-
- subdirs is the sequence of subdirectories.
- """
- Makefile.__init__(self, configuration, dir=dir, makefile=makefile, installs=installs)
-
- self._subdirs = subdirs
-
- def generate_macros_and_rules(self, mfile):
- """Generate the macros and rules.
-
- mfile is the file object.
- """
- # We don't want them.
- pass
-
- def generate_target_default(self, mfile):
- """Generate the default target.
-
- mfile is the file object.
- """
- self._subdir_target(mfile)
-
- def generate_target_install(self, mfile):
- """Generate the install target.
-
- mfile is the file object.
- """
- self._subdir_target(mfile, "install")
-
- def generate_target_clean(self, mfile):
- """Generate the clean target.
-
- mfile is the file object.
- """
- self._subdir_target(mfile, "clean")
-
- def _subdir_target(self, mfile, target="all"):
- """Create a target for a list of sub-directories.
-
- mfile is the file object.
- target is the name of the target.
- """
- if target == "all":
- tname = ""
- else:
- tname = " " + target
-
- mfile.write("\n" + target + ":\n")
-
- for d in self._subdirs:
- if self.generator == "MINGW":
- mfile.write("\t@$(MAKE) -C %s%s\n" % (d, tname))
- elif self.generator == "UNIX":
- mfile.write("\t@(cd %s; $(MAKE)%s)\n" % (d, tname))
- else:
- mfile.write("\tcd %s\n" % d)
- mfile.write("\t$(MAKE)%s\n" % tname)
- mfile.write("\t@cd ..\n")
-
-
-class PythonModuleMakefile(Makefile):
- """The class that represents a Python module Makefile.
- """
- def __init__(self, configuration, dstdir, srcdir=None, dir=None,
- makefile="Makefile", installs=None):
- """Initialise an instance of a parent Makefile.
-
- dstdir is the name of the directory where the module's Python code will
- be installed.
- srcdir is the name of the directory (relative to the directory in which
- the Makefile will be created) containing the module's Python code. It
- defaults to the same directory.
- """
- Makefile.__init__(self, configuration, dir=dir, makefile=makefile, installs=installs)
-
- if not srcdir:
- srcdir = "."
-
- if dir:
- self._moddir = os.path.join(dir, srcdir)
- else:
- self._moddir = srcdir
-
- self._srcdir = srcdir
- self._dstdir = dstdir
-
- def generate_macros_and_rules(self, mfile):
- """Generate the macros and rules.
-
- mfile is the file object.
- """
- # We don't want them.
- pass
-
- def generate_target_install(self, mfile):
- """Generate the install target.
-
- mfile is the file object.
- """
- Makefile.generate_target_install(self, mfile)
-
- os.path.walk(self._moddir, self._visit, mfile)
-
- def _visit(self, mfile, dirname, names):
- """Install the files from a particular directory.
-
- mfile is the file object.
- dirname is the sub-directory.
- names is the list of files to install from the sub-directory.
- """
- tail = dirname[len(self._moddir):]
-
- flist = []
- for f in names:
- # Ignore certain files.
- if f in ("Makefile", ):
- continue
-
- if os.path.isfile(os.path.join(dirname, f)):
- flist.append(os.path.join(self._srcdir + tail, f))
-
- self.install_file(mfile, flist, self._dstdir + tail)
-
-
-class ModuleMakefile(Makefile):
- """The class that represents a Python extension module Makefile
- """
- def __init__(self, configuration, build_file, install_dir=None, static=0,
- console=0, qt=0, opengl=0, threaded=0, warnings=1, debug=0,
- dir=None, makefile="Makefile", installs=None, strip=1,
- export_all=0, universal=''):
- """Initialise an instance of a module Makefile.
-
- build_file is the file containing the target specific information. If
- it is a dictionary instead then its contents are validated.
- install_dir is the directory the target will be installed in.
- static is set if the module should be built as a static library.
- strip is set if the module should be stripped of unneeded symbols when
- installed. The default is 1.
- export_all is set if all the module's symbols should be exported rather
- than just the module's initialisation function. Exporting all symbols
- increases the size of the module and slows down module load times but
- may avoid problems with modules that use exceptions. The default is 0.
- """
- Makefile.__init__(self, configuration, console, qt, opengl, 1, threaded, warnings, debug, dir, makefile, installs, universal)
-
- self._build = self.parse_build_file(build_file)
- self._install_dir = install_dir
- self._dir = dir
- self.static = static
-
- # Don't strip or restrict the exports if this is a debug or static
- # build.
- if debug or static:
- self._strip = 0
- self._limit_exports = 0
- else:
- self._strip = strip
-
- # The deprecated configuration flag has precedence.
- if self.config.export_all:
- self._limit_exports = 0
- else:
- self._limit_exports = not export_all
-
- # Save the target name for later.
- self._target = self._build["target"]
-
- if sys.platform != "win32" and static:
- self._target = "lib" + self._target
-
- if sys.platform == "win32" and debug:
- self._target = self._target + "_d"
-
- def finalise(self):
- """Finalise the macros common to all module Makefiles.
- """
- if self.console:
- lflags_console = "LFLAGS_CONSOLE"
- else:
- lflags_console = "LFLAGS_WINDOWS"
-
- if self.static:
- self.DEFINES.append("SIP_STATIC_MODULE")
- else:
- self.CFLAGS.extend(self.optional_list("CFLAGS_SHLIB"))
- self.CXXFLAGS.extend(self.optional_list("CXXFLAGS_SHLIB"))
-
- lflags_dll = self.optional_list("LFLAGS_DLL")
-
- if lflags_dll:
- self.LFLAGS.extend(lflags_dll)
- elif self.console:
- lflags_console = "LFLAGS_CONSOLE_DLL"
- else:
- lflags_console = "LFLAGS_WINDOWS_DLL"
-
- # We use this to explictly create bundles on MacOS. Apple's Python
- # can handle extension modules that are bundles or dynamic
- # libraries, but python.org versions need bundles (unless built
- # with DYNLOADFILE=dynload_shlib.o).
- if sys.platform == "darwin":
- lflags_plugin = ["-bundle"]
- else:
- lflags_plugin = self.optional_list("LFLAGS_PLUGIN")
-
- if not lflags_plugin:
- lflags_plugin = self.optional_list("LFLAGS_SHLIB")
-
- self.LFLAGS.extend(lflags_plugin)
-
- self.LFLAGS.extend(self.optional_list(lflags_console))
-
- if sys.platform == "darwin":
- # We use the -F flag to explictly specify the directory containing
- # the Python framework rather than rely on the default search path.
- # This allows Apple's Python to be used even if a later python.org
- # version is also installed.
- dl = string.split(sys.exec_prefix, os.sep)
- try:
- dl = dl[:dl.index("Python.framework")]
- except ValueError:
- error("SIP requires Python to be built as a framework")
- self.LFLAGS.append("-F%s" % string.join(dl, os.sep))
- self.LFLAGS.append("-framework Python")
-
- Makefile.finalise(self)
-
- if not self.static:
- if self.optional_string("AIX_SHLIB"):
- # AIX needs a lot of special handling.
- if self.required_string('LINK') == 'g++':
- # g++ is used for linking.
- # For SIP v4 and g++:
- # 1.) Import the python symbols
- aix_lflags = ['-Wl,-bI:%s/python.exp' % self.config.py_lib_dir]
-
- if self._limit_exports:
- aix_lflags.append('-Wl,-bnoexpall')
- aix_lflags.append('-Wl,-bnoentry')
- aix_lflags.append('-Wl,-bE:%s.exp' % self._target)
- else:
- # IBM VisualAge C++ is used for linking.
- # For SIP v4 and xlC:
- # 1.) Create a shared object
- # 2.) Import the python symbols
- aix_lflags = ['-qmkshrobj',
- '-bI:%s/python.exp' % self.config.py_lib_dir]
-
- if self._limit_exports:
- aix_lflags.append('-bnoexpall')
- aix_lflags.append('-bnoentry')
- aix_lflags.append('-bE:%s.exp' % self._target)
-
- self.LFLAGS.extend(aix_lflags)
- else:
- if self._limit_exports:
- if sys.platform[:5] == 'linux':
- self.LFLAGS.extend(['-Wl,--version-script=%s.exp' % self._target])
- elif sys.platform[:5] == 'sunos':
- if self.required_string('LINK') == 'g++':
- self.LFLAGS.extend(['-Wl,-z,noversion', '-Wl,-M,%s.exp' % self._target])
- else:
- self.LFLAGS.extend(['-z' 'noversion', '-M', '%s.exp' % self._target])
- elif sys.platform[:5] == 'hp-ux':
- self.LFLAGS.extend(['-Wl,+e,init%s' % self._target])
- elif sys.platform[:5] == 'irix' and self.required_string('LINK') != 'g++':
- # Doesn't work when g++ is used for linking on IRIX.
- self.LFLAGS.extend(['-Wl,-exported_symbol,init%s' % self._target])
-
- # Force the shared linker if there is one.
- link_shlib = self.optional_list("LINK_SHLIB")
-
- if link_shlib:
- self.LINK.set(link_shlib)
-
- def module_as_lib(self, mname):
- """Return the name of a SIP v3.x module when it is used as a library.
- This will raise an exception when used with SIP v4.x modules.
-
- mname is the name of the module.
- """
- raise ValueError, "module_as_lib() can only be used with SIP v3.x"
-
- def generate_macros_and_rules(self, mfile):
- """Generate the macros and rules generation.
-
- mfile is the file object.
- """
- if self.static:
- if sys.platform == "win32":
- ext = "lib"
- else:
- ext = "a"
- else:
- if sys.platform == "win32":
- ext = "pyd"
- elif sys.platform == "darwin":
- ext = "so"
- elif sys.platform == "cygwin":
- ext = "dll"
- else:
- ext = self.optional_string("EXTENSION_PLUGIN")
- if not ext:
- ext = self.optional_string("EXTENSION_SHLIB", "so")
-
- mfile.write("TARGET = %s\n" % (self._target + "." + ext))
- mfile.write("OFILES = %s\n" % self._build["objects"])
- mfile.write("HFILES = %s %s\n" % (self._build["headers"], self._build["moc_headers"]))
- mfile.write("\n")
-
- if self.static:
- if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
- mfile.write("LIB = %s\n" % self.required_string("LIB"))
- elif self.generator == "MINGW":
- mfile.write("AR = %s\n" % self.required_string("LIB"))
- self._ranlib = None
- else:
- mfile.write("AR = %s\n" % self.required_string("AR"))
-
- self._ranlib = self.optional_string("RANLIB")
-
- if self._ranlib:
- mfile.write("RANLIB = %s\n" % self._ranlib)
-
- Makefile.generate_macros_and_rules(self, mfile)
-
- def generate_target_default(self, mfile):
- """Generate the default target.
-
- mfile is the file object.
- """
- mfile.write("\n$(TARGET): $(OFILES)\n")
-
- if self.generator in ("MSVC", "MSVC.NET"):
- if self.static:
- mfile.write("\t$(LIB) /OUT:$(TARGET) @<<\n")
- mfile.write("\t $(OFILES)\n")
- mfile.write("<<\n")
- else:
- mfile.write("\t$(LINK) $(LFLAGS) /OUT:$(TARGET) @<<\n")
- mfile.write("\t $(OFILES) $(LIBS)\n")
- mfile.write("<<\n")
-
- if "embed_manifest_dll" in self.optional_list("CONFIG"):
- mfile.write("\tmt -nologo -manifest $(TARGET).manifest -outputresource:$(TARGET);2\n")
- elif self.generator == "BMAKE":
- if self.static:
- mfile.write("\t-%s $(TARGET)\n" % (self.rm))
- mfile.write("\t$(LIB) $(TARGET) @&&|\n")
-
- for of in string.split(self._build["objects"]):
- mfile.write("+%s \\\n" % (of))
-
- mfile.write("|\n")
- else:
- mfile.write("\t$(LINK) @&&|\n")
- mfile.write("\t$(LFLAGS) $(OFILES) ,$(TARGET),,$(LIBS),%s\n" % (self._target))
- mfile.write("|\n")
-
- # Create the .def file that renames the entry point.
- defname = self._target + ".def"
-
- if self._dir:
- defname = os.path.join(self._dir, defname)
-
- try:
- dfile = open(defname, "w")
- except IOError, detail:
- error("Unable to create \"%s\": %s" % (defname, detail))
-
- dfile.write("EXPORTS\n")
- dfile.write("init%s=_init%s\n" % (self._target, self._target))
-
- dfile.close()
-
- else:
- if self.static:
- mfile.write("\t-%s $(TARGET)\n" % self.rm)
- mfile.write("\t$(AR) $(TARGET) $(OFILES)\n")
-
- if self._ranlib:
- mfile.write("\t$(RANLIB) $(TARGET)\n")
- else:
- if self._limit_exports:
- # Create an export file for AIX, Linux and Solaris.
- if sys.platform[:5] == 'linux':
- mfile.write("\t@echo '{ global: init%s; local: *; };' > %s.exp\n" % (self._target, self._target))
- elif sys.platform[:5] == 'sunos':
- mfile.write("\t@echo '{ global: init%s; local: *; };' > %s.exp\n" % (self._target, self._target))
- elif sys.platform[:3] == 'aix':
- mfile.write("\t@echo '#!' >%s.exp" % self._target)
- mfile.write("; \\\n\t echo 'init%s' >>%s.exp\n" % (self._target, self._target))
-
- mfile.write("\t$(LINK) $(LFLAGS) -o $(TARGET) $(OFILES) $(LIBS)\n")
-
- mfile.write("\n$(OFILES): $(HFILES)\n")
-
- for mf in string.split(self._build["moc_headers"]):
- root, discard = os.path.splitext(mf)
- cpp = "moc_" + root + ".cpp"
-
- mfile.write("\n%s: %s\n" % (cpp, mf))
- mfile.write("\t$(MOC) -o %s %s\n" % (cpp, mf))
-
- def generate_target_install(self, mfile):
- """Generate the install target.
-
- mfile is the file object.
- """
- if self._install_dir is None:
- self._install_dir = self.config.default_mod_dir
-
- mfile.write("\ninstall: $(TARGET)\n")
- self.install_file(mfile, "$(TARGET)", self._install_dir, self._strip)
-
- def generate_target_clean(self, mfile):
- """Generate the clean target.
-
- mfile is the file object.
- """
- mfile.write("\nclean:\n")
- self.clean_build_file_objects(mfile, self._build)
-
- # Remove any export file on AIX, Linux and Solaris.
- if self._limit_exports and (sys.platform[:5] == 'linux' or
- sys.platform[:5] == 'sunos' or
- sys.platform[:3] == 'aix'):
- mfile.write("\t-%s %s.exp\n" % (self.rm, self._target))
-
-
-class SIPModuleMakefile(ModuleMakefile):
- """The class that represents a SIP generated module Makefile.
- """
- def finalise(self):
- """Finalise the macros for a SIP generated module Makefile.
- """
- self.INCDIR.append(self.config.sip_inc_dir)
-
- ModuleMakefile.finalise(self)
-
-
-class ProgramMakefile(Makefile):
- """The class that represents a program Makefile.
- """
- def __init__(self, configuration, build_file=None, install_dir=None,
- console=0, qt=0, opengl=0, python=0, threaded=0, warnings=1,
- debug=0, dir=None, makefile="Makefile", installs=None,
- universal=''):
- """Initialise an instance of a program Makefile.
-
- build_file is the file containing the target specific information. If
- it is a dictionary instead then its contents are validated.
- install_dir is the directory the target will be installed in.
- """
- Makefile.__init__(self, configuration, console, qt, opengl, python, threaded, warnings, debug, dir, makefile, installs, universal)
-
- self._install_dir = install_dir
-
- if build_file:
- self._build = self.parse_build_file(build_file)
- else:
- self._build = None
-
- def build_command(self, source):
- """Create a command line that will build an executable. Returns a
- tuple of the name of the executable and the command line.
-
- source is the name of the source file.
- """
- self.ready()
-
- # The name of the executable.
- exe, ignore = os.path.splitext(source)
-
- if sys.platform in ("win32", "cygwin"):
- exe = exe + ".exe"
-
- # The command line.
- build = []
-
- build.append(self.required_string("CXX"))
-
- for f in self.optional_list("DEFINES"):
- build.append("-D" + f)
-
- for f in self.optional_list("INCDIR"):
- build.append("-I" + _quote(f))
-
- build.extend(self.optional_list("CXXFLAGS"))
-
- # Borland requires all flags to precede all file names.
- if self.generator != "BMAKE":
- build.append(source)
-
- if self.generator in ("MSVC", "MSVC.NET"):
- build.append("-Fe")
- build.append("/link")
- libdir_prefix = "/LIBPATH:"
- elif self.generator == "BMAKE":
- build.append("-e" + exe)
- libdir_prefix = "-L"
- else:
- build.append("-o")
- build.append(exe)
- libdir_prefix = "-L"
-
- for ld in self.optional_list("LIBDIR"):
- if sys.platform == "darwin" and self.config.qt_framework:
- build.append("-F" + _quote(ld))
-
- build.append(libdir_prefix + _quote(ld))
-
- lflags = self.optional_list("LFLAGS")
-
- # This is a huge hack demonstrating my lack of understanding of how the
- # Borland compiler works.
- if self.generator == "BMAKE":
- blflags = []
-
- for lf in lflags:
- for f in string.split(lf):
- # Tell the compiler to pass the flags to the linker.
- if f[-1] == "-":
- f = "-l-" + f[1:-1]
- elif f[0] == "-":
- f = "-l" + f[1:]
-
- # Remove any explicit object files otherwise the compiler
- # will complain that they can't be found, but they don't
- # seem to be needed.
- if string.lower(f[-4:]) != ".obj":
- blflags.append(f)
-
- lflags = blflags
-
- build.extend(lflags)
-
- build.extend(self.optional_list("LIBS"))
-
- if self.generator == "BMAKE":
- build.append(source)
-
- return (exe, string.join(build))
-
- def finalise(self):
- """Finalise the macros for a program Makefile.
- """
- if self.generator in ("MSVC", "MSVC.NET"):
- self.LFLAGS.append("/INCREMENTAL:NO")
-
- if self.console:
- lflags_console = "LFLAGS_CONSOLE"
- else:
- lflags_console = "LFLAGS_WINDOWS"
-
- self.LFLAGS.extend(self.optional_list(lflags_console))
-
- Makefile.finalise(self)
-
- def generate_macros_and_rules(self, mfile):
- """Generate the macros and rules generation.
-
- mfile is the file object.
- """
- if not self._build:
- raise ValueError, "pass a filename as build_file when generating a Makefile"
-
- target = self._build["target"]
-
- if sys.platform in ("win32", "cygwin"):
- target = target + ".exe"
-
- mfile.write("TARGET = %s\n" % target)
- mfile.write("OFILES = %s\n" % self._build["objects"])
- mfile.write("HFILES = %s\n" % self._build["headers"])
- mfile.write("\n")
-
- Makefile.generate_macros_and_rules(self, mfile)
-
- def generate_target_default(self, mfile):
- """Generate the default target.
-
- mfile is the file object.
- """
- mfile.write("\n$(TARGET): $(OFILES)\n")
-
- if self.generator in ("MSVC", "MSVC.NET"):
- mfile.write("\t$(LINK) $(LFLAGS) /OUT:$(TARGET) @<<\n")
- mfile.write("\t $(OFILES) $(LIBS)\n")
- mfile.write("<<\n")
-
- if "embed_manifest_dll" in self.optional_list("CONFIG"):
- mfile.write("\tmt -nologo -manifest $(TARGET).manifest -outputresource:$(TARGET);1\n")
- elif self.generator == "BMAKE":
- mfile.write("\t$(LINK) @&&|\n")
- mfile.write("\t$(LFLAGS) $(OFILES) ,$(TARGET),,$(LIBS),,\n")
- mfile.write("|\n")
- else:
- mfile.write("\t$(LINK) $(LFLAGS) -o $(TARGET) $(OFILES) $(LIBS)\n")
-
- mfile.write("\n$(OFILES): $(HFILES)\n")
-
- for mf in string.split(self._build["moc_headers"]):
- root, discard = os.path.splitext(mf)
- cpp = "moc_" + root + ".cpp"
-
- mfile.write("\n%s: %s\n" % (cpp, mf))
- mfile.write("\t$(MOC) -o %s %s\n" % (cpp, mf))
-
- def generate_target_install(self, mfile):
- """Generate the install target.
-
- mfile is the file object.
- """
- if self._install_dir is None:
- self._install_dir = self.config.default_bin_dir
-
- mfile.write("\ninstall: $(TARGET)\n")
- self.install_file(mfile, "$(TARGET)", self._install_dir)
-
- def generate_target_clean(self, mfile):
- """Generate the clean target.
-
- mfile is the file object.
- """
- mfile.write("\nclean:\n")
- self.clean_build_file_objects(mfile, self._build)
-
-
-def _quote(s):
- """Return a string surrounded by double quotes it if contains a space.
-
- s is the string.
- """
- if string.find(s, " ") >= 0:
- s = '"' + s + '"'
-
- return s
-
-
-def version_to_string(v):
- """Convert a 3 part version number encoded as a hexadecimal value to a
- string.
- """
- return "%u.%u.%u" % (((v >> 16) & 0xff), ((v >> 8) & 0xff), (v & 0xff))
-
-
-def read_version(filename, description, numdefine=None, strdefine=None):
- """Read the version information for a package from a file. The information
- is specified as #defines of a numeric (hexadecimal or decimal) value and/or
- a string value.
-
- filename is the name of the file.
- description is the descriptive name of the package.
- numdefine is the name of the #define of the numeric version. It is ignored
- if it is None.
- strdefine is the name of the #define of the string version. It is ignored
- if it is None.
-
- Returns a tuple of the version as a number and as a string.
- """
- need_num = numdefine is not None
- need_str = strdefine is not None
-
- vers = None
- versstr = None
-
- f = open(filename)
- l = f.readline()
-
- while l and (need_num or need_str):
- wl = string.split(l)
- if len(wl) >= 3 and wl[0] == "#define":
- if need_num and wl[1] == numdefine:
- v = wl[2]
-
- if v[0:2] == "0x":
- vers = string.atoi(v,16)
- else:
- dec = int(v)
- maj = dec / 100
- min = (dec % 100) / 10
- bug = (dec % 10)
- vers = (maj << 16) + (min << 8) + bug
-
- need_num = 0
-
- if need_str and wl[1] == strdefine:
- # Take account of embedded spaces.
- versstr = string.join(wl[2:])[1:-1]
- need_str = 0
-
- l = f.readline()
-
- f.close()
-
- if need_num or need_str:
- error("The %s version number could not be determined by parsing %s." % (description, filename))
-
- return (vers, versstr)
-
-
-def create_content(dict, macros=None):
- """Convert a dictionary to a string (typically to use as the content to a
- call to create_config_module()). Dictionary values that are strings are
- quoted. Dictionary values that are lists are converted to quoted strings.
-
- dict is the dictionary.
- macros is the optional dictionary of platform specific build macros.
- """
- content = "_pkg_config = {\n"
-
- keys = dict.keys()
- keys.sort()
-
- # Format it nicely.
- width = 0
-
- for k in keys:
- klen = len(k)
-
- if width < klen:
- width = klen
-
- for k in keys:
- val = dict[k]
- vtype = type(val)
-
- if val is None:
- val = "None"
- elif vtype == types.ListType:
- val = "'" + string.join(val) + "'"
- elif vtype == types.StringType:
- val = "'" + val + "'"
- elif vtype == types.IntType:
- if string.find(k, "version") >= 0:
- # Assume it's a hexadecimal version number. It doesn't matter
- # if it isn't, we are just trying to make it look pretty.
- val = "0x%06x" % val
- else:
- val = str(val)
- else:
- val = "'" + str(val) + "'"
-
- content = content + " '" + k + "':" + (" " * (width - len(k) + 2)) + string.replace(val, "\\", "\\\\")
-
- if k != keys[-1]:
- content = content + ","
-
- content = content + "\n"
-
- content = content + "}\n\n"
-
- # Format the optional macros.
- content = content + "_default_macros = "
-
- if macros:
- content = content + "{\n"
-
- names = macros.keys()
- names.sort()
-
- width = 0
- for c in names:
- clen = len(c)
- if width < clen:
- width = clen
-
- for c in names:
- if c == names[-1]:
- sep = ""
- else:
- sep = ","
-
- k = "'" + c + "':"
- content = content + " %-*s '%s'%s\n" % (1 + width + 2, k, string.replace(macros[c], "\\", "\\\\"), sep)
-
- content = content + "}\n"
- else:
- content = content + "None\n"
-
- return content
-
-
-def create_config_module(module, template, content, macros=None):
- """Create a configuration module by replacing "@" followed by
- "SIP_CONFIGURATION" followed by "@" in a template file with a content
- string.
-
- module is the name of the module file.
- template is the name of the template file.
- content is the content string. If it is a dictionary it is first converted
- to a string using create_content().
- macros is an optional dictionary of platform specific build macros. It is
- only used if create_content() is called to convert the content to a string.
- """
- if type(content) == types.DictType:
- content = create_content(content, macros)
-
- # Allow this file to used as a template.
- key = "@" + "SIP_CONFIGURATION" + "@"
-
- df = open(module, "w")
- sf = open(template, "r")
-
- line = sf.readline()
- while line:
- if string.find(line, key) >= 0:
- line = content
-
- df.write(line)
-
- line = sf.readline()
-
-
-def version_to_sip_tag(version, tags, description):
- """Convert a version number to a SIP tag.
-
- version is the version number. If it is negative then the latest version
- is assumed. (This is typically useful if a snapshot is indicated by a
- negative version number.)
- tags is the dictionary of tags keyed by version number. The tag used is
- the one with the smallest key (ie. earliest version) that is greater than
- the given version number.
- description is the descriptive name of the package used for error messages.
-
- Returns the corresponding tag.
- """
- vl = tags.keys()
- vl.sort()
-
- # For a snapshot use the latest tag.
- if version < 0:
- tag = tags[vl[-1]]
- else:
- for v in vl:
- if version < v:
- tag = tags[v]
- break
- else:
- error("Unsupported %s version: 0x%06x." % (description, version))
-
- return tag
-
-
-def error(msg):
- """Display an error message and terminate.
-
- msg is the text of the error message.
- """
- sys.stderr.write(format("Error: " + msg) + "\n")
- sys.exit(1)
-
-
-def inform(msg):
- """Display an information message.
-
- msg is the text of the error message.
- """
- sys.stdout.write(format(msg) + "\n")
-
-
-def format(msg, leftmargin=0, rightmargin=78):
- """Format a message by inserting line breaks at appropriate places.
-
- msg is the text of the message.
- leftmargin is the position of the left margin.
- rightmargin is the position of the right margin.
-
- Return the formatted message.
- """
- curs = leftmargin
- fmsg = " " * leftmargin
-
- for w in string.split(msg):
- l = len(w)
- if curs != leftmargin and curs + l > rightmargin:
- fmsg = fmsg + "\n" + (" " * leftmargin)
- curs = leftmargin
-
- if curs > leftmargin:
- fmsg = fmsg + " "
- curs = curs + 1
-
- fmsg = fmsg + w
- curs = curs + l
-
- return fmsg
-
-
-def parse_build_macros(filename, names, overrides=None, properties=None):
- """Parse a qmake compatible file of build system macros and convert it to a
- dictionary. A macro is a name/value pair. The dictionary is returned or
- None if any of the overrides was invalid.
-
- filename is the name of the file to parse.
- names is a list of the macro names to extract from the file.
- overrides is an optional list of macro names and values that modify those
- found in the file. They are of the form "name=value" (in which case the
- value replaces the value found in the file) or "name+=value" (in which case
- the value is appended to the value found in the file).
- properties is an optional dictionary of property name and values that are
- used to resolve any expressions of the form "$[name]" in the file.
- """
- # Validate and convert the overrides to a dictionary.
- orides = {}
-
- if overrides is not None:
- for oride in overrides:
- prefix = ""
- name_end = string.find(oride, "+=")
-
- if name_end >= 0:
- prefix = "+"
- val_start = name_end + 2
- else:
- name_end = string.find(oride, "=")
-
- if name_end >= 0:
- val_start = name_end + 1
- else:
- return None
-
- name = oride[:name_end]
-
- if name not in names:
- return None
-
- orides[name] = prefix + oride[val_start:]
-
- # This class defines a file like object that handles the nested include()
- # directives in qmake files.
- class qmake_build_file_reader:
- def __init__(self, filename):
- self.filename = filename
- self.currentfile = None
- self.filestack = []
- self.pathstack = []
- self.cond_fname = None
- self._openfile(filename)
-
- def _openfile(self, filename):
- try:
- f = open(filename, 'r')
- except IOError, detail:
- # If this file is conditional then don't raise an error.
- if self.cond_fname == filename:
- return
-
- error("Unable to open %s: %s" % (filename, detail))
-
- if self.currentfile:
- self.filestack.append(self.currentfile)
- self.pathstack.append(self.path)
-
- self.currentfile = f
- self.path = os.path.dirname(filename)
-
- def readline(self):
- line = self.currentfile.readline()
- sline = line.strip()
-
- if self.cond_fname and sline == '}':
- # The current condition is closed.
- self.cond_fname = None
- line = self.currentfile.readline()
- elif sline.startswith('exists(') and sline.endswith('{'):
- # A new condition is opened so extract the filename.
- self.cond_fname = self._normalise(sline[:-1].strip()[7:-1].strip())
- line = self.currentfile.readline()
- elif sline.startswith('include('):
- nextfile = self._normalise(sline[8:-1].strip())
- self._openfile(nextfile)
- return self.readline()
-
- if not line and self.filestack:
- self.currentfile = self.filestack.pop()
- self.path = self.pathstack.pop()
- return self.readline()
-
- return line
-
- # Normalise a filename by expanding any environment variables and
- # making sure it is absolute.
- def _normalise(self, fname):
- if "$(" in fname:
- fname = os.path.normpath(self._expandvars(fname))
-
- if not os.path.isabs(fname):
- fname = os.path.join(self.path, fname)
-
- return fname
-
- # Expand the environment variables in a filename.
- def _expandvars(self, fname):
- i = 0
- while True:
- m = re.search(r'\$\((\w+)\)', fname[i:])
- if not m:
- break
-
- i, j = m.span(0)
- name = m.group(1)
- if name in os.environ:
- tail = fname[j:]
- fname = fname[:i] + os.environ[name]
- i = len(fname)
- fname += tail
- else:
- i = j
-
- return fname
-
- f = qmake_build_file_reader(filename)
-
- # Get everything into a dictionary.
- raw = {
- "DIR_SEPARATOR": os.sep,
- "LITERAL_WHITESPACE": " ",
- "LITERAL_DOLLAR": "$",
- "LITERAL_HASH": "#"
- }
-
- line = f.readline()
- while line:
- # Handle line continuations.
- while len(line) > 1 and line[-2] == "\\":
- line = line[:-2]
-
- next = f.readline()
-
- if next:
- line = line + next
- else:
- break
-
- line = string.strip(line)
-
- # Ignore comments.
- if line and line[0] != "#":
- assstart = string.find(line, "+")
- if assstart > 0 and line[assstart + 1] == '=':
- assend = assstart + 1
- else:
- assstart = string.find(line, "=")
- assend = assstart
-
- if assstart > 0:
- lhs = string.strip(line[:assstart])
- rhs = string.strip(line[assend + 1:])
-
- raw[lhs] = rhs
-
- line = f.readline()
-
- # Go through the raw dictionary extracting the macros we need and
- # resolving any macro expansions. First of all, make sure every macro has
- # a value.
- refined = {}
-
- for m in names:
- refined[m] = ""
-
- macro_prefix = "QMAKE_"
-
- for lhs in raw.keys():
- # Strip any prefix.
- if string.find(lhs, macro_prefix) == 0:
- reflhs = lhs[len(macro_prefix):]
- else:
- reflhs = lhs
-
- # See if we are interested in this one.
- if reflhs not in names:
- continue
-
- rhs = raw[lhs]
-
- # Resolve any references.
- estart = string.find(rhs, "$$(")
- mstart = string.find(rhs, "$$")
-
- while mstart >= 0 and mstart != estart:
- rstart = mstart + 2
- if rstart < len(rhs) and rhs[rstart] == "{":
- rstart = rstart + 1
- term = "}"
- elif rstart < len(rhs) and rhs[rstart] == "[":
- rstart = rstart + 1
- term = "]"
- else:
- term = string.whitespace
-
- mend = rstart
- while mend < len(rhs) and rhs[mend] not in term:
- mend = mend + 1
-
- lhs = rhs[rstart:mend]
-
- if term in "}]":
- mend = mend + 1
-
- if term == "]":
- if properties is None or lhs not in properties.keys():
- error("%s: property '%s' is not defined." % (filename, lhs))
-
- value = properties[lhs]
- else:
- try:
- value = raw[lhs]
- except KeyError:
- error("%s: macro '%s' is not defined." % (filename, lhs))
-
- rhs = rhs[:mstart] + value + rhs[mend:]
- estart = string.find(rhs, "$$(")
- mstart = string.find(rhs, "$$")
-
- # Expand any POSIX style environment variables.
- pleadin = ["$$(", "$("]
-
- for pl in pleadin:
- estart = string.find(rhs, pl)
-
- if estart >= 0:
- nstart = estart + len(pl)
- break
- else:
- estart = -1
-
- while estart >= 0:
- eend = string.find(rhs[nstart:], ")")
-
- if eend < 0:
- break
-
- eend = nstart + eend
-
- name = rhs[nstart:eend]
-
- try:
- env = os.environ[name]
- except KeyError:
- env = ""
-
- rhs = rhs[:estart] + env + rhs[eend + 1:]
-
- for pl in pleadin:
- estart = string.find(rhs, pl)
-
- if estart >= 0:
- nstart = estart + len(pl)
- break
- else:
- estart = -1
-
- # Expand any Windows style environment variables.
- estart = string.find(rhs, "%")
-
- while estart >= 0:
- eend = string.find(rhs[estart + 1:], "%")
-
- if eend < 0:
- break
-
- eend = estart + 1 + eend
-
- name = rhs[estart + 1:eend]
-
- try:
- env = os.environ[name]
- except KeyError:
- env = ""
-
- rhs = rhs[:estart] + env + rhs[eend + 1:]
-
- estart = string.find(rhs, "%")
-
- refined[reflhs] = rhs
-
- # Handle the user overrides.
- for lhs in orides.keys():
- rhs = refined[lhs]
- oride = orides[lhs]
-
- if string.find(oride, "+") == 0:
- if rhs:
- rhs = rhs + " " + oride[1:]
- else:
- rhs = oride[1:]
- else:
- rhs = oride
-
- refined[lhs] = rhs
-
- return refined
-
-
-def create_wrapper(script, wrapper, gui=0):
- """Create a platform dependent executable wrapper around a Python script.
-
- script is the full pathname of the script.
- wrapper is the name of the wrapper file to create.
- gui is non-zero if a GUI enabled version of the interpreter should be used.
-
- Returns the platform specific name of the wrapper.
- """
- if sys.platform == "win32":
- wrapper = wrapper + ".bat"
-
- wf = open(wrapper, "w")
-
- if sys.platform == "win32":
- exe = sys.executable
-
- if gui:
- exe = exe[:-4] + "w.exe"
-
- wf.write("@\"%s\" \"%s\" %%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9\n" % (exe, script))
- elif sys.platform == "darwin":
- # python, pythonw and sys.executable are all different images. We
- # would prefer to use the latter (because it includes the version
- # number) but that would mean being unable to support the "gui"
- # argument.
- if gui:
- exe = "pythonw"
- else:
- exe = "python"
-
- wf.write("exec %s %s ${1+\"$@\"}\n" % (exe, script))
- else:
- wf.write("exec %s %s ${1+\"$@\"}\n" % (sys.executable, script))
-
- wf.close()
-
- if sys.platform != "win32":
- sbuf = os.stat(wrapper)
- mode = sbuf.st_mode
- mode |= (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
-
- os.chmod(wrapper, mode)
-
- return wrapper