From 32a324f73be3fbd3392ec6773480c16b29552925 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 22 Sep 2016 09:46:39 -0700 Subject: [PATCH] Some minor cleanup --- build.py | 454 +++++++++++++++++----------------- buildtools/build_wxwidgets.py | 193 +++++++-------- buildtools/builder.py | 12 +- buildtools/config.py | 188 +++++++------- buildtools/distutils_hacks.py | 51 ++-- buildtools/sipdistutils.py | 3 +- buildtools/version.py | 10 +- setup.py | 72 +++--- wscript | 78 +++--- 9 files changed, 530 insertions(+), 531 deletions(-) diff --git a/build.py b/build.py index 4f3ebe45..788bdded 100755 --- a/build.py +++ b/build.py @@ -49,12 +49,12 @@ PYTHON = None # it will be set later PYTHON_ARCH = 'UNKNOWN' # wx version numbers -version2 = "%d.%d" % (version.VER_MAJOR, version.VER_MINOR) +version2 = "%d.%d" % (version.VER_MAJOR, version.VER_MINOR) version3 = "%d.%d.%d" % (version.VER_MAJOR, version.VER_MINOR, version.VER_RELEASE) version2_nodot = version2.replace(".", "") version3_nodot = version3.replace(".", "") unstable_series = (version.VER_MINOR % 2) == 1 # is the minor version odd or even? - + isWindows = sys.platform.startswith('win') isDarwin = sys.platform == "darwin" devMode = False @@ -82,8 +82,8 @@ wafMD5 = 'e44003373c965f4221bbdc4c9b846128' doxygenCurrentVersion = '1.8.8' doxygenMD5 = { 'darwin' : '71c590e6cab47100f23919a2696cc7fd', - 'win32' : 'a3dcff227458e423c132f16f57e26510', - 'linux' : '083b3d8f614b538696041c7364e0f334', + 'win32' : 'a3dcff227458e423c132f16f57e26510', + 'linux' : '083b3d8f614b538696041c7364e0f334', } # And the location where they can be downloaded from @@ -97,43 +97,43 @@ def usage(): Usage: ./build.py [command(s)] [options] Commands: - N.N NN Major.Minor version number of the Python to use to run - the other commands. Default is 2.7. Or you can use + N.N NN Major.Minor version number of the Python to use to run + the other commands. Default is 2.7. Or you can use --python to specify the actual Python executable to use. - + dox Run Doxygen to produce the XML file used by ETG scripts doxhtml Run Doxygen to create the HTML documentation for wx - touch 'touch' the etg files so they will all get run the next + touch 'touch' the etg files so they will all get run the next time the etg command is run. - etg Run the ETG scripts that are out of date to update their + etg Run the ETG scripts that are out of date to update their SIP files and their Sphinx input files sip Run sip to generate the C++ wrapper source - + wxlib Build the Sphinx input files for wx.lib wxpy Build the Sphinx input files for wx.py wxtools Build the Sphinx input files for wx.tools sphinx Run the documentation building process using Sphinx - + docset Build Dash or Zeal compatible docsets - + build Build both wxWidgets and wxPython build_wx Do only the wxWidgets part of the build build_py Build wxPython only install Install both wxWidgets and wxPython - install_wx Install wxWidgets (but only if this tool was used to + install_wx Install wxWidgets (but only if this tool was used to build it) install_py Install wxPython only - + sdist Build a tarball containing all source files bdist Create a binary tarball release of wxPython Phoenix docs_bdist Build a tarball containing the documentation bdist_egg Build a Python egg. Requires magic. bdist_wheel Build a Python wheel. Requires magic. - + test Run the unit test suite test_* Run just the one named test module - + clean_wx Clean the wx parts of the build clean_py Clean the wxPython parts of the build clean_sphinx Clean the sphinx files @@ -143,12 +143,12 @@ Usage: ./build.py [command(s)] [options] parser = makeOptionParser() parser.print_help() - + def main(args): setPythonVersion(args) setDevModeOptions(args) - + os.environ['PYTHONPATH'] = phoenixDir() os.environ['PYTHONUNBUFFERED'] = 'yes' os.environ['WXWIN'] = wxDir() @@ -160,9 +160,9 @@ def main(args): if not args or 'help' in args or '--help' in args or '-h' in args: usage() sys.exit(1) - + options, commands = parseArgs(args) - + cfg = Config(noWxConfig=True) msg('cfg.VERSION: %s' % cfg.VERSION) msg('') @@ -182,7 +182,7 @@ def main(args): elif cmd.startswith('unittests/test_'): test_names.append(cmd) elif 'cmd_'+cmd in globals(): - function = globals()['cmd_'+cmd] + function = globals()['cmd_'+cmd] function(options, args) else: print('*** Unknown command: ' + cmd) @@ -194,13 +194,13 @@ def main(args): cmd_test(options, args, test_names) msg("Done!") - - + + #--------------------------------------------------------------------------- # Helper functions (see also buildtools.config for more) #--------------------------------------------------------------------------- - + def setPythonVersion(args): global PYVER global PYSHORTVER @@ -209,7 +209,7 @@ def setPythonVersion(args): havePyVer = False havePyPath = False - + for idx, arg in enumerate(args): if re.match(r'^[0-9]\.[0-9]$', arg): havePyVer = True @@ -235,7 +235,7 @@ def setPythonVersion(args): getOutput=True, echoCmd=False) PYSHORTVER = PYVER[0] + PYVER[2] break - + if havePyVer: if isWindows and os.environ.get('TOOLS'): # Use $TOOLS to find the correct Python. If set then it should be @@ -246,7 +246,7 @@ def setPythonVersion(args): # $TOOLS\Python33\python.exe # $TOOLS\amd64\Python27\python.exe # $TOOLS\amd64\Python33\python.exe - # + # TOOLS = os.environ.get('TOOLS') if 'cygdrive' in TOOLS: TOOLS = runcmd(getCygwinPath()+'/bin/cygpath -w '+TOOLS, True, False) @@ -256,10 +256,10 @@ def setPythonVersion(args): CPU = os.environ.get('CPU') if use64flag or CPU in ['AMD64', 'X64', 'amd64', 'x64']: TOOLS = posixjoin(TOOLS, 'amd64') - PYTHON = posixjoin(TOOLS, + PYTHON = posixjoin(TOOLS, 'python%s' % PYSHORTVER, 'python.exe') - + elif isWindows: # Otherwise check if the invoking Python is the right version if sys.version[:3] != PYVER: @@ -268,22 +268,22 @@ def setPythonVersion(args): PYTHON = sys.executable PYVER = sys.version[:3] PYSHORTVER = PYVER[0] + PYVER[2] - + elif not isWindows: # find a pythonX.Y on the PATH PYTHON = runcmd("which python%s" % PYVER, True, False) - - + + if not PYTHON: # If no version or path were specified then default to the python # that invoked this script PYTHON = sys.executable PYVER = sys.version[:3] PYSHORTVER = PYVER[0] + PYVER[2] - + PYTHON = os.path.abspath(PYTHON) msg('Will build using: "%s"' % PYTHON) - + msg(runcmd([PYTHON, '-c', 'import sys; print(sys.version)'], True, False)) PYTHON_ARCH = runcmd( [PYTHON, '-c', 'import platform; print(platform.architecture()[0])'], @@ -295,7 +295,7 @@ def setPythonVersion(args): if PYTHON_ARCH == '64bit': # Make sure this is set in case it wasn't above. os.environ['CPU'] = 'X64' - + def setDevModeOptions(args): @@ -323,7 +323,7 @@ def setDevModeOptions(args): myDevModeOptions.append('--debug') if isWindows: myDevModeOptions.append('--cairo') - + if '--dev' in args: global devMode devMode = True @@ -348,14 +348,14 @@ def numCPUs(): else: # OSX: p = subprocess.Popen("sysctl -n hw.ncpu", shell=True, stdout=subprocess.PIPE) return int(p.stdout.read()) - + # Windows: if "NUMBER_OF_PROCESSORS" in os.environ: ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]) if ncpus > 0: return ncpus return 1 # Default - + def getMSWSettings(options): checkCompiler(quiet=True) @@ -364,7 +364,7 @@ def getMSWSettings(options): msw = MSWsettings() msw.CPU = os.environ.get('CPU') if msw.CPU in ['AMD64', 'X64'] or PYTHON_ARCH == '64bit': - msw.dllDir = posixjoin(wxDir(), "lib", "vc%s_x64_dll" % getVisCVersion()) + msw.dllDir = posixjoin(wxDir(), "lib", "vc%s_x64_dll" % getVisCVersion()) else: msw.dllDir = posixjoin(wxDir(), "lib", "vc%s_dll" % getVisCVersion()) msw.buildDir = posixjoin(wxDir(), "build", "msw") @@ -373,7 +373,7 @@ def getMSWSettings(options): if options.debug: msw.dll_type = "ud" return msw - + @@ -387,7 +387,7 @@ def makeOptionParser(): ("osx_carbon", (False, "Build the OSX Carbon port on Mac (unsupported)")), ("mac_framework", (False, "Build wxWidgets as a Mac framework.")), ("mac_arch", ("", "Comma separated list of architectures to build on Mac")), - + ("use_syswx", (False, "Try to use an installed wx rather than building the " "one in this source tree. The wx-config in {prefix}/bin " "or the first found on the PATH determines which wx is " @@ -403,16 +403,16 @@ def makeOptionParser(): "this flag you should either build with an already " "installed wxWidgets, or allow this script to build and " "install wxWidgets.")), - + ("build_dir", ("", "Directory to store wx build files. (Not used on Windows)")), - ("prefix", ("", "Prefix value to pass to the wx build.")), + ("prefix", ("", "Prefix value to pass to the wx build.")), ("destdir", ("", "Installation root for wxWidgets, files will go to {destdir}/{prefix}")), - + ("extra_setup", ("", "Extra args to pass on setup.py's command line.")), ("extra_make", ("", "Extra args to pass on [n]make's command line.")), ("extra_waf", ("", "Extra args to pass on waf's command line.")), ("extra_pytest", ("", "Extra args to pass on py.test's command line.")), - + (("j","jobs"), ("", "Number of parallel compile jobs to do, if supported.")), ("both", (False, "Build both a debug and release version. (Only used on Windows)")), ("unicode", (True, "Build wxPython with unicode support (always on for wx2.9+)")), @@ -444,11 +444,11 @@ def makeOptionParser(): dest=dest, help=txt) return parser - + def parseArgs(args): parser = makeOptionParser() options, args = parser.parse_args(args) - + if isWindows: # We always use magic on Windows options.no_magic = False @@ -456,7 +456,7 @@ def parseArgs(args): elif options.use_syswx: # Turn off magic if using the system wx options.no_magic = True - + # Some options don't make sense for release builds if options.release_build: options.debug = False @@ -464,7 +464,7 @@ def parseArgs(args): options.relwithdebug = False if os.path.exists('REV.txt'): os.unlink('REV.txt') - + return options, args @@ -472,16 +472,16 @@ class pushDir(object): def __init__(self, newDir): self.cwd = os.getcwd() os.chdir(newDir) - + def __del__(self): # pop back to the original dir os.chdir(self.cwd) - + def getBuildDir(options): BUILD_DIR = opj(phoenixDir(), 'build', 'wxbld') if options.build_dir: - BUILD_DIR = os.path.abspath(options.build_dir) + BUILD_DIR = os.path.abspath(options.build_dir) return BUILD_DIR @@ -495,7 +495,7 @@ def deleteIfExists(deldir, verbose=True): if verbose: import traceback msg("Error: %s" % traceback.format_exc(1)) - + def delFiles(fileList, verbose=True): for afile in fileList: if verbose: @@ -527,17 +527,17 @@ def getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits=False): def _error_msg(txt): msg('ERROR: ' + txt) msg(' Set %s in the environment to use a local build of %s instead' % (envVar, cmdName)) - - + + msg('Checking for %s...' % cmd) if os.path.exists(cmd): # if the file exists run some verification checks on it - + # first make sure it is a normal file if not os.path.isfile(cmd): _error_msg('%s exists but is not a regular file.' % cmd) sys.exit(1) - + # now check the MD5 if not in dev mode and it's set to None if not (devMode and md5 is None): m = hashlib.md5() @@ -546,28 +546,28 @@ def getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits=False): _error_msg('MD5 mismatch, got "%s"\n ' 'expected "%s"' % (m.hexdigest(), md5)) sys.exit(1) - + # If the cmd is a script run by some interpreter, or similar, # then we don't need to check anything else if not platformBinary: return cmd - + # Ensure that commands that are platform binaries are executable if not os.access(cmd, os.R_OK | os.X_OK): - _error_msg('Cannot execute %s due to permissions error' % cmd) + _error_msg('Cannot execute %s due to permissions error' % cmd) sys.exit(1) - + try: p = subprocess.Popen([cmd, '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ) p.wait() except OSError as e: _error_msg('Could not execute %s, got "%s"' % (cmd, e)) sys.exit(1) - + # if we get this far then all is well, the cmd is good to go return cmd - - + + msg('Not found. Attempting to download...') url = '%s/%s.bz2' % (toolsURL, os.path.basename(cmd)) try: @@ -582,19 +582,19 @@ def getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits=False): import traceback traceback.print_exc() sys.exit(1) - + import bz2 data = bz2.decompress(data) with open(cmd, 'wb') as f: f.write(data) os.chmod(cmd, 0o755) - + # Recursive call so the MD5 value will be double-checked on what was # just downloaded return getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits) - + # The download and MD5 check only needs to happen once per run, cache the sip # cmd value here the first time through. _sipCmd = None @@ -620,8 +620,8 @@ def getDoxCmd(): if _doxCmd is None: _doxCmd = getTool('doxygen', doxygenCurrentVersion, doxygenMD5, 'DOXYGEN', True) return _doxCmd - - + + class CommandTimer(object): @@ -629,14 +629,14 @@ class CommandTimer(object): self.name = name self.startTime = datetime.datetime.now() msg('Running command: %s' % self.name) - + def __del__(self): delta = datetime.datetime.now() - self.startTime time = "" if delta.seconds / 60 > 0: time = "%dm" % (delta.seconds / 60) time += "%d.%ds" % (delta.seconds % 60, delta.microseconds / 1000) - msg('Finished command: %s (%s)' % (self.name, time)) + msg('Finished command: %s (%s)' % (self.name, time)) def uploadPackage(fileName, options, mask=defaultMask, keep=50): @@ -658,7 +658,7 @@ def uploadPackage(fileName, options, mask=defaultMask, keep=50): uploadDir = 'release-builds' else: uploadDir = 'snapshot-builds' - + # copy the new file to the server cmd = 'scp {} {}:{}'.format(fileName, host, uploadDir) #msg(cmd) @@ -667,21 +667,21 @@ def uploadPackage(fileName, options, mask=defaultMask, keep=50): # Make sure it is readable by all cmd = 'ssh {} "cd {}; chmod a+r {}"'.format(host, uploadDir, os.path.basename(fileName)) runcmd(cmd) - + # get the list of all snapshot files on the server cmd = 'ssh {} "cd {}; ls {}"'.format(host, uploadDir, mask) allFiles = runcmd(cmd, getOutput=True) allFiles = allFiles.strip().split('\n') - allFiles.sort() + allFiles.sort() # Leave the last keep number of builds, including this new one, on the server. # Delete the rest. - rmFiles = allFiles[:-keep] + rmFiles = allFiles[:-keep] if rmFiles: msg("Deleting %s" % ", ".join(rmFiles)) cmd = 'ssh {} "cd {}; rm {}"'.format(host, uploadDir, " ".join(rmFiles)) runcmd(cmd) - + msg("Upload complete!") @@ -698,7 +698,7 @@ def checkCompiler(quiet=False): CC = runcmd('"%s" -c "%s"' % (PYTHON, cmd), getOutput=True, echoCmd=False) if not quiet: msg("MSVC: %s" % CC) - + # Now get the environment variables which that compiler needs from # its vcvarsall.bat command and load them into this process's # environment. @@ -707,21 +707,21 @@ def checkCompiler(quiet=False): "env = msvc.query_vcvarsall(msvc.VERSION, arch); " \ "print(env)" env = eval(runcmd('"%s" -c "%s"' % (PYTHON, cmd), getOutput=True, echoCmd=False)) - + def _b(v): return str(v) #if PY2: # return bytes(v) #else: # return bytes(v, 'utf8') - + os.environ['PATH'] = _b(env['path']) os.environ['INCLUDE'] = _b(env['include']) os.environ['LIB'] = _b(env['lib']) os.environ['LIBPATH'] = _b(env['libpath']) - - -def getWafBuildBase(): + + +def getWafBuildBase(): base = posixjoin('build', 'waf', PYVER) if isWindows: if PYTHON_ARCH == '64bit': @@ -729,26 +729,26 @@ def getWafBuildBase(): else: base = posixjoin(base, 'x86') return base - - + + def getCygwinPath(): """ Try to locate the path where cygwin is installed. - + If CYGWIN_BASE is set in the environment then use that. Otherwise look in default install locations. """ if os.environ.get('CYGWIN_BASE'): return os.environ.get('CYGWIN_BASE') - + for path in ['c:/cygwin', 'c:/cygwin64']: if os.path.isdir(path): return path - + return None - - + + #--------------------------------------------------------------------------- # Command functions and helpers #--------------------------------------------------------------------------- @@ -757,7 +757,7 @@ def getCygwinPath(): def _doDox(arg): doxCmd = getDoxCmd() doxCmd = os.path.abspath(doxCmd) - + if isWindows: cygwin_path = getCygwinPath() doxCmd = doxCmd.replace('\\', '/') @@ -774,29 +774,29 @@ def _doDox(arg): cmd = './regen.sh %s' % arg runcmd(cmd) - + def cmd_dox(options, args): cmdTimer = CommandTimer('dox') _doDox('xml') - - + + def cmd_doxhtml(options, args): cmdTimer = CommandTimer('doxhtml') _doDox('html') _doDox('chm') - - + + # NOTE: Because of the use of defaults and plutil the following docset # commands will only work correctly on OSX. def cmd_docset_wx(options, args): cmdTimer = CommandTimer('docset_wx') cfg = Config() - + # Use Doxygen to generate the docset _doDox('docset') - + # Remove any existing docset in the dist dir and move the new docset in - srcname = posixjoin(wxDir(), 'docs/doxygen/out/docset', + srcname = posixjoin(wxDir(), 'docs/doxygen/out/docset', 'wxWidgets-%s.docset' % cfg.VERSION[:3]) destname = 'dist/wxWidgets-%s.docset' % version3 if not os.path.isdir(srcname): @@ -807,8 +807,8 @@ def cmd_docset_wx(options, args): shutil.move(srcname, destname) shutil.copyfile(wxICON, posixjoin(destname, 'icon.png')) runcmd('plutil -convert xml1 {}/Contents/Info.plist'.format(destname)) - - + + def cmd_docset_py(options, args): cmdTimer = CommandTimer('docset_py') if not os.path.isdir('docs/html'): @@ -820,9 +820,9 @@ def cmd_docset_py(options, args): docset = posixjoin('dist', '{}.docset'.format(name)) if os.path.isdir(docset): shutil.rmtree(docset) - + # run the docset generator - VERBOSE = '--verbose' if options.verbose else '' + VERBOSE = '--verbose' if options.verbose else '' runcmd('doc2dash {} --name "{}" --icon {} --destination dist docs/html' .format(VERBOSE, name, pyICON)) @@ -832,8 +832,8 @@ def cmd_docset_py(options, args): runcmd('defaults write {}/Contents/Info dashIndexFilePath main.html'.format(docset)) runcmd('defaults write {}/Contents/Info DocSetPlatformFamily wxpy'.format(docset)) runcmd('plutil -convert xml1 {}/Contents/Info.plist'.format(docset)) - - + + def cmd_docset(options, args): cmd_docset_wx(options, args) cmd_docset_py(options, args) @@ -844,7 +844,7 @@ def cmd_etg(options, args): cmdTimer = CommandTimer('etg') cfg = Config() assert os.path.exists(cfg.DOXY_XML_DIR), "Doxygen XML folder not found: " + cfg.DOXY_XML_DIR - + pwd = pushDir(cfg.ROOT_DIR) # TODO: Better support for selecting etg cmd-line flags... @@ -869,12 +869,12 @@ def cmd_etg(options, args): deps += ns.DEPENDS if hasattr(ns, 'OTHERDEPS'): deps += ns.OTHERDEPS - + # run the script only if any dependencies are newer if newer_group(deps, sipfile): runcmd('"%s" %s %s' % (PYTHON, script, flags)) - + def cmd_sphinx(options, args): from sphinxtools.postprocess import genIndexes, makeHeadings, postProcess, genGallery @@ -884,7 +884,7 @@ def cmd_sphinx(options, args): sphinxDir = os.path.join(phoenixDir(), 'docs', 'sphinx') if not os.path.isdir(sphinxDir): - raise Exception('Missing sphinx folder in the distribution') + raise Exception('Missing sphinx folder in the distribution') textFiles = glob.glob(sphinxDir + '/*.txt') if not textFiles: @@ -892,7 +892,7 @@ def cmd_sphinx(options, args): # Copy the rst files into txt files restDir = os.path.join(sphinxDir, 'rest_substitutions', 'overviews') - rstFiles = glob.glob(restDir + '/*.rst') + rstFiles = glob.glob(restDir + '/*.rst') for rst in rstFiles: rstName = os.path.split(rst)[1] txt = os.path.join(sphinxDir, os.path.splitext(rstName)[0] + '.txt') @@ -907,7 +907,7 @@ def cmd_sphinx(options, args): for rst in rstFiles: txt = os.path.join(sphinxDir, os.path.splitext(os.path.basename(rst))[0] + '.txt') copyIfNewer(rst, txt) - + makeHeadings() pwd2 = pushDir(sphinxDir) @@ -915,7 +915,7 @@ def cmd_sphinx(options, args): htmlDir = os.path.join(phoenixDir(), 'docs', 'html') runcmd('sphinx-build -b html -d %s/doctrees . %s' % (buildDir, htmlDir)) del pwd2 - + msg('Postprocessing sphinx output...') postProcess(htmlDir) @@ -952,7 +952,7 @@ def cmd_docs_bdist(options, args): pwd = pushDir(phoenixDir()) cfg = Config() - + rootname = "%s-docs-%s" % (baseName, cfg.VERSION) tarfilename = "dist/%s.tar.gz" % rootname @@ -960,20 +960,20 @@ def cmd_docs_bdist(options, args): os.makedirs('dist') if os.path.exists(tarfilename): os.remove(tarfilename) - + msg("Archiving Phoenix documentation...") tarball = tarfile.open(name=tarfilename, mode="w:gz") - tarball.add('docs/html', os.path.join(rootname, 'docs/html'), - filter=lambda info: None if '.svn' in info.name else info) + tarball.add('docs/html', os.path.join(rootname, 'docs/html'), + filter=lambda info: None if '.svn' in info.name else info) tarball.close() - + if options.upload: - uploadPackage(tarfilename, options, keep=5, + uploadPackage(tarfilename, options, keep=5, mask='%s-docs-%s*' % (baseName, cfg.VER_MAJOR)) - + msg('Documentation tarball built at %s' % tarfilename) - - + + def cmd_sip(options, args): cmdTimer = CommandTimer('sip') cfg = Config() @@ -984,7 +984,7 @@ def cmd_sip(options, args): if core_file in modules: modules.remove(core_file) modules.insert(0, core_file) - + for src_name in modules: tmpdir = tempfile.mkdtemp() tmpdir = tmpdir.replace('\\', '/') @@ -993,7 +993,7 @@ def cmd_sip(options, args): sbf = posixjoin(cfg.SIPOUT, base) + '.sbf' pycode = base[1:] # remove the leading _ pycode = posixjoin(cfg.PKGDIR, pycode) + '.py' - + # Check if any of the included files are newer than the .sbf file # produced by the previous run of sip. If not then we don't need to # run sip again. @@ -1001,14 +1001,14 @@ def cmd_sip(options, args): sipFiles = getSipFiles(etg.INCLUDES) + [opj(cfg.SIPGEN, base+'.sip')] if not newer_group(sipFiles, sbf) and os.path.exists(pycode): continue - - pycode = '-X pycode'+base+':'+pycode + + pycode = '-X pycode'+base+':'+pycode sip = getSipCmd() cmd = '%s %s -c %s -b %s %s %s' % \ (sip, cfg.SIPOPTS, tmpdir, sbf, pycode, src_name) runcmd(cmd) - + def processSrc(src, keepHashLines=False): with textfile_open(src, 'rt') as f: srcTxt = f.read() @@ -1020,7 +1020,7 @@ def cmd_sip(options, args): import re srcTxt = re.sub(r'^#line.*\n', '', srcTxt, flags=re.MULTILINE) return srcTxt - + # Check each file in tmpdir to see if it is different than the same file # in cfg.SIPOUT. If so then copy the new one to cfg.SIPOUT, otherwise # ignore it. @@ -1037,7 +1037,7 @@ def cmd_sip(options, args): srcTxt = processSrc(src, options.keep_hash_lines) with textfile_open(dest, 'rt') as f: destTxt = f.read() - + if srcTxt == destTxt: pass else: @@ -1045,18 +1045,18 @@ def cmd_sip(options, args): f = textfile_open(dest, 'wt') f.write(srcTxt) f.close() - + # Remove tmpdir and its contents shutil.rmtree(tmpdir) - - - + + + def cmd_touch(options, args): cmdTimer = CommandTimer('touch') pwd = pushDir(phoenixDir()) runcmd('touch etg/*.py') - + def cmd_test(options, args, tests=None): # Run all tests @@ -1088,7 +1088,7 @@ def cmd_test(options, args, tests=None): runcmd(cmd, fatal=False) - + def cmd_build(options, args): cmdTimer = CommandTimer('build') cmd_build_wx(options, args) @@ -1100,16 +1100,16 @@ def cmd_build_wx(options, args): cmdTimer = CommandTimer('build_wx') if not isWindows and options.use_syswx: msg("use_syswx option specified, skipping wxWidgets build") - return + return checkCompiler() - + build_options = ['--wxpython', '--unicode'] if options.jobs: build_options.append('--jobs=%s' % options.jobs) if isWindows: - # Windows-specific pre build stuff + # Windows-specific pre build stuff if options.cairo: build_options.append('--cairo') cairo_root = os.path.join(phoenixDir(), 'packaging', 'cairo-msw') @@ -1118,11 +1118,11 @@ def cmd_build_wx(options, args): if options.jom: build_options.append('--jom') - else: + else: # Platform is something other than MSW if options.osx_carbon: options.osx_cocoa = False - + BUILD_DIR = getBuildDir(options) DESTDIR = options.destdir PREFIX = options.prefix @@ -1131,10 +1131,10 @@ def cmd_build_wx(options, args): PREFIX = "/Library/Frameworks/wx.framework/Versions/%s" % version2 if PREFIX: build_options.append('--prefix=%s' % PREFIX) - + if not os.path.exists(BUILD_DIR): os.makedirs(BUILD_DIR) - if isDarwin and options.mac_arch: + if isDarwin and options.mac_arch: build_options.append("--mac_universal_binary=%s" % options.mac_arch) if options.no_config: @@ -1151,17 +1151,17 @@ def cmd_build_wx(options, args): break else: build_options.append("--no_config") - + if isDarwin and options.osx_cocoa: build_options.append("--osx_cocoa") - + #if options.install: # build_options.append('--installdir=%s' % DESTDIR) # build_options.append("--install") - + if options.mac_framework and isDarwin: build_options.append("--mac_framework") - + # Change to what will be the wxWidgets build folder # (Note, this needs to be after any testing for file/path existance, etc. # because they may be specified as relative paths.) @@ -1169,32 +1169,32 @@ def cmd_build_wx(options, args): if options.debug or (isWindows and options.both): build_options.append('--debug') - + if options.extra_make: build_options.append('--extra_make="%s"' % options.extra_make) - + if options.gtk3: build_options.append('--gtk3') - + try: # Import and run the wxWidgets build script from buildtools import build_wxwidgets as wxbuild - + print('wxWidgets build options: ' + str(build_options)) wxbuild.main(wxDir(), build_options) - + # build again without the --debug flag? if isWindows and options.both: build_options.remove('--debug') print('wxWidgets build options: ' + str(build_options)) wxbuild.main(wxDir(), build_options) - + except Exception: print("ERROR: failed building wxWidgets") import traceback traceback.print_exc() sys.exit(1) - + # Build the wx message catalogs, but first check that there is a msgfmt # command available if findCmd('msgfmt'): @@ -1205,13 +1205,13 @@ def cmd_build_wx(options, args): else: print("WARNING: msgfmt command not found, message catalogs not rebulit.\n" " Please install gettext and associated tools.") - - + + def copyWxDlls(options): if options.no_magic or options.use_syswx: - return - + return + if isWindows: # Copy the wxWidgets DLLs to the wxPython package folder msw = getMSWSettings(options) @@ -1245,27 +1245,27 @@ def copyWxDlls(options): elif isDarwin: # Copy the wxWidgets dylibs - cfg = Config() - wxlibdir = os.path.join(getBuildDir(options), "lib") + cfg = Config() + wxlibdir = os.path.join(getBuildDir(options), "lib") dlls = glob.glob(wxlibdir + '/*.dylib') for dll in dlls: copyIfNewer(dll, posixjoin(phoenixDir(), cfg.PKGDIR, os.path.basename(dll)), verbose=True) - + # Now use install_name_tool to change the extension modules to look # in the same folder for the wx libs, instead of the build dir. Also # change the wx libs the same way. - macSetLoaderNames(glob.glob(opj(phoenixDir(), cfg.PKGDIR, '*.so')) + + macSetLoaderNames(glob.glob(opj(phoenixDir(), cfg.PKGDIR, '*.so')) + glob.glob(opj(phoenixDir(), cfg.PKGDIR, '*.dylib'))) - + else: # Not Windows and not OSX. For now that means that we'll assume it's wxGTK. - cfg = Config() - wxlibdir = os.path.join(getBuildDir(options), "lib") + cfg = Config() + wxlibdir = os.path.join(getBuildDir(options), "lib") dlls = glob.glob(wxlibdir + '/libwx_*.so') dlls += glob.glob(wxlibdir + '/libwx_*.so.[0-9]*') for dll in dlls: copyIfNewer(dll, posixjoin(phoenixDir(), cfg.PKGDIR, os.path.basename(dll)), verbose=True) - + # If all went well the wxPython extensions should already be looking # for the wxlib's in $ORIGIN, so there is nothing else to do here @@ -1275,7 +1275,7 @@ def copyWxDlls(options): def cmd_waf_py(options, args): cmdTimer = CommandTimer('waf_py') cmd_build_py(options, args) - + def cmd_build_py(options, args): cmdTimer = CommandTimer('build_py') @@ -1292,21 +1292,21 @@ def cmd_build_py(options, args): WX_CONFIG = wxcfg else: WX_CONFIG = 'wx-config' # hope it is on the PATH - - + + wafBuildBase = wafBuildDir = getWafBuildBase() if isWindows: wafBuildDir = posixjoin(wafBuildBase, 'release') - + build_options = list() if options.verbose: build_options.append('--verbose') - + if options.debug or (isWindows and options.both): build_options.append("--debug") if isWindows: wafBuildDir = posixjoin(wafBuildBase, 'debug') - if isDarwin and options.mac_arch: + if isDarwin and options.mac_arch: build_options.append("--mac_arch=%s" % options.mac_arch) if isWindows: if PYTHON_ARCH == '64bit': @@ -1323,17 +1323,17 @@ def cmd_build_py(options, args): build_options.append('--msvc_relwithdebug') if options.gtk3: build_options.append('--gtk3') - + build_options.append('--python="%s"' % PYTHON) build_options.append('--out=%s' % wafBuildDir) # this needs to be the last option - + if not isWindows and not isDarwin and not options.no_magic and not options.use_syswx: # Using $ORIGIN in the rpath will cause the dynamic linker to look # for shared libraries in a folder relative to the loading binary's # location. Here we'll use just $ORIGIN so it should look in the same # folder as the wxPython extension modules. os.environ['LD_RUN_PATH'] = '$ORIGIN' - + # Run waf to perform the builds pwd = pushDir(phoenixDir()) cmd = '"%s" %s %s configure build %s' % (PYTHON, waf, ' '.join(build_options), options.extra_waf) @@ -1349,9 +1349,9 @@ def cmd_build_py(options, args): copyWxDlls(options) if isWindows or isDarwin: - cfg = Config() + cfg = Config() cfg.build_locale_dir(opj(cfg.PKGDIR, 'locale')) - + print("\n------------ BUILD FINISHED ------------") print("To use wxPython from the build folder (without installing):") print(" - Set your PYTHONPATH variable to %s." % phoenixDir()) @@ -1365,28 +1365,28 @@ def cmd_install(options, args): cmdTimer = CommandTimer('install') cmd_install_wx(options, args) cmd_install_py(options, args) - - + + def cmd_install_wx(options, args): cmdTimer = CommandTimer('install_wx') if isWindows: msg('No wxWidgets installation required on Windows') return - + if options.use_syswx: msg("use_syswx option specified, skipping wxWidgets install") - return - + return + if not options.no_magic: msg('Magic is in use, wxWidgets will be installed with wxPython') - return - + return + # Otherwise, run 'make install' in the wx build folder BUILD_DIR = getBuildDir(options) DESTDIR = '' if not options.destdir else 'DESTDIR=' + options.destdir pwd = pushDir(BUILD_DIR) runcmd("make install %s %s" % (DESTDIR, options.extra_make)) - + def cmd_install_py(options, args): @@ -1397,37 +1397,37 @@ def cmd_install_py(options, args): PYTHON, DESTDIR, VERBOSE, options.extra_setup) runcmd(cmd) - + def _doSimpleSetupCmd(options, args, setupCmd): cmdTimer = CommandTimer(setupCmd) VERBOSE = '--verbose' if options.verbose else '' cmd = '"%s" setup.py %s --skip-build %s %s' % (PYTHON, setupCmd, VERBOSE, options.extra_setup) runcmd(cmd) - + def cmd_bdist_egg(options, args): _doSimpleSetupCmd(options, args, 'bdist_egg') - cfg = Config() + cfg = Config() if options.upload: filemask = "dist/%s-%s-*.egg" % (baseName, cfg.VERSION.replace('-', '_')) filenames = glob.glob(filemask) assert len(filenames) == 1 uploadPackage(filenames[0], options) - + def cmd_bdist_wheel(options, args): _doSimpleSetupCmd(options, args, 'bdist_wheel') - cfg = Config() + cfg = Config() if options.upload: filemask = "dist/%s-%s-*.whl" % (baseName, cfg.VERSION.replace('-', '_')) filenames = glob.glob(filemask) assert len(filenames) == 1 uploadPackage(filenames[0], options) - - + + def cmd_bdist_wininst(options, args): _doSimpleSetupCmd(options, args, 'bdist_wininst') - cfg = Config() + cfg = Config() if options.upload: filemask = "dist/%s-%s-*.exe" % (baseName, cfg.VERSION.replace('-', '_')) filenames = glob.glob(filemask) @@ -1453,15 +1453,15 @@ def cmd_clean_wx(options, args): if options.both: options.debug = True msw = getMSWSettings(options) - cfg = Config() + cfg = Config() deleteIfExists(opj(msw.dllDir, 'msw'+msw.dll_type)) delFiles(glob.glob(opj(msw.dllDir, 'wx*%s%s*' % (version2_nodot, msw.dll_type)))) - delFiles(glob.glob(opj(msw.dllDir, 'wx*%s%s*' % (version3_nodot, msw.dll_type)))) + delFiles(glob.glob(opj(msw.dllDir, 'wx*%s%s*' % (version3_nodot, msw.dll_type)))) if PYTHON_ARCH == '64bit': deleteIfExists(opj(msw.buildDir, 'vc%s_msw%sdll_x64' % (getVisCVersion(), msw.dll_type))) else: deleteIfExists(opj(msw.buildDir, 'vc%s_msw%sdll' % (getVisCVersion(), msw.dll_type))) - + if options.both: options.debug = False options.both = False @@ -1470,7 +1470,7 @@ def cmd_clean_wx(options, args): else: BUILD_DIR = getBuildDir(options) deleteIfExists(BUILD_DIR) - + def cmd_clean_py(options, args): cmdTimer = CommandTimer('clean_py') @@ -1486,7 +1486,7 @@ def cmd_clean_py(options, args): msw = getMSWSettings(options) for wc in [ 'wx*' + version2_nodot + msw.dll_type + '*.dll', 'wx*' + version3_nodot + msw.dll_type + '*.dll']: - files += glob.glob(opj(cfg.PKGDIR, wc)) + files += glob.glob(opj(cfg.PKGDIR, wc)) delFiles(files) if options.both: @@ -1495,13 +1495,13 @@ def cmd_clean_py(options, args): cmd_clean_py(options, args) options.both = True - + def cmd_clean_sphinx(options, args): cmdTimer = CommandTimer('clean_sphinx') assert os.getcwd() == phoenixDir() sphinxDir = opj(phoenixDir(), 'docs', 'sphinx') - + globs = [ opj(sphinxDir, '*.txt'), opj(sphinxDir, '*.rst'), opj(sphinxDir, '*.inc'), @@ -1523,21 +1523,21 @@ def cmd_clean_sphinx(options, args): if os.path.exists(d): shutil.rmtree(d) - + def cmd_clean(options, args): cmd_clean_wx(options, args) cmd_clean_py(options, args) - - + + def cmd_cleanall(options, args): # These take care of all the object, lib, shared lib files created by the # compilation part of build cmd_clean_wx(options, args) cmd_clean_py(options, args) - + # Clean all the intermediate and generated files from the sphinx command cmd_clean_sphinx(options, args) - + # Now also scrub out all of the SIP and C++ source files that are # generated by the Phoenix ETG system. cmdTimer = CommandTimer('cleanall') @@ -1547,7 +1547,7 @@ def cmd_cleanall(options, args): files += glob.glob(wc) delFiles(files) - + def cmd_buildall(options, args): # (re)build everything cmd_build_wx(options, args) @@ -1557,8 +1557,8 @@ def cmd_buildall(options, args): cmd_sip(options, args) cmd_build_py(options, args) cmd_test(options, args) - - + + def cmd_sdist(options, args): # Build a source tarball that includes the generated SIP and CPP files. cmdTimer = CommandTimer('sdist') @@ -1570,24 +1570,24 @@ def cmd_sdist(options, args): if not isGit: msg("Sorry, I don't know what to do in this source tree, no git workspace found.") return - + # make a tree for building up the archive files PDEST = 'build/sdist' WDEST = posixjoin(PDEST, 'ext/wxWidgets') if not os.path.exists(PDEST): os.makedirs(PDEST) - + # and a place to put the final tarball if not os.path.exists('dist'): os.mkdir('dist') - - if isGit: + + if isGit: # pull out an archive copy of the repo files msg('Exporting Phoenix...') runcmd('git archive HEAD | tar -x -C %s' % PDEST, echoCmd=False) msg('Exporting wxWidgets...') runcmd('(cd %s; git archive HEAD) | tar -x -C %s' % (wxDir(), WDEST), echoCmd=False) - + # copy Phoenix's generated code into the archive tree msg('Copying generated files...') for srcdir in ['cpp', 'gen']: @@ -1610,7 +1610,7 @@ def cmd_sdist(options, args): cmd_egg_info(options, args, egg_base=PDEST) copyFile(opj(PDEST, 'wxPython_Phoenix.egg-info/PKG-INFO'), opj(PDEST, 'PKG-INFO')) - + # build the tarball msg('Archiving Phoenix source...') rootname = "%s-%s" % (baseName, cfg.VERSION) @@ -1620,7 +1620,7 @@ def cmd_sdist(options, args): tarball = tarfile.open(name=tarfilename, mode="w:gz") pwd = pushDir(PDEST) for name in glob.glob('*'): - tarball.add(name, os.path.join(rootname, name)) + tarball.add(name, os.path.join(rootname, name)) tarball.close() msg('Cleaning up...') del pwd @@ -1628,7 +1628,7 @@ def cmd_sdist(options, args): if options.upload: uploadPackage(tarfilename, options) - + msg("Source release built at %s" % tarfilename) @@ -1643,10 +1643,10 @@ def cmd_bdist(options, args): cfg = Config() dllext = ".so" - wxlibdir = os.path.join(getBuildDir(options), "lib") + wxlibdir = os.path.join(getBuildDir(options), "lib") if sys.platform.startswith('darwin'): dllext = ".dylib" - + platform = sys.platform if isWindows and PYTHON_ARCH == '64bit': platform = 'win64' @@ -1655,17 +1655,17 @@ def cmd_bdist(options, args): if not os.path.exists('dist'): os.makedirs('dist') - + if os.path.exists(tarfilename): os.remove(tarfilename) msg("Archiving Phoenix binaries to %s..." % tarfilename) tarball = tarfile.open(name=tarfilename, mode="w:gz") - tarball.add('wx', opj(rootname, 'wx'), + tarball.add('wx', opj(rootname, 'wx'), filter=lambda info: None if '.svn' in info.name \ or info.name.endswith('.pyc') \ or '__pycache__' in info.name else info) - tarball.add(eggInfoName, opj(rootname, eggInfoName)) - + tarball.add(eggInfoName, opj(rootname, eggInfoName)) + if not isDarwin and not isWindows and not options.no_magic and not options.use_syswx: # If the DLLs are not already in the wx package folder then go fetch # them now. @@ -1679,11 +1679,11 @@ def cmd_bdist(options, args): if options.upload: uploadPackage(tarfilename, options) - + msg("Binary release built at %s" % tarfilename) - + def cmd_setrev(options, args): # Grab the current revision number from the version control system # (if possible) and write it to a file we'll use later for @@ -1693,24 +1693,24 @@ def cmd_setrev(options, args): if options.release_build: # Ignore this command for release builds, they are not supposed to - # include current VCS revision info in the version number. + # include current VCS revision info in the version number. msg('This is a release build, setting REV.txt skipped') - + else: svnrev = getVcsRev() f = open('REV.txt', 'w') svnrev = '.dev'+svnrev f.write(svnrev) f.close() - msg('REV.txt set to "%s"' % svnrev) + msg('REV.txt set to "%s"' % svnrev) cfg = Config() cfg.resetVersion() msg('cfg.VERSION: %s' % cfg.VERSION) - - + + #--------------------------------------------------------------------------- if __name__ == '__main__': - main(sys.argv[1:]) + main(sys.argv[1:]) diff --git a/buildtools/build_wxwidgets.py b/buildtools/build_wxwidgets.py index 31af3e54..eedc6619 100644 --- a/buildtools/build_wxwidgets.py +++ b/buildtools/build_wxwidgets.py @@ -49,7 +49,7 @@ def numCPUs(): else: # OSX: p = subprocess.Popen("sysctl -n hw.ncpu", shell=True, stdout=subprocess.PIPE) return p.stdout.read() - + # Windows: if "NUMBER_OF_PROCESSORS" in os.environ: ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]); @@ -76,7 +76,7 @@ def getVisCVersion(): # TODO: Add more tests to get the other versions... else: return 'FIXME' - + def exitIfError(code, msg): if code != 0: @@ -85,23 +85,23 @@ def exitIfError(code, msg): raise builder.BuildError(msg) else: sys.exit(1) - - + + def getWxRelease(wxRoot=None): if not wxRoot: global wxRootDir wxRoot = wxRootDir - + configureText = open(os.path.join(wxRoot, "configure.in"), "r").read() majorVersion = re.search("wx_major_version_number=(\d+)", configureText).group(1) minorVersion = re.search("wx_minor_version_number=(\d+)", configureText).group(1) - + versionText = "%s.%s" % (majorVersion, minorVersion) - + if int(minorVersion) % 2: releaseVersion = re.search("wx_release_number=(\d+)", configureText).group(1) versionText += ".%s" % (releaseVersion) - + return versionText @@ -112,7 +112,7 @@ def getFrameworkName(options): name += "Cocoa" else: name += "Carbon" - return name + return name def getPrefixInFramework(options, wxRoot=None): @@ -144,7 +144,7 @@ def macFixupInstallNames(destdir, prefix, buildDir=None): cmd = 'install_name_tool -change %s/lib/%s %s/lib/%s %s/lib/%s' % \ (destdir+prefix,dep, prefix,dep, destdir+prefix,lib) print(cmd) - run(cmd) + run(cmd) os.chdir(pwd) @@ -160,7 +160,7 @@ def getoutput(cmd): output = None output = sp.stdout.read() if sys.version_info > (3,): - outputEncoding = 'cp1252' if sys.platform == 'win32' else 'utf-8' + outputEncoding = 'cp1252' if sys.platform == 'win32' else 'utf-8' output = output.decode(outputEncoding) output = output.rstrip() rval = sp.wait() @@ -169,7 +169,7 @@ def getoutput(cmd): print("Command '%s' failed with exit code %d." % (cmd, rval)) sys.exit(rval) return output - + def main(wxDir, args): global wxRootDir @@ -178,26 +178,26 @@ def main(wxDir, args): global configure_opts global wxBuilder global nmakeCommand - + wxRootDir = wxDir - + contribDir = os.path.join("contrib", "src") installDir = None VERSION = tuple([int(i) for i in getWxRelease().split('.')[:2]]) - + if sys.platform.startswith("win"): contribDir = os.path.join(wxRootDir, "contrib", "build") - + if sys.platform.startswith("win"): toolkit = "msvc" else: toolkit = "autoconf" - + defJobs = str(numCPUs()) defFwPrefix = '/Library/Frameworks' - - option_dict = { + + option_dict = { "clean" : (False, "Clean all files from the build directory"), "debug" : (False, "Build the library in debug symbols"), "builddir" : ("", "Directory where the build will be performed for autoconf builds."), @@ -207,10 +207,10 @@ def main(wxDir, args): "installdir" : ("", "Directory where built wxWidgets will be installed"), "gtk3" : (False, "On Linux build for gtk3 (default gtk2)"), "mac_distdir" : (None, "If set on Mac, will create an installer package in the specified dir."), - "mac_universal_binary" + "mac_universal_binary" : ("", "Comma separated list of architectures to include in the Mac universal binary"), "mac_framework" : (False, "Install the Mac build as a framework"), - "mac_framework_prefix" + "mac_framework_prefix" : (defFwPrefix, "Prefix where the framework should be installed. Default: %s" % defFwPrefix), "cairo" : (False, "Enable dynamically loading the Cairo lib for wxGraphicsContext on MSW"), "no_config" : (False, "Turn off configure step on autoconf builds"), @@ -226,7 +226,7 @@ def main(wxDir, args): "verbose" : (False, "Print commands as they are run, (to aid with debugging this script)"), "jom" : (False, "Use jom.exe instead of nmake for MSW builds."), } - + parser = optparse.OptionParser(usage="usage: %prog [options]", version="%prog 1.0") keys = option_dict.keys() @@ -235,39 +235,39 @@ def main(wxDir, args): action = "store" if type(default) == bool: action = "store_true" - parser.add_option("--" + opt, default=default, action=action, dest=opt, + parser.add_option("--" + opt, default=default, action=action, dest=opt, help=option_dict[opt][1]) - + options, arguments = parser.parse_args(args=args) global verbose if options.verbose: verbose = True - + # compiler / build system specific args buildDir = options.builddir args = [] installDir = options.installdir prefixDir = options.prefix - + if toolkit == "autoconf": if not buildDir: buildDir = os.getcwd() configure_opts = [] if options.features != "": configure_opts.extend(options.features.split(" ")) - + if options.unicode: configure_opts.append("--enable-unicode") - + if options.debug: configure_opts.append("--enable-debug") - + if options.osx_cocoa: configure_opts.append("--with-osx_cocoa") elif options.osx_carbon: configure_opts.append("--with-osx_carbon") - + if options.gtk3: configure_opts.append("--with-gtk=3") @@ -297,9 +297,9 @@ def main(wxDir, args): # TODO: there should be a command line option to set the SDK... if sys.platform.startswith("darwin"): for xcodePath in getXcodePaths(): - sdks = [ xcodePath+"/SDKs/MacOSX10.{}.sdk".format(n) + sdks = [ xcodePath+"/SDKs/MacOSX10.{}.sdk".format(n) for n in range(5, 15) ] - + # use the lowest available sdk on the build machine for sdk in sdks: if os.path.exists(sdk): @@ -313,8 +313,8 @@ def main(wxDir, args): if prefixDir: prefixDir = os.path.abspath(prefixDir) configure_opts.append("--prefix=" + prefixDir) - - + + if options.wxpython: configure_opts.extend(wxpy_configure_opts) if options.debug: @@ -322,16 +322,16 @@ def main(wxDir, args): configure_opts.append("--enable-debug_gdb") configure_opts.append("--disable-optimise") configure_opts.remove("--enable-optimise") - - + + if options.rebake: retval = run("make -f autogen.mk") exitIfError(retval, "Error running autogen.mk") - + if options.mac_framework: # TODO: Should options.install be automatically turned on if the # mac_framework flag is given? - + # framework builds always need to be monolithic if not "--enable-monolithic" in configure_opts: configure_opts.append("--enable-monolithic") @@ -340,7 +340,7 @@ def main(wxDir, args): # plus the framework specific dir structure. prefixDir = getPrefixInFramework(options) configure_opts.append("--prefix=" + prefixDir) - + # the framework build adds symlinks above the installDir + prefixDir folder # so we need to wipe from the framework root instead of inside the prefixDir. frameworkRootDir = os.path.abspath(os.path.join(installDir + prefixDir, "..", "..")) @@ -348,30 +348,30 @@ def main(wxDir, args): if os.path.exists(frameworkRootDir): shutil.rmtree(frameworkRootDir) - if options.mac_universal_binary: + if options.mac_universal_binary: if options.mac_universal_binary == 'default': if options.osx_cocoa: - configure_opts.append("--enable-universal_binary=i386,x86_64") + configure_opts.append("--enable-universal_binary=i386,x86_64") else: - configure_opts.append("--enable-universal_binary") + configure_opts.append("--enable-universal_binary") else: configure_opts.append("--enable-universal_binary=%s" % options.mac_universal_binary) - + print("Configure options: " + repr(configure_opts)) wxBuilder = builder.AutoconfBuilder() if not options.no_config and not options.clean: olddir = os.getcwd() if buildDir: os.chdir(buildDir) - exitIfError(wxBuilder.configure(dir=wxRootDir, options=configure_opts), + exitIfError(wxBuilder.configure(dir=wxRootDir, options=configure_opts), "Error running configure") os.chdir(olddir) if options.config_only: print("Exiting after configure") return - + elif toolkit in ["msvc", "msvcProject"]: flags = {} buildDir = os.path.abspath(os.path.join(wxRootDir, "build", "msw")) @@ -381,12 +381,12 @@ def main(wxDir, args): flags["wxUSE_UNICODE"] = "1" if VERSION < (2,9): flags["wxUSE_UNICODE_MSLU"] = "1" - + if options.cairo: if not os.environ.get("CAIRO_ROOT"): print("WARNING: Expected CAIRO_ROOT set in the environment!") flags["wxUSE_CAIRO"] = "1" - + if options.wxpython: flags["wxDIALOG_UNIT_COMPATIBILITY "] = "0" flags["wxUSE_DEBUGREPORT"] = "0" @@ -401,27 +401,27 @@ def main(wxDir, args): # Remove this when Windows XP finally dies, or when there is a # solution for ticket #13116... flags["wxUSE_COMPILER_TLS"] = "0" - + if VERSION < (2,9): flags["wxUSE_DIB_FOR_BITMAP"] = "1" if VERSION >= (2,9): flags["wxUSE_UIACTIONSIMULATOR"] = "1" - + mswIncludeDir = os.path.join(wxRootDir, "include", "wx", "msw") setup0File = os.path.join(mswIncludeDir, "setup0.h") with open(setup0File, "rb") as f: setupText = f.read() if PY3: setupText = setupText.decode('utf-8') - + for flag in flags: setupText, subsMade = re.subn(flag + "\s+?\d", "%s %s" % (flag, flags[flag]), setupText) if subsMade == 0: print("Flag %s wasn't found in setup0.h!" % flag) sys.exit(1) - + with open(os.path.join(mswIncludeDir, "setup.h"), "wb") as f: if PY3: setupText = setupText.encode('utf-8') @@ -435,7 +435,7 @@ def main(wxDir, args): args.append("UNICODE=1") if VERSION < (2,9): args.append("MSLU=1") - + if options.wxpython: args.append("OFFICIAL_BUILD=1") args.append("COMPILER_VERSION=%s" % getVisCVersion()) @@ -443,12 +443,12 @@ def main(wxDir, args): args.append("MONOLITHIC=0") args.append("USE_OPENGL=1") args.append("USE_GDIPLUS=1") - + if not options.debug: args.append("BUILD=release") else: args.append("BUILD=debug") - + if options.shared: args.append("SHARED=1") @@ -456,61 +456,61 @@ def main(wxDir, args): args.append( "CPPFLAGS=/I%s" % os.path.join(os.environ.get("CAIRO_ROOT", ""), 'include\\cairo')) - + if options.jom: nmakeCommand = 'jom.exe' - + wxBuilder = builder.MSVCBuilder(commandName=nmakeCommand) - + if toolkit == "msvcProject": args = [] if options.shared or options.wxpython: args.append("wx_dll.dsw") else: args.append("wx.dsw") - + # TODO: wxBuilder = builder.MSVCProjectBuilder() - - + + if not wxBuilder: print("Builder not available for your specified platform/compiler.") sys.exit(1) - + if options.clean: print("Performing cleanup.") wxBuilder.clean(dir=buildDir, options=args) - + sys.exit(0) if options.extra_make: args.append(options.extra_make) - + if not sys.platform.startswith("win"): args.append("--jobs=" + options.jobs) exitIfError(wxBuilder.build(dir=buildDir, options=args), "Error building") - + if options.install: extra=None if installDir: extra = ['DESTDIR='+installDir] - wxBuilder.install(dir=buildDir, options=extra) - + wxBuilder.install(dir=buildDir, options=extra) + if options.install and options.mac_framework: - + def renameLibrary(libname, frameworkname): reallib = libname links = [] while os.path.islink(reallib): links.append(reallib) reallib = "lib/" + os.readlink(reallib) - + #print("reallib is %s" % reallib) run("mv -f %s lib/%s.dylib" % (reallib, frameworkname)) - + for link in links: run("ln -s -f %s.dylib %s" % (frameworkname, link)) - + frameworkRootDir = prefixDir if installDir: print("installDir = %s" % installDir) @@ -525,7 +525,7 @@ def main(wxDir, args): version_full = getoutput("bin/wx-config --version") basename = getoutput("bin/wx-config --basename") configname = getoutput("bin/wx-config --selected-config") - + os.makedirs("Resources") wxplist = dict( CFBundleDevelopmentRegion="English", @@ -539,26 +539,26 @@ def main(wxDir, args): CFBundleShortVersionString=version_full, CFBundleInfoDictionaryVersion="6.0", ) - + import plistlib plistlib.writePlist(wxplist, os.path.join(frameworkRootDir, "Resources", "Info.plist")) - + # we make wx the "actual" library file and link to it from libwhatever.dylib # so that things can link to wx and survive minor version changes renameLibrary("lib/lib%s-%s.dylib" % (basename, version), fwname) run("ln -s -f lib/%s.dylib %s" % (fwname, fwname)) - + run("ln -s -f include Headers") - - for lib in ["GL", "STC", "Gizmos", "Gizmos_xrc"]: + + for lib in ["GL", "STC", "Gizmos", "Gizmos_xrc"]: libfile = "lib/lib%s_%s-%s.dylib" % (basename, lib.lower(), version) if os.path.exists(libfile): frameworkDir = "framework/wx%s/%s" % (lib, version) if not os.path.exists(frameworkDir): os.makedirs(frameworkDir) renameLibrary(libfile, "wx" + lib) - run("ln -s -f ../../../%s %s/wx%s" % (libfile, frameworkDir, lib)) - + run("ln -s -f ../../../%s %s/wx%s" % (libfile, frameworkDir, lib)) + for lib in glob.glob("lib/*.dylib"): if not os.path.islink(lib): corelibname = "lib/lib%s-%s.0.dylib" % (basename, version) @@ -566,8 +566,8 @@ def main(wxDir, args): run("install_name_tool -change %s %s %s" % (os.path.join(frameworkRootDir, corelibname), os.path.join(prefixDir, corelibname), lib)) os.chdir("include") - - header_template = """ + + header_template = """ #ifndef __WX_FRAMEWORK_HEADER__ #define __WX_FRAMEWORK_HEADER__ @@ -579,42 +579,42 @@ def main(wxDir, args): header_dir = "wx-%s/wx" % version for include in glob.glob(header_dir + "/*.h"): headers += "#include \n" - + framework_header = open("%s.h" % fwname, "w") framework_header.write(header_template % headers) framework_header.close() - + run("ln -s -f %s wx" % header_dir) os.chdir("wx-%s/wx" % version) run("ln -s -f ../../../lib/wx/include/%s/wx/setup.h setup.h" % configname) - + os.chdir(os.path.join(frameworkRootDir, "..")) run("ln -s -f %s Current" % getWxRelease()) os.chdir("..") run("ln -s -f Versions/Current/Headers Headers") run("ln -s -f Versions/Current/Resources Resources") run("ln -s -f Versions/Current/%s %s" % (fwname, fwname)) - + # sanity check to ensure the symlink works os.chdir("Versions/Current") - + # put info about the framework into wx-config os.chdir(frameworkRootDir) text = file('lib/wx/config/%s' % configname).read() text = text.replace("MAC_FRAMEWORK=", "MAC_FRAMEWORK=%s" % getFrameworkName(options)) if options.mac_framework_prefix not in ['/Library/Frameworks', '/System/Library/Frameworks']: - text = text.replace("MAC_FRAMEWORK_PREFIX=", + text = text.replace("MAC_FRAMEWORK_PREFIX=", "MAC_FRAMEWORK_PREFIX=%s" % options.mac_framework_prefix) file('lib/wx/config/%s' % configname, 'w').write(text) - + # The framework is finished! - print("wxWidgets framework created at: " + - os.path.join( installDir, + print("wxWidgets framework created at: " + + os.path.join( installDir, options.mac_framework_prefix, '%s.framework' % fwname)) - - + + # adjust the install_name if needed if sys.platform.startswith("darwin") and \ options.install and \ @@ -633,7 +633,7 @@ def main(wxDir, args): if os.path.exists(options.mac_distdir): shutil.rmtree(options.mac_distdir) - + packagedir = os.path.join(options.mac_distdir, "packages") os.makedirs(packagedir) basename = os.path.basename(prefixDir.split(".")[0]) @@ -648,14 +648,13 @@ def main(wxDir, args): cmd = packageMakerPath + ' '.join(args) print("cmd = %s" % cmd) run(cmd) - + os.chdir(options.mac_distdir) - + run('hdiutil create -srcfolder %s -volname "%s" -imagekey zlib-level=9 %s.dmg' % (packagedir, packageName, packageName)) - + shutil.rmtree(packagedir) - + if __name__ == '__main__': exitWithException = False # use sys.exit instead main(sys.argv[0], sys.argv[1:]) - diff --git a/buildtools/builder.py b/buildtools/builder.py index 22a30469..cbc45d6b 100644 --- a/buildtools/builder.py +++ b/buildtools/builder.py @@ -69,7 +69,7 @@ class Builder: for dir in dirs: if os.path.isfile(os.path.join(dir, self.name)): - return True + return True else: result = os.system("which %s" % self.name) @@ -93,7 +93,7 @@ class Builder: if projectFile: result.append(projectFile) return result - + def clean(self, dir=None, projectFile=None, options=[]): """ dir = the directory containing the project file @@ -125,7 +125,7 @@ class Builder: # Important Note: if extending args, check it first! # NoneTypes are not iterable and will crash the clean, build, or install! # Very very irritating when this happens right at the end. - if options: + if options: args.extend(options) result = runInDir(args, dir) return result @@ -179,7 +179,7 @@ class AutoconfBuilder(GNUMakeBuilder): if configdir == parentdir: break - configdir = parentdir + configdir = parentdir else: configure_cmd = config_cmd break @@ -211,10 +211,10 @@ class MSVCBuilder(Builder): result = [] if projectFile: result.extend(['-f', projectFile]) - + return result - + class MSVCProjectBuilder(Builder): def __init__(self): Builder.__init__(self, commandName="VCExpress.exe", formatName="msvcProject") diff --git a/buildtools/config.py b/buildtools/config.py index 560eb607..14e72b57 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -34,7 +34,7 @@ runSilently = False #---------------------------------------------------------------------- class Configuration(object): - + ##SIP = SIPdefault # Where is the sip binary? SIPINC = 'sip/siplib' # Use our local copy of sip.h SIPGEN = 'sip/gen' # Where the generated .sip files go @@ -67,10 +67,10 @@ class Configuration(object): # 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 @@ -83,18 +83,18 @@ class Configuration(object): 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, noWxConfig=False): self.CLEANUP = list() - + self.resetVersion() - + # change the PORT default for wxMac if sys.platform[:6] == "darwin": self.WXPORT = 'osx_cocoa' @@ -111,7 +111,7 @@ class Configuration(object): self.WXPLAT2 = None self.WXDIR = wxDir() - + self.includes = [phoenixDir() + '/sip/siplib', # to get our version of sip.h phoenixDir() + '/src', # for any hand-written headers ] @@ -126,22 +126,22 @@ class Configuration(object): '-I', os.path.join(phoenixDir(), 'src'), '-I', os.path.join(phoenixDir(), 'sip', 'gen'), ]) - + if noWxConfig: # this is as far as we go for now return # otherwise do the rest of it self.finishSetup() - - + + def finishSetup(self, wx_config=None, debug=None): if wx_config is not None: self.WX_CONFIG = wx_config if debug is not None: self.debug = debug - + #--------------------------------------- # MSW specific settings if os.name == 'nt' and self.COMPILER == 'msvc': @@ -149,18 +149,18 @@ class Configuration(object): # from the wxWidgets makefiles for MSVC, other compilers settings # will probably vary... self.WXPLAT = '__WXMSW__' - + if os.environ.get('CPU', None) in ['AMD64', 'X64']: self.VCDLL = 'vc%s_x64_dll' % getVisCVersion() else: self.VCDLL = 'vc%s_dll' % getVisCVersion() - + self.includes += ['include', opj(self.WXDIR, 'lib', self.VCDLL, 'msw' + self.libFlag()), opj(self.WXDIR, 'include'), opj(self.WXDIR, 'contrib', 'include'), ] - + self.defines = [ ('WIN32', None), ('_WINDOWS', None), (self.WXPLAT, None), @@ -168,45 +168,45 @@ class Configuration(object): ('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' + self.WXDLLVER + self.libFlag(), + self.libs += [ 'wxbase' + self.WXDLLVER + self.libFlag(), 'wxbase' + self.WXDLLVER + self.libFlag() + '_net', self.makeLibName('core')[0], ] - + self.libs += ['kernel32', 'user32', 'gdi32', 'comdlg32', 'winspool', 'winmm', 'shell32', 'oldnames', 'comctl32', 'odbc32', 'ole32', 'oleaut32', 'uuid', 'rpcrt4', 'advapi32', 'wsock32'] - + self.cflags = [ '/UNDEBUG', '/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'] - self.defines = [ #('NDEBUG',), # using a 1-tuple makes it do an undef + 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: @@ -214,11 +214,11 @@ class Configuration(object): 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') @@ -228,13 +228,13 @@ class Configuration(object): # 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 == "": for arch in self.ARCH.split(','): @@ -242,11 +242,11 @@ class Configuration(object): self.cflags.append(arch) self.lflags.append("-arch") self.lflags.append(arch) - + if not os.environ.get('CC') or not os.environ.get('CXX'): self.CC = os.environ["CC"] = self.getWxConfigValue('--cc') self.CXX = os.environ["CXX"] = self.getWxConfigValue('--cxx') - + # We want to use the linker command from wx to make sure # we get the right sysroot, but we also need to ensure that # the other linker flags that distutils wants to use are @@ -261,14 +261,14 @@ class Configuration(object): # Strip this argument and the next one: del LDSHARED[index:index+2] except ValueError: - break + break LDSHARED = ' '.join(LDSHARED) # Combine with wx's ld command and stash it in the env # where distutils will get it later. LDSHARED = self.getWxConfigValue('--ld').replace(' -o', '') + ' ' + LDSHARED os.environ["LDSHARED"] = LDSHARED - - + + # wxGTK settings else: # Set flags for other Unix type platforms @@ -293,23 +293,23 @@ class Configuration(object): 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) self.cflags.insert(0, '-UNDEBUG') - + if self.debug and self.WXPORT == 'msw' and self.COMPILER != 'mingw32': self.defines.append( ('_DEBUG', None) ) @@ -322,11 +322,11 @@ class Configuration(object): if val: name = name+'='+val self.wafDefines.append(name) - + # --------------------------------------------------------------- # Helper functions - + def resetVersion(self): # load the version numbers into this instance's namespace versionfile = opj(os.path.split(__file__)[0], 'version.py') @@ -340,15 +340,15 @@ class Configuration(object): f = open('REV.txt') self.VER_FLAGS += f.read().strip() f.close() - - self.VERSION = "%s.%s.%s%s" % (self.VER_MAJOR, - self.VER_MINOR, + + self.VERSION = "%s.%s.%s%s" % (self.VER_MAJOR, + self.VER_MINOR, self.VER_RELEASE, self.VER_FLAGS) - + self.WXDLLVER = '%d%d' % (self.VER_MAJOR, self.VER_MINOR) - - + + def parseCmdLine(self): self.debug = '--debug' in sys.argv or '-g' in sys.argv @@ -439,12 +439,12 @@ class Configuration(object): else: # TODO: Python3 version using os.walk generator return [] - - + + 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 @@ -454,12 +454,12 @@ class Configuration(object): 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: @@ -469,8 +469,8 @@ class Configuration(object): srcdir, [os.path.basename(f) for f in glob.glob(opj(srcdir, '*'))]) return file_list - - + + def makeLibName(self, name, checkMonolithic=False, isMSWBase=False): if checkMonolithic and self.MONOLITHIC: return [] @@ -482,8 +482,8 @@ class Configuration(object): else: libname = 'wx%s%s%s' % (basename, self.WXDLLVER, self.libFlag()) return [libname] - - + + def libFlag(self): if not self.debug: rv = '' @@ -493,18 +493,18 @@ class Configuration(object): 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': + if lflags[0][:2] != '-L': dirs = libdirs + ['/usr/lib', '/usr/local/lib'] else: dirs = libdirs @@ -516,10 +516,10 @@ class Configuration(object): 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 @@ -540,9 +540,9 @@ class Configuration(object): 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 @@ -557,9 +557,9 @@ class Configuration(object): else: newLFLAGS.append(flag) return newLFLAGS - - + + # We'll use a factory function so we can use the Configuration class as a singleton _config = None @@ -577,7 +577,7 @@ def msg(text): if not runSilently: print(text) - + def opj(*args): path = os.path.join(*args) return os.path.normpath(path) @@ -606,7 +606,7 @@ def loadETG(name): self.__dict__['__name__'] = 'namespace' def nsdict(self): return self.__dict__ - + ns = _Namespace() myExecfile(name, ns.nsdict()) return ns @@ -618,7 +618,7 @@ def etg2sip(etgfile): sipfile = posixjoin(cfg.SIPGEN, sipfile) return sipfile - + def _getSbfValue(etg, keyName): cfg = Config() @@ -649,8 +649,8 @@ def findCmd(cmd): if os.path.exists(c): return c return None - - + + def phoenixDir(): return os.path.abspath(posixjoin(os.path.dirname(__file__), '..')) @@ -679,27 +679,27 @@ def copyFile(src, dest, verbose=False): os.symlink(linkto, dest) else: shutil.copy2(src, dest) - - + + def copyIfNewer(src, dest, verbose=False): if os.path.isdir(dest): dest = os.path.join(dest, os.path.basename(src)) if newer(src, dest): copyFile(src, dest, verbose) - - + + def writeIfChanged(filename, text): """ Check the current contents of filename and only overwrite with text if the content is different (therefore preserving the timestamp if there is no update.) """ - + if os.path.exists(filename): f = textfile_open(filename, 'rt') current = f.read() f.close() - + if current == text: return @@ -713,14 +713,14 @@ def macFixDependencyInstallName(destdir, prefix, extension, buildDir): print("**** macFixDependencyInstallName(%s, %s, %s, %s)" % (destdir, prefix, extension, buildDir)) pwd = os.getcwd() os.chdir(destdir+prefix+'/lib') - dylibs = glob.glob('*.dylib') + dylibs = glob.glob('*.dylib') for lib in dylibs: #cmd = 'install_name_tool -change %s/lib/%s %s/lib/%s %s' % \ # (destdir+prefix,lib, prefix,lib, extension) cmd = 'install_name_tool -change %s/lib/%s %s/lib/%s %s' % \ (buildDir,lib, prefix,lib, extension) print(cmd) - os.system(cmd) + os.system(cmd) os.chdir(pwd) @@ -741,7 +741,7 @@ def macSetLoaderNames(filenames): newName = '@loader_path/' + os.path.basename(curName) cmd = 'install_name_tool -change %s %s %s' % (curName, newName, filename) os.system(cmd) - + def getVcsRev(): # Some helpers for the code below @@ -749,10 +749,10 @@ def getVcsRev(): import datetime now = datetime.datetime.now() return "%d%02d%02d.%02d%02d" % (now.year, now.month, now.day, now.hour, now.minute) - + def _getSvnRevision(): if not os.path.exists('.svn'): - return None + return None svnrev = None try: rev = runcmd('svnversion', getOutput=True, echoCmd=False) @@ -760,7 +760,7 @@ def getVcsRev(): return None svnrev = rev.split(':')[0] return svnrev - + def _getGitRevision(): try: revcount = runcmd('git rev-list --count HEAD', getOutput=True, echoCmd=False) @@ -768,7 +768,7 @@ def getVcsRev(): except: return None return "{}+{}".format(revcount, revhash) - + # Try getting the revision number from SVN, or GIT, or just fall back # to the date. svnrev = _getSvnRevision() @@ -804,7 +804,7 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True): if getOutput: otherKwArgs = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - + sp = subprocess.Popen(cmd, shell=True, env=os.environ, **otherKwArgs) output = None @@ -814,7 +814,7 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True): if sys.version_info > (3,): output = output.decode(outputEncoding) output = output.rstrip() - + rval = sp.wait() if rval: # Failed! @@ -824,10 +824,10 @@ def runcmd(cmd, getOutput=False, echoCmd=True, fatal=True): print(output) if fatal: sys.exit(rval) - + return output - - + + def myExecfile(filename, ns): if sys.version_info < (3,): execfile(filename, ns) @@ -835,7 +835,7 @@ def myExecfile(filename, ns): with open(filename, 'r') as f: exec(f.read(), ns) - + def textfile_open(filename, mode='rt'): """ Simple wrapper around open() that will use codecs.open on Python2 and @@ -862,9 +862,9 @@ def getSipFiles(names): if os.path.exists(name): files.append(name) return files - - + + def getVisCVersion(): text = runcmd("cl.exe", getOutput=True, echoCmd=False) if 'Version 13' in text: @@ -873,12 +873,14 @@ def getVisCVersion(): return '90' if 'Version 16' in text: return '100' + if 'Version 18' in text: + return '120' if 'Version 19' in text: return '140' # TODO: Add more tests to get the other versions... else: return 'FIXME' - + _haveObjDump = None def canGetSOName(): @@ -892,7 +894,7 @@ def getSOName(filename): output = runcmd('objdump -p %s' % filename, True) result = re.search('^\s+SONAME\s+(.+)$', output, re.MULTILINE) if result: - return result.group(1) + return result.group(1) return None diff --git a/buildtools/distutils_hacks.py b/buildtools/distutils_hacks.py index e747cf2b..97e688a1 100644 --- a/buildtools/distutils_hacks.py +++ b/buildtools/distutils_hacks.py @@ -46,7 +46,7 @@ class wx_extra_clean(distutils.command.clean.clean): from distutils.filelist import FileList distutils.command.clean.clean.run(self) - + cfg = Config() if self.all: fl = FileList() @@ -136,8 +136,8 @@ class wx_install_headers(distutils.command.install_headers.install_headers): - - + + #---------------------------------------------------------------------- # These functions and class are copied from distutils in Python 2.5 # and then grafted back into the distutils modules so we can change @@ -157,7 +157,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args): 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. - + I've further modified our copy of this function to check if there is a -isysroot flag in the CC/CXX values in the environment. If so then we want to make sure that we keep that one and strip the others, instead of @@ -165,7 +165,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args): """ ccHasSysroot = '-isysroot' in os.environ.get('CC', '') \ or '-isysroot' in os.environ.get('CXX', '') - + stripArch = stripSysroot = 0 compiler_so = list(compiler_so) @@ -201,7 +201,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args): except ValueError: break - # Check if the SDK that is used during compilation actually exists, + # 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 @@ -235,7 +235,7 @@ class MyUnixCCompiler(distutils.unixccompiler.UnixCCompiler): extra_postargs) except DistutilsExecError as msg: raise CompileError(msg) - + _orig_parse_makefile = distutils.sysconfig.parse_makefile def _parse_makefile(filename, g=None): rv = _orig_parse_makefile(filename, g) @@ -265,15 +265,15 @@ _orig_setup_compile = distutils.ccompiler.CCompiler._setup_compile def _setup_compile(self, outdir, macros, incdirs, sources, depends, extra): macros, objects, extra, pp_opts, build = \ _orig_setup_compile(self, outdir, macros, incdirs, sources, depends, extra) - + # Remove items from the build collection that don't need to be built # because their obj file is newer than the source fle and any other # dependencies. for obj in objects: src, ext = build[obj] if not newer_group([src] + depends, obj): - del build[obj] - return macros, objects, extra, pp_opts, build + del build[obj] + return macros, objects, extra, pp_opts, build distutils.ccompiler.CCompiler._setup_compile = _setup_compile @@ -327,7 +327,7 @@ if os.name == 'nt' and sys.version_info >= (2,6): #---------------------------------------------------------------------- - + from .sipdistutils import build_ext @@ -339,20 +339,20 @@ class etgsip_build_ext(build_ext): 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 - - + return cfg.SIPOUT + + def build_extension(self, extension): """ Modify the dependency list, adding the sip files generated @@ -367,7 +367,7 @@ class etgsip_build_ext(build_ext): # 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 @@ -379,13 +379,13 @@ class etgsip_build_ext(build_ext): 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 = etg2sip(etg) - + deps = [etg] ns = loadETG(etg) if hasattr(ns, 'OTHERDEPS'): @@ -398,14 +398,14 @@ class etgsip_build_ext(build_ext): 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) - - + + def _sip_compile(self, sip_bin, source, sbf): cfg = Config() - + other_opts = [] base = os.path.basename(source) if base.startswith('_'): @@ -413,9 +413,8 @@ class etgsip_build_ext(build_ext): pycode = posixjoin(cfg.PKGDIR, pycode) other_opts = ['-X', 'pycode:'+pycode] self.spawn([sip_bin] + self.sip_opts + - other_opts + + other_opts + ["-c", self._sip_output_dir(), "-b", sbf, "-I", self._sip_sipfiles_dir(), source]) - diff --git a/buildtools/sipdistutils.py b/buildtools/sipdistutils.py index 9c4ade00..c1cf9418 100644 --- a/buildtools/sipdistutils.py +++ b/buildtools/sipdistutils.py @@ -79,7 +79,7 @@ class build_ext (build_ext_base): def _sip_output_dir(self): return self.build_temp - + def build_extension (self, ext): oldforce = self.force @@ -148,4 +148,3 @@ class build_ext (build_ext_base): "-b", sbf, "-I", self._sip_sipfiles_dir(), source]) - diff --git a/buildtools/version.py b/buildtools/version.py index 58d613d0..640a3835 100644 --- a/buildtools/version.py +++ b/buildtools/version.py @@ -18,11 +18,11 @@ VER_RELEASE = 3 # wxPython RELEASE number for the given wxWidgets VER_FLAGS = "" # wxPython release flags -# The VER_FLAGS value is appended to the version number constructed from first -# 3 components and should be set according to the following patterns. These -# should help us to better follow the PEP-0440 notions of version numbers, -# where public version identifiers are supposed to conform to the following -# scheme: +# The VER_FLAGS value is appended to the version number constructed from the +# first 3 components and should be set according to the following patterns. +# These should help us to better follow the PEP-0440 notions of version +# numbers, where public version identifiers are supposed to conform to the +# following scheme: # # [N!]N(.N)*[{a|b|rc}N][.postN][.devN] # diff --git a/setup.py b/setup.py index 90c16770..580457cf 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ try: except ImportError: haveWheel = False -from buildtools.config import Config, msg, opj, runcmd, canGetSOName, getSOName +from buildtools.config import Config, msg, opj, runcmd, canGetSOName, getSOName #---------------------------------------------------------------------- @@ -85,30 +85,30 @@ class wx_build(orig_build): ('skip-build', None, 'skip building the C/C++ code (assumes it has already been done)'), ] boolean_options = ['skip-build'] - - + + def initialize_options(self): orig_build.initialize_options(self) self.skip_build = '--skip-build' in sys.argv - + def finalize_options(self): orig_build.finalize_options(self) self.build_lib = self.build_platlib - - def run(self): + + def run(self): if not self.skip_build: # Run build.py to do the actual building of the extension modules msg('WARNING: Building this way assumes that all generated files have been \n' 'generated already. If that is not the case then use build.py directly \n' 'to generate the source and perform the build stage. You can use \n' '--skip-build with the bdist_* or install commands to avoid this \n' - 'message and the wxWidgets and Phoenix build steps in the future.\n') - + 'message and the wxWidgets and Phoenix build steps in the future.\n') + # Use the same Python that is running this script. cmd = ['"{}"'.format(sys.executable), '-u', 'build.py', 'build'] cmd = ' '.join(cmd) runcmd(cmd) - + # Let distutils handle building up the package folder under the # build/lib folder like normal. orig_build.run(self) @@ -120,20 +120,20 @@ def _cleanup_symlinks(cmd): # The links are not really needed since the extensions link to the # specific soname, and they could bloat the egg too much if they were # left in. - # - # TODO: can eggs have post-install scripts that would allow us to + # + # TODO: can eggs have post-install scripts that would allow us to # restore the links? No. # build_lib = cmd.get_finalized_command('build').build_lib build_lib = opj(build_lib, 'wx') for libname in glob.glob(opj(build_lib, 'libwx*')): - + if os.path.islink(libname): if isDarwin: # On Mac the name used by the extension module is the real # file, so we can just get rid of all the links. os.unlink(libname) - + elif canGetSOName(): # On linux the soname used in the extension modules may # be (probably is) one of the symlinks, so we have to be @@ -151,12 +151,12 @@ def _cleanup_symlinks(cmd): # Otherwise just leave the symlink there since we don't # know what to do with it. pass - - + + class wx_bdist_egg(orig_bdist_egg): def finalize_options(self): orig_bdist_egg.finalize_options(self) - + # Redo the calculation of the egg's filename since we always have # extension modules, but they are not built by setuptools so it # doesn't know about them. @@ -169,16 +169,16 @@ class wx_bdist_egg(orig_bdist_egg): ).egg_name() self.egg_output = os.path.join(self.dist_dir, basename+'.egg') - + def run(self): # Ensure that there is a basic library build for bdist_egg to pull from. self.run_command("build") - + _cleanup_symlinks(self) - + # Run the default bdist_egg command orig_bdist_egg.run(self) - + if haveWheel: class wx_bdist_wheel(orig_bdist_wheel): @@ -191,25 +191,25 @@ if haveWheel: from setuptools.dist import Distribution #Distribution.is_pure = _is_pure Distribution.has_ext_modules = _has_ext_modules - + orig_bdist_wheel.finalize_options(self) def run(self): # Ensure that there is a basic library build for bdist_egg to pull from. self.run_command("build") - + _cleanup_symlinks(self) - + # Run the default bdist_wheel command orig_bdist_wheel.run(self) - + class wx_install(orig_install): def finalize_options(self): orig_install.finalize_options(self) self.install_lib = self.install_platlib - + def run(self): self.run_command("build") orig_install.run(self) @@ -222,7 +222,7 @@ class wx_sdist(orig_sdist): cmd = ['"{}"'.format(sys.executable), '-u', 'build.py', 'sdist'] cmd = ' '.join(cmd) runcmd(cmd) - + # Put the filename in dist_files in case the upload command is used. # On the other hand, PyPI's upload size limit is waaaaaaaaay too # small so it probably doesn't matter too much... @@ -230,7 +230,7 @@ class wx_sdist(orig_sdist): self.distribution.dist_files.append(('sdist', '', sdist_file)) - + # Map these new classes to the appropriate distutils command names. CMDCLASS = { @@ -272,8 +272,8 @@ def wx_copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0, import distutils.file_util orig_copy_file = distutils.file_util.copy_file distutils.file_util.copy_file = wx_copy_file - - + + def wx_copy_tree(src, dst, preserve_mode=1, preserve_times=1, preserve_symlinks=0, update=0, verbose=1, dry_run=0): @@ -294,18 +294,18 @@ cfg = Config(noWxConfig=True) WX_PKGLIST = [cfg.PKGDIR] + [cfg.PKGDIR + '.' + pkg for pkg in find_packages('wx')] ENTRY_POINTS = { - 'console_scripts' : [ + 'console_scripts' : [ "img2png = wx.tools.img2png:main", "img2py = wx.tools.img2py:main", "img2xpm = wx.tools.img2xpm:main", "pywxrc = wx.tools.pywxrc:main", # ], -# 'gui_scripts' : [ +# 'gui_scripts' : [ "helpviewer = wx.tools.helpviewer:main", "pycrust = wx.py.PyCrust:main", "pyshell = wx.py.PyShell:main", "pyslices = wx.py.PySlices:main", - "pyslicesshell = wx.py.PySlicesShell:main", + "pyslicesshell = wx.py.PySlicesShell:main", ], } @@ -317,12 +317,12 @@ BUILD_OPTIONS = { } #'build_base' : cfg.BUILD_BASE } #if cfg.WXPORT == 'msw': # BUILD_OPTIONS[ 'compiler' ] = cfg.COMPILER - + #---------------------------------------------------------------------- - + if __name__ == '__main__': - setup(name = NAME, + setup(name = NAME, version = cfg.VERSION, description = DESCRIPTION, long_description = LONG_DESCRIPTION, @@ -338,7 +338,7 @@ if __name__ == '__main__': zip_safe = False, use_2to3 = False, include_package_data = True, - + packages = WX_PKGLIST, ext_package = cfg.PKGDIR, diff --git a/wscript b/wscript index 0aa06e43..63985c05 100644 --- a/wscript +++ b/wscript @@ -34,7 +34,7 @@ def options(opt): opt.load('python') opt.add_option('--debug', dest='debug', action='store_true', default=False, - help='Turn on debug compile options.') + help='Turn on debug compile options.') opt.add_option('--python', dest='python', default='', action='store', help='Full path to the Python executable to use.') opt.add_option('--wx_config', dest='wx_config', default='wx-config', action='store', @@ -64,8 +64,8 @@ def options(opt): -def configure(conf): - if isWindows: +def configure(conf): + if isWindows: # For now simply choose the compiler version based on the Python # version. We have a chicken-egg problem here. The compiler needs to # be selected before the Python stuff can be configured, but we need @@ -85,7 +85,7 @@ def configure(conf): if isWindows: # Search for the Python headers without doing some stuff that could # iccorectly fail on Windows. See my_check_python_headers below. - conf.my_check_python_headers() + conf.my_check_python_headers() else: conf.check_python_headers() @@ -165,7 +165,7 @@ def configure(conf): lst[1:1] = ['/Z7'] conf.env['LINKFLAGS_PYEXT'].append('/DEBUG') - else: + else: # Configuration stuff for non-Windows ports using wx-config conf.env.CFLAGS_WX = list() conf.env.CXXFLAGS_WX = list() @@ -178,49 +178,49 @@ def configure(conf): # Check wx-config exists and fetch some values from it rpath = ' --no-rpath' if not conf.options.no_magic else '' - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs core,net' + rpath, uselib_store='WX', mandatory=True) # Run it again with different libs options to get different # sets of flags stored to use with varous extension modules below. - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs adv,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs adv,core,net' + rpath, uselib_store='WXADV', mandatory=True) libname = '' if cfg.MONOLITHIC else 'stc,' # workaround bug in wx-config - conf.check_cfg(path=conf.options.wx_config, package='', - args=('--cxxflags --libs %score,net' % libname) + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args=('--cxxflags --libs %score,net' % libname) + rpath, uselib_store='WXSTC', mandatory=True) - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs html,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs html,core,net' + rpath, uselib_store='WXHTML', mandatory=True) - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs gl,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs gl,core,net' + rpath, uselib_store='WXGL', mandatory=True) - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs webview,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs webview,core,net' + rpath, uselib_store='WXWEBVIEW', mandatory=True) if isDarwin: - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs core,net' + rpath, uselib_store='WXWEBKIT', mandatory=True) - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs xml,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs xml,core,net' + rpath, uselib_store='WXXML', mandatory=True) - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs xrc,xml,core,net' + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs xrc,xml,core,net' + rpath, uselib_store='WXXRC', mandatory=True) libname = '' if cfg.MONOLITHIC else 'richtext,' # workaround bug in wx-config - conf.check_cfg(path=conf.options.wx_config, package='', - args='--cxxflags --libs %score,net' % libname + rpath, + conf.check_cfg(path=conf.options.wx_config, package='', + args='--cxxflags --libs %score,net' % libname + rpath, uselib_store='WXRICHTEXT', mandatory=True) conf.check_cfg(path=conf.options.wx_config, package='', @@ -283,10 +283,10 @@ def configure(conf): # Some Mac-specific stuff if isDarwin: - conf.env.MACOSX_DEPLOYMENT_TARGET = "10.5" + conf.env.MACOSX_DEPLOYMENT_TARGET = "10.5" if conf.options.mac_arch: - conf.env.ARCH_WXPY = conf.options.mac_arch.split(',') + conf.env.ARCH_WXPY = conf.options.mac_arch.split(',') #import pprint #pprint.pprint( [(k, conf.env[k]) for k in conf.env.keys()] ) @@ -356,35 +356,35 @@ def my_check_python_headers(conf): conf.env.append_value('LIB_PYEMBED', [libname]) conf.env['LIBPATH_PYEXT'] = conf.env['LIBPATH_PYEMBED'] conf.env['LIB_PYEXT'] = conf.env['LIB_PYEMBED'] - + else: result = None for name in ('python' + env['PYTHON_VERSION'], 'python' + env['PYTHON_VERSION'].replace('.', '')): - + # LIBPATH_PYEMBED is already set; see if it works. if not result and env['LIBPATH_PYEMBED']: path = env['LIBPATH_PYEMBED'] conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) - + if not result and dct['LIBDIR']: path = [dct['LIBDIR']] conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) - + if not result and dct['LIBPL']: path = [dct['LIBPL']] conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) - + if not result: path = [os.path.join(dct['prefix'], "libs")] conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) - + if result: break # do not forget to set LIBPATH_PYEMBED - + if result: env['LIBPATH_PYEMBED'] = path env.append_value('LIB_PYEMBED', [name]) @@ -484,7 +484,7 @@ def build(bld): "# This file was generated by Phoenix's wscript.\n\n" "VERSION_STRING = '%(VERSION)s'\n" % cfg.__dict__) - + # copy the wx locale message catalogs to the package dir if isWindows or isDarwin: @@ -509,7 +509,7 @@ def build(bld): 'sip/siplib/voidptr.c', ], uselib = 'WX WXPY', - ) + ) makeExtCopyRule(bld, 'siplib') # Add build rules for each of our ETG generated extension modules @@ -569,11 +569,11 @@ def makeExtCopyRule(bld, name): # This is the task function to be called by the above rule. -def copyFileToPkg(task): +def copyFileToPkg(task): from distutils.file_util import copy_file from buildtools.config import opj - src = task.inputs[0].abspath() - tgt = task.outputs[0].abspath() + src = task.inputs[0].abspath() + tgt = task.outputs[0].abspath() open(tgt, "wb").close() # essentially just a unix 'touch' command tgt = opj(cfg.PKGDIR, os.path.basename(src)) copy_file(src, tgt, verbose=1)