From: <md...@us...> - 2007-07-31 18:42:46
|
Revision: 3646 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3646&view=rev Author: mdboom Date: 2007-07-31 11:42:39 -0700 (Tue, 31 Jul 2007) Log Message: ----------- Refactor distutils script to display information about the extensions being built. Use pkg-config to find freetype if possible. Modified Paths: -------------- trunk/matplotlib/setup.cfg trunk/matplotlib/setup.py trunk/matplotlib/setupext.py Modified: trunk/matplotlib/setup.cfg =================================================================== --- trunk/matplotlib/setup.cfg 2007-07-31 14:05:01 UTC (rev 3645) +++ trunk/matplotlib/setup.cfg 2007-07-31 18:42:39 UTC (rev 3646) @@ -1,2 +1,7 @@ [egg_info] tag_svn_revision = 1 + +[status] +# To suppress display of the dependencies and their versions +# at the top of the build log, uncomment the following line: +# suppress = 1 \ No newline at end of file Modified: trunk/matplotlib/setup.py =================================================================== --- trunk/matplotlib/setup.py 2007-07-31 14:05:01 UTC (rev 3645) +++ trunk/matplotlib/setup.py 2007-07-31 18:42:39 UTC (rev 3646) @@ -35,7 +35,7 @@ # build wxPython extension code to efficiently blit agg into wx. Only # needed for wxpython <2.8 if you plan on doing animations -BUILD_WXAGG = 0 +BUILD_WXAGG = 1 # build a small extension to manage the focus on win32 platforms. @@ -71,18 +71,57 @@ setuptools requirement, you must delete the old matplotlib install directory.""") +if major==2 and minor1<3 or major<2: + raise SystemExit("""matplotlib requires Python 2.3 or later.""") + import glob from distutils.core import setup from setupext import build_agg, build_gtkagg, build_tkagg, build_wxagg,\ build_ft2font, build_image, build_windowing, build_transforms, \ build_contour, build_nxutils, build_enthought, build_swigagg, build_gdk, \ - build_subprocess, build_ttconv + build_subprocess, build_ttconv, print_line, print_status, print_message, \ + print_raw, check_for_freetype, check_for_libpng, check_for_gtk, check_for_tk, \ + check_for_wx, check_for_numpy, check_for_qt, check_for_qt4, check_for_cairo #import distutils.sysconfig +# jdh +packages = [ + 'matplotlib', + 'matplotlib.backends', + 'matplotlib.toolkits', + 'matplotlib.numerix', + 'matplotlib.numerix.mlab', + 'matplotlib.numerix.ma', + 'matplotlib.numerix.npyma', + 'matplotlib.numerix.linear_algebra', + 'matplotlib.numerix.random_array', + 'matplotlib.numerix.fft', + 'matplotlib.config' + ] + +ext_modules = [] + +# these are not optional +BUILD_FT2FONT = 1 +BUILD_TTCONV = 1 +BUILD_CONTOUR = 1 +BUILD_NXUTILS = 1 + for line in file('lib/matplotlib/__init__.py').readlines(): - if line[:11] == '__version__': + if (line.startswith('__version__') or + line.startswith('__revision__') or + line.startswith('__date__')): exec(line.strip()) +print_line() +print_raw("BUILDING MATPLOTLIB") +print_status('matplotlib', '%s (r%s)' % (__version__, __revision__.split()[-2])) +print_status('platform', sys.platform) +if sys.platform == 'win32': + print_status('Windows version', sys.getwindowsversion()) +print_raw("") +print_raw("REQUIRED DEPENDENCIES") + # Specify all the required mpl data package_data = {'matplotlib':['mpl-data/fonts/afm/*.afm', 'mpl-data/fonts/pdfcorefonts/*.afm', @@ -98,43 +137,19 @@ 'backends/Matplotlib.nib/*', ]} +if not check_for_numpy(): + sys.exit() + # The NUMERIX variable (a list) is left over from the days when it had # a string for each of the supported backends. Now there is only one # supported backend, so this approach could (should?) get changed for # simplicity. -try: - import numpy - NUMERIX = ['numpy'] -except ImportError: - raise RuntimeError("You must install numpy to build matplotlib") +import numpy +NUMERIX = ['numpy'] rc['numerix'] = NUMERIX[-1] -ext_modules = [] - -# these are not optional -BUILD_FT2FONT = 1 -BUILD_TTCONV = 1 -BUILD_CONTOUR = 1 -BUILD_NXUTILS = 1 - -# jdh -packages = [ - 'matplotlib', - 'matplotlib.backends', - 'matplotlib.toolkits', - 'matplotlib.numerix', - 'matplotlib.numerix.mlab', - 'matplotlib.numerix.ma', - 'matplotlib.numerix.npyma', - 'matplotlib.numerix.linear_algebra', - 'matplotlib.numerix.random_array', - 'matplotlib.numerix.fft', - 'matplotlib.config' - ] - - try: import subprocess except ImportError: havesubprocess = False else: havesubprocess = True @@ -146,12 +161,28 @@ subprocess_dir = os.path.dirname(subprocess.__file__) if subprocess_dir.endswith('.egg/subprocess'): havesubprocess = False - + if not havesubprocess: packages.append('subprocess') if sys.platform == 'win32': build_subprocess(ext_modules, packages) +if not check_for_freetype(): + sys.exit(1) + +if BUILD_FT2FONT: + build_ft2font(ext_modules, packages) + +if BUILD_TTCONV: + build_ttconv(ext_modules, packages) + +if 1: # I don't think we need to make these optional + build_contour(ext_modules, packages) + build_nxutils(ext_modules, packages) + +print_raw("") +print_raw("OPTIONAL DEPENDENCIES") + try: import datetime except ImportError: havedate = False else: havedate = True @@ -174,115 +205,70 @@ add_dateutil() else: # only add them if we need them - try: import dateutil - except ImportError: - add_dateutil() - try: import pytz + try: + import pytz except ImportError: add_pytz() + try: + import dateutil + except ImportError: + add_dateutil() + build_swigagg(ext_modules, packages) build_transforms(ext_modules, packages) build_enthought(ext_modules, packages) -def havegtk(): - 'check for the presence of pygtk' - if havegtk.gotit is not None: return havegtk.gotit - try: - import gtk - except ImportError: - print 'building for GTK requires pygtk; you must be able to "import gtk" in your build/install environment' - havegtk.gotit = False - except RuntimeError: - print 'pygtk present but import failed' - havegtk.gotit = False - else: - version = (2,2,0) - if gtk.pygtk_version < version: - print "Error: GTK backend requires PyGTK %d.%d.%d (or later), " \ - "%d.%d.%d was detected." % ( - version + gtk.pygtk_version) - havegtk.gotit = False - else: - havegtk.gotit = True - return havegtk.gotit +if check_for_gtk() and (BUILD_GTK or BUILD_GTKAGG): + if BUILD_GTK: + build_gdk(ext_modules, packages) + rc['backend'] = 'GTK' + if BUILD_GTKAGG: + BUILD_AGG = 1 + build_gtkagg(ext_modules, packages) + rc['backend'] = 'GTKAgg' -havegtk.gotit = None - -if BUILD_GTK and havegtk(): - build_gdk(ext_modules, packages) - rc['backend'] = 'GTK' - -if BUILD_GTKAGG and havegtk(): +if check_for_tk() and BUILD_TKAGG: BUILD_AGG = 1 - build_gtkagg(ext_modules, packages) - rc['backend'] = 'GTKAgg' + build_tkagg(ext_modules, packages) + rc['backend'] = 'TkAgg' -if BUILD_TKAGG: - try: - import Tkinter - except ImportError: - print 'TKAgg requires TkInter' - BUILD_TKAGG = 0 - except RuntimeError: - print 'Tkinter present but import failed' - BUILD_TKAGG = 0 +explanation = None +if check_for_wx() and BUILD_WXAGG: + BUILD_AGG = 1 + import wx + if wx.__version__ < (2.8): + build_wxagg(ext_modules, packages) + wxagg_backend_status = "yes" else: - try: - tk = Tkinter.Tk() - tk.withdraw() - except Tkinter.TclError: - print 'Tkinter present, but window failed to open' - BUILD_TKAGG = 0 - else: - BUILD_AGG = 1 - build_tkagg(ext_modules, packages) - rc['backend'] = 'TkAgg' + print_message("WxAgg extension not required for wxPython < 2.8") + rc['backend'] = 'WXAgg' -if BUILD_WXAGG: - try: - import wx - except ImportError: - if BUILD_WXAGG != 'auto': - print 'WXAgg\'s accelerator requires wxPython' - BUILD_WXAGG = 0 - else: - if getattr(wx, '__version__', '0.0')[0:3] < '2.8': - BUILD_AGG = 1 - build_wxagg(ext_modules, packages, - not (isinstance(BUILD_WXAGG, str) # don't abort if BUILD_WXAGG - and BUILD_WXAGG.lower() == 'auto')) # is "auto" - rc['backend'] = 'WXAgg' - -if BUILD_AGG: +# These are informational only. We don't build +# any extensions for them. +check_for_qt() +check_for_qt4() +check_for_cairo() + +if check_for_libpng() and BUILD_AGG: build_agg(ext_modules, packages) if rc['backend'] == 'PS': rc['backend'] = 'Agg' - - -if BUILD_FT2FONT: - build_ft2font(ext_modules, packages) - -if BUILD_TTCONV: - build_ttconv(ext_modules, packages) - if BUILD_WINDOWING and sys.platform=='win32': build_windowing(ext_modules, packages) if BUILD_IMAGE: build_image(ext_modules, packages) -if 1: # I don't think we need to make these optional - build_contour(ext_modules, packages) - build_nxutils(ext_modules, packages) - for mod in ext_modules: if VERBOSE: mod.extra_compile_args.append('-DVERBOSE') +print_raw("") +print_raw("[Edit setup.cfg to suppress the above messages]") +print_line() - # packagers: set rc['numerix'] and rc['backend'] here to override the auto # defaults, eg #rc['numerix'] = numpy Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2007-07-31 14:05:01 UTC (rev 3645) +++ trunk/matplotlib/setupext.py 2007-07-31 18:42:39 UTC (rev 3646) @@ -60,8 +60,12 @@ } import sys, os, stat +import commands +from sets import Set +from textwrap import fill from distutils.core import Extension import glob +import ConfigParser major, minor1, minor2, s, tmp = sys.version_info if major<2 or (major==2 and minor1<3): @@ -81,7 +85,7 @@ BUILT_WINDOWING = False BUILT_CONTOUR = False BUILT_NXUTILS = False -BUILT_ENTHOUGHT = False +BUILT_ENTHOUGHT = False BUILT_CONTOUR = False BUILT_GDK = False @@ -90,6 +94,42 @@ # for nonstandard installation/build with --prefix variable numpy_inc_dirs = [] +# Based on the contents of setup.cfg, determine if the status block +# should be displayed +display_status = True +if os.path.exists("setup.cfg"): + config = ConfigParser.SafeConfigParser() + config.read("setup.cfg") + try: + if config.get("status", "suppress"): + display_status = False + except: + pass + +if display_status: + def print_line(char='='): + print char * 76 + + def print_status(package, status): + initial_indent = "%22s: " % package + indent = ' ' * 24 + print fill(status, width=76, + initial_indent=initial_indent, + subsequent_indent=indent) + + def print_message(message): + indent = ' ' * 24 + "* " + print fill(message, width=76, + initial_indent=indent, + subsequent_indent=indent) + + def print_raw(section): + print section +else: + def print_line(*args, **kwargs): + pass + print_status = print_message = print_raw = print_line + class CleanUpFile: """CleanUpFile deletes the specified filename when self is destroyed.""" def __init__(self, name): @@ -123,8 +163,99 @@ else: std_libs = ['stdc++', 'm'] +def has_pkgconfig(): + if has_pkgconfig.cache is not None: + return has_pkgconfig.cache + if sys.platform == 'win32': + has_pkgconfig.cache = False + else: + status, output = commands.getstatusoutput("pkg-config --help") + has_pkgconfig.cache = (status == 0) + return has_pkgconfig.cache +has_pkgconfig.cache = None + +def get_pkgconfig(module, + packages, + flags="--libs --cflags", + pkg_config_exec='pkg-config'): + """Loosely based on an article in the Python Cookbook: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/502261""" + if not has_pkgconfig(): + return False + + _flags = {'-I': 'include_dirs', + '-L': 'library_dirs', + '-l': 'libraries', + '-D': 'define_macros', + '-U': 'undef_macros'} + + status, output = commands.getstatusoutput( + "%s %s %s" % (pkg_config_exec, flags, packages)) + if status == 0: + for token in output.split(): + attr = _flags.get(token[:2], None) + if attr is not None: + set = getattr(module, attr) + if token[2:] not in set: + set.append(token[2:]) + else: + if token not in module.extra_link_args: + module.extra_link_args.append(token) + return True + return False + +def get_pkgconfig_version(package): + default = "unknown (no pkg-config)" + if not has_pkgconfig(): + return default + + status, output = commands.getstatusoutput( + "pkg-config %s --modversion" % (package)) + if status == 0: + return output + return default + +def try_pkgconfig(module, package, fallback): + if not get_pkgconfig(module, package): + module.libraries.append(fallback) + +def find_include_file(include_dirs, filename): + for d in include_dirs: + if os.path.exists(os.path.join(d, filename)): + return True + return False + +def check_for_freetype(): + module = Extension('test', []) + add_base_flags(module) + if not get_pkgconfig(module, 'freetype2'): + basedirs = module.include_dirs[:] # copy the list to avoid inf loop! + for d in basedirs: + module.include_dirs.append(os.path.join(d, 'freetype2')) + + if not find_include_file(module.include_dirs, 'ft2build.h'): + print_message( + "Could not find 'freetype2' headers in any of %s" % + ", ".join(["'%s'" % x for x in module.include_dirs])) + return False + + print_status("freetype2", get_pkgconfig_version('freetype2')) + return True + +def check_for_libpng(): + module = Extension("test", []) + get_pkgconfig(module, 'libpng') + add_base_flags(module) + if not find_include_file(module.include_dirs, 'png.h'): + print_message( + ", ".join("Could not find 'libpng' headers in any of %s" % + ["'%s'" % x for x in module.include_dirs])) + return False + + print_status("libpng", get_pkgconfig_version('libpng')) + return True + def add_base_flags(module): - incdirs = filter(os.path.exists, [os.path.join(p, 'include') for p in basedir[sys.platform] ]) libdirs = filter(os.path.exists, @@ -141,6 +272,57 @@ ret = os.popen(s).read().strip() return ret +def check_for_qt(): + try: + import pyqtconfig + except ImportError: + print_status("Qt", "no") + return False + else: + print_status("Qt", "Qt: %s, pyqt: %s" % + (pyqtconfig.Configuration().pyqt_version_str, + pyqtconfig.Configuration().qt_version)) + return True + +def check_for_qt4(): + try: + import PyQt4.pyqtconfig + except ImportError: + print_status("Qt4", "no") + return False + else: + print_status("Qt4", "Qt: %s, pyqt: %s" % + (PyQt4.pyqtconfig.Configuration().pyqt_version_str, + PyQt4.pyqtconfig.Configuration().qt_version)) + return True + +def check_for_cairo(): + try: + import cairo + except ImportError: + print_status("Cairo", "no") + return False + else: + print_status("Cairo", cairo.version) + +def check_for_numpy(): + gotit = False + try: + import numpy + except ImportError: + print_status("numpy", "no") + print_message("You must install numpy to build matplotlib.") + return False + module = Extension('test', []) + add_numpy_flags(module) + add_base_flags(module) + if not find_include_file(module.include_dirs, os.path.join("numpy", "arrayobject.h")): + print_status("numpy", "no") + print_message("Could not find the headers for numpy. You may need to install the development package.") + return False + print_status("numpy", numpy.__version__) + return True + def add_numpy_flags(module): "Add the modules flags to build extensions which use numpy" import numpy @@ -154,13 +336,11 @@ 'Add the module flags to build extensions which use agg' # before adding the freetype flags since -z comes later - module.libraries.append('png') + try_pkgconfig(module, 'libpng', 'png') module.libraries.append('z') add_base_flags(module) module.include_dirs.extend(['src','swig', '%s/include'%AGG_VERSION, '.']) - - # put these later for correct link order module.libraries.extend(std_libs) @@ -168,24 +348,26 @@ 'Add the module flags to build extensions which use gd' module.libraries.append('gd') - def add_ft2font_flags(module): - 'Add the module flags to build extensions which use gd' - module.libraries.extend(['freetype', 'z' ]) + 'Add the module flags to ft2font extension' + module.libraries.append('z') add_base_flags(module) - basedirs = module.include_dirs[:] # copy the list to avoid inf loop! - for d in basedirs: - module.include_dirs.append(os.path.join(d, 'freetype2')) - p = os.path.join(d, 'lib/freetype2/include') - if os.path.exists(p): module.include_dirs.append(p) - p = os.path.join(d, 'lib/freetype2/include/freetype2') - if os.path.exists(p): module.include_dirs.append(p) + if not get_pkgconfig(module, 'freetype2'): + module.libraries.append('freetype') + + basedirs = module.include_dirs[:] # copy the list to avoid inf loop! + for d in basedirs: + module.include_dirs.append(os.path.join(d, 'freetype2')) + p = os.path.join(d, 'lib/freetype2/include') + if os.path.exists(p): module.include_dirs.append(p) + p = os.path.join(d, 'lib/freetype2/include/freetype2') + if os.path.exists(p): module.include_dirs.append(p) - basedirs = module.library_dirs[:] # copy the list to avoid inf loop! - for d in basedirs: - p = os.path.join(d, 'freetype2/lib') - if os.path.exists(p): module.library_dirs.append(p) + basedirs = module.library_dirs[:] # copy the list to avoid inf loop! + for d in basedirs: + p = os.path.join(d, 'freetype2/lib') + if os.path.exists(p): module.library_dirs.append(p) if sys.platform == 'win32' and win32_compiler == 'mingw32': module.libraries.append('gw32c') @@ -193,8 +375,48 @@ # put this last for library link order module.libraries.extend(std_libs) +def check_for_gtk(): + 'check for the presence of pygtk' + gotit = False + explanation = None + try: + import gtk + except ImportError: + explanation = 'Building for Gtk+ requires pygtk; you must be able to "import gtk" in your build/install environment' + except RuntimeError: + explanation = 'pygtk present but import failed' + else: + version = (2,2,0) + if gtk.pygtk_version < version: + explanation = "Error: GTK backend requires PyGTK %d.%d.%d (or later), " \ + "%d.%d.%d was detected." % ( + version + gtk.pygtk_version) + else: + gotit = True + if gotit: + module = Extension('test', []) + add_pygtk_flags(module) + if not find_include_file(module.include_dirs, os.path.join("gtk", "gtk.h")): + explanation = ( + "Could not find Gtk+ headers in any of %s" % + ", ".join(["'%s'" % x for x in module.include_dirs])) + gotit = False + def ver2str(tup): + return ".".join([str(x) for x in tup]) + + if gotit: + import gobject + print_status("Gtk+", "gtk+: %s, glib: %s, pygtk: %s, pygobject: %s" % + (ver2str(gtk.gtk_version), ver2str(gobject.glib_version), + ver2str(gtk.pygtk_version), ver2str(gobject.pygobject_version))) + else: + print_status("Gtk+", "no") + print_message(explanation) + + return gotit + def add_pygtk_flags(module): 'Add the module flags to build extensions which use gtk' @@ -220,36 +442,61 @@ add_base_flags(module) - # set for msvc compiler if not present - if not os.environ.has_key('PKG_CONFIG_PATH'): - os.environ['PKG_CONFIG_PATH'] = 'C:\GTK\lib\pkgconfig' + if sys.platform != 'win32': + # If Gtk+ is installed, pkg-config is required to be installed + get_pkgconfig(module, 'pygtk-2.0 gtk+-2.0') - pygtkIncludes = getoutput('pkg-config --cflags-only-I pygtk-2.0').split() - gtkIncludes = getoutput('pkg-config --cflags-only-I gtk+-2.0').split() - includes = pygtkIncludes + gtkIncludes - module.include_dirs.extend([include[2:] for include in includes]) + # visual studio doesn't need the math library + if sys.platform == 'win32' and win32_compiler == 'msvc' and 'm' in module.libraries: + module.libraries.remove('m') - pygtkLinker = getoutput('pkg-config --libs pygtk-2.0').split() - gtkLinker = getoutput('pkg-config --libs gtk+-2.0').split() - linkerFlags = pygtkLinker + gtkLinker - module.libraries.extend( - [flag[2:] for flag in linkerFlags if flag.startswith('-l')]) +def check_for_wx(): + gotit = False + explanation = None + try: + import wx + except ImportError: + explanation = 'wxPython not found' + else: + if sys.platform == 'win32' and win32_compiler == 'mingw32': + explanation = "The wxAgg extension can not be built using the mingw32 compiler on Windows, since the default wxPython binary is built using MS Visual Studio" + else: + wxconfig = find_wx_config() + if wxconfig is None: + explanation = """ +WXAgg's accelerator requires `wx-config'. +The `wx-config\' executable could not be located in any directory of the +PATH environment variable. If you want to build WXAgg, and wx-config is +in some other location or has some other name, set the WX_CONFIG +environment variable to the full path of the executable like so: - module.library_dirs.extend( - [flag[2:] for flag in linkerFlags if flag.startswith('-L')]) +export WX_CONFIG=/usr/lib/wxPython-2.6.1.0-gtk2-unicode/bin/wx-config +""" + elif not check_wxpython_broken_macosx104_version(wxconfig): + explanation = 'WXAgg\'s accelerator not building because a broken wxPython (installed by Apple\'s Mac OS X) was found.' + else: + gotit = True + if gotit: + module = Extension("test", []) + add_wx_flags(module, wxconfig) + if not find_include_file( + module.include_dirs, + os.path.join("wx", "wxPython", "wxPython.h")): + explanation = ("Could not find wxPython headers in any of %s" % + ", ".join(["'%s'" % x for x in module.include_dirs])) + gotit = False - module.extra_link_args.extend( - [flag for flag in linkerFlags if not - (flag.startswith('-l') or flag.startswith('-L'))]) - - # visual studio doesn't need the math library - if sys.platform == 'win32' and win32_compiler == 'msvc' and 'm' in module.libraries: - module.libraries.remove('m') - - + if gotit: + print_status("wxPython", wx.__version__) + else: + print_status("wxPython", "no") + if explanation is not None: + print_message(explanation) + return gotit + def find_wx_config(): """If the WX_CONFIG environment variable has been set, returns it value. Otherwise, search for `wx-config' in the PATH directories and return the @@ -268,24 +515,6 @@ return None - -def check_wxpython_headers(wxconfig): - """Determines if wxPython.h can be found in one of the wxWidgets include - directories. - """ - - flags = getoutput(wxconfig + ' --cppflags').split() - incdirs = [os.path.join(p, 'include') for p in basedir[sys.platform] - if os.path.exists(p)] - - incdirs += [x[2:] for x in flags if x.startswith('-I')] - header = os.path.join('wx', 'wxPython', 'wxPython.h') - - for d in incdirs: - if os.path.exists(os.path.join(d, header)): - return True - return False - def check_wxpython_broken_macosx104_version(wxconfig): """Determines if we're using a broken wxPython installed by Mac OS X 10.4""" if sys.platform == 'darwin': @@ -308,31 +537,8 @@ module.libraries.extend(wxlibs) return - def getWX(fmt, *args): - return getoutput(wxconfig + ' ' + (fmt % args)).split() + get_pkgconfig(module, '', flags='--cppflags --libs', pkg_config_exec='wx-config') - wxFlags = getWX('--cppflags') - wxLibs = getWX('--libs') - - - add_base_flags(module) - module.include_dirs.extend( - [x[2:] for x in wxFlags if x.startswith('-I')]) - - - module.define_macros.extend( - [(x[2:], None) for x in wxFlags if x.startswith('-D')]) - module.undef_macros.extend( - [x[2:] for x in wxFlags if x.startswith('-U')]) - - module.libraries.extend( - [x[2:] for x in wxLibs if x.startswith('-l')]) - module.library_dirs.extend( - [x[2:] for x in wxLibs if x.startswith('-L')]) - module.extra_link_args.extend( - [x for x in wxLibs if not (x.startswith('-l') or x.startswith('-L'))]) - - # Make sure you use the Tk version given by Tkinter.TkVersion # or else you'll build for a wrong version of the Tcl # interpreter (leading to nasty segfaults). @@ -342,21 +548,12 @@ def find_tcltk(): """Finds Tcl/Tk includes/libraries/version by interrogating Tkinter.""" - try: - import Tkinter - except: - print "Tkinter not properly installed\n" - sys.exit(1) - if Tkinter.TkVersion < 8.3: - print "Tcl/Tk v8.3 or later required\n" - sys.exit(1) + # By this point, we already know that Tkinter imports correctly + import Tkinter o = FoundTclTk() try: tk=Tkinter.Tk() except Tkinter.TclError: - print "Using default library and include directories for Tcl and Tk because a" - print "Tk window failed to open. You may need to define DISPLAY for Tk to work" - print "so that setup can determine where your libraries are located." o.tcl_lib = "/usr/local/lib" o.tcl_inc = "/usr/local/include" o.tk_lib = "/usr/local/lib" @@ -389,24 +586,60 @@ os.path.exists('/usr/include/tk.h')): o.tcl_inc = '/usr/include/' o.tk_inc = '/usr/include/' - - if not os.path.exists(o.tcl_inc): - print 'cannot find tcl/tk headers. giving up.' - sys.exit() return o +def check_for_tk(): + gotit = False + explanation = None + try: + import Tkinter + except ImportError: + explanation = 'TKAgg requires Tkinter' + except RuntimeError: + explanation = 'Tkinter present but import failed' + else: + if Tkinter.TkVersion < 8.3: + explanation = "Tcl/Tk v8.3 or later required\n" + sys.exit(1) + else: + try: + tk = Tkinter.Tk() + tk.withdraw() + except Tkinter.TclError: + explanation = """\ +Using default library and include directories for Tcl and Tk because a +Tk window failed to open. You may need to define DISPLAY for Tk to work +so that setup can determine where your libraries are located.""" + gotit = True + if gotit: + module = Extension('test', []) + try: + add_tk_flags(module) + except RuntimeError, e: + explanation = str(e) + gotit = False + if not find_include_file(module.include_dirs, "tk.h"): + explanation = 'Tkinter present, but header files are not installed. You may need to install development packages.' + gotit = False + + if gotit: + print_status("Tkinter", "Tkinter: %s, Tk: %s, Tcl: %s" % + (Tkinter.__version__.split()[-2], Tkinter.TkVersion, Tkinter.TclVersion)) + else: + print_status("Tkinter", "no") + if explanation is not None: + print_message(explanation) + return gotit + def add_tk_flags(module): 'Add the module flags to build extensions which use tk' if sys.platform=='win32': major, minor1, minor2, s, tmp = sys.version_info - print 'building tkagg', major, minor1 if major==2 and minor1 in [3, 4, 5]: - print '\tBuilding for python2%d'%minor1 module.include_dirs.extend(['win32_static/include/tcl84']) module.libraries.extend(['tk84', 'tcl84']) elif major==2 and minor1==2: - print '\tBuilding for python22' module.include_dirs.extend(['win32_static/include/tcl83']) module.libraries.extend(['tk83', 'tcl83']) else: @@ -503,7 +736,10 @@ def build_ttconv(ext_modules, packages): global BUILT_TTCONV if BUILT_TTCONV: return # only build it if you you haven't already - deps = ['src/_ttconv.cpp', 'ttconv/pprdrv_tt.cpp', 'ttconv/pprdrv_tt2.cpp', 'ttconv/ttutil.cpp'] + deps = ['src/_ttconv.cpp', + 'ttconv/pprdrv_tt.cpp', + 'ttconv/pprdrv_tt2.cpp', + 'ttconv/ttutil.cpp'] deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) @@ -523,11 +759,9 @@ deps, ) - # add agg flags before pygtk because agg only supports freetype1 # and pygtk includes freetype2. This is a bit fragile. - add_agg_flags(module) add_ft2font_flags(module) add_pygtk_flags(module) @@ -557,62 +791,11 @@ BUILT_TKAGG = True -def build_wxagg(ext_modules, packages, abortOnFailure): +def build_wxagg(ext_modules, packages): global BUILT_WXAGG if BUILT_WXAGG: return - wxconfig = find_wx_config() - - # Avoid aborting the whole build process if `wx-config' can't be found and - # BUILD_WXAGG in setup.py is set to "auto" - if sys.platform == 'win32': - # mingw32 cannot link against distributed wx libs - # since they are built with VisualStudio - if win32_compiler == 'mingw32': - return - else: - pass - - elif wxconfig is None: - print """ -WXAgg's accelerator requires `wx-config'. - -The `wx-config\' executable could not be located in any directory of the -PATH environment variable. If you want to build WXAgg, and wx-config is -in some other location or has some other name, set the WX_CONFIG -environment variable to the full path of the executable like so: - -export WX_CONFIG=/usr/lib/wxPython-2.6.1.0-gtk2-unicode/bin/wx-config -""" - if not abortOnFailure: - print """Building MPL without wxAgg""" - BUILT_WXAGG = True - return - else: - sys.exit(1) - elif not check_wxpython_headers(wxconfig): - print 'WXAgg\'s accelerator requires the wxPython headers.' - - if not abortOnFailure: - BUILT_WXAGG = True - return - else: - print """ -The wxPython header files could not be located in any of the standard -include -directories or include directories reported by `wx-config --cppflags'.""" - sys.exit(1) - elif not check_wxpython_broken_macosx104_version(wxconfig): - print 'WXAgg\'s accelerator not building because a broken wxPython (installed by Apple\'s Mac OS X) was found.' - if not abortOnFailure: - BUILT_WXAGG = True - return - else: - print """ -The wxPython installation is the broken version installed with Mac OS X 10.4.""" - sys.exit(1) - deps = ['src/_wxagg.cpp', 'src/mplutils.cpp'] deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) @@ -627,8 +810,6 @@ BUILT_WXAGG = True - - def build_agg(ext_modules, packages): global BUILT_AGG if BUILT_AGG: return # only build it if you you haven't already This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |