diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-01-04 17:26:31 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-01-04 17:26:31 +0000 |
commit | 8e2654541c6eae0f308908f501cccbc86b2f9101 (patch) | |
tree | bfcfe3b282c8fb659832bf86a841ce76852094ad /numpy/f2py/f2py2e.py | |
parent | ddaed649c23bbd0ad36cdafdfe9cd92397ce69e3 (diff) | |
download | numpy-8e2654541c6eae0f308908f501cccbc86b2f9101.tar.gz |
Moved scipy directory to numpy
Diffstat (limited to 'numpy/f2py/f2py2e.py')
-rwxr-xr-x | numpy/f2py/f2py2e.py | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py new file mode 100755 index 000000000..6230590d1 --- /dev/null +++ b/numpy/f2py/f2py2e.py @@ -0,0 +1,555 @@ +#!/usr/bin/env python +""" + +f2py2e - Fortran to Python C/API generator. 2nd Edition. + See __usage__ below. + +Copyright 1999--2005 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 LGPL. See http://www.fsf.org + +NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. +$Date: 2005/05/06 08:31:19 $ +Pearu Peterson +""" +__version__ = "$Revision: 1.90 $"[10:-1] + +import __version__ +f2py_version = __version__.version + +import sys,os,string,pprint,shutil,types,re +errmess=sys.stderr.write +#outmess=sys.stdout.write +show=pprint.pprint + +import crackfortran +import rules +import cb_rules +import common_rules +import auxfuncs +import cfuncs +import capi_maps +import func2subr +import f90mod_rules + +outmess = auxfuncs.outmess + +try: + from scipy import __core_version__ as scipy_core_version +except ImportError: + scipy_distutils_version = 'N/A' + +__usage__ = """\ +Usage: + +1) To construct extension module sources: + + f2py [<options>] <fortran files> [[[only:]||[skip:]] \\ + <fortran functions> ] \\ + [: <fortran files> ...] + +2) To compile fortran files and build extension modules: + + f2py -c [<options>, <build_flib options>, <extra options>] <fortran files> + +3) To generate signature files: + + f2py -h <filename.pyf> ...< same options as in (1) > + +Description: This program generates a Python C/API file (<modulename>module.c) + that contains wrappers for given fortran functions so that they + can be called from Python. With the -c option the corresponding + extension modules are built. + +Options: + + -h <filename> Write signatures of the fortran routines to file <filename> + and exit. You can then edit <filename> and use it instead + of <fortran files>. If <filename>==stdout then the + signatures are printed to stdout. + <fortran functions> Names of fortran routines for which Python C/API + functions will be generated. Default is all that are found + in <fortran files>. + <fortran files> Paths to fortran/signature files that will be scanned for + <fortran functions> in order to determine their signatures. + skip: Ignore fortran functions that follow until `:'. + only: Use only fortran functions that follow until `:'. + : Get back to <fortran files> mode. + + -m <modulename> Name of the module; f2py generates a Python/C API + file <modulename>module.c or extension module <modulename>. + Default is 'untitled'. + + --[no-]lower Do [not] lower the cases in <fortran files>. By default, + --lower is assumed with -h key, and --no-lower without -h key. + + --build-dir <dirname> All f2py generated files are created in <dirname>. + Default is tempfile.mktemp(). + + --overwrite-signature Overwrite existing signature file. + + --[no-]latex-doc Create (or not) <modulename>module.tex. + Default is --no-latex-doc. + --short-latex Create 'incomplete' LaTeX document (without commands + \\documentclass, \\tableofcontents, and \\begin{document}, + \\end{document}). + + --[no-]rest-doc Create (or not) <modulename>module.rst. + Default is --no-rest-doc. + + --debug-capi Create C/API code that reports the state of the wrappers + during runtime. Useful for debugging. + + --[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77 + functions. --wrap-functions is default because it ensures + maximum portability/compiler independence. + + --include_paths <path1>:<path2>:... Search include files from the given + directories. + + --help-link [..] List system resources found by system_info.py. See also + --link-<resource> switch below. [..] is optional list + of resources names. E.g. try 'f2py --help-link lapack_opt'. + + --quiet Run quietly. + --verbose Run with extra verbosity. + -v Print f2py version ID and exit. + + +scipy.distutils options (only effective with -c): + + --fcompiler= Specify Fortran compiler type by vendor + --compiler= Specify C compiler type (as defined by distutils) + + --help-fcompiler List available Fortran compilers and exit + --f77exec= Specify the path to F77 compiler + --f90exec= Specify the path to F90 compiler + --f77flags= Specify F77 compiler flags + --f90flags= Specify F90 compiler flags + --opt= Specify optimization flags + --arch= Specify architecture specific optimization flags + --noopt Compile without optimization + --noarch Compile without arch-dependent optimization + --debug Compile with debugging information + +Extra options (only effective with -c): + + --link-<resource> Link extension module with <resource> as defined + by scipy.distutils/system_info.py. E.g. to link + with optimized LAPACK libraries (vecLib on MacOSX, + ATLAS elsewhere), use --link-lapack_opt. + See also --help-link switch. + + -L/path/to/lib/ -l<libname> + -D<define> -U<name> + -I/path/to/include/ + <filename>.o <filename>.so <filename>.a + + Using the following macros may be required with non-gcc Fortran + compilers: + -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN + -DUNDERSCORE_G77 + + When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY + interface is printed out at exit (platforms: Linux). + + When using -DF2PY_REPORT_ON_ARRAY_COPY=<int>, a message is + sent to stderr whenever F2PY interface makes a copy of an + array. Integer <int> sets the threshold for array sizes when + a message should be shown. + +Version: %s +scipy_core Version: %s +Requires: Python 2.3 or higher. +License: LGPL (see http://www.fsf.org) +Copyright 1999 - 2005 Pearu Peterson all rights reserved. +http://cens.ioc.ee/projects/f2py2e/"""%(f2py_version, scipy_core_version) + + +def scaninputline(inputline): + files,funcs,skipfuncs,onlyfuncs,debug=[],[],[],[],[] + f,f2,f3,f4,f5,f6,f7=1,0,0,0,0,0,0 + verbose = 1 + dolc=-1 + dolatexdoc = 0 + dorestdoc = 0 + wrapfuncs = 1 + buildpath = '.' + include_paths = [] + signsfile,modulename=None,None + options = {'buildpath':buildpath} + for l in inputline: + if l=='': pass + elif l=='only:': f=0 + elif l=='skip:': f=-1 + elif l==':': f=1;f4=0 + elif l[:8]=='--debug-': debug.append(l[8:]) + elif l=='--lower': dolc=1 + elif l=='--build-dir': f6=1 + elif l=='--no-lower': dolc=0 + elif l=='--quiet': verbose = 0 + elif l=='--verbose': verbose += 1 + elif l=='--latex-doc': dolatexdoc=1 + elif l=='--no-latex-doc': dolatexdoc=0 + elif l=='--rest-doc': dorestdoc=1 + elif l=='--no-rest-doc': dorestdoc=0 + elif l=='--wrap-functions': wrapfuncs=1 + elif l=='--no-wrap-functions': wrapfuncs=0 + elif l=='--short-latex': options['shortlatex']=1 + elif l=='--overwrite-signature': options['h-overwrite']=1 + elif l=='-h': f2=1 + elif l=='-m': f3=1 + elif l[:2]=='-v': + print f2py_version + sys.exit() + elif l=='--show-compilers': + f5=1 + elif l[:8]=='-include': + cfuncs.outneeds['userincludes'].append(l[9:-1]) + cfuncs.userincludes[l[9:-1]]='#include '+l[8:] + elif l[:15]=='--include_paths': + f7=1 + elif l[0]=='-': + errmess('Unknown option %s\n'%`l`) + sys.exit() + elif f2: f2=0;signsfile=l + elif f3: f3=0;modulename=l + elif f6: f6=0;buildpath=l + elif f7: f7=0;include_paths.extend(l.split(os.pathsep)) + elif f==1: + try: + open(l).close() + files.append(l) + except IOError,detail: + errmess('IOError: %s. Skipping file "%s".\n'%(str(detail),l)) + elif f==-1: skipfuncs.append(l) + elif f==0: onlyfuncs.append(l) + if not f5 and not files and not modulename: + print __usage__ + sys.exit() + if not os.path.isdir(buildpath): + if not verbose: + outmess('Creating build directory %s'%(buildpath)) + os.mkdir(buildpath) + if signsfile: + signsfile = os.path.join(buildpath,signsfile) + if signsfile and os.path.isfile(signsfile) and not options.has_key('h-overwrite'): + errmess('Signature file "%s" exists!!! Use --overwrite-signature to overwrite.\n'%(signsfile)) + sys.exit() + + options['debug']=debug + options['verbose']=verbose + if dolc==-1 and not signsfile: options['do-lower']=0 + else: options['do-lower']=dolc + if modulename: options['module']=modulename + if signsfile: options['signsfile']=signsfile + if onlyfuncs: options['onlyfuncs']=onlyfuncs + if skipfuncs: options['skipfuncs']=skipfuncs + options['dolatexdoc'] = dolatexdoc + options['dorestdoc'] = dorestdoc + options['wrapfuncs'] = wrapfuncs + options['buildpath']=buildpath + options['include_paths']=include_paths + return files,options + +def callcrackfortran(files,options): + rules.options=options + funcs=[] + crackfortran.debug=options['debug'] + crackfortran.verbose=options['verbose'] + if options.has_key('module'): + crackfortran.f77modulename=options['module'] + if options.has_key('skipfuncs'): + crackfortran.skipfuncs=options['skipfuncs'] + if options.has_key('onlyfuncs'): + crackfortran.onlyfuncs=options['onlyfuncs'] + crackfortran.include_paths[:]=options['include_paths'] + crackfortran.dolowercase=options['do-lower'] + postlist=crackfortran.crackfortran(files) + if options.has_key('signsfile'): + outmess('Saving signatures to file "%s"\n'%(options['signsfile'])) + pyf=crackfortran.crack2fortran(postlist) + if options['signsfile'][-6:]=='stdout': + sys.stdout.write(pyf) + else: + f=open(options['signsfile'],'w') + f.write(pyf) + f.close() + return postlist + +def buildmodules(list): + cfuncs.buildcfuncs() + outmess('Building modules...\n') + modules,mnames,isusedby=[],[],{} + for i in range(len(list)): + if string.find(list[i]['name'],'__user__')>=0: + cb_rules.buildcallbacks(list[i]) + else: + if list[i].has_key('use'): + for u in list[i]['use'].keys(): + if not isusedby.has_key(u): isusedby[u]=[] + isusedby[u].append(list[i]['name']) + modules.append(list[i]) + mnames.append(list[i]['name']) + ret = {} + for i in range(len(mnames)): + if isusedby.has_key(mnames[i]): + outmess('\tSkipping module "%s" which is used by %s.\n'%(mnames[i],string.join(map(lambda s:'"%s"'%s,isusedby[mnames[i]]),','))) + else: + um=[] + if modules[i].has_key('use'): + for u in modules[i]['use'].keys(): + if isusedby.has_key(u) and u in mnames: + um.append(modules[mnames.index(u)]) + else: + outmess('\tModule "%s" uses nonexisting "%s" which will be ignored.\n'%(mnames[i],u)) + ret[mnames[i]] = {} + dict_append(ret[mnames[i]],rules.buildmodule(modules[i],um)) + return ret + +def dict_append(d_out,d_in): + for (k,v) in d_in.items(): + if not d_out.has_key(k): + d_out[k] = [] + if type(v) is types.ListType: + d_out[k] = d_out[k] + v + else: + d_out[k].append(v) + +def run_main(comline_list): + """Run f2py as if string.join(comline_list,' ') is used as a command line. + In case of using -h flag, return None. + """ + reload(crackfortran) + f2pydir=os.path.dirname(os.path.abspath(cfuncs.__file__)) + fobjhsrc = os.path.join(f2pydir,'src','fortranobject.h') + fobjcsrc = os.path.join(f2pydir,'src','fortranobject.c') + files,options=scaninputline(comline_list) + auxfuncs.options=options + postlist=callcrackfortran(files,options) + isusedby={} + for i in range(len(postlist)): + if postlist[i].has_key('use'): + for u in postlist[i]['use'].keys(): + if not isusedby.has_key(u): isusedby[u]=[] + isusedby[u].append(postlist[i]['name']) + for i in range(len(postlist)): + if postlist[i]['block']=='python module' and string.find(postlist[i]['name'],'__user__')<0: + if isusedby.has_key(postlist[i]['name']): + #if not quiet: + outmess('Skipping Makefile build for module "%s" which is used by %s\n'%(postlist[i]['name'],string.join(map(lambda s:'"%s"'%s,isusedby[postlist[i]['name']]),','))) + if options.has_key('signsfile'): + if options['verbose']>1: + outmess('Stopping. Edit the signature file and then run f2py on the signature file: ') + outmess('%s %s\n'%(os.path.basename(sys.argv[0]),options['signsfile'])) + return + for i in range(len(postlist)): + if postlist[i]['block']!='python module': + if not options.has_key('python module'): + errmess('Tip: If your original code is Fortran 77 then you must use -m option.\n') + raise TypeError,'All blocks must be module blocks but got %s'%(`postlist[i]['block']`) + auxfuncs.debugoptions=options['debug'] + f90mod_rules.options=options + auxfuncs.wrapfuncs=options['wrapfuncs'] + + ret=buildmodules(postlist) + + for mn in ret.keys(): + dict_append(ret[mn],{'csrc':fobjcsrc,'h':fobjhsrc}) + return ret + +def filter_files(prefix,suffix,files,remove_prefix=None): + """ + Filter files by prefix and suffix. + """ + filtered,rest = [],[] + match = re.compile(prefix+r'.*'+suffix+r'\Z').match + if remove_prefix: + ind = len(prefix) + else: + ind = 0 + for file in map(string.strip,files): + if match(file): filtered.append(file[ind:]) + else: rest.append(file) + return filtered,rest + +def get_prefix(module): + p = os.path.dirname(os.path.dirname(module.__file__)) + return p + +def run_compile(): + """ + Do it all in one call! + """ + import tempfile,os,shutil + + i = sys.argv.index('-c') + del sys.argv[i] + + remove_build_dir = 0 + try: i = sys.argv.index('--build-dir') + except ValueError: i=None + if i is not None: + build_dir = sys.argv[i+1] + del sys.argv[i+1] + del sys.argv[i] + else: + remove_build_dir = 1 + build_dir = os.path.join(tempfile.mktemp()) + + sysinfo_flags = filter(re.compile(r'[-][-]link[-]').match,sys.argv[1:]) + sys.argv = filter(lambda a,flags=sysinfo_flags:a not in flags,sys.argv) + if sysinfo_flags: + sysinfo_flags = [f[7:] for f in sysinfo_flags] + + f2py_flags = filter(re.compile(r'[-][-]((no[-]|)(wrap[-]functions|lower)|debug[-]capi|quiet)|[-]include').match,sys.argv[1:]) + sys.argv = filter(lambda a,flags=f2py_flags:a not in flags,sys.argv) + f2py_flags2 = [] + fl = 0 + for a in sys.argv[1:]: + if a in ['only:','skip:']: + fl = 1 + elif a==':': + fl = 0 + if fl or a==':': + f2py_flags2.append(a) + if f2py_flags2 and f2py_flags2[-1]!=':': + f2py_flags2.append(':') + f2py_flags.extend(f2py_flags2) + + sys.argv = filter(lambda a,flags=f2py_flags2:a not in flags,sys.argv) + + flib_flags = filter(re.compile(r'[-][-]((f(90)?compiler([-]exec|)|compiler)=|help[-]compiler)').match,sys.argv[1:]) + sys.argv = filter(lambda a,flags=flib_flags:a not in flags,sys.argv) + fc_flags = filter(re.compile(r'[-][-]((f(77|90)(flags|exec)|opt|arch)=|(debug|noopt|noarch|help[-]fcompiler))').match,sys.argv[1:]) + sys.argv = filter(lambda a,flags=fc_flags:a not in flags,sys.argv) + + if 1: + del_list = [] + for s in flib_flags: + v = '--fcompiler=' + if s[:len(v)]==v: + from scipy.distutils import fcompiler + allowed_keys = fcompiler.fcompiler_class.keys() + nv = ov = s[len(v):].lower() + if ov not in allowed_keys: + vmap = {} # XXX + try: + nv = vmap[ov] + except KeyError: + if ov not in vmap.values(): + print 'Unknown vendor: "%s"' % (s[len(v):]) + nv = ov + i = flib_flags.index(s) + flib_flags[i] = '--fcompiler=' + nv + continue + for s in del_list: + i = flib_flags.index(s) + del flib_flags[i] + assert len(flib_flags)<=2,`flib_flags` + setup_flags = filter(re.compile(r'[-][-](verbose)').match,sys.argv[1:]) + sys.argv = filter(lambda a,flags=setup_flags:a not in flags,sys.argv) + if '--quiet' in f2py_flags: + setup_flags.append('--quiet') + + modulename = 'untitled' + sources = sys.argv[1:] + if '-m' in sys.argv: + i = sys.argv.index('-m') + modulename = sys.argv[i+1] + del sys.argv[i+1],sys.argv[i] + sources = sys.argv[1:] + else: + from scipy.distutils.command.build_src import get_f2py_modulename + pyf_files,sources = filter_files('','[.]pyf([.]src|)',sources) + sources = pyf_files + sources + for f in pyf_files: + modulename = get_f2py_modulename(f) + if modulename: + break + + extra_objects, sources = filter_files('','[.](o|a|so)',sources) + include_dirs, sources = filter_files('-I','',sources,remove_prefix=1) + library_dirs, sources = filter_files('-L','',sources,remove_prefix=1) + libraries, sources = filter_files('-l','',sources,remove_prefix=1) + undef_macros, sources = filter_files('-U','',sources,remove_prefix=1) + define_macros, sources = filter_files('-D','',sources,remove_prefix=1) + using_numarray = 0 + using_numeric = 0 + for i in range(len(define_macros)): + name_value = string.split(define_macros[i],'=',1) + if len(name_value)==1: + name_value.append(None) + if len(name_value)==2: + define_macros[i] = tuple(name_value) + else: + print 'Invalid use of -D:',name_value + + from scipy.distutils.system_info import get_info + + num_include_dir = None + num_info = {} + #import scipy + #n = 'scipy' + #p = get_prefix(scipy) + #from scipy.distutils.misc_util import get_scipy_include_dirs + #num_info = {'include_dirs': get_scipy_include_dirs()} + + if num_info: + include_dirs.extend(num_info.get('include_dirs',[])) + + from scipy.distutils.core import setup,Extension + ext_args = {'name':modulename,'sources':sources, + 'include_dirs': include_dirs, + 'library_dirs': library_dirs, + 'libraries': libraries, + 'define_macros': define_macros, + 'undef_macros': undef_macros, + 'extra_objects': extra_objects, + 'f2py_options': f2py_flags, + } + + if sysinfo_flags: + from scipy.distutils.misc_util import dict_append + for n in sysinfo_flags: + i = get_info(n) + if not i: + outmess('No %s resources found in system'\ + ' (try `f2py --help-link`)\n' % (`n`)) + dict_append(ext_args,**i) + + ext = Extension(**ext_args) + sys.argv = [sys.argv[0]] + setup_flags + sys.argv.extend(['build', + '--build-temp',build_dir, + '--build-base',build_dir, + '--build-platlib','.']) + if fc_flags: + sys.argv.extend(['config_fc']+fc_flags) + if flib_flags: + sys.argv.extend(['build_ext']+flib_flags) + + setup(ext_modules = [ext]) + + if remove_build_dir and os.path.exists(build_dir): + outmess('Removing build directory %s\n'%(build_dir)) + shutil.rmtree(build_dir) + +def main(): + if '--help-link' in sys.argv[1:]: + sys.argv.remove('--help-link') + from scipy.distutils.system_info import show_all + show_all() + return + if '-c' in sys.argv[1:]: + run_compile() + else: + run_main(sys.argv[1:]) + +#if __name__ == "__main__": +# main() + + +# EOF + |