File:  [CENS] / python / pyGiNaC / setup3.py
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Tue Apr 24 17:32:25 2001 UTC (17 years, 2 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
Impl. constant,started matrix

    1: #!/usr/bin/env python
    2: #
    3: #   Setup file for building/installing PyGiNaC
    4: #
    5: # Requirements:
    6: #   Python 2.0 or higher (http://www.python.org/)
    7: #   GiNaC 0.8.1 or higher (http://www.ginac.de/)
    8: #     For GiNaC, you'll need CLN 1.1 (http://clisp.cons.org/~haible/packages-cln.html)
    9: #       Optional, but recommended, CLN can use GMP 3.1.1 (http://www.swox.com/gmp/)
   10: #   Boost 1.21.1 or higher (http://www.boost.org/)
   11: #  
   12: # Usage:
   13: #   > python setup.py doc install  # this will generate ginac.doc, builds _ginac
   14: #                                  # and installs the package.
   15: #   > python setup.py test -v      # this will generate and run test/test_dt.py
   16: #
   17: # In Python `import ginac'. Module `ginac' extension classes exposing
   18: # almost all GiNaC classes to Python.
   19: # See GiNaC documentation (http://www.ginac.de/tutorial/) for usage.
   20: #
   21: # Notes:
   22: # 1. Compilation of PyGiNaC requires more than 160MB memory (with gcc -O2
   23: #   on Intel Linux). However, if you don't need all the GiNaC classes
   24: #   to be exposed to Python, you can edit the list `wrap_input' below
   25: #   to indicate your needs, this will decrease also the memory consumption
   26: #   during the compilation. You don't need to worry about class dependencies
   27: #   they are solved automatically. After you edit `wrap_input', run
   28: #  > python setup.py reinstall
   29: #
   30: # Pearu Peterson <pearu@cens.ioc.ee>
   31: # 30 March 2001
   32: # 23 April 2001
   33: 
   34: __credits__ = """\
   35: GiNaC people (www.ginac.de), for the GiNaC library.
   36: Boost.Python people (www.boost.org), for BPL that considerably
   37: simplified the wrapping of GiNaC C++ classes to Python.
   38: """
   39: 
   40: import sys,os,string,time
   41: 
   42: #++++++++++++++ Require Python 2.x +++++++++++++
   43: 
   44: if eval(sys.version[0])<2:
   45:     print "You'll need Python 2.0 or higher to build PyGiNaC"
   46:     sys.exit()
   47: 
   48: #++++++++++++++ Rebuild ++++++++++++++++++++++++
   49: rebuild = 0
   50: gendoc = 0
   51: gentest = 0
   52: disable_opt = 1 # set 0 for final compilation
   53: 
   54: if 'test' in sys.argv:
   55:     i = sys.argv.index('test')
   56:     gentest = 1
   57:     if len(sys.argv)>i+1 and sys.argv[i+1]=='-v':
   58:         gentest = 2
   59:         del sys.argv[i+1]
   60:     del sys.argv[i]
   61: if 'doc' in sys.argv:
   62:     del sys.argv[sys.argv.index('doc')]
   63:     gendoc = 1
   64: 
   65: if 'rebuild' in sys.argv:
   66:     sys.argv[sys.argv.index('rebuild')] = 'build'
   67:     rebuild = 1
   68: if 'reinstall' in sys.argv:
   69:     sys.argv[sys.argv.index('reinstall')] = 'install'
   70:     rebuild = 1
   71: 
   72: wrap_input = ['symbol','numeric','constant','relational',
   73:               'lst','idx','varidx','power','add','mul',
   74:               'ncmul','pseries','matrix','function','inifcns',
   75:               'function','flags','exvector',
   76:               'indexed','color','clifford','tensor']
   77: 
   78: wrap_input = ['symbol','numeric','constant','relational',
   79:               'lst','power','add','mul',
   80:               'ncmul','pseries','matrix','function','inifcns',
   81:               'function','flags','exvector']
   82: 
   83: #wrap_input += ['indexed','color','clifford','tensor']
   84: 
   85: #wrap_input = ['function','inifcns']
   86: #wrap_input = ['add','mul','power','lst','pseries','relational','matrix','numeric','constant','symbol','varidx']
   87: #wrap_input = ['symbol','function']
   88: #wrap_input = ['symbol','tensor']
   89: #wrap_input = ['symbol','add','mul','lst','numeric','power']
   90: 
   91: wrap_input = ['ex','symbol','numeric','lst','add','mul','power',
   92:               'inifcns','function','relational','seq',
   93:               'constant','matrix']
   94: 
   95: #++++++++++++++++ Parameters ++++++++++++++++
   96: #nof_lst_params = 10   # max 15 for ginac, max 10 for boost.python, min 1
   97: #nof_ncmul_params = 6  # max 6
   98: nof_function_params = 12 # max 12 for ginac (depends also on the code in function_py.cpp)
   99: #++++++++++++++++++++ boost +++++++++++++++++++++
  100: 
  101: boost_dir = '/usr/local/share/boost'
  102: 
  103: if not os.path.isdir(boost_dir):
  104:     print 'boost_dir=%s must be existing directory.'%(`boost_dir`)
  105:     print 'Get Boost from http://www.boost.org/ and fix its path in setup.py'
  106:     sys.exit()
  107: 
  108: bpl_dir = os.path.join(boost_dir,'libs','python','src')
  109: bpl_src = map(lambda f:os.path.join(bpl_dir,f),
  110:               ['classes.cpp','conversions.cpp','extension_class.cpp',
  111:                'functions.cpp','init_function.cpp','module_builder.cpp',
  112:                'objects.cpp','types.cpp'])
  113: 
  114: #++++++++++++++++++++++++++++++++++++++++++++++++
  115: from distutils.core import setup, Extension
  116: 
  117: #+++HACK: replace linker gcc with g++ +++++++++++
  118: from distutils import sysconfig
  119: save_init_posix = sysconfig._init_posix
  120: def my_init_posix():
  121:     save_init_posix()
  122:     g = sysconfig._config_vars
  123:     if g['LDSHARED'][:3]=='gcc':
  124:         print 'my_init_posix: changing LDSHARED =',`g['LDSHARED']`,
  125:         g['LDSHARED'] = 'g++'+g['LDSHARED'][3:]
  126:         print 'to',`g['LDSHARED']`
  127:     if disable_opt and g['OPT'][:6]=='-g -O2':
  128:         print 'my_init_posix: changing OPT =',`g['OPT']`,
  129:         g['OPT'] = '-g'+g['OPT'][6:]
  130:         print 'to',`g['OPT']`
  131: sysconfig._init_posix = my_init_posix
  132: 
  133: #+++++++++++++++++ PyGiNaC version ++++++++++++++
  134: 
  135: wrapper_dir = 'wrappers3'
  136: lib_dir = 'lib3'
  137: 
  138: major_version = 0
  139: minor_version = 3
  140: try: execfile(os.path.join('tools','get_revision.py'))
  141: except: revision_version = 0
  142: version='%d.%d.%d'%(major_version,minor_version,revision_version)
  143: 
  144: #++++++++++++++++ ginac._ginac +++++++++++++++++++++
  145: 
  146: ginac_cpp = os.path.join('src','_ginac.cpp')
  147: 
  148: 
  149: ex_src = [
  150:     os.path.join(wrapper_dir,'ginac_enhancements.cpp'),
  151:     os.path.join(wrapper_dir,'ex_py.cpp'),
  152:     os.path.join(wrapper_dir,'python_repr.cpp'),
  153:     os.path.join(wrapper_dir,'python_str.cpp'),
  154:     os.path.join(wrapper_dir,'pyfunc.cpp'),
  155:     os.path.join(wrapper_dir,'slice.c'),
  156:     ]
  157: 
  158: if gentest:
  159:     import re
  160:     dt_match = re.compile(r'\s*/[*]DT(?P<text>.*?)[*]/',re.M|re.S)
  161:     mdt_match = re.compile(r'\s*/[*]M_DT(?P<text>.*?)[*]/',re.M|re.S)
  162:     fdt_match = re.compile(r'\s*/[*]F_DT(?P<text>.*?)[*]/',re.M|re.S)
  163:     todo_match = re.compile(r'\s*/[*]\s*TODO(?P<text>.*?)[*]/',re.M|re.S)
  164:     fon = os.path.join(lib_dir,'doc','__init__.py')
  165:     fo = open(fon,'w')
  166:     ftodo = open('TODO_py.txt','w')
  167:     fo.write('''#!/usr/bin/env python
  168: import sys,os
  169: from distutils import util
  170: sys.path.insert(0,os.path.abspath(os.path.join("build","lib.%s-%s" % (util.get_platform(),sys.version[0:3]))))
  171: ''')
  172:     ex_methods = []
  173:     for s in wrap_input:
  174:         f = s + '_py.cpp'
  175:         fn = os.path.join(wrapper_dir,f)
  176:         if not os.path.isfile(fn): continue
  177:         m = dt_match.findall(open(fn,'r').read())
  178:         if m:
  179:             fo.write('\nclass test_%s:\n    """\n'%s)
  180:             fo.write(''.join(m))
  181:             fo.write('\n"""\n')
  182:         m = mdt_match.findall(open(fn,'r').read())
  183:         if m:
  184:             for l in m:
  185:                 p,d=l.split('\n',1)
  186:                 ex_methods.append('''\n    def %s:\n        """%s"""\n'''%(p.strip(),d.strip()))
  187:         m = todo_match.findall(open(fn,'r').read())
  188:         if m:
  189:             ftodo.write('In file %s:\n'%fn)
  190:             ftodo.write('\n'.join(map(lambda s:s.strip(),m))+'\n')
  191:         m = fdt_match.findall(open(fn,'r').read())
  192:         if m:
  193:             for l in m:
  194:                 p,d=l.split('\n',1)
  195:                 fo.write('''def %s:\n    """%s"""\n'''%(p.strip(),d.strip()))
  196:     fo.write('''\
  197: class ex:
  198: %s
  199: def _test():
  200:     import doctest
  201:     import __init__ as tt
  202:     return doctest.testmod(tt)
  203: if __name__ == "__main__":
  204:     _test()\n'''%('\n'.join(ex_methods)))
  205:     fo.close()
  206:     ftodo.close()
  207:     if gentest==2:
  208:         os.system('%s %s -v'%(sys.executable,fon))
  209:     else:
  210:         os.system('%s %s'%(sys.executable,fon))
  211: 
  212: if len(sys.argv)==1:
  213:     print "PyGiNaC Version",version
  214:     sys.exit()
  215: 
  216: if rebuild:
  217:     print 'Creating file',os.path.join(wrapper_dir,'ex_py_subs.cpp')
  218:     f=open(os.path.join(wrapper_dir,'ex_py_subs.cpp'),'w')
  219:     for n in wrap_input:
  220:         ff = n + '_py.cpp'
  221:         fn = os.path.join(wrapper_dir,ff)
  222:         if n=='ex': continue
  223:         if not os.path.isfile(fn):
  224:             print 'File does not exist:',fn,'    Skipping.'
  225:             continue
  226:         f.write('#include "%s"\n'%ff)
  227:     f.write('#undef PYGINAC_DEFS\n#undef PYGINAC_EX_PROTOS\n#undef PYGINAC_PROTOS\n')
  228:     f.close()
  229:     os.system('touch wrappers3/ex_py.cpp')
  230:     print 'Creating file',os.path.join(wrapper_dir,'function_py_subs.cpp')
  231:     f=open(os.path.join(wrapper_dir,'function_py_subs.cpp'),'w')
  232:     protos,impl = [],[]
  233:     for k in ['eval','evalf']:
  234:         for i in range(nof_function_params+1):
  235:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]+['const GiNaC::ex & ser']
  236:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  237:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i,' '.join(a2)))
  238:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  239:     if 1:
  240:         k = 'derivative'
  241:         for i in range(nof_function_params+1):
  242:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]
  243:             a1 += ['const GiNaC::ex & ser','unsigned n']
  244:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  245:             a2 += ['args.set_item(%s,n);'%i]
  246:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i+1,' '.join(a2)))
  247:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  248:     if 1:
  249:         k = 'series'
  250:         for i in range(nof_function_params+1):
  251:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]
  252:             a1 += ['const GiNaC::ex & ser']
  253:             a1 += ['const GiNaC::relational & rel']
  254:             a1 += ['int order']
  255:             a1 += ['unsigned opt']
  256:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  257:             a2+= ['args.set_item(%s,rel);'%i]
  258:             a2+= ['args.set_item(%s,order);'%(i+1)]
  259:             a2+= ['args.set_item(%s,opt);'%(i+2)]
  260:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i+3,' '.join(a2)))
  261:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  262:     f.write('#ifdef PYGINAC_PROTOS\n')
  263:     f.write('\n'.join(protos))
  264:     f.write('#else\n')
  265:     f.write('\n'.join(impl))
  266:     f.write('#endif\n')
  267:     f.close() 
  268:            
  269: ginac_ext = Extension('ginac._ginac3',
  270:                       sources=ex_src+bpl_src,
  271:                       include_dirs=[boost_dir,wrapper_dir],
  272:                       libraries=['ginac','cln'],
  273:                       library_dirs=[],
  274:                       )
  275: 
  276: #++++++++++++++++++++ setup +++++++++++++++++++++
  277: 
  278: setup (name = "PyGiNaC",
  279:        version = version,
  280:        description = "PyGiNaC --- the wrapper of C++ library GiNaC to Python",
  281:        author = "Pearu Peterson",
  282:        author_email = "pearu@cens.ioc.ee",
  283:        maintainer = "Pearu Peterson",
  284:        maintainer_email = "pearu@cens.ioc.ee",
  285:        licence = "LGPL",
  286:        long_description= """
  287: GiNaC is an open framework for symbolic computation within the C++
  288: programming language (http://www.ginac.de/).
  289: PyGiNaC is a Python extension package that implements a complete
  290: and transparent interface to the GiNaC library.
  291: """,
  292:        url = "http://cens.ioc.ee/projects/pyginac/",
  293:        ext_modules = [ ginac_ext ],
  294:        packages = ['ginac','ginac.doc'],
  295:        package_dir = {'ginac': lib_dir,
  296:                       'ginac.doc':os.path.join(lib_dir,'doc') },
  297:        )
  298: 
  299: print "PyGiNaC Version",version

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>