mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-12-16 01:30:07 +01:00
initial commit of experimental Phoenix code
git-svn-id: https://svn.wxwidgets.org/svn/wx/sandbox/trunk/Phoenix@66111 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
0
buildtools/__init__.py
Normal file
0
buildtools/__init__.py
Normal file
503
buildtools/config.py
Normal file
503
buildtools/config.py
Normal file
@@ -0,0 +1,503 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: buildtools.config
|
||||
# Purpose: Code to set and validate platform options and etc. for
|
||||
# the wxPython build. Moved to their own module and
|
||||
# class to help setup.py to be simpler.
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 3-Nov-2010
|
||||
# Copyright: (c) 2010 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import os
|
||||
import glob
|
||||
import fnmatch
|
||||
import tempfile
|
||||
|
||||
from distutils.file_util import copy_file
|
||||
from distutils.dir_util import mkpath
|
||||
from distutils.dep_util import newer
|
||||
from distutils.spawn import spawn
|
||||
|
||||
|
||||
runSilently = False
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class Configuration(object):
|
||||
|
||||
USE_SIP = True
|
||||
SIP = '/projects/sip/sip/sipgen/sip'
|
||||
SIPINC = 'sip/siplib' # Use our local copy of sip.h
|
||||
SIPGEN = 'sip/gen' # Where the generated .zip files go
|
||||
SIPFILES = 'sip' # where to find other sip files for %Include or %Import
|
||||
SIPOUT = 'sip/cpp' # where to put the generated C++ code
|
||||
|
||||
SIPOPTS = ' '.join(['-e', # turn on exceptions support
|
||||
'-k', # turn on keyword args support
|
||||
'-o', # turn on auto-docstrings
|
||||
#'-g', # always release and reaquire the GIL
|
||||
#'-r', # turn on function call tracing
|
||||
'-I', 'src'
|
||||
])
|
||||
|
||||
WX_CONFIG = None
|
||||
# Usually you shouldn't need to touch this, but you can set it to
|
||||
# pass an alternate version of wx-config or alternate flags,
|
||||
# eg. as required by the .deb in-tree build. By default a
|
||||
# wx-config command will be assembled based on version, port,
|
||||
# etc. and it will be looked for on the default $PATH.
|
||||
|
||||
WXPORT = 'gtk2'
|
||||
# On Linux/Unix there are several ports of wxWidgets available.
|
||||
# Setting this value lets you select which will be used for the
|
||||
# wxPython build. Possibilites are 'gtk', 'gtk2' and 'x11'.
|
||||
# Currently only gtk and gtk2 works.
|
||||
|
||||
BUILD_BASE = "build"
|
||||
# Directory to use for temporary build files.
|
||||
|
||||
MONOLITHIC = 0
|
||||
# The core wxWidgets lib can be built as either a single
|
||||
# monolithic DLL or as a collection of DLLs. This flag controls
|
||||
# which set of libs will be used on Windows. (For other platforms
|
||||
# it is automatic via using wx-config.)
|
||||
|
||||
WXDLLVER = None
|
||||
# Version part of wxWidgets LIB/DLL names
|
||||
|
||||
COMPILER = 'msvc'
|
||||
# Used to select which compiler will be used on Windows. This not
|
||||
# only affects distutils, but also some of the default flags and
|
||||
# other assumptions in this script. Current supported values are
|
||||
# 'msvc' and 'mingw32'
|
||||
|
||||
ARCH = ''
|
||||
# If this is set, add an -arch XXX flag to cflags. Only tested (and
|
||||
# presumably, needed) for OS X.
|
||||
|
||||
NO_SCRIPTS = False
|
||||
# Don't install the tools/script files
|
||||
|
||||
PKGDIR = 'wx'
|
||||
# The name of the top-level package
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Basic initialization and configuration code
|
||||
|
||||
def __init__(self):
|
||||
self.CLEANUP = list()
|
||||
|
||||
# load the version numbers into this instance's namespace
|
||||
execfile(opj(os.path.split(__file__)[0], 'version.py'), self.__dict__)
|
||||
|
||||
# If we're doing a dated build then alter the VERSION strings
|
||||
if os.path.exists('DAILY_BUILD'):
|
||||
self.VER_FLAGS += '.b' + open('DAILY_BUILD').read().strip()
|
||||
self.VERSION = "%s.%s.%s.%s%s" % (self.VER_MAJOR,
|
||||
self.VER_MINOR,
|
||||
self.VER_RELEASE,
|
||||
self.VER_SUBREL,
|
||||
self.VER_FLAGS)
|
||||
|
||||
self.WXDLLVER = '%d%d' % (self.VER_MAJOR, self.VER_MINOR)
|
||||
|
||||
# change the PORT default for wxMac
|
||||
if sys.platform[:6] == "darwin":
|
||||
self.WXPORT = 'osx_carbon'
|
||||
|
||||
# and do the same for wxMSW, just for consistency
|
||||
if os.name == 'nt':
|
||||
self.WXPORT = 'msw'
|
||||
|
||||
self.parseCmdLine()
|
||||
|
||||
if self.WXPORT != 'msw':
|
||||
# make sure we only use the compiler value on MSW builds
|
||||
self.COMPILER=None
|
||||
|
||||
self.WXPLAT2 = None
|
||||
|
||||
|
||||
if os.environ.has_key('WXWIN'):
|
||||
self.WXDIR = os.environ['WXWIN']
|
||||
else:
|
||||
if os.path.exists('../wxWidgets'):
|
||||
self.WXDIR = '../wxWidgets' # assumes in parallel SVN tree
|
||||
else:
|
||||
self.WXDIR = '..' # assumes wxPython is subdir
|
||||
msg("WARNING: WXWIN not set in environment. Assuming '%s'" % self.WXDIR)
|
||||
|
||||
self.includes = ['sip/siplib'] # to get our version of sip.h
|
||||
|
||||
#---------------------------------------
|
||||
# MSW specific settings
|
||||
if os.name == 'nt' and self.COMPILER == 'msvc':
|
||||
# Set compile flags and such for MSVC. These values are derived
|
||||
# from the wxWidgets makefiles for MSVC, other compilers settings
|
||||
# will probably vary...
|
||||
self.WXPLAT = '__WXMSW__'
|
||||
|
||||
if os.environ.get('CPU', None) == 'AMD64':
|
||||
self.VCDLL = 'vc_amd64_dll'
|
||||
else:
|
||||
self.VCDLL = 'vc_dll'
|
||||
|
||||
self.includes = ['include', 'src',
|
||||
opj(WXDIR, 'lib', VCDLL, 'msw' + self.libFlag()),
|
||||
opj(WXDIR, 'include'),
|
||||
opj(WXDIR, 'contrib', 'include'),
|
||||
]
|
||||
|
||||
self.defines = [ ('WIN32', None),
|
||||
('_WINDOWS', None),
|
||||
(WXPLAT, None),
|
||||
('WXUSINGDLL', '1'),
|
||||
('ISOLATION_AWARE_ENABLED', None),
|
||||
('NDEBUG',), # using a 1-tuple makes it do an undef
|
||||
]
|
||||
|
||||
self.libs = []
|
||||
self.libdirs = [ opj(self.WXDIR, 'lib', self.VCDLL) ]
|
||||
if self.MONOLITHIC:
|
||||
self.libs += makeLibName('')
|
||||
else:
|
||||
self.libs += [ 'wxbase' + WXDLLVER + libFlag(),
|
||||
'wxbase' + WXDLLVER + libFlag() + '_net',
|
||||
'wxbase' + WXDLLVER + libFlag() + '_xml',
|
||||
self.makeLibName('core')[0],
|
||||
self.makeLibName('adv')[0],
|
||||
self.makeLibName('html')[0],
|
||||
]
|
||||
|
||||
self.libs += ['kernel32', 'user32', 'gdi32', 'comdlg32',
|
||||
'winspool', 'winmm', 'shell32', 'oldnames', 'comctl32',
|
||||
'odbc32', 'ole32', 'oleaut32', 'uuid', 'rpcrt4',
|
||||
'advapi32', 'wsock32']
|
||||
|
||||
self.cflags = [ '/Gy',
|
||||
'/EHsc',
|
||||
# '/GX-' # workaround for internal compiler error in MSVC on some machines
|
||||
]
|
||||
self.lflags = None
|
||||
|
||||
# Other MSVC flags...
|
||||
# Uncomment these to have debug info for all kinds of builds
|
||||
#self.cflags += ['/Od', '/Z7']
|
||||
#self.lflags = ['/DEBUG', ]
|
||||
|
||||
|
||||
#---------------------------------------
|
||||
# Posix (wxGTK, wxMac or mingw32) settings
|
||||
elif os.name == 'posix' or COMPILER == 'mingw32':
|
||||
self.Verify_WX_CONFIG()
|
||||
self.includes = ['include', 'src']
|
||||
self.defines = [ ('NDEBUG',), # using a 1-tuple makes it do an undef
|
||||
]
|
||||
self.libdirs = []
|
||||
self.libs = []
|
||||
|
||||
self.cflags = self.getWxConfigValue('--cxxflags')
|
||||
self.cflags = self.cflags.split()
|
||||
if self.debug:
|
||||
self.cflags.append('-ggdb')
|
||||
self.cflags.append('-O0')
|
||||
else:
|
||||
self.cflags.append('-O3')
|
||||
|
||||
lflags = self.getWxConfigValue('--libs')
|
||||
self.MONOLITHIC = (lflags.find("_xrc") == -1)
|
||||
self.lflags = lflags.split()
|
||||
|
||||
self.WXBASENAME = self.getWxConfigValue('--basename')
|
||||
self.WXRELEASE = self.getWxConfigValue('--release')
|
||||
self.WXPREFIX = self.getWxConfigValue('--prefix')
|
||||
|
||||
# wxMac settings
|
||||
if sys.platform[:6] == "darwin":
|
||||
self.WXPLAT = '__WXMAC__'
|
||||
|
||||
if self.WXPORT == 'osx_carbon':
|
||||
# Flags and such for a Darwin (Max OS X) build of Python
|
||||
self.WXPLAT2 = '__WXOSX_CARBON__'
|
||||
else:
|
||||
self.WXPLAT2 = '__WXOSX_COCOA__'
|
||||
|
||||
self.libs = ['stdc++']
|
||||
if not self.ARCH == "":
|
||||
self.cflags.append("-arch")
|
||||
self.cflags.append(self.ARCH)
|
||||
self.lflags.append("-arch")
|
||||
self.lflags.append(self.ARCH)
|
||||
|
||||
if not os.environ.get('CC') or not os.environ.get('CXX'):
|
||||
os.environ["CXX"] = self.getWxConfigValue('--cxx')
|
||||
os.environ["CC"] = self.getWxConfigValue('--cc')
|
||||
|
||||
# wxGTK settings
|
||||
else:
|
||||
# Set flags for other Unix type platforms
|
||||
if self.WXPORT == 'gtk':
|
||||
msg("WARNING: The GTK 1.x port is not supported")
|
||||
self.WXPLAT = '__WXGTK__'
|
||||
portcfg = os.popen('gtk-config --cflags', 'r').read()[:-1]
|
||||
self.BUILD_BASE = self.BUILD_BASE + '-' + self.WXPORT
|
||||
elif self.WXPORT == 'gtk2':
|
||||
self.WXPLAT = '__WXGTK__'
|
||||
portcfg = os.popen('pkg-config gtk+-2.0 --cflags', 'r').read()[:-1]
|
||||
elif self.WXPORT == 'x11':
|
||||
msg("WARNING: The wxX11 port is no supported")
|
||||
self.WXPLAT = '__WXX11__'
|
||||
portcfg = ''
|
||||
self.BUILD_BASE = self.BUILD_BASE + '-' + self.WXPORT
|
||||
elif self.WXPORT == 'msw':
|
||||
self.WXPLAT = '__WXMSW__'
|
||||
portcfg = ''
|
||||
else:
|
||||
raise SystemExit, "Unknown WXPORT value: " + self.WXPORT
|
||||
|
||||
self.cflags += portcfg.split()
|
||||
|
||||
# Some distros (e.g. Mandrake) put libGLU in /usr/X11R6/lib, but
|
||||
# wx-config doesn't output that for some reason. For now, just
|
||||
# add it unconditionally but we should really check if the lib is
|
||||
# really found there or wx-config should be fixed.
|
||||
if self.WXPORT != 'msw':
|
||||
self.libdirs.append("/usr/X11R6/lib")
|
||||
|
||||
# Move the various -I, -D, etc. flags we got from the config scripts
|
||||
# into the distutils lists.
|
||||
self.cflags = self.adjustCFLAGS(self.cflags, self.defines, self.includes)
|
||||
self.lflags = self.adjustLFLAGS(self.lflags, self.libdirs, self.libs)
|
||||
|
||||
if self.debug and self.WXPORT == 'msw' and self.COMPILER != 'mingw32':
|
||||
self.defines.append( ('_DEBUG', None) )
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Helper functions
|
||||
|
||||
def parseCmdLine(self):
|
||||
self.debug = '--debug' in sys.argv or '-g' in sys.argv
|
||||
|
||||
# the values of the items in the class namespace that start
|
||||
# with an upper case letter can be overridden on the command
|
||||
# line
|
||||
for key, default in Configuration.__dict__.items():
|
||||
if key[0] < 'A' or key[0] > 'Z':
|
||||
continue
|
||||
for idx, arg in enumerate(sys.argv):
|
||||
if arg and arg.startswith(key + '='):
|
||||
value = arg.split('=', 1)[1]
|
||||
if isinstance(default, int):
|
||||
value = int(value)
|
||||
setattr(self, key, value)
|
||||
sys.argv[idx] = None
|
||||
|
||||
# remove the cmd line args that we recognized
|
||||
sys.argv = [arg for arg in sys.argv if arg is not None]
|
||||
|
||||
|
||||
def Verify_WX_CONFIG(self):
|
||||
"""
|
||||
Called for the builds that need wx-config. If WX_CONFIG is
|
||||
not set then determines the flags needed based on build
|
||||
options and searches for wx-config on the PATH.
|
||||
"""
|
||||
# if WX_CONFIG hasn't been set to an explicit value then construct one.
|
||||
if self.WX_CONFIG is None:
|
||||
self.WX_CONFIG='wx-config'
|
||||
port = self.WXPORT
|
||||
if port == "x11":
|
||||
port = "x11univ"
|
||||
flags = ' --toolkit=%s' % port
|
||||
flags += ' --unicode=yes'
|
||||
flags += ' --version=%s.%s' % (self.VER_MAJOR, self.VER_MINOR)
|
||||
|
||||
searchpath = os.environ["PATH"]
|
||||
for p in searchpath.split(':'):
|
||||
fp = os.path.join(p, 'wx-config')
|
||||
if os.path.exists(fp) and os.access(fp, os.X_OK):
|
||||
# success
|
||||
msg("Found wx-config: " + fp)
|
||||
msg(" Using flags: " + flags)
|
||||
self.WX_CONFIG = fp + flags
|
||||
if runSilently:
|
||||
self.WX_CONFIG += " 2>/dev/null "
|
||||
break
|
||||
else:
|
||||
msg("ERROR: WX_CONFIG not specified and wx-config not found on the $PATH")
|
||||
|
||||
# TODO: execute WX_CONFIG --list and verify a matching config is found
|
||||
|
||||
|
||||
def getWxConfigValue(self, flag):
|
||||
cmd = "%s %s" % (self.WX_CONFIG, flag)
|
||||
value = os.popen(cmd, 'r').read()[:-1]
|
||||
return value
|
||||
|
||||
|
||||
|
||||
def build_locale_dir(self, destdir, verbose=1):
|
||||
"""Build a locale dir under the wxPython package for MSW"""
|
||||
moFiles = glob.glob(opj(self.WXDIR, 'locale', '*.mo'))
|
||||
for src in moFiles:
|
||||
lang = os.path.splitext(os.path.basename(src))[0]
|
||||
dest = opj(destdir, lang, 'LC_MESSAGES')
|
||||
mkpath(dest, verbose=verbose)
|
||||
copy_file(src, opj(dest, 'wxstd.mo'), update=1, verbose=verbose)
|
||||
self.CLEANUP.append(opj(dest, 'wxstd.mo'))
|
||||
self.CLEANUP.append(dest)
|
||||
|
||||
|
||||
def build_locale_list(self, srcdir):
|
||||
# get a list of all files under the srcdir, to be used for install_data
|
||||
def walk_helper(lst, dirname, files):
|
||||
for f in files:
|
||||
filename = opj(dirname, f)
|
||||
if not os.path.isdir(filename):
|
||||
lst.append( (dirname, [filename]) )
|
||||
file_list = []
|
||||
os.path.walk(srcdir, walk_helper, file_list)
|
||||
return file_list
|
||||
|
||||
|
||||
def find_data_files(self, srcdir, *wildcards, **kw):
|
||||
# get a list of all files under the srcdir matching wildcards,
|
||||
# returned in a format to be used for install_data
|
||||
|
||||
def walk_helper(arg, dirname, files):
|
||||
if '.svn' in dirname:
|
||||
return
|
||||
names = []
|
||||
lst, wildcards = arg
|
||||
for wc in wildcards:
|
||||
wc_name = opj(dirname, wc)
|
||||
for f in files:
|
||||
filename = opj(dirname, f)
|
||||
|
||||
if fnmatch.fnmatch(filename, wc_name) and not os.path.isdir(filename):
|
||||
names.append(filename)
|
||||
if names:
|
||||
lst.append( (dirname, names ) )
|
||||
|
||||
file_list = []
|
||||
recursive = kw.get('recursive', True)
|
||||
if recursive:
|
||||
os.path.walk(srcdir, walk_helper, (file_list, wildcards))
|
||||
else:
|
||||
walk_helper((file_list, wildcards),
|
||||
srcdir,
|
||||
[os.path.basename(f) for f in glob.glob(opj(srcdir, '*'))])
|
||||
return file_list
|
||||
|
||||
|
||||
def makeLibName(self, name):
|
||||
if os.name == 'posix' or self.COMPILER == 'mingw32':
|
||||
libname = '%s_%s-%s' % (self.WXBASENAME, name, self.WXRELEASE)
|
||||
elif name:
|
||||
libname = 'wxmsw%s%s_%s' % (self.WXDLLVER, self.libFlag(), name)
|
||||
else:
|
||||
libname = 'wxmsw%s%s' % (self.WXDLLVER, self.libFlag())
|
||||
return [libname]
|
||||
|
||||
|
||||
def libFlag(self):
|
||||
if not self.debug:
|
||||
rv = ''
|
||||
else:
|
||||
rv = 'd'
|
||||
if True: ##UNICODE:
|
||||
rv = 'u' + rv
|
||||
return rv
|
||||
|
||||
|
||||
def findLib(self, name, libdirs):
|
||||
name = self.makeLibName(name)[0]
|
||||
if os.name == 'posix' or self.COMPILER == 'mingw32':
|
||||
lflags = self.getWxConfigValue('--libs')
|
||||
lflags = lflags.split()
|
||||
|
||||
# if wx-config --libs output does not start with -L, wx is
|
||||
# installed with a standard prefix and wx-config does not
|
||||
# output these libdirs because they are already searched by
|
||||
# default by the compiler and linker.
|
||||
if lflags[0][:2] != '-L':
|
||||
dirs = libdirs + ['/usr/lib', '/usr/local/lib']
|
||||
else:
|
||||
dirs = libdirs
|
||||
name = 'lib'+name
|
||||
else:
|
||||
dirs = libdirs[:]
|
||||
for d in dirs:
|
||||
p = os.path.join(d, name)
|
||||
if glob.glob(p+'*') != []:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
def adjustCFLAGS(self, cflags, defines, includes):
|
||||
"""
|
||||
Extract the raw -I, -D, and -U flags from cflags and put them into
|
||||
defines and includes as needed.
|
||||
"""
|
||||
newCFLAGS = []
|
||||
for flag in cflags:
|
||||
if flag[:2] == '-I':
|
||||
includes.append(flag[2:])
|
||||
elif flag[:2] == '-D':
|
||||
flag = flag[2:]
|
||||
if flag.find('=') == -1:
|
||||
defines.append( (flag, None) )
|
||||
else:
|
||||
defines.append( tuple(flag.split('=')) )
|
||||
elif flag[:2] == '-U':
|
||||
defines.append( (flag[2:], ) )
|
||||
else:
|
||||
newCFLAGS.append(flag)
|
||||
return newCFLAGS
|
||||
|
||||
|
||||
|
||||
def adjustLFLAGS(self, lflags, libdirs, libs):
|
||||
"""
|
||||
Extract the -L and -l flags from lflags and put them in libdirs and
|
||||
libs as needed
|
||||
"""
|
||||
newLFLAGS = []
|
||||
for flag in lflags:
|
||||
if flag[:2] == '-L':
|
||||
libdirs.append(flag[2:])
|
||||
elif flag[:2] == '-l':
|
||||
libs.append(flag[2:])
|
||||
else:
|
||||
newLFLAGS.append(flag)
|
||||
return newLFLAGS
|
||||
|
||||
|
||||
|
||||
# We'll use a factory function so we can use the Configuration class as a singleton
|
||||
_config = None
|
||||
|
||||
def Config(*args, **kw):
|
||||
global _config
|
||||
if _config is None:
|
||||
_config = Configuration(*args, **kw)
|
||||
return _config
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# other helpers
|
||||
|
||||
def msg(text):
|
||||
if not runSilently:
|
||||
print text
|
||||
|
||||
def opj(*args):
|
||||
path = os.path.join(*args)
|
||||
return os.path.normpath(path)
|
||||
375
buildtools/distutils_hacks.py
Normal file
375
buildtools/distutils_hacks.py
Normal file
@@ -0,0 +1,375 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Name: buildtools.distutils_hacks
|
||||
# Purpose: Various hacks that have been needed to override features
|
||||
# or work-around problems in Python's distutils.
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 3-Nov-2010
|
||||
# Copyright: (c) 2010 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
import distutils.command.install
|
||||
import distutils.command.install_data
|
||||
import distutils.command.install_headers
|
||||
import distutils.command.clean
|
||||
from distutils.dep_util import newer
|
||||
|
||||
from config import Config
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# New command classes
|
||||
|
||||
|
||||
class wx_smart_install_data(distutils.command.install_data.install_data):
|
||||
"""need to change self.install_dir to the actual library dir"""
|
||||
def run(self):
|
||||
install_cmd = self.get_finalized_command('install')
|
||||
self.install_dir = getattr(install_cmd, 'install_lib')
|
||||
return distutils.command.install_data.install_data.run(self)
|
||||
|
||||
|
||||
class wx_extra_clean(distutils.command.clean.clean):
|
||||
"""
|
||||
Also cleans stuff that this setup.py copies itself. If the
|
||||
--all flag was used also searches for .pyc, .pyd, .so files
|
||||
"""
|
||||
def run(self):
|
||||
from distutils import log
|
||||
from distutils.filelist import FileList
|
||||
|
||||
distutils.command.clean.clean.run(self)
|
||||
|
||||
cfg = Config()
|
||||
if self.all:
|
||||
fl = FileList()
|
||||
fl.include_pattern("*.pyc", 0)
|
||||
fl.include_pattern("*.pyd", 0)
|
||||
fl.include_pattern("*.so", 0)
|
||||
cfg.CLEANUP += fl.files
|
||||
|
||||
for f in cfg.CLEANUP:
|
||||
if os.path.isdir(f):
|
||||
try:
|
||||
if not self.dry_run and os.path.exists(f):
|
||||
os.rmdir(f)
|
||||
log.info("removing '%s'", f)
|
||||
except IOError:
|
||||
log.warning("unable to remove '%s'", f)
|
||||
|
||||
else:
|
||||
try:
|
||||
if not self.dry_run and os.path.exists(f):
|
||||
os.remove(f)
|
||||
log.info("removing '%s'", f)
|
||||
except IOError:
|
||||
log.warning("unable to remove '%s'", f)
|
||||
|
||||
|
||||
|
||||
# The Ubuntu Python adds a --install-layout option to distutils that
|
||||
# is used in our package build. If we detect that the current
|
||||
# distutils does not have it then make sure that it is removed from
|
||||
# the command-line options, otherwise the build will fail.
|
||||
for item in distutils.command.install.install.user_options:
|
||||
if item[0] == 'install-layout=':
|
||||
break
|
||||
else:
|
||||
for arg in sys.argv:
|
||||
if arg.startswith('--install-layout'):
|
||||
sys.argv.remove(arg)
|
||||
break
|
||||
|
||||
|
||||
|
||||
class wx_install(distutils.command.install.install):
|
||||
"""
|
||||
Turns off install_path_file
|
||||
"""
|
||||
def initialize_options(self):
|
||||
distutils.command.install.install.initialize_options(self)
|
||||
self.install_path_file = 0
|
||||
|
||||
|
||||
class wx_install_headers(distutils.command.install_headers.install_headers):
|
||||
"""
|
||||
Install the header files to the WXPREFIX, with an extra dir per
|
||||
filename too
|
||||
"""
|
||||
def initialize_options(self):
|
||||
self.root = None
|
||||
distutils.command.install_headers.install_headers.initialize_options(self)
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('install', ('root', 'root'))
|
||||
distutils.command.install_headers.install_headers.finalize_options(self)
|
||||
|
||||
def run(self):
|
||||
if os.name == 'nt':
|
||||
return
|
||||
headers = self.distribution.headers
|
||||
if not headers:
|
||||
return
|
||||
|
||||
cfg = Config()
|
||||
root = self.root
|
||||
#print "WXPREFIX is %s, root is %s" % (WXPREFIX, root)
|
||||
# hack for universal builds, which append i386/ppc
|
||||
# to the root
|
||||
if root is None or cfg.WXPREFIX.startswith(os.path.dirname(root)):
|
||||
root = ''
|
||||
for header, location in headers:
|
||||
install_dir = os.path.normpath(root +
|
||||
cfg.WXPREFIX +
|
||||
'/include/wx-%d.%d/wx' % (cfg.VER_MAJOR, cfg.VER_MINOR) +
|
||||
location)
|
||||
self.mkpath(install_dir)
|
||||
(out, _) = self.copy_file(header, install_dir)
|
||||
self.outfiles.append(out)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# These functions and class are copied from distutils in Python 2.5
|
||||
# and then grafted back into the distutils modules so we can change
|
||||
# how the -arch and -isysroot compiler args are handled. Basically if
|
||||
# -arch is specified in our compiler args then we need to strip all of
|
||||
# the -arch and -isysroot args provided by Python.
|
||||
|
||||
import distutils.unixccompiler
|
||||
import distutils.sysconfig
|
||||
from distutils.errors import DistutilsExecError, CompileError
|
||||
|
||||
def _darwin_compiler_fixup(compiler_so, cc_args):
|
||||
"""
|
||||
This function will strip '-isysroot PATH' and '-arch ARCH' from the
|
||||
compile flags if the user has specified one them in extra_compile_flags.
|
||||
|
||||
This is needed because '-arch ARCH' adds another architecture to the
|
||||
build, without a way to remove an architecture. Furthermore GCC will
|
||||
barf if multiple '-isysroot' arguments are present.
|
||||
"""
|
||||
stripArch = stripSysroot = 0
|
||||
|
||||
compiler_so = list(compiler_so)
|
||||
kernel_version = os.uname()[2] # 8.4.3
|
||||
major_version = int(kernel_version.split('.')[0])
|
||||
|
||||
if major_version < 8:
|
||||
# OSX before 10.4.0, these don't support -arch and -isysroot at
|
||||
# all.
|
||||
stripArch = stripSysroot = True
|
||||
else:
|
||||
stripArch = '-arch' in cc_args
|
||||
stripSysroot = '-isysroot' in cc_args or stripArch # <== This line changed
|
||||
|
||||
if stripArch:
|
||||
while 1:
|
||||
try:
|
||||
index = compiler_so.index('-arch')
|
||||
# Strip this argument and the next one:
|
||||
del compiler_so[index:index+2]
|
||||
except ValueError:
|
||||
break
|
||||
|
||||
if stripSysroot:
|
||||
try:
|
||||
index = compiler_so.index('-isysroot')
|
||||
# Strip this argument and the next one:
|
||||
del compiler_so[index:index+2]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Check if the SDK that is used during compilation actually exists,
|
||||
# the universal build requires the usage of a universal SDK and not all
|
||||
# users have that installed by default.
|
||||
sysroot = None
|
||||
if '-isysroot' in cc_args:
|
||||
idx = cc_args.index('-isysroot')
|
||||
sysroot = cc_args[idx+1]
|
||||
elif '-isysroot' in compiler_so:
|
||||
idx = compiler_so.index('-isysroot')
|
||||
sysroot = compiler_so[idx+1]
|
||||
|
||||
if sysroot and not os.path.isdir(sysroot):
|
||||
log.warn("Compiling with an SDK that doesn't seem to exist: %s",
|
||||
sysroot)
|
||||
log.warn("Please check your Xcode installation")
|
||||
|
||||
return compiler_so
|
||||
|
||||
|
||||
def _darwin_compiler_fixup_24(compiler_so, cc_args):
|
||||
compiler_so = _darwin_compiler_fixup(compiler_so, cc_args)
|
||||
return compiler_so, cc_args
|
||||
|
||||
|
||||
class MyUnixCCompiler(distutils.unixccompiler.UnixCCompiler):
|
||||
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
||||
compiler_so = self.compiler_so
|
||||
if sys.platform == 'darwin':
|
||||
compiler_so = _darwin_compiler_fixup(compiler_so, cc_args + extra_postargs)
|
||||
try:
|
||||
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
|
||||
extra_postargs)
|
||||
except DistutilsExecError, msg:
|
||||
raise CompileError, msg
|
||||
|
||||
|
||||
_orig_parse_makefile = distutils.sysconfig.parse_makefile
|
||||
def _parse_makefile(filename, g=None):
|
||||
rv = _orig_parse_makefile(filename, g)
|
||||
|
||||
# If a different deployment target is specified in the
|
||||
# environment then make sure it is put in the global
|
||||
# config dict.
|
||||
if os.getenv('MACOSX_DEPLOYMENT_TARGET'):
|
||||
val = os.getenv('MACOSX_DEPLOYMENT_TARGET')
|
||||
rv['MACOSX_DEPLOYMENT_TARGET'] = val
|
||||
rv['CONFIGURE_MACOSX_DEPLOYMENT_TARGET'] = val
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
distutils.unixccompiler.UnixCCompiler = MyUnixCCompiler
|
||||
distutils.unixccompiler._darwin_compiler_fixup = _darwin_compiler_fixup
|
||||
distutils.unixccompiler._darwin_compiler = _darwin_compiler_fixup_24
|
||||
distutils.sysconfig.parse_makefile = _parse_makefile
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Another hack-job for the CygwinCCompiler class, this time replacing
|
||||
# the _compile function with one that will pass the -I flags to windres.
|
||||
|
||||
import distutils.cygwinccompiler
|
||||
from distutils.errors import DistutilsExecError, CompileError
|
||||
|
||||
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
||||
if ext == '.rc' or ext == '.res':
|
||||
# gcc needs '.res' and '.rc' compiled to object files !!!
|
||||
try:
|
||||
#self.spawn(["windres", "-i", src, "-o", obj])
|
||||
self.spawn(["windres", "-i", src, "-o", obj] +
|
||||
[arg for arg in cc_args if arg.startswith("-I")] )
|
||||
except DistutilsExecError, msg:
|
||||
raise CompileError, msg
|
||||
else: # for other files use the C-compiler
|
||||
try:
|
||||
self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
|
||||
extra_postargs)
|
||||
except DistutilsExecError, msg:
|
||||
raise CompileError, msg
|
||||
|
||||
distutils.cygwinccompiler.CygwinCCompiler._compile = _compile
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Yet another distutils hack, this time for the msvc9compiler. There
|
||||
# is a bug in at least version distributed with Python 2.6 where it
|
||||
# adds '/pdb:None' to the linker command-line, but that just results
|
||||
# in a 'None' file being created instead of putting the debug info
|
||||
# into the .pyd files as expected. So we'll strip out that option via
|
||||
# a monkey-patch of the msvc9compiler.MSVCCompiler.initialize method.
|
||||
|
||||
if os.name == 'nt' and sys.version_info >= (2,6):
|
||||
import distutils.msvc9compiler
|
||||
_orig_initialize = distutils.msvc9compiler.MSVCCompiler.initialize
|
||||
|
||||
def _initialize(self, *args, **kw):
|
||||
rv = _orig_initialize(self, *args, **kw)
|
||||
try:
|
||||
self.ldflags_shared_debug.remove('/pdb:None')
|
||||
except ValueError:
|
||||
pass
|
||||
return rv
|
||||
|
||||
distutils.msvc9compiler.MSVCCompiler.initialize = _initialize
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
|
||||
from sipdistutils import build_ext
|
||||
|
||||
class etgsip_build_ext(build_ext):
|
||||
"""
|
||||
Override some parts of the SIP build command class so we can better
|
||||
control how SIP is used
|
||||
"""
|
||||
def _find_sip(self):
|
||||
cfg = Config()
|
||||
return cfg.SIP
|
||||
|
||||
def _sip_inc_dir(self):
|
||||
cfg = Config()
|
||||
return cfg.SIPINC
|
||||
|
||||
def _sip_sipfiles_dir(self):
|
||||
cfg = Config()
|
||||
return cfg.SIPFILES
|
||||
|
||||
def _sip_output_dir(self):
|
||||
cfg = Config()
|
||||
return cfg.SIPOUT
|
||||
|
||||
|
||||
def etg2sip(self, etgfile):
|
||||
cfg = Config()
|
||||
sipfile = os.path.splitext(os.path.basename(etgfile))[0] + '.sip'
|
||||
sipfile = os.path.join(cfg.SIPGEN, sipfile)
|
||||
return sipfile
|
||||
|
||||
|
||||
def build_extension(self, extension):
|
||||
"""
|
||||
Modify the dependency list, adding the sip files generated
|
||||
from the etg files.
|
||||
"""
|
||||
sources = extension.sources
|
||||
if sources is not None and isinstance(sources, (list, tuple)):
|
||||
etg_sources = [s for s in sources if s.startswith('etg/')]
|
||||
for e in etg_sources:
|
||||
extension.depends.append(self.etg2sip(e))
|
||||
|
||||
# let the base class do the rest
|
||||
return build_ext.build_extension(self, extension)
|
||||
|
||||
|
||||
def swig_sources (self, sources, extension):
|
||||
"""
|
||||
Run our ETG scripts to generate their .sip files, and adjust
|
||||
the sources list before passing on to the base class, which
|
||||
will then be responsible for running SIP and building the
|
||||
generated C++ files.
|
||||
"""
|
||||
if not self.extensions:
|
||||
return
|
||||
|
||||
cfg = Config()
|
||||
|
||||
etg_sources = [s for s in sources if s.startswith('etg/')]
|
||||
other_sources = [s for s in sources if not s.startswith('etg/')]
|
||||
|
||||
for etg in etg_sources:
|
||||
sipfile = self.etg2sip(etg)
|
||||
|
||||
if newer(etg, sipfile):
|
||||
cmd = [sys.executable, etg, '--sip']
|
||||
#if cfg.verbose:
|
||||
# cmd.append('--verbose')
|
||||
self.spawn(cmd)
|
||||
|
||||
if '%Module ' in file(sipfile).read():
|
||||
other_sources.append(sipfile)
|
||||
|
||||
# now call the base class version of this method
|
||||
return build_ext.swig_sources(self, other_sources, extension)
|
||||
|
||||
155
buildtools/sipdistutils.py
Normal file
155
buildtools/sipdistutils.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# Subclasses disutils.command.build_ext,
|
||||
# replacing it with a SIP version that compiles .sip -> .cpp
|
||||
# before calling the original build_ext command.
|
||||
# Written by Giovanni Bajo <rasky at develer dot com>
|
||||
# Based on Pyrex.Distutils, written by Graham Fawcett and Darrel Gallion.
|
||||
|
||||
# NOTE: This has been tweaked slightly to allow the folder used for the SIP
|
||||
# output to be overridden in a derived class. It is otherwise the same as the
|
||||
# module provided by sip. --Robin
|
||||
|
||||
import distutils.command.build_ext
|
||||
from distutils.dep_util import newer, newer_group
|
||||
import os
|
||||
import sys
|
||||
from hashlib import sha1
|
||||
|
||||
build_ext_base = distutils.command.build_ext.build_ext
|
||||
|
||||
def replace_suffix(path, new_suffix):
|
||||
return os.path.splitext(path)[0] + new_suffix
|
||||
|
||||
class build_ext (build_ext_base):
|
||||
|
||||
description = "Compile SIP descriptions, then build C/C++ extensions (compile/link to build directory)"
|
||||
|
||||
user_options = build_ext_base.user_options[:]
|
||||
user_options = [opt for opt in user_options if not opt[0].startswith("swig")]
|
||||
user_options += [
|
||||
('sip-opts=', None,
|
||||
"list of sip command line options"),
|
||||
]
|
||||
|
||||
def initialize_options (self):
|
||||
build_ext_base.initialize_options(self)
|
||||
self.sip_opts = None
|
||||
|
||||
def finalize_options (self):
|
||||
build_ext_base.finalize_options(self)
|
||||
if self.sip_opts is None:
|
||||
self.sip_opts = []
|
||||
else:
|
||||
self.sip_opts = self.sip_opts.split(' ')
|
||||
|
||||
def _get_sip_output_list(self, sbf):
|
||||
"""
|
||||
Parse the sbf file specified to extract the name of the generated source
|
||||
files. Make them absolute assuming they reside in the temp directory.
|
||||
"""
|
||||
for L in file(sbf):
|
||||
key, value = L.split("=", 1)
|
||||
if key.strip() == "sources":
|
||||
out = []
|
||||
for o in value.split():
|
||||
out.append(os.path.join(self._sip_output_dir(), o))
|
||||
return out
|
||||
|
||||
raise RuntimeError("cannot parse SIP-generated '%s'" % sbf)
|
||||
|
||||
def _find_sip(self):
|
||||
import sipconfig
|
||||
cfg = sipconfig.Configuration()
|
||||
if os.name == "nt":
|
||||
if not os.path.splitext(os.path.basename(cfg.sip_bin))[1]:
|
||||
return cfg.sip_bin + ".exe"
|
||||
return cfg.sip_bin
|
||||
|
||||
def _sip_inc_dir(self):
|
||||
import sipconfig
|
||||
cfg = sipconfig.Configuration()
|
||||
return cfg.sip_inc_dir
|
||||
|
||||
def _sip_sipfiles_dir(self):
|
||||
import sipconfig
|
||||
cfg = sipconfig.Configuration()
|
||||
return cfg.default_sip_dir
|
||||
|
||||
def _sip_calc_signature(self):
|
||||
sip_bin = self._find_sip()
|
||||
return sha1(open(sip_bin, "rb").read()).hexdigest()
|
||||
|
||||
def _sip_signature_file(self):
|
||||
return os.path.join(self._sip_output_dir(), "sip.signature")
|
||||
|
||||
def _sip_output_dir(self):
|
||||
return self.build_temp
|
||||
|
||||
def build_extension (self, ext):
|
||||
oldforce = self.force
|
||||
|
||||
if not self.force:
|
||||
sip_sources = [source for source in ext.sources if source.endswith('.sip')]
|
||||
if sip_sources:
|
||||
sigfile = self._sip_signature_file()
|
||||
if not os.path.isfile(sigfile):
|
||||
self.force = True
|
||||
else:
|
||||
old_sig = open(sigfile).read()
|
||||
new_sig = self._sip_calc_signature()
|
||||
if old_sig != new_sig:
|
||||
self.force = True
|
||||
|
||||
build_ext_base.build_extension(self, ext)
|
||||
|
||||
self.force = oldforce
|
||||
|
||||
def swig_sources (self, sources, extension=None):
|
||||
if not self.extensions:
|
||||
return
|
||||
|
||||
# Add the SIP include directory to the include path
|
||||
if extension is not None:
|
||||
extension.include_dirs.append(self._sip_inc_dir())
|
||||
depends = extension.depends
|
||||
else:
|
||||
# pre-2.4 compatibility
|
||||
self.include_dirs.append(self._sip_inc_dir())
|
||||
depends = [] # ?
|
||||
|
||||
# Filter dependencies list: we are interested only in .sip files,
|
||||
# since the main .sip files can only depend on additional .sip
|
||||
# files. For instance, if a .h changes, there is no need to
|
||||
# run sip again.
|
||||
depends = [f for f in depends if os.path.splitext(f)[1] == ".sip"]
|
||||
|
||||
# Create the temporary directory if it does not exist already
|
||||
if not os.path.isdir(self._sip_output_dir()):
|
||||
os.makedirs(self._sip_output_dir())
|
||||
|
||||
# Collect the names of the source (.sip) files
|
||||
sip_sources = []
|
||||
sip_sources = [source for source in sources if source.endswith('.sip')]
|
||||
other_sources = [source for source in sources if not source.endswith('.sip')]
|
||||
generated_sources = []
|
||||
|
||||
sip_bin = self._find_sip()
|
||||
|
||||
for sip in sip_sources:
|
||||
# Use the sbf file as dependency check
|
||||
sipbasename = os.path.basename(sip)
|
||||
sbf = os.path.join(self._sip_output_dir(), replace_suffix(sipbasename, ".sbf"))
|
||||
if newer_group([sip]+depends, sbf) or self.force:
|
||||
self._sip_compile(sip_bin, sip, sbf)
|
||||
open(self._sip_signature_file(), "w").write(self._sip_calc_signature())
|
||||
out = self._get_sip_output_list(sbf)
|
||||
generated_sources.extend(out)
|
||||
|
||||
return generated_sources + other_sources
|
||||
|
||||
def _sip_compile(self, sip_bin, source, sbf):
|
||||
self.spawn([sip_bin] + self.sip_opts +
|
||||
["-c", self._sip_output_dir(),
|
||||
"-b", sbf,
|
||||
"-I", self._sip_sipfiles_dir(),
|
||||
source])
|
||||
|
||||
8
buildtools/version.py
Normal file
8
buildtools/version.py
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
# wxPython version numbers used in build
|
||||
|
||||
VER_MAJOR = 2 # The first three must match wxWidgets
|
||||
VER_MINOR = 9
|
||||
VER_RELEASE = 2
|
||||
VER_SUBREL = 0 # wxPython release num for x.y.z release of wxWidgets
|
||||
VER_FLAGS = "" # release flags, such as prerelease or RC num, etc.
|
||||
Reference in New Issue
Block a user