|
|
|
# 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) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
# This copy of SIP may also used under the terms of the GNU General Public
|
|
|
|
# License v2 or v3 as published by the Free Software Foundation which can be
|
|
|
|
# found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
|
|
|
|
#
|
|
|
|
# SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import stat
|
|
|
|
import string
|
|
|
|
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) == list:
|
|
|
|
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 remove(self, value):
|
|
|
|
"""Remove a value from the macro. It doesn't matter if the value
|
|
|
|
wasn't present.
|
|
|
|
|
|
|
|
value is the value to remove.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
self._macro.remove(value)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
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=None,
|
|
|
|
arch=None):
|
|
|
|
"""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 it is None then the value is taken from the configuration.
|
|
|
|
arch is the space separated MacOS/X architectures to build. If it is
|
|
|
|
None then it is taken from the configuration.
|
|
|
|
"""
|
|
|
|
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) != list:
|
|
|
|
qt = ["QtCore", "QtGui"]
|
|
|
|
|
|
|
|
self._threaded = configuration.qt_threaded
|
|
|
|
else:
|
|
|
|
self._threaded = threaded
|
|
|
|
|
|
|
|
self.config = configuration
|
|
|
|
self.console = console
|
|
|
|
self._qt = qt
|
|
|
|
self._opengl = opengl
|
|
|
|
self._python = python
|
|
|
|
self._warnings = warnings
|
|
|
|
self._debug = debug
|
|
|
|
self._makefile = makefile
|
|
|
|
self._installs = installs
|
|
|
|
|
|
|
|
# Make sure the destination directory is an absolute path.
|
|
|
|
if dir:
|
|
|
|
self.dir = os.path.abspath(dir)
|
|
|
|
else:
|
|
|
|
self.dir = os.path.curdir
|
|
|
|
|
|
|
|
# Assume we are building in the source tree.
|
|
|
|
self._src_dir = self.dir
|
|
|
|
|
|
|
|
if universal is None:
|
|
|
|
self._universal = configuration.universal
|
|
|
|
else:
|
|
|
|
self._universal = universal
|
|
|
|
|
|
|
|
if arch is None:
|
|
|
|
self._arch = configuration.arch
|
|
|
|
else:
|
|
|
|
self._arch = arch
|
|
|
|
|
|
|
|
self._finalised = 0
|
|
|
|
|
|
|
|
# Copy the macros and convert them all to instance lists.
|
|
|
|
macros = configuration.build_macros()
|
|
|
|
|
|
|
|
for m in list(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 = val.split()
|
|
|
|
|
|
|
|
# We also want to treat lists of libraries in the same way so that
|
|
|
|
# duplicates get eliminated.
|
|
|
|
if m[:4] == "LIBS":
|
|
|
|
val = val.split()
|
|
|
|
|
|
|
|
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.
|
|
|
|
# Note that we used to think that if Qt was built with exceptions, RTTI
|
|
|
|
# and STL support enabled then anything that linked against it also
|
|
|
|
# needed the same flags. However, detecting this was broken for some
|
|
|
|
# time and nobody complained. For the moment we'll leave the code in
|
|
|
|
# but it will never be used.
|
|
|
|
if self._qt:
|
|
|
|
wcfg = self.config.qt_winconfig.split()
|
|
|
|
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 specific configuration.
|
|
|
|
if sys.platform == 'darwin':
|
|
|
|
mac_cflags = []
|
|
|
|
mac_lflags = []
|
|
|
|
|
|
|
|
for a in self._arch.split():
|
|
|
|
aflag = '-arch ' + a
|
|
|
|
mac_cflags.append(aflag)
|
|
|
|
mac_lflags.append(aflag)
|
|
|
|
|
|
|
|
if self._universal:
|
|
|
|
mac_cflags.append('-isysroot %s' % self._universal)
|
|
|
|
mac_lflags.append('-Wl,-syslibroot,%s' % self._universal)
|
|
|
|
|
|
|
|
cflags.lextend(mac_cflags)
|
|
|
|
cxxflags.lextend(mac_cflags)
|
|
|
|
lflags.lextend(mac_lflags)
|
|
|
|
|
|
|
|
# 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:
|
|
|
|
# Note that qmake doesn't define anything for QtHelp.
|
|
|
|
if mod == "QtCore":
|
|
|
|
defines.append("QT_CORE_LIB")
|
|
|
|
elif mod == "QtGui":
|
|
|
|
defines.append("QT_GUI_LIB")
|
|
|
|
elif mod == "QtMultimedia":
|
|
|
|
defines.append("QT_MULTIMEDIA_LIB")
|
|
|
|
elif mod == "QtNetwork":
|
|
|
|
defines.append("QT_NETWORK_LIB")
|
|
|
|
elif mod == "QtOpenGL":
|
|
|
|
defines.append("QT_OPENGL_LIB")
|
|
|
|
elif mod == "QtScript":
|
|
|
|
defines.append("QT_SCRIPT_LIB")
|
|
|
|
elif mod == "QtScriptTools":
|
|
|
|
defines.append("QT_SCRIPTTOOLS_LIB")
|
|
|
|
elif mod == "QtSql":
|
|
|
|
defines.append("QT_SQL_LIB")
|
|
|
|
elif mod == "QtTest":
|
|
|
|
defines.append("QT_TEST_LIB")
|
|
|
|
elif mod == "QtWebKit":
|
|
|
|
defines.append("QT_WEBKIT_LIB")
|
|
|
|
elif mod == "QtXml":
|
|
|
|
defines.append("QT_XML_LIB")
|
|
|
|
elif mod == "QtXmlPatterns":
|
|
|
|
defines.append("QT_XMLPATTERNS_LIB")
|
|
|
|
elif mod == "phonon":
|
|
|
|
defines.append("QT_PHONON_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",
|
|
|
|
"QtWebKit": "LIBS_WEBKIT"
|
|
|
|
}
|
|
|
|
|
|
|
|
# For Windows: the dependencies between Qt libraries.
|
|
|
|
qdepmap = {
|
|
|
|
"QtAssistant": ("QtNetwork", "QtGui", "QtCore"),
|
|
|
|
"QtGui": ("QtCore", ),
|
|
|
|
"QtHelp": ("QtSql", "QtGui", "QtCore"),
|
|
|
|
"QtMultimedia": ("QtGui", "QtCore"),
|
|
|
|
"QtNetwork": ("QtCore", ),
|
|
|
|
"QtOpenGL": ("QtGui", "QtCore"),
|
|
|
|
"QtScript": ("QtCore", ),
|
|
|
|
"QtScriptTools": ("QtScript", "QtGui", "QtCore"),
|
|
|
|
"QtSql": ("QtCore", ),
|
|
|
|
"QtSvg": ("QtXml", "QtGui", "QtCore"),
|
|
|
|
"QtTest": ("QtGui", "QtCore"),
|
|
|
|
"QtWebKit": ("QtNetwork", "QtGui", "QtCore"),
|
|
|
|
"QtXml": ("QtCore", ),
|
|
|
|
"QtXmlPatterns": ("QtNetwork", "QtCore"),
|
|
|
|
"phonon": ("QtGui", "QtCore"),
|
|
|
|
"QtDesigner": ("QtGui", "QtCore"),
|
|
|
|
"QAxContainer": ("QtGui", "QtCore")
|
|
|
|
}
|
|
|
|
|
|
|
|
# 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 list(wdepmap.keys()):
|
|
|
|
deps.extend(self.optional_list(wdepmap[mod]))
|
|
|
|
|
|
|
|
if mod in list(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 list(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 + version_to_string(self.config.qt_version).replace(".", "")
|
|
|
|
|
|
|
|
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:
|
|
|
|
if self.config.qt_version < 0x040000 or self._opengl or "QtGui" in self._qt:
|
|
|
|
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 _add_manifest(self, target=None):
|
|
|
|
"""Add the link flags for creating a manifest file.
|
|
|
|
"""
|
|
|
|
if target is None:
|
|
|
|
target = "$(TARGET)"
|
|
|
|
|
|
|
|
self.LFLAGS.append("/MANIFEST")
|
|
|
|
self.LFLAGS.append("/MANIFESTFILE:%s.manifest" % target)
|
|
|
|
|
|
|
|
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" and "shared" in self.config.qt_winconfig.split():
|
|
|
|
if (mname in ("QtCore", "QtDesigner", "QtGui", "QtHelp",
|
|
|
|
"QtMultimedia", "QtNetwork", "QtOpenGL", "QtScript",
|
|
|
|
"QtScriptTools", "QtSql", "QtSvg", "QtTest",
|
|
|
|
"QtWebKit", "QtXml", "QtXmlPatterns", "phonon") 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 = ' '.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:
|
|
|
|
error("Unable to open \"%s\"" % prl_name)
|
|
|
|
|
|
|
|
line = f.readline()
|
|
|
|
while line:
|
|
|
|
line = line.strip()
|
|
|
|
if line and line[0] != "#":
|
|
|
|
eq = line.find("=")
|
|
|
|
if eq > 0 and line[:eq].strip() == "QMAKE_PRL_LIBS":
|
|
|
|
prl_libs = line[eq + 1:].split()
|
|
|
|
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) == dict:
|
|
|
|
bfname = "dictionary"
|
|
|
|
bdict = filename
|
|
|
|
else:
|
|
|
|
if os.path.isabs(filename):
|
|
|
|
# We appear to be building out of the source tree.
|
|
|
|
self._src_dir = os.path.dirname(filename)
|
|
|
|
bfname = filename
|
|
|
|
else:
|
|
|
|
bfname = os.path.join(self.dir, filename)
|
|
|
|
|
|
|
|
bdict = {}
|
|
|
|
|
|
|
|
try:
|
|
|
|
f = open(bfname, "r")
|
|
|
|
except IOError:
|
|
|
|
error("Unable to open \"%s\"" % bfname)
|
|
|
|
|
|
|
|
line_nr = 1
|
|
|
|
line = f.readline()
|
|
|
|
|
|
|
|
while line:
|
|
|
|
line = line.strip()
|
|
|
|
|
|
|
|
if line and line[0] != "#":
|
|
|
|
eq = line.find("=")
|
|
|
|
|
|
|
|
if eq <= 0:
|
|
|
|
error("\"%s\" line %d: Line must be in the form 'name = value value...'." % (bfname, line_nr))
|
|
|
|
|
|
|
|
bdict[line[:eq].strip()] = line[eq + 1:].strip()
|
|
|
|
|
|
|
|
line_nr = line_nr + 1
|
|
|
|
line = f.readline()
|
|
|
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
# Check the compulsory values.
|
|
|
|
for i in ("target", "sources"):
|
|
|
|
try:
|
|
|
|
bdict[i]
|
|
|
|
except KeyError:
|
|
|
|
error("\"%s\" is missing from \"%s\"." % (i, bfname))
|
|
|
|
|
|
|
|
# Get the optional values.
|
|
|
|
for i in ("headers", "tqmoc_headers"):
|
|
|
|
try:
|
|
|
|
bdict[i]
|
|
|
|
except KeyError:
|
|
|
|
bdict[i] = ""
|
|
|
|
|
|
|
|
# Generate the list of objects.
|
|
|
|
if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
|
|
|
|
ext = ".obj"
|
|
|
|
else:
|
|
|
|
ext = ".o"
|
|
|
|
|
|
|
|
olist = []
|
|
|
|
|
|
|
|
for f in bdict["sources"].split():
|
|
|
|
root, discard = os.path.splitext(f)
|
|
|
|
olist.append(root + ext)
|
|
|
|
|
|
|
|
for f in bdict["tqmoc_headers"].split():
|
|
|
|
if not self._qt:
|
|
|
|
error("\"%s\" defines \"tqmoc_headers\" for a non-Qt module." % bfname)
|
|
|
|
|
|
|
|
root, discard = os.path.splitext(f)
|
|
|
|
olist.append("tqmoc_" + root + ext)
|
|
|
|
|
|
|
|
bdict["objects"] = ' '.join(olist)
|
|
|
|
|
|
|
|
return bdict
|
|
|
|
|
|
|
|
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 build["objects"].split():
|
|
|
|
mfile.write("\t-%s %s\n" % (self.rm, f))
|
|
|
|
|
|
|
|
for f in build["tqmoc_headers"].split():
|
|
|
|
root, discard = os.path.splitext(f)
|
|
|
|
mfile.write("\t-%s tqmoc_%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()
|
|
|
|
|
|
|
|
# Make sure the destination directory exists.
|
|
|
|
try:
|
|
|
|
os.makedirs(self.dir)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
mfname = os.path.join(self.dir, self._makefile)
|
|
|
|
|
|
|
|
try:
|
|
|
|
mfile = open(mfname, "w")
|
|
|
|
except IOError:
|
|
|
|
error("Unable to create \"%s\"" % mfname)
|
|
|
|
|
|
|
|
self.generate_macros_and_rules(mfile)
|
|
|
|
self.generate_target_default(mfile)
|
|
|
|
self.generate_target_install(mfile)
|
|
|
|
|
|
|
|
if self._installs:
|
|
|
|
if type(self._installs) != list:
|
|
|
|
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 = []
|
|
|
|
|
|
|
|
if not self._debug:
|
|
|
|
cppflags.append("-DNDEBUG")
|
|
|
|
|
|
|
|
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" % ' '.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" % ' '.join(libs))
|
|
|
|
|
|
|
|
if self._qt:
|
|
|
|
mfile.write("MOC = %s\n" % _quote(self.required_string("MOC")))
|
|
|
|
|
|
|
|
if self._src_dir != self.dir:
|
|
|
|
mfile.write("VPATH = %s\n\n" % self._src_dir)
|
|
|
|
|
|
|
|
# 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) |