File:  [CENS] / python / pyGiNaC / setup3.py
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Wed Apr 25 19:22:25 2001 UTC (17 years, 5 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
Finished matrix, impl. lsolve, removed redudant Py_INCREF

    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',
   82:               'flags','exvector']
   83: 
   84: #wrap_input += ['indexed','color','clifford','tensor']
   85: 
   86: #wrap_input = ['function','inifcns']
   87: #wrap_input = ['add','mul','power','lst','pseries','relational','matrix','numeric','constant','symbol','varidx']
   88: #wrap_input = ['symbol','function']
   89: #wrap_input = ['symbol','tensor']
   90: #wrap_input = ['symbol','add','mul','lst','numeric','power']
   91: 
   92: wrap_input = ['ex','symbol','numeric','lst','add','mul','power',
   93:               'inifcns','function','relational','seq',
   94:               'constant','matrix']
   95: 
   96: #++++++++++++++++ Parameters ++++++++++++++++
   97: #nof_lst_params = 10   # max 15 for ginac, max 10 for boost.python, min 1
   98: #nof_ncmul_params = 6  # max 6
   99: nof_function_params = 12 # max 12 for ginac (depends also on the code in function_py.cpp)
  100: #++++++++++++++++++++ boost +++++++++++++++++++++
  101: 
  102: boost_dir = '/usr/local/share/boost'
  103: 
  104: if not os.path.isdir(boost_dir):
  105:     print 'boost_dir=%s must be existing directory.'%(`boost_dir`)
  106:     print 'Get Boost from http://www.boost.org/ and fix its path in setup.py'
  107:     sys.exit()
  108: 
  109: bpl_dir = os.path.join(boost_dir,'libs','python','src')
  110: bpl_src = map(lambda f:os.path.join(bpl_dir,f),
  111:               ['classes.cpp','conversions.cpp','extension_class.cpp',
  112:                'functions.cpp','init_function.cpp','module_builder.cpp',
  113:                'objects.cpp','types.cpp'])
  114: 
  115: #++++++++++++++++++++++++++++++++++++++++++++++++
  116: from distutils.core import setup, Extension
  117: 
  118: #+++HACK: replace linker gcc with g++ +++++++++++
  119: from distutils import sysconfig
  120: save_init_posix = sysconfig._init_posix
  121: def my_init_posix():
  122:     save_init_posix()
  123:     g = sysconfig._config_vars
  124:     if g['LDSHARED'][:3]=='gcc':
  125:         print 'my_init_posix: changing LDSHARED =',`g['LDSHARED']`,
  126:         g['LDSHARED'] = 'g++'+g['LDSHARED'][3:]
  127:         print 'to',`g['LDSHARED']`
  128:     if disable_opt and g['OPT'][:6]=='-g -O2':
  129:         print 'my_init_posix: changing OPT =',`g['OPT']`,
  130:         g['OPT'] = '-g'+g['OPT'][6:]
  131:         print 'to',`g['OPT']`
  132: sysconfig._init_posix = my_init_posix
  133: 
  134: #+++++++++++++++++ PyGiNaC version ++++++++++++++
  135: 
  136: wrapper_dir = 'wrappers3'
  137: lib_dir = 'lib3'
  138: 
  139: major_version = 0
  140: minor_version = 3
  141: try: execfile(os.path.join('tools','get_revision.py'))
  142: except: revision_version = 0
  143: version='%d.%d.%d'%(major_version,minor_version,revision_version)
  144: 
  145: #++++++++++++++++ ginac._ginac +++++++++++++++++++++
  146: 
  147: ginac_cpp = os.path.join('src','_ginac.cpp')
  148: 
  149: 
  150: ex_src = [
  151:     os.path.join(wrapper_dir,'ginac_enhancements.cpp'),
  152:     os.path.join(wrapper_dir,'ex_py.cpp'),
  153:     os.path.join(wrapper_dir,'python_repr.cpp'),
  154:     os.path.join(wrapper_dir,'python_str.cpp'),
  155:     os.path.join(wrapper_dir,'pyfunc.cpp'),
  156:     os.path.join(wrapper_dir,'slice.c'),
  157:     ]
  158: 
  159: if gentest:
  160:     import re
  161:     dt_match = re.compile(r'\s*/[*]DT(?P<text>.*?)[*]/',re.M|re.S)
  162:     mdt_match = re.compile(r'\s*/[*]M_DT(?P<text>.*?)[*]/',re.M|re.S)
  163:     fdt_match = re.compile(r'\s*/[*]F_DT(?P<text>.*?)[*]/',re.M|re.S)
  164:     todo_match = re.compile(r'\s*/[*]\s*TODO(?P<text>.*?)[*]/',re.M|re.S)
  165:     fon = os.path.join(lib_dir,'doc','__init__.py')
  166:     fo = open(fon,'w')
  167:     ftodo = open('TODO_py.txt','w')
  168:     fo.write('''#!/usr/bin/env python
  169: import sys,os
  170: from distutils import util
  171: sys.path.insert(0,os.path.abspath(os.path.join("build","lib.%s-%s" % (util.get_platform(),sys.version[0:3]))))
  172: ''')
  173:     ex_methods = []
  174:     i = 0
  175:     for s in wrap_input:
  176:         i += 1
  177:         f = s + '_py.cpp'
  178:         fn = os.path.join(wrapper_dir,f)
  179:         if not os.path.isfile(fn): continue
  180:         m = dt_match.findall(open(fn,'r').read())
  181:         if m:
  182:             fo.write('\nclass test_%.2i_%s:\n    """\n'%(i,s))
  183:             fo.write(''.join(m))
  184:             fo.write('\n"""\n')
  185:         m = mdt_match.findall(open(fn,'r').read())
  186:         if m:
  187:             for l in m:
  188:                 p,d=l.split('\n',1)
  189:                 ex_methods.append('''\n    def %s:\n        """%s"""\n'''%(p.strip(),d.strip()))
  190:         m = todo_match.findall(open(fn,'r').read())
  191:         if m:
  192:             ftodo.write('In %s:\n'%fn)
  193:             ftodo.write('\n'.join(map(lambda s:'\t'+s.strip(),m))+'\n')
  194:         m = fdt_match.findall(open(fn,'r').read())
  195:         if m:
  196:             for l in m:
  197:                 p,d=l.split('\n',1)
  198:                 fo.write('''def %s:\n    """%s"""\n'''%(p.strip(),d.strip()))
  199:     fo.write('''\
  200: class ex:
  201: %s
  202: def _test():
  203:     import doctest
  204:     import __init__ as tt
  205:     return doctest.testmod(tt)
  206: if __name__ == "__main__":
  207:     _test()\n'''%('\n'.join(ex_methods)))
  208:     fo.close()
  209:     ftodo.close()
  210:     if gentest==2:
  211:         os.system('%s %s -v'%(sys.executable,fon))
  212:     else:
  213:         os.system('%s %s'%(sys.executable,fon))
  214: 
  215: if len(sys.argv)==1:
  216:     print "PyGiNaC Version",version
  217:     sys.exit()
  218: 
  219: if rebuild:
  220:     print 'Creating file',os.path.join(wrapper_dir,'ex_py_subs.cpp')
  221:     f=open(os.path.join(wrapper_dir,'ex_py_subs.cpp'),'w')
  222:     for n in wrap_input:
  223:         ff = n + '_py.cpp'
  224:         fn = os.path.join(wrapper_dir,ff)
  225:         if n=='ex': continue
  226:         if not os.path.isfile(fn):
  227:             print 'File does not exist:',fn,'    Skipping.'
  228:             continue
  229:         f.write('#include "%s"\n'%ff)
  230:     f.write('#undef PYGINAC_DEFS\n#undef PYGINAC_EX_PROTOS\n#undef PYGINAC_PROTOS\n')
  231:     f.close()
  232:     os.system('touch wrappers3/ex_py.cpp')
  233:     print 'Creating file',os.path.join(wrapper_dir,'function_py_subs.cpp')
  234:     f=open(os.path.join(wrapper_dir,'function_py_subs.cpp'),'w')
  235:     protos,impl = [],[]
  236:     for k in ['eval','evalf']:
  237:         for i in range(nof_function_params+1):
  238:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]+['const GiNaC::ex & ser']
  239:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  240:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i,' '.join(a2)))
  241:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  242:     if 1:
  243:         k = 'derivative'
  244:         for i in range(nof_function_params+1):
  245:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]
  246:             a1 += ['const GiNaC::ex & ser','unsigned n']
  247:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  248:             a2 += ['args.set_item(%s,n);'%i]
  249:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i+1,' '.join(a2)))
  250:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  251:     if 1:
  252:         k = 'series'
  253:         for i in range(nof_function_params+1):
  254:             a1 = ['const GiNaC::ex & a'+`j` for j in range(i)]
  255:             a1 += ['const GiNaC::ex & ser']
  256:             a1 += ['const GiNaC::relational & rel']
  257:             a1 += ['int order']
  258:             a1 += ['unsigned opt']
  259:             a2 = ['args.set_item(%s,a%s);'%(j,j) for j in range(i)]
  260:             a2+= ['args.set_item(%s,rel);'%i]
  261:             a2+= ['args.set_item(%s,order);'%(i+1)]
  262:             a2+= ['args.set_item(%s,opt);'%(i+2)]
  263:             impl.append('PYGINAC_CB_FUNC(%s,%s,(%s),%s,%s)\n'%(k,i,', '.join(a1),i+3,' '.join(a2)))
  264:             protos.append('PYGINAC_CB_FUNC_PROTO(%s,%s,(%s));\n'%(k,i,', '.join(a1)))
  265:     f.write('#ifdef PYGINAC_PROTOS\n')
  266:     f.write('\n'.join(protos))
  267:     f.write('#else\n')
  268:     f.write('\n'.join(impl))
  269:     f.write('#endif\n')
  270:     f.close() 
  271:            
  272: ginac_ext = Extension('ginac._ginac3',
  273:                       sources=ex_src+bpl_src,
  274:                       include_dirs=[boost_dir,wrapper_dir],
  275:                       libraries=['ginac','cln'],
  276:                       library_dirs=[],
  277:                       )
  278: 
  279: #++++++++++++++++++++ setup +++++++++++++++++++++
  280: 
  281: setup (name = "PyGiNaC",
  282:        version = version,
  283:        description = "PyGiNaC --- the wrapper of C++ library GiNaC to Python",
  284:        author = "Pearu Peterson",
  285:        author_email = "pearu@cens.ioc.ee",
  286:        maintainer = "Pearu Peterson",
  287:        maintainer_email = "pearu@cens.ioc.ee",
  288:        licence = "LGPL",
  289:        long_description= """
  290: GiNaC is an open framework for symbolic computation within the C++
  291: programming language (http://www.ginac.de/).
  292: PyGiNaC is a Python extension package that implements a complete
  293: and transparent interface to the GiNaC library.
  294: """,
  295:        url = "http://cens.ioc.ee/projects/pyginac/",
  296:        ext_modules = [ ginac_ext ],
  297:        packages = ['ginac','ginac.doc'],
  298:        package_dir = {'ginac': lib_dir,
  299:                       'ginac.doc':os.path.join(lib_dir,'doc') },
  300:        )
  301: 
  302: print "PyGiNaC Version",version

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