diff options
Diffstat (limited to 'system_info.py')
-rw-r--r-- | system_info.py | 1864 |
1 files changed, 1864 insertions, 0 deletions
diff --git a/system_info.py b/system_info.py new file mode 100644 index 000000000..08ada4783 --- /dev/null +++ b/system_info.py @@ -0,0 +1,1864 @@ +#!/bin/env python +""" +This file defines a set of system_info classes for getting +information about various resources (libraries, library directories, +include directories, etc.) in the system. Currently, the following +classes are available: + + atlas_info + atlas_threads_info + atlas_blas_info + atlas_blas_threads_info + lapack_atlas_info + blas_info + lapack_info + blas_opt_info # usage recommended + lapack_opt_info # usage recommended + fftw_info,dfftw_info,sfftw_info + fftw_threads_info,dfftw_threads_info,sfftw_threads_info + djbfft_info + x11_info + lapack_src_info + blas_src_info + numpy_info + numarray_info + numpy_info + boost_python_info + agg2_info + wx_info + gdk_pixbuf_xlib_2_info + gdk_pixbuf_2_info + gdk_x11_2_info + gtkp_x11_2_info + gtkp_2_info + xft_info + freetype2_info + umfpack_info + +Usage: + info_dict = get_info(<name>) + where <name> is a string 'atlas','x11','fftw','lapack','blas', + 'lapack_src', 'blas_src', etc. For a complete list of allowed names, + see the definition of get_info() function below. + + Returned info_dict is a dictionary which is compatible with + distutils.setup keyword arguments. If info_dict == {}, then the + asked resource is not available (system_info could not find it). + + Several *_info classes specify an environment variable to specify + the locations of software. When setting the corresponding environment + variable to 'None' then the software will be ignored, even when it + is available in system. + +Global parameters: + system_info.search_static_first - search static libraries (.a) + in precedence to shared ones (.so, .sl) if enabled. + system_info.verbosity - output the results to stdout if enabled. + +The file 'site.cfg' is looked for in + +1) Directory of main setup.py file being run. +2) Home directory of user running the setup.py file (Not implemented yet) +3) System wide directory (location of this file...) + +The first one found is used to get system configuration options The +format is that used by ConfigParser (i.e., Windows .INI style). The +section DEFAULT has options that are the default for each section. The +available sections are fftw, atlas, and x11. Appropiate defaults are +used if nothing is specified. + +The order of finding the locations of resources is the following: + 1. environment variable + 2. section in site.cfg + 3. DEFAULT section in site.cfg +Only the first complete match is returned. + +Example: +---------- +[DEFAULT] +library_dirs = /usr/lib:/usr/local/lib:/opt/lib +include_dirs = /usr/include:/usr/local/include:/opt/include +src_dirs = /usr/local/src:/opt/src +# search static libraries (.a) in preference to shared ones (.so) +search_static_first = 0 + +[fftw] +fftw_libs = rfftw, fftw +fftw_opt_libs = rfftw_threaded, fftw_threaded +# if the above aren't found, look for {s,d}fftw_libs and {s,d}fftw_opt_libs + +[atlas] +library_dirs = /usr/lib/3dnow:/usr/lib/3dnow/atlas +# for overriding the names of the atlas libraries +atlas_libs = lapack, f77blas, cblas, atlas + +[x11] +library_dirs = /usr/X11R6/lib +include_dirs = /usr/X11R6/include +---------- + +Authors: + Pearu Peterson <pearu@cens.ioc.ee>, February 2002 + David M. Cooke <cookedm@physics.mcmaster.ca>, April 2002 + +Copyright 2002 Pearu Peterson all rights reserved, +Pearu Peterson <pearu@cens.ioc.ee> +Permission to use, modify, and distribute this software is given under the +terms of the SciPy (BSD style) license. See LICENSE.txt that came with +this distribution for specifics. + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +""" + +import sys +import os +import re +import copy +import warnings +from glob import glob +import ConfigParser + +from distutils.errors import DistutilsError +from distutils.dist import Distribution +import distutils.sysconfig +from distutils import log + +from numpy.distutils.exec_command import \ + find_executable, exec_command, get_pythonexe +from numpy.distutils.misc_util import is_sequence, is_string +from numpy.distutils.command.config import config as cmd_config + +if sys.platform == 'win32': + default_lib_dirs = ['C:\\', + os.path.join(distutils.sysconfig.EXEC_PREFIX, + 'libs')] + default_include_dirs = [] + default_src_dirs = ['.'] + default_x11_lib_dirs = [] + default_x11_include_dirs = [] +else: + default_lib_dirs = ['/usr/local/lib', '/opt/lib', '/usr/lib', + '/opt/local/lib', '/sw/lib'] + default_include_dirs = ['/usr/local/include', + '/opt/include', '/usr/include', + '/opt/local/include', '/sw/include'] + default_src_dirs = ['.','/usr/local/src', '/opt/src','/sw/src'] + default_x11_lib_dirs = ['/usr/X11R6/lib','/usr/X11/lib','/usr/lib'] + default_x11_include_dirs = ['/usr/X11R6/include','/usr/X11/include', + '/usr/include'] + +if os.path.join(sys.prefix, 'lib') not in default_lib_dirs: + default_lib_dirs.insert(0,os.path.join(sys.prefix, 'lib')) + default_include_dirs.append(os.path.join(sys.prefix, 'include')) + default_src_dirs.append(os.path.join(sys.prefix, 'src')) + +default_lib_dirs = filter(os.path.isdir, default_lib_dirs) +default_include_dirs = filter(os.path.isdir, default_include_dirs) +default_src_dirs = filter(os.path.isdir, default_src_dirs) + +so_ext = distutils.sysconfig.get_config_vars('SO')[0] or '' + +def get_standard_file(fname): + """Returns a list of files named 'fname' from + 1) System-wide directory (directory-location of this module) + 2) Users HOME directory (os.environ['HOME']) + 3) Local directory + """ + # System-wide file + filenames = [] + try: + f = __file__ + except NameError: + f = sys.argv[0] + else: + sysfile = os.path.join(os.path.split(os.path.abspath(f))[0], + fname) + if os.path.isfile(sysfile): + filenames.append(sysfile) + + # Home directory + # And look for the user config file + try: + f = os.environ['HOME'] + except KeyError: + pass + else: + user_file = os.path.join(f, fname) + if os.path.isfile(user_file): + filenames.append(user_file) + + # Local file + if os.path.isfile(fname): + filenames.append(os.path.abspath(fname)) + + return filenames + +def get_info(name,notfound_action=0): + """ + notfound_action: + 0 - do nothing + 1 - display warning message + 2 - raise error + """ + cl = {'atlas':atlas_info, # use lapack_opt or blas_opt instead + 'atlas_threads':atlas_threads_info, # ditto + 'atlas_blas':atlas_blas_info, + 'atlas_blas_threads':atlas_blas_threads_info, + 'lapack_atlas':lapack_atlas_info, # use lapack_opt instead + 'lapack_atlas_threads':lapack_atlas_threads_info, # ditto + 'mkl':mkl_info, + 'lapack_mkl':lapack_mkl_info, # use lapack_opt instead + 'blas_mkl':blas_mkl_info, # use blas_opt instead + 'x11':x11_info, + 'fft_opt':fft_opt_info, + 'fftw':fftw_info, + 'fftw2':fftw2_info, + 'fftw3':fftw3_info, + 'dfftw':dfftw_info, + 'sfftw':sfftw_info, + 'fftw_threads':fftw_threads_info, + 'dfftw_threads':dfftw_threads_info, + 'sfftw_threads':sfftw_threads_info, + 'djbfft':djbfft_info, + 'blas':blas_info, # use blas_opt instead + 'lapack':lapack_info, # use lapack_opt instead + 'lapack_src':lapack_src_info, + 'blas_src':blas_src_info, + 'numpy':numpy_info, + 'f2py':f2py_info, + 'Numeric':Numeric_info, + 'numeric':Numeric_info, + 'numarray':numarray_info, + 'numerix':numerix_info, + 'lapack_opt':lapack_opt_info, + 'blas_opt':blas_opt_info, + 'boost_python':boost_python_info, + 'agg2':agg2_info, + 'wx':wx_info, + 'gdk_pixbuf_xlib_2':gdk_pixbuf_xlib_2_info, + 'gdk-pixbuf-xlib-2.0':gdk_pixbuf_xlib_2_info, + 'gdk_pixbuf_2':gdk_pixbuf_2_info, + 'gdk-pixbuf-2.0':gdk_pixbuf_2_info, + 'gdk':gdk_info, + 'gdk_2':gdk_2_info, + 'gdk-2.0':gdk_2_info, + 'gdk_x11_2':gdk_x11_2_info, + 'gdk-x11-2.0':gdk_x11_2_info, + 'gtkp_x11_2':gtkp_x11_2_info, + 'gtk+-x11-2.0':gtkp_x11_2_info, + 'gtkp_2':gtkp_2_info, + 'gtk+-2.0':gtkp_2_info, + 'xft':xft_info, + 'freetype2':freetype2_info, + 'umfpack':umfpack_info, + 'amd':amd_info, + }.get(name.lower(),system_info) + return cl().get_info(notfound_action) + +class NotFoundError(DistutilsError): + """Some third-party program or library is not found.""" + +class AtlasNotFoundError(NotFoundError): + """ + Atlas (http://math-atlas.sourceforge.net/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [atlas]) or by setting + the ATLAS environment variable.""" + +class LapackNotFoundError(NotFoundError): + """ + Lapack (http://www.netlib.org/lapack/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [lapack]) or by setting + the LAPACK environment variable.""" + +class LapackSrcNotFoundError(LapackNotFoundError): + """ + Lapack (http://www.netlib.org/lapack/) sources not found. + Directories to search for the sources can be specified in the + numpy/distutils/site.cfg file (section [lapack_src]) or by setting + the LAPACK_SRC environment variable.""" + +class BlasNotFoundError(NotFoundError): + """ + Blas (http://www.netlib.org/blas/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [blas]) or by setting + the BLAS environment variable.""" + +class BlasSrcNotFoundError(BlasNotFoundError): + """ + Blas (http://www.netlib.org/blas/) sources not found. + Directories to search for the sources can be specified in the + numpy/distutils/site.cfg file (section [blas_src]) or by setting + the BLAS_SRC environment variable.""" + +class FFTWNotFoundError(NotFoundError): + """ + FFTW (http://www.fftw.org/) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [fftw]) or by setting + the FFTW environment variable.""" + +class DJBFFTNotFoundError(NotFoundError): + """ + DJBFFT (http://cr.yp.to/djbfft.html) libraries not found. + Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [djbfft]) or by setting + the DJBFFT environment variable.""" + +class NumericNotFoundError(NotFoundError): + """ + Numeric (http://www.numpy.org/) module not found. + Get it from above location, install it, and retry setup.py.""" + +class X11NotFoundError(NotFoundError): + """X11 libraries not found.""" + +class UmfpackNotFoundError(NotFoundError): + """ + UMFPACK sparse solver (http://www.cise.ufl.edu/research/sparse/umfpack/) + not found. Directories to search for the libraries can be specified in the + numpy/distutils/site.cfg file (section [umfpack]) or by setting + the UMFPACK environment variable.""" + +class system_info: + + """ get_info() is the only public method. Don't use others. + """ + section = 'DEFAULT' + dir_env_var = None + search_static_first = 0 # XXX: disabled by default, may disappear in + # future unless it is proved to be useful. + verbosity = 1 + saved_results = {} + + notfounderror = NotFoundError + + def __init__ (self, + default_lib_dirs=default_lib_dirs, + default_include_dirs=default_include_dirs, + verbosity = 1, + ): + self.__class__.info = {} + self.local_prefixes = [] + defaults = {} + defaults['libraries'] = '' + defaults['library_dirs'] = os.pathsep.join(default_lib_dirs) + defaults['include_dirs'] = os.pathsep.join(default_include_dirs) + defaults['src_dirs'] = os.pathsep.join(default_src_dirs) + defaults['search_static_first'] = str(self.search_static_first) + self.cp = ConfigParser.ConfigParser(defaults) + self.files = get_standard_file('site.cfg') + self.parse_config_files() + self.search_static_first = self.cp.getboolean(self.section, + 'search_static_first') + assert isinstance(self.search_static_first, int) + + def parse_config_files(self): + self.cp.read(self.files) + if not self.cp.has_section(self.section): + self.cp.add_section(self.section) + + def calc_libraries_info(self): + libs = self.get_libraries() + dirs = self.get_lib_dirs() + info = {} + for lib in libs: + i = None + for d in dirs: + i = self.check_libs(d,[lib]) + if i is not None: + break + if i is not None: + dict_append(info,**i) + else: + log.info('Library %s was not found. Ignoring' % (lib)) + return info + + def set_info(self,**info): + if info: + lib_info = self.calc_libraries_info() + dict_append(info,**lib_info) + self.saved_results[self.__class__.__name__] = info + + def has_info(self): + return self.saved_results.has_key(self.__class__.__name__) + + def get_info(self,notfound_action=0): + """ Return a dictonary with items that are compatible + with numpy.distutils.setup keyword arguments. + """ + flag = 0 + if not self.has_info(): + flag = 1 + log.info(self.__class__.__name__ + ':') + if hasattr(self, 'calc_info'): + self.calc_info() + if notfound_action: + if not self.has_info(): + if notfound_action==1: + warnings.warn(self.notfounderror.__doc__) + elif notfound_action==2: + raise self.notfounderror,self.notfounderror.__doc__ + else: + raise ValueError(repr(notfound_action)) + + if not self.has_info(): + log.info(' NOT AVAILABLE') + self.set_info() + else: + log.info(' FOUND:') + + res = self.saved_results.get(self.__class__.__name__) + if self.verbosity>0 and flag: + for k,v in res.items(): + v = str(v) + if k=='sources' and len(v)>200: v = v[:60]+' ...\n... '+v[-60:] + log.info(' %s = %s', k, v) + log.info('') + + return copy.deepcopy(res) + + def get_paths(self, section, key): + dirs = self.cp.get(section, key).split(os.pathsep) + env_var = self.dir_env_var + if env_var: + if is_sequence(env_var): + e0 = env_var[-1] + for e in env_var: + if os.environ.has_key(e): + e0 = e + break + if not env_var[0]==e0: + log.info('Setting %s=%s' % (env_var[0],e0)) + env_var = e0 + if env_var and os.environ.has_key(env_var): + d = os.environ[env_var] + if d=='None': + log.info('Disabled %s: %s',self.__class__.__name__,'(%s is None)' \ + % (env_var,)) + return [] + if os.path.isfile(d): + dirs = [os.path.dirname(d)] + dirs + l = getattr(self,'_lib_names',[]) + if len(l)==1: + b = os.path.basename(d) + b = os.path.splitext(b)[0] + if b[:3]=='lib': + log.info('Replacing _lib_names[0]==%r with %r' \ + % (self._lib_names[0], b[3:])) + self._lib_names[0] = b[3:] + else: + ds = d.split(os.pathsep) + ds2 = [] + for d in ds: + if os.path.isdir(d): + ds2.append(d) + for dd in ['include','lib']: + d1 = os.path.join(d,dd) + if os.path.isdir(d1): + ds2.append(d1) + dirs = ds2 + dirs + default_dirs = self.cp.get('DEFAULT', key).split(os.pathsep) + dirs.extend(default_dirs) + ret = [] + for d in dirs: + if os.path.isdir(d) and d not in ret: + ret.append(d) + log.debug('( %s = %s )', key, ':'.join(ret)) + return ret + + def get_lib_dirs(self, key='library_dirs'): + return self.get_paths(self.section, key) + + def get_include_dirs(self, key='include_dirs'): + return self.get_paths(self.section, key) + + def get_src_dirs(self, key='src_dirs'): + return self.get_paths(self.section, key) + + def get_libs(self, key, default): + try: + libs = self.cp.get(self.section, key) + except ConfigParser.NoOptionError: + if not default: + return [] + if is_string(default): + return [default] + return default + return [b for b in [a.strip() for a in libs.split(',')] if b] + + def get_libraries(self, key='libraries'): + return self.get_libs(key,'') + + def check_libs(self,lib_dir,libs,opt_libs =[]): + """If static or shared libraries are available then return + their info dictionary. + + Checks for all libraries as shared libraries first, then + static (or vice versa if self.search_static_first is True). + """ + if self.search_static_first: + exts = ['.a', so_ext] + else: + exts = [so_ext, '.a'] + if sys.platform == 'cygwin': + exts.append('.dll.a') + info = None + for ext in exts: + info = self._check_libs(lib_dir,libs,opt_libs,[ext]) + if info is not None: + break + if not info: + log.info(' libraries %s not found in %s', ','.join(libs), lib_dir) + return info + + def check_libs2(self, lib_dir, libs, opt_libs =[]): + """If static or shared libraries are available then return + their info dictionary. + + Checks each library for shared or static. + """ + if self.search_static_first: + exts = ['.a', so_ext] + else: + exts = [so_ext, '.a'] + if sys.platform=='cygwin': + exts.append('.dll.a') + info = self._check_libs(lib_dir,libs,opt_libs,exts) + if not info: + log.info(' libraries %s not found in %s', ','.join(libs), lib_dir) + return info + + def _lib_list(self, lib_dir, libs, exts): + assert is_string(lib_dir) + liblist = [] + # for each library name, see if we can find a file for it. + for l in libs: + for ext in exts: + p = self.combine_paths(lib_dir, 'lib'+l+ext) + if p: + assert len(p)==1 + liblist.append(l) + break + return liblist + + def _check_libs(self,lib_dir,libs, opt_libs, exts): + found_libs = self._lib_list(lib_dir, libs, exts) + if len(found_libs) == len(libs): + info = {'libraries' : found_libs, 'library_dirs' : [lib_dir]} + opt_found_libs = self._lib_list(lib_dir, opt_libs, exts) + if len(opt_found_libs) == len(opt_libs): + info['libraries'].extend(opt_found_libs) + return info + else: + return None + + def combine_paths(self,*args): + return combine_paths(*args,**{'verbosity':self.verbosity}) + + +class fft_opt_info(system_info): + + def calc_info(self): + info = {} + fftw_info = get_info('fftw3') or get_info('fftw2') or get_info('dfftw') + djbfft_info = get_info('djbfft') + if fftw_info: + dict_append(info,**fftw_info) + if djbfft_info: + dict_append(info,**djbfft_info) + self.set_info(**info) + return + + +class fftw_info(system_info): + #variables to override + section = 'fftw' + dir_env_var = 'FFTW' + notfounderror = FFTWNotFoundError + ver_info = [ { 'name':'fftw3', + 'libs':['fftw3'], + 'includes':['fftw3.h'], + 'macros':[('SCIPY_FFTW3_H',None)]}, + { 'name':'fftw2', + 'libs':['rfftw', 'fftw'], + 'includes':['fftw.h','rfftw.h'], + 'macros':[('SCIPY_FFTW_H',None)]}] + + def __init__(self): + system_info.__init__(self) + + def calc_ver_info(self,ver_param): + """Returns True on successful version detection, else False""" + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + incl_dir = None + libs = self.get_libs(self.section+'_libs', ver_param['libs']) + info = None + for d in lib_dirs: + r = self.check_libs(d,libs) + if r is not None: + info = r + break + if info is not None: + flag = 0 + for d in incl_dirs: + if len(self.combine_paths(d,ver_param['includes']))==len(ver_param['includes']): + dict_append(info,include_dirs=[d]) + flag = 1 + incl_dirs = [d] + incl_dir = d + break + if flag: + dict_append(info,define_macros=ver_param['macros']) + else: + info = None + if info is not None: + self.set_info(**info) + return True + else: + log.info(' %s not found' % (ver_param['name'])) + return False + + def calc_info(self): + for i in self.ver_info: + if self.calc_ver_info(i): + break + +class fftw2_info(fftw_info): + #variables to override + section = 'fftw' + dir_env_var = 'FFTW' + notfounderror = FFTWNotFoundError + ver_info = [ { 'name':'fftw2', + 'libs':['rfftw', 'fftw'], + 'includes':['fftw.h','rfftw.h'], + 'macros':[('SCIPY_FFTW_H',None)]} + ] + +class fftw3_info(fftw_info): + #variables to override + section = 'fftw3' + dir_env_var = 'FFTW3' + notfounderror = FFTWNotFoundError + ver_info = [ { 'name':'fftw3', + 'libs':['fftw3'], + 'includes':['fftw3.h'], + 'macros':[('SCIPY_FFTW3_H',None)]}, + ] + +class dfftw_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [ { 'name':'dfftw', + 'libs':['drfftw','dfftw'], + 'includes':['dfftw.h','drfftw.h'], + 'macros':[('SCIPY_DFFTW_H',None)]} ] + +class sfftw_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [ { 'name':'sfftw', + 'libs':['srfftw','sfftw'], + 'includes':['sfftw.h','srfftw.h'], + 'macros':[('SCIPY_SFFTW_H',None)]} ] + +class fftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [ { 'name':'fftw threads', + 'libs':['rfftw_threads','fftw_threads'], + 'includes':['fftw_threads.h','rfftw_threads.h'], + 'macros':[('SCIPY_FFTW_THREADS_H',None)]} ] + +class dfftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [ { 'name':'dfftw threads', + 'libs':['drfftw_threads','dfftw_threads'], + 'includes':['dfftw_threads.h','drfftw_threads.h'], + 'macros':[('SCIPY_DFFTW_THREADS_H',None)]} ] + +class sfftw_threads_info(fftw_info): + section = 'fftw' + dir_env_var = 'FFTW' + ver_info = [ { 'name':'sfftw threads', + 'libs':['srfftw_threads','sfftw_threads'], + 'includes':['sfftw_threads.h','srfftw_threads.h'], + 'macros':[('SCIPY_SFFTW_THREADS_H',None)]} ] + +class djbfft_info(system_info): + section = 'djbfft' + dir_env_var = 'DJBFFT' + notfounderror = DJBFFTNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend(self.combine_paths(d,['djbfft'])+[d]) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + info = None + for d in lib_dirs: + p = self.combine_paths (d,['djbfft.a']) + if p: + info = {'extra_objects':p} + break + p = self.combine_paths (d,['libdjbfft.a','libdjbfft'+so_ext]) + if p: + info = {'libraries':['djbfft'],'library_dirs':[d]} + break + if info is None: + return + for d in incl_dirs: + if len(self.combine_paths(d,['fftc8.h','fftfreq.h']))==2: + dict_append(info,include_dirs=[d], + define_macros=[('SCIPY_DJBFFT_H',None)]) + self.set_info(**info) + return + return + +class mkl_info(system_info): + section = 'mkl' + dir_env_var = 'MKL' + _lib_mkl = ['mkl','vml','guide'] + + def get_mkl_rootdir(self): + mklroot = os.environ.get('MKLROOT',None) + if mklroot is not None: + return mklroot + paths = os.environ.get('LD_LIBRARY_PATH','').split(os.pathsep) + ld_so_conf = '/etc/ld.so.conf' + if os.path.isfile(ld_so_conf): + for d in open(ld_so_conf,'r').readlines(): + d = d.strip() + if d: paths.append(d) + intel_mkl_dirs = [] + for path in paths: + path_atoms = path.split(os.sep) + for m in path_atoms: + if m.startswith('mkl'): + d = os.sep.join(path_atoms[:path_atoms.index(m)+2]) + intel_mkl_dirs.append(d) + break + for d in paths: + dirs = glob(os.path.join(d,'mkl','*')) + glob(os.path.join(d,'mkl*')) + for d in dirs: + if os.path.isdir(os.path.join(d,'lib')): + return d + return None + + def __init__(self): + mklroot = self.get_mkl_rootdir() + if mklroot is None: + system_info.__init__(self) + else: + from cpuinfo import cpu + l = 'mkl' # use shared library + if cpu.is_Itanium(): + plt = '64' + #l = 'mkl_ipf' + elif cpu.is_Xeon(): + plt = 'em64t' + #l = 'mkl_em64t' + else: + plt = '32' + #l = 'mkl_ia32' + if l not in self._lib_mkl: + self._lib_mkl.insert(0,l) + system_info.__init__(self, + default_lib_dirs=[os.path.join(mklroot,'lib',plt)], + default_include_dirs=[os.path.join(mklroot,'include')]) + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + incl_dirs = self.get_include_dirs() + mkl_libs = self.get_libs('mkl_libs',self._lib_mkl) + mkl = None + for d in lib_dirs: + mkl = self.check_libs2(d,mkl_libs) + if mkl is not None: + break + if mkl is None: + return + info = {} + dict_append(info,**mkl) + dict_append(info,libraries = ['pthread'], include_dirs = incl_dirs) + self.set_info(**info) + +class lapack_mkl_info(mkl_info): + + def calc_info(self): + mkl = get_info('mkl') + if not mkl: + return + lapack_libs = self.get_libs('lapack_libs',['mkl_lapack32','mkl_lapack64']) + info = {'libraries': lapack_libs} + dict_append(info,**mkl) + self.set_info(**info) + +class blas_mkl_info(mkl_info): + pass + +class atlas_info(system_info): + section = 'atlas' + dir_env_var = 'ATLAS' + _lib_names = ['f77blas','cblas'] + if sys.platform[:7]=='freebsd': + _lib_atlas = ['atlas_r'] + _lib_lapack = ['alapack_r'] + else: + _lib_atlas = ['atlas'] + _lib_lapack = ['lapack'] + + notfounderror = AtlasNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend(self.combine_paths(d,['atlas*','ATLAS*', + 'sse','3dnow','sse2'])+[d]) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + info = {} + atlas_libs = self.get_libs('atlas_libs', + self._lib_names + self._lib_atlas) + lapack_libs = self.get_libs('lapack_libs',self._lib_lapack) + atlas = None + lapack = None + atlas_1 = None + for d in lib_dirs: + atlas = self.check_libs(d,atlas_libs,[]) + lapack_atlas = self.check_libs(d,['lapack_atlas'],[]) + if atlas is not None: + lib_dirs2 = self.combine_paths(d,['atlas*','ATLAS*'])+[d] + for d2 in lib_dirs2: + lapack = self.check_libs(d2,lapack_libs,[]) + if lapack is not None: + break + else: + lapack = None + if lapack is not None: + break + if atlas: + atlas_1 = atlas + log.info(self.__class__) + if atlas is None: + atlas = atlas_1 + if atlas is None: + return + include_dirs = self.get_include_dirs() + h = (self.combine_paths(lib_dirs+include_dirs,'cblas.h') or [None])[0] + if h: + h = os.path.dirname(h) + dict_append(info,include_dirs=[h]) + info['language'] = 'c' + if lapack is not None: + dict_append(info,**lapack) + dict_append(info,**atlas) + elif 'lapack_atlas' in atlas['libraries']: + dict_append(info,**atlas) + dict_append(info,define_macros=[('ATLAS_WITH_LAPACK_ATLAS',None)]) + self.set_info(**info) + return + else: + dict_append(info,**atlas) + dict_append(info,define_macros=[('ATLAS_WITHOUT_LAPACK',None)]) + message = """ +********************************************************************* + Could not find lapack library within the ATLAS installation. +********************************************************************* +""" + warnings.warn(message) + self.set_info(**info) + return + + # Check if lapack library is complete, only warn if it is not. + lapack_dir = lapack['library_dirs'][0] + lapack_name = lapack['libraries'][0] + lapack_lib = None + for e in ['.a',so_ext]: + fn = os.path.join(lapack_dir,'lib'+lapack_name+e) + if os.path.exists(fn): + lapack_lib = fn + break + if lapack_lib is not None: + sz = os.stat(lapack_lib)[6] + if sz <= 4000*1024: + message = """ +********************************************************************* + Lapack library (from ATLAS) is probably incomplete: + size of %s is %sk (expected >4000k) + + Follow the instructions in the KNOWN PROBLEMS section of the file + numpy/INSTALL.txt. +********************************************************************* +""" % (lapack_lib,sz/1024) + warnings.warn(message) + else: + info['language'] = 'f77' + + self.set_info(**info) + +class atlas_blas_info(atlas_info): + _lib_names = ['f77blas','cblas'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + info = {} + atlas_libs = self.get_libs('atlas_libs', + self._lib_names + self._lib_atlas) + atlas = None + for d in lib_dirs: + atlas = self.check_libs(d,atlas_libs,[]) + if atlas is not None: + break + if atlas is None: + return + include_dirs = self.get_include_dirs() + h = (self.combine_paths(lib_dirs+include_dirs,'cblas.h') or [None])[0] + if h: + h = os.path.dirname(h) + dict_append(info,include_dirs=[h]) + info['language'] = 'c' + + dict_append(info,**atlas) + + self.set_info(**info) + return + + +class atlas_threads_info(atlas_info): + dir_env_var = ['PTATLAS','ATLAS'] + _lib_names = ['ptf77blas','ptcblas'] + +class atlas_blas_threads_info(atlas_blas_info): + dir_env_var = ['PTATLAS','ATLAS'] + _lib_names = ['ptf77blas','ptcblas'] + +class lapack_atlas_info(atlas_info): + _lib_names = ['lapack_atlas'] + atlas_info._lib_names + +class lapack_atlas_threads_info(atlas_threads_info): + _lib_names = ['lapack_atlas'] + atlas_threads_info._lib_names + +class lapack_info(system_info): + section = 'lapack' + dir_env_var = 'LAPACK' + _lib_names = ['lapack'] + notfounderror = LapackNotFoundError + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + lapack_libs = self.get_libs('lapack_libs', self._lib_names) + for d in lib_dirs: + lapack = self.check_libs(d,lapack_libs,[]) + if lapack is not None: + info = lapack + break + else: + return + info['language'] = 'f77' + self.set_info(**info) + +class lapack_src_info(system_info): + section = 'lapack_src' + dir_env_var = 'LAPACK_SRC' + notfounderror = LapackSrcNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d,['LAPACK*/SRC','SRC'])) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d,'dgesv.f')): + src_dir = d + break + if not src_dir: + #XXX: Get sources from netlib. May be ask first. + return + # The following is extracted from LAPACK-3.0/SRC/Makefile + allaux=''' + ilaenv ieeeck lsame lsamen xerbla + ''' # *.f + laux = ''' + bdsdc bdsqr disna labad lacpy ladiv lae2 laebz laed0 laed1 + laed2 laed3 laed4 laed5 laed6 laed7 laed8 laed9 laeda laev2 + lagtf lagts lamch lamrg lanst lapy2 lapy3 larnv larrb larre + larrf lartg laruv las2 lascl lasd0 lasd1 lasd2 lasd3 lasd4 + lasd5 lasd6 lasd7 lasd8 lasd9 lasda lasdq lasdt laset lasq1 + lasq2 lasq3 lasq4 lasq5 lasq6 lasr lasrt lassq lasv2 pttrf + stebz stedc steqr sterf + ''' # [s|d]*.f + lasrc = ''' + gbbrd gbcon gbequ gbrfs gbsv gbsvx gbtf2 gbtrf gbtrs gebak + gebal gebd2 gebrd gecon geequ gees geesx geev geevx gegs gegv + gehd2 gehrd gelq2 gelqf gels gelsd gelss gelsx gelsy geql2 + geqlf geqp3 geqpf geqr2 geqrf gerfs gerq2 gerqf gesc2 gesdd + gesv gesvd gesvx getc2 getf2 getrf getri getrs ggbak ggbal + gges ggesx ggev ggevx ggglm gghrd gglse ggqrf ggrqf ggsvd + ggsvp gtcon gtrfs gtsv gtsvx gttrf gttrs gtts2 hgeqz hsein + hseqr labrd lacon laein lags2 lagtm lahqr lahrd laic1 lals0 + lalsa lalsd langb lange langt lanhs lansb lansp lansy lantb + lantp lantr lapll lapmt laqgb laqge laqp2 laqps laqsb laqsp + laqsy lar1v lar2v larf larfb larfg larft larfx largv larrv + lartv larz larzb larzt laswp lasyf latbs latdf latps latrd + latrs latrz latzm lauu2 lauum pbcon pbequ pbrfs pbstf pbsv + pbsvx pbtf2 pbtrf pbtrs pocon poequ porfs posv posvx potf2 + potrf potri potrs ppcon ppequ pprfs ppsv ppsvx pptrf pptri + pptrs ptcon pteqr ptrfs ptsv ptsvx pttrs ptts2 spcon sprfs + spsv spsvx sptrf sptri sptrs stegr stein sycon syrfs sysv + sysvx sytf2 sytrf sytri sytrs tbcon tbrfs tbtrs tgevc tgex2 + tgexc tgsen tgsja tgsna tgsy2 tgsyl tpcon tprfs tptri tptrs + trcon trevc trexc trrfs trsen trsna trsyl trti2 trtri trtrs + tzrqf tzrzf + ''' # [s|c|d|z]*.f + sd_lasrc = ''' + laexc lag2 lagv2 laln2 lanv2 laqtr lasy2 opgtr opmtr org2l + org2r orgbr orghr orgl2 orglq orgql orgqr orgr2 orgrq orgtr + orm2l orm2r ormbr ormhr orml2 ormlq ormql ormqr ormr2 ormr3 + ormrq ormrz ormtr rscl sbev sbevd sbevx sbgst sbgv sbgvd sbgvx + sbtrd spev spevd spevx spgst spgv spgvd spgvx sptrd stev stevd + stevr stevx syev syevd syevr syevx sygs2 sygst sygv sygvd + sygvx sytd2 sytrd + ''' # [s|d]*.f + cz_lasrc = ''' + bdsqr hbev hbevd hbevx hbgst hbgv hbgvd hbgvx hbtrd hecon heev + heevd heevr heevx hegs2 hegst hegv hegvd hegvx herfs hesv + hesvx hetd2 hetf2 hetrd hetrf hetri hetrs hpcon hpev hpevd + hpevx hpgst hpgv hpgvd hpgvx hprfs hpsv hpsvx hptrd hptrf + hptri hptrs lacgv lacp2 lacpy lacrm lacrt ladiv laed0 laed7 + laed8 laesy laev2 lahef lanhb lanhe lanhp lanht laqhb laqhe + laqhp larcm larnv lartg lascl laset lasr lassq pttrf rot spmv + spr stedc steqr symv syr ung2l ung2r ungbr unghr ungl2 unglq + ungql ungqr ungr2 ungrq ungtr unm2l unm2r unmbr unmhr unml2 + unmlq unmql unmqr unmr2 unmr3 unmrq unmrz unmtr upgtr upmtr + ''' # [c|z]*.f + ####### + sclaux = laux + ' econd ' # s*.f + dzlaux = laux + ' secnd ' # d*.f + slasrc = lasrc + sd_lasrc # s*.f + dlasrc = lasrc + sd_lasrc # d*.f + clasrc = lasrc + cz_lasrc + ' srot srscl ' # c*.f + zlasrc = lasrc + cz_lasrc + ' drot drscl ' # z*.f + oclasrc = ' icmax1 scsum1 ' # *.f + ozlasrc = ' izmax1 dzsum1 ' # *.f + sources = ['s%s.f'%f for f in (sclaux+slasrc).split()] \ + + ['d%s.f'%f for f in (dzlaux+dlasrc).split()] \ + + ['c%s.f'%f for f in (clasrc).split()] \ + + ['z%s.f'%f for f in (zlasrc).split()] \ + + ['%s.f'%f for f in (allaux+oclasrc+ozlasrc).split()] + sources = [os.path.join(src_dir,f) for f in sources] + #XXX: should we check here actual existence of source files? + info = {'sources':sources,'language':'f77'} + self.set_info(**info) + +atlas_version_c_text = r''' +/* This file is generated from numpy_distutils/system_info.py */ +void ATL_buildinfo(void); +int main(void) { + ATL_buildinfo(); + return 0; +} +''' + +_cached_atlas_version = {} +def get_atlas_version(**config): + libraries = config.get('libraries', []) + library_dirs = config.get('library_dirs', []) + key = (tuple(libraries), tuple(library_dirs)) + if _cached_atlas_version.has_key(key): + return _cached_atlas_version[key] + c = cmd_config(Distribution()) + s, o = c.get_output(atlas_version_c_text, + libraries=libraries, library_dirs=library_dirs) + + atlas_version = None + if not s: + m = re.search(r'ATLAS version (?P<version>\d+[.]\d+[.]\d+)',o) + if m: + atlas_version = m.group('version') + if atlas_version is None: + if re.search(r'undefined symbol: ATL_buildinfo',o,re.M): + atlas_version = '3.2.1_pre3.3.6' + else: + log.info('Status: %d', s) + log.info('Output: %s', o) + _cached_atlas_version[key] = atlas_version + return atlas_version + +from distutils.util import get_platform + +class lapack_opt_info(system_info): + + def calc_info(self): + + if sys.platform=='darwin' and not os.environ.get('ATLAS',None): + args = [] + link_args = [] + if get_platform()[-4:] == 'i386': + intel = 1 + else: + intel = 0 + if os.path.exists('/System/Library/Frameworks/Accelerate.framework/'): + if intel: + args.extend(['-msse3']) + else: + args.extend(['-faltivec']) + link_args.extend(['-Wl,-framework','-Wl,Accelerate']) + elif os.path.exists('/System/Library/Frameworks/vecLib.framework/'): + if intel: + args.extend(['-msse3']) + else: + args.extend(['-faltivec']) + link_args.extend(['-Wl,-framework','-Wl,vecLib']) + if args: + self.set_info(extra_compile_args=args, + extra_link_args=link_args, + define_macros=[('NO_ATLAS_INFO',3)]) + return + + lapack_mkl_info = get_info('lapack_mkl') + if lapack_mkl_info: + self.set_info(**lapack_mkl_info) + return + + atlas_info = get_info('atlas_threads') + if not atlas_info: + atlas_info = get_info('atlas') + #atlas_info = {} ## uncomment for testing + atlas_version = None + need_lapack = 0 + need_blas = 0 + info = {} + if atlas_info: + version_info = atlas_info.copy() + atlas_version = get_atlas_version(**version_info) + if not atlas_info.has_key('define_macros'): + atlas_info['define_macros'] = [] + if atlas_version is None: + atlas_info['define_macros'].append(('NO_ATLAS_INFO',2)) + else: + atlas_info['define_macros'].append(('ATLAS_INFO', + '"\\"%s\\""' % atlas_version)) + if atlas_version=='3.2.1_pre3.3.6': + atlas_info['define_macros'].append(('NO_ATLAS_INFO',4)) + l = atlas_info.get('define_macros',[]) + if ('ATLAS_WITH_LAPACK_ATLAS',None) in l \ + or ('ATLAS_WITHOUT_LAPACK',None) in l: + need_lapack = 1 + info = atlas_info + else: + warnings.warn(AtlasNotFoundError.__doc__) + need_blas = 1 + need_lapack = 1 + dict_append(info,define_macros=[('NO_ATLAS_INFO',1)]) + + if need_lapack: + lapack_info = get_info('lapack') + #lapack_info = {} ## uncomment for testing + if lapack_info: + dict_append(info,**lapack_info) + else: + warnings.warn(LapackNotFoundError.__doc__) + lapack_src_info = get_info('lapack_src') + if not lapack_src_info: + warnings.warn(LapackSrcNotFoundError.__doc__) + return + dict_append(info,libraries=[('flapack_src',lapack_src_info)]) + + if need_blas: + blas_info = get_info('blas') + #blas_info = {} ## uncomment for testing + if blas_info: + dict_append(info,**blas_info) + else: + warnings.warn(BlasNotFoundError.__doc__) + blas_src_info = get_info('blas_src') + if not blas_src_info: + warnings.warn(BlasSrcNotFoundError.__doc__) + return + dict_append(info,libraries=[('fblas_src',blas_src_info)]) + + self.set_info(**info) + return + + +class blas_opt_info(system_info): + + def calc_info(self): + + if sys.platform=='darwin' and not os.environ.get('ATLAS',None): + args = [] + link_args = [] + if get_platform()[-4:] == 'i386': + intel = 1 + else: + intel = 0 + if os.path.exists('/System/Library/Frameworks/Accelerate.framework/'): + if intel: + args.extend(['-msse3']) + else: + args.extend(['-faltivec']) + args.extend([ + '-I/System/Library/Frameworks/vecLib.framework/Headers']) + link_args.extend(['-Wl,-framework','-Wl,Accelerate']) + elif os.path.exists('/System/Library/Frameworks/vecLib.framework/'): + if intel: + args.extend(['-msse3']) + else: + args.extend(['-faltivec']) + args.extend([ + '-I/System/Library/Frameworks/vecLib.framework/Headers']) + link_args.extend(['-Wl,-framework','-Wl,vecLib']) + if args: + self.set_info(extra_compile_args=args, + extra_link_args=link_args, + define_macros=[('NO_ATLAS_INFO',3)]) + return + + blas_mkl_info = get_info('blas_mkl') + if blas_mkl_info: + self.set_info(**blas_mkl_info) + return + + atlas_info = get_info('atlas_blas_threads') + if not atlas_info: + atlas_info = get_info('atlas_blas') + atlas_version = None + need_blas = 0 + info = {} + if atlas_info: + version_info = atlas_info.copy() + atlas_version = get_atlas_version(**version_info) + if not atlas_info.has_key('define_macros'): + atlas_info['define_macros'] = [] + if atlas_version is None: + atlas_info['define_macros'].append(('NO_ATLAS_INFO',2)) + else: + atlas_info['define_macros'].append(('ATLAS_INFO', + '"\\"%s\\""' % atlas_version)) + info = atlas_info + else: + warnings.warn(AtlasNotFoundError.__doc__) + need_blas = 1 + dict_append(info,define_macros=[('NO_ATLAS_INFO',1)]) + + if need_blas: + blas_info = get_info('blas') + if blas_info: + dict_append(info,**blas_info) + else: + warnings.warn(BlasNotFoundError.__doc__) + blas_src_info = get_info('blas_src') + if not blas_src_info: + warnings.warn(BlasSrcNotFoundError.__doc__) + return + dict_append(info,libraries=[('fblas_src',blas_src_info)]) + + self.set_info(**info) + return + + +class blas_info(system_info): + section = 'blas' + dir_env_var = 'BLAS' + _lib_names = ['blas'] + notfounderror = BlasNotFoundError + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + blas_libs = self.get_libs('blas_libs', self._lib_names) + for d in lib_dirs: + blas = self.check_libs(d,blas_libs,[]) + if blas is not None: + info = blas + break + else: + return + info['language'] = 'f77' # XXX: is it generally true? + self.set_info(**info) + + +class blas_src_info(system_info): + section = 'blas_src' + dir_env_var = 'BLAS_SRC' + notfounderror = BlasSrcNotFoundError + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d,['blas'])) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d,'daxpy.f')): + src_dir = d + break + if not src_dir: + #XXX: Get sources from netlib. May be ask first. + return + blas1 = ''' + caxpy csscal dnrm2 dzasum saxpy srotg zdotc ccopy cswap drot + dznrm2 scasum srotm zdotu cdotc dasum drotg icamax scnrm2 + srotmg zdrot cdotu daxpy drotm idamax scopy sscal zdscal crotg + dcabs1 drotmg isamax sdot sswap zrotg cscal dcopy dscal izamax + snrm2 zaxpy zscal csrot ddot dswap sasum srot zcopy zswap + ''' + blas2 = ''' + cgbmv chpmv ctrsv dsymv dtrsv sspr2 strmv zhemv ztpmv cgemv + chpr dgbmv dsyr lsame ssymv strsv zher ztpsv cgerc chpr2 dgemv + dsyr2 sgbmv ssyr xerbla zher2 ztrmv cgeru ctbmv dger dtbmv + sgemv ssyr2 zgbmv zhpmv ztrsv chbmv ctbsv dsbmv dtbsv sger + stbmv zgemv zhpr chemv ctpmv dspmv dtpmv ssbmv stbsv zgerc + zhpr2 cher ctpsv dspr dtpsv sspmv stpmv zgeru ztbmv cher2 + ctrmv dspr2 dtrmv sspr stpsv zhbmv ztbsv + ''' + blas3 = ''' + cgemm csymm ctrsm dsyrk sgemm strmm zhemm zsyr2k chemm csyr2k + dgemm dtrmm ssymm strsm zher2k zsyrk cher2k csyrk dsymm dtrsm + ssyr2k zherk ztrmm cherk ctrmm dsyr2k ssyrk zgemm zsymm ztrsm + ''' + sources = [os.path.join(src_dir,f+'.f') \ + for f in (blas1+blas2+blas3).split()] + #XXX: should we check here actual existence of source files? + info = {'sources':sources,'language':'f77'} + self.set_info(**info) + +class x11_info(system_info): + section = 'x11' + notfounderror = X11NotFoundError + + def __init__(self): + system_info.__init__(self, + default_lib_dirs=default_x11_lib_dirs, + default_include_dirs=default_x11_include_dirs) + + def calc_info(self): + if sys.platform in ['win32']: + return + lib_dirs = self.get_lib_dirs() + include_dirs = self.get_include_dirs() + x11_libs = self.get_libs('x11_libs', ['X11']) + for lib_dir in lib_dirs: + info = self.check_libs(lib_dir, x11_libs, []) + if info is not None: + break + else: + return + inc_dir = None + for d in include_dirs: + if self.combine_paths(d, 'X11/X.h'): + inc_dir = d + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir]) + self.set_info(**info) + +class _numpy_info(system_info): + section = 'Numeric' + modulename = 'Numeric' + notfounderror = NumericNotFoundError + + def __init__(self): + include_dirs = [] + try: + module = __import__(self.modulename) + prefix = [] + for name in module.__file__.split(os.sep): + if name=='lib': + break + prefix.append(name) + include_dirs.append(distutils.sysconfig.get_python_inc( + prefix=os.sep.join(prefix))) + except ImportError: + pass + py_incl_dir = distutils.sysconfig.get_python_inc() + include_dirs.append(py_incl_dir) + for d in default_include_dirs: + d = os.path.join(d, os.path.basename(py_incl_dir)) + if d not in include_dirs: + include_dirs.append(d) + system_info.__init__(self, + default_lib_dirs=[], + default_include_dirs=include_dirs) + + def calc_info(self): + try: + module = __import__(self.modulename) + except ImportError: + return + info = {} + macros = [] + for v in ['__version__','version']: + vrs = getattr(module,v,None) + if vrs is None: + continue + macros = [(self.modulename.upper()+'_VERSION', + '"\\"%s\\""' % (vrs)), + (self.modulename.upper(),None)] + break +## try: +## macros.append( +## (self.modulename.upper()+'_VERSION_HEX', +## hex(vstr2hex(module.__version__))), +## ) +## except Exception,msg: +## print msg + dict_append(info, define_macros = macros) + include_dirs = self.get_include_dirs() + inc_dir = None + for d in include_dirs: + if self.combine_paths(d, + os.path.join(self.modulename, + 'arrayobject.h')): + inc_dir = d + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir]) + if info: + self.set_info(**info) + return + +class numarray_info(_numpy_info): + section = 'numarray' + modulename = 'numarray' + +class Numeric_info(_numpy_info): + section = 'Numeric' + modulename = 'Numeric' + +class numpy_info(_numpy_info): + section = 'numpy' + modulename = 'numpy' + +class numerix_info(system_info): + section = 'numerix' + def calc_info(self): + which = None, None + if os.getenv("NUMERIX"): + which = os.getenv("NUMERIX"), "environment var" + # If all the above fail, default to numpy. + if which[0] is None: + which = "numpy", "defaulted" + try: + import numpy + which = "numpy", "defaulted" + except ImportError,msg1: + try: + import Numeric + which = "numeric", "defaulted" + except ImportError,msg2: + try: + import numarray + which = "numarray", "defaulted" + except ImportError,msg3: + log.info(msg1) + log.info(msg2) + log.info(msg3) + which = which[0].strip().lower(), which[1] + if which[0] not in ["numeric", "numarray", "numpy"]: + raise ValueError("numerix selector must be either 'Numeric' " + "or 'numarray' or 'numpy' but the value obtained" + " from the %s was '%s'." % (which[1], which[0])) + os.environ['NUMERIX'] = which[0] + self.set_info(**get_info(which[0])) + +class f2py_info(system_info): + def calc_info(self): + try: + import numpy.f2py as f2py + except ImportError: + return + f2py_dir = os.path.join(os.path.dirname(f2py.__file__),'src') + self.set_info(sources = [os.path.join(f2py_dir,'fortranobject.c')], + include_dirs = [f2py_dir]) + return + +class boost_python_info(system_info): + section = 'boost_python' + dir_env_var = 'BOOST' + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d,['boost*'])) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d,'libs','python','src','module.cpp')): + src_dir = d + break + if not src_dir: + return + py_incl_dir = distutils.sysconfig.get_python_inc() + srcs_dir = os.path.join(src_dir,'libs','python','src') + bpl_srcs = glob(os.path.join(srcs_dir,'*.cpp')) + bpl_srcs += glob(os.path.join(srcs_dir,'*','*.cpp')) + info = {'libraries':[('boost_python_src',{'include_dirs':[src_dir,py_incl_dir], + 'sources':bpl_srcs})], + 'include_dirs':[src_dir], + } + if info: + self.set_info(**info) + return + +class agg2_info(system_info): + section = 'agg2' + dir_env_var = 'AGG2' + + def get_paths(self, section, key): + pre_dirs = system_info.get_paths(self, section, key) + dirs = [] + for d in pre_dirs: + dirs.extend([d] + self.combine_paths(d,['agg2*'])) + return [ d for d in dirs if os.path.isdir(d) ] + + def calc_info(self): + src_dirs = self.get_src_dirs() + src_dir = '' + for d in src_dirs: + if os.path.isfile(os.path.join(d,'src','agg_affine_matrix.cpp')): + src_dir = d + break + if not src_dir: + return + if sys.platform=='win32': + agg2_srcs = glob(os.path.join(src_dir,'src','platform','win32','agg_win32_bmp.cpp')) + else: + agg2_srcs = glob(os.path.join(src_dir,'src','*.cpp')) + agg2_srcs += [os.path.join(src_dir,'src','platform','X11','agg_platform_support.cpp')] + + info = {'libraries':[('agg2_src',{'sources':agg2_srcs, + 'include_dirs':[os.path.join(src_dir,'include')], + })], + 'include_dirs':[os.path.join(src_dir,'include')], + } + if info: + self.set_info(**info) + return + +class _pkg_config_info(system_info): + section = None + config_env_var = 'PKG_CONFIG' + default_config_exe = 'pkg-config' + append_config_exe = '' + version_macro_name = None + release_macro_name = None + version_flag = '--modversion' + cflags_flag = '--cflags' + + def get_config_exe(self): + if os.environ.has_key(self.config_env_var): + return os.environ[self.config_env_var] + return self.default_config_exe + def get_config_output(self, config_exe, option): + s,o = exec_command(config_exe+' '+self.append_config_exe+' '+option,use_tee=0) + if not s: + return o + + def calc_info(self): + config_exe = find_executable(self.get_config_exe()) + if not os.path.isfile(config_exe): + log.warn('File not found: %s. Cannot determine %s info.' \ + % (config_exe, self.section)) + return + info = {} + macros = [] + libraries = [] + library_dirs = [] + include_dirs = [] + extra_link_args = [] + extra_compile_args = [] + version = self.get_config_output(config_exe,self.version_flag) + if version: + macros.append((self.__class__.__name__.split('.')[-1].upper(), + '"\\"%s\\""' % (version))) + if self.version_macro_name: + macros.append((self.version_macro_name+'_%s' % (version.replace('.','_')),None)) + if self.release_macro_name: + release = self.get_config_output(config_exe,'--release') + if release: + macros.append((self.release_macro_name+'_%s' % (release.replace('.','_')),None)) + opts = self.get_config_output(config_exe,'--libs') + if opts: + for opt in opts.split(): + if opt[:2]=='-l': + libraries.append(opt[2:]) + elif opt[:2]=='-L': + library_dirs.append(opt[2:]) + else: + extra_link_args.append(opt) + opts = self.get_config_output(config_exe,self.cflags_flag) + if opts: + for opt in opts.split(): + if opt[:2]=='-I': + include_dirs.append(opt[2:]) + elif opt[:2]=='-D': + if '=' in opt: + n,v = opt[2:].split('=') + macros.append((n,v)) + else: + macros.append((opt[2:],None)) + else: + extra_compile_args.append(opt) + if macros: dict_append(info, define_macros = macros) + if libraries: dict_append(info, libraries = libraries) + if library_dirs: dict_append(info, library_dirs = library_dirs) + if include_dirs: dict_append(info, include_dirs = include_dirs) + if extra_link_args: dict_append(info, extra_link_args = extra_link_args) + if extra_compile_args: dict_append(info, extra_compile_args = extra_compile_args) + if info: + self.set_info(**info) + return + +class wx_info(_pkg_config_info): + section = 'wx' + config_env_var = 'WX_CONFIG' + default_config_exe = 'wx-config' + append_config_exe = '' + version_macro_name = 'WX_VERSION' + release_macro_name = 'WX_RELEASE' + version_flag = '--version' + cflags_flag = '--cxxflags' + +class gdk_pixbuf_xlib_2_info(_pkg_config_info): + section = 'gdk_pixbuf_xlib_2' + append_config_exe = 'gdk-pixbuf-xlib-2.0' + version_macro_name = 'GDK_PIXBUF_XLIB_VERSION' + +class gdk_pixbuf_2_info(_pkg_config_info): + section = 'gdk_pixbuf_2' + append_config_exe = 'gdk-pixbuf-2.0' + version_macro_name = 'GDK_PIXBUF_VERSION' + +class gdk_x11_2_info(_pkg_config_info): + section = 'gdk_x11_2' + append_config_exe = 'gdk-x11-2.0' + version_macro_name = 'GDK_X11_VERSION' + +class gdk_2_info(_pkg_config_info): + section = 'gdk_2' + append_config_exe = 'gdk-2.0' + version_macro_name = 'GDK_VERSION' + +class gdk_info(_pkg_config_info): + section = 'gdk' + append_config_exe = 'gdk' + version_macro_name = 'GDK_VERSION' + +class gtkp_x11_2_info(_pkg_config_info): + section = 'gtkp_x11_2' + append_config_exe = 'gtk+-x11-2.0' + version_macro_name = 'GTK_X11_VERSION' + + +class gtkp_2_info(_pkg_config_info): + section = 'gtkp_2' + append_config_exe = 'gtk+-2.0' + version_macro_name = 'GTK_VERSION' + +class xft_info(_pkg_config_info): + section = 'xft' + append_config_exe = 'xft' + version_macro_name = 'XFT_VERSION' + +class freetype2_info(_pkg_config_info): + section = 'freetype2' + append_config_exe = 'freetype2' + version_macro_name = 'FREETYPE2_VERSION' + +class amd_info(system_info): + section = 'amd' + dir_env_var = 'AMD' + _lib_names = ['amd'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + amd_libs = self.get_libs('amd_libs', self._lib_names) + for d in lib_dirs: + amd = self.check_libs(d,amd_libs,[]) + if amd is not None: + info = amd + break + else: + return + + include_dirs = self.get_include_dirs() + + inc_dir = None + for d in include_dirs: + p = self.combine_paths(d,'amd.h') + if p: + inc_dir = os.path.dirname(p[0]) + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir], + define_macros=[('SCIPY_AMD_H',None)], + swig_opts = ['-I' + inc_dir]) + + self.set_info(**info) + return + +class umfpack_info(system_info): + section = 'umfpack' + dir_env_var = 'UMFPACK' + notfounderror = UmfpackNotFoundError + _lib_names = ['umfpack'] + + def calc_info(self): + lib_dirs = self.get_lib_dirs() + + umfpack_libs = self.get_libs('umfpack_libs', self._lib_names) + for d in lib_dirs: + umf = self.check_libs(d,umfpack_libs,[]) + if umf is not None: + info = umf + break + else: + return + + include_dirs = self.get_include_dirs() + + inc_dir = None + for d in include_dirs: + p = self.combine_paths(d,['','umfpack'],'umfpack.h') + if p: + inc_dir = os.path.dirname(p[0]) + break + if inc_dir is not None: + dict_append(info, include_dirs=[inc_dir], + define_macros=[('SCIPY_UMFPACK_H',None)], + swig_opts = ['-I' + inc_dir]) + + amd = get_info('amd') + dict_append(info, **get_info('amd')) + + self.set_info(**info) + return + +## def vstr2hex(version): +## bits = [] +## n = [24,16,8,4,0] +## r = 0 +## for s in version.split('.'): +## r |= int(s) << n[0] +## del n[0] +## return r + +#-------------------------------------------------------------------- + +def combine_paths(*args,**kws): + """ Return a list of existing paths composed by all combinations of + items from arguments. + """ + r = [] + for a in args: + if not a: continue + if is_string(a): + a = [a] + r.append(a) + args = r + if not args: return [] + if len(args)==1: + result = reduce(lambda a,b:a+b,map(glob,args[0]),[]) + elif len (args)==2: + result = [] + for a0 in args[0]: + for a1 in args[1]: + result.extend(glob(os.path.join(a0,a1))) + else: + result = combine_paths(*(combine_paths(args[0],args[1])+args[2:])) + verbosity = kws.get('verbosity',1) + log.debug('(paths: %s)', ','.join(result)) + return result + +language_map = {'c':0,'c++':1,'f77':2,'f90':3} +inv_language_map = {0:'c',1:'c++',2:'f77',3:'f90'} +def dict_append(d,**kws): + languages = [] + for k,v in kws.items(): + if k=='language': + languages.append(v) + continue + if d.has_key(k): + if k in ['library_dirs','include_dirs','define_macros']: + [d[k].append(vv) for vv in v if vv not in d[k]] + else: + d[k].extend(v) + else: + d[k] = v + if languages: + l = inv_language_map[max([language_map.get(l,0) for l in languages])] + d['language'] = l + return + +def parseCmdLine(argv=(None,)): + import optparse + parser = optparse.OptionParser("usage: %prog [-v] [info objs]") + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', + default=False, + help='be verbose and print more messages') + + opts, args = parser.parse_args(args=argv[1:]) + return opts, args + +def show_all(argv=None): + import inspect + if argv is None: + argv = sys.argv + opts, args = parseCmdLine(argv) + if opts.verbose: + log.set_threshold(log.DEBUG) + else: + log.set_threshold(log.INFO) + show_only = [] + for n in args: + if n[-5:] != '_info': + n = n + '_info' + show_only.append(n) + show_all = not show_only + _gdict_ = globals().copy() + for name, c in _gdict_.iteritems(): + if not inspect.isclass(c): + continue + if not issubclass(c, system_info) or c is system_info: + continue + if not show_all: + if name not in show_only: + continue + del show_only[show_only.index(name)] + conf = c() + conf.verbosity = 2 + r = conf.get_info() + if show_only: + log.info('Info classes not defined: %s',','.join(show_only)) + +if __name__ == "__main__": + show_all() |