xref: /petsc/src/binding/petsc4py/setup.py (revision 3594a89dd4e17cdeb3c4d4dd4e0166b2e32eea57)
15808f684SSatish Balay#!/usr/bin/env python
25808f684SSatish Balay# Author:  Lisandro Dalcin
35808f684SSatish Balay# Contact: dalcinl@gmail.com
45808f684SSatish Balay
55808f684SSatish Balay"""
65808f684SSatish BalayPETSc for Python
75808f684SSatish Balay"""
85808f684SSatish Balay
95808f684SSatish Balayimport sys
105808f684SSatish Balayimport os
115808f684SSatish Balayimport re
125808f684SSatish Balay
135808f684SSatish Balaytry:
145808f684SSatish Balay    import setuptools
155808f684SSatish Balayexcept ImportError:
165808f684SSatish Balay    setuptools = None
175808f684SSatish Balay
185808f684SSatish Balaypyver = sys.version_info[:2]
195808f684SSatish Balayif pyver < (2, 6) or (3, 0) <= pyver < (3, 2):
205808f684SSatish Balay    raise RuntimeError("Python version 2.6, 2.7 or >= 3.2 required")
215808f684SSatish Balayif pyver == (2, 6) or pyver == (3, 2):
225808f684SSatish Balay    sys.stderr.write(
235808f684SSatish Balay        "WARNING: Python %d.%d is not supported.\n" % pyver)
245808f684SSatish Balay
255808f684SSatish Balay# --------------------------------------------------------------------
265808f684SSatish Balay# Metadata
275808f684SSatish Balay# --------------------------------------------------------------------
285808f684SSatish Balay
295808f684SSatish Balaytopdir = os.path.abspath(os.path.dirname(__file__))
305808f684SSatish Balay
315808f684SSatish Balayfrom conf.metadata import metadata
325808f684SSatish Balay
335808f684SSatish Balaydef name():
345808f684SSatish Balay    return 'petsc4py'
355808f684SSatish Balay
365808f684SSatish Balaydef version():
375808f684SSatish Balay    with open(os.path.join(topdir, 'src', '__init__.py')) as f:
385808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
395808f684SSatish Balay        return m.groups()[0]
405808f684SSatish Balay
415808f684SSatish Balaydef description():
425808f684SSatish Balay    with open(os.path.join(topdir, 'DESCRIPTION.rst')) as f:
435808f684SSatish Balay        return f.read()
445808f684SSatish Balay
455808f684SSatish Balayname     = name()
465808f684SSatish Balayversion  = version()
475808f684SSatish Balay
485808f684SSatish Balayurl      = 'https://gitlab.com/petsc/petsc4py'
495808f684SSatish Balaypypiroot = 'https://pypi.io/packages/source/%s/%s/' % (name[0], name)
505808f684SSatish Balaydownload = pypiroot + '%(name)s-%(version)s.tar.gz' % vars()
515808f684SSatish Balay
525808f684SSatish Balaydevstat  = ['Development Status :: 5 - Production/Stable']
535808f684SSatish Balaykeywords = ['PETSc', 'MPI']
545808f684SSatish Balay
555808f684SSatish Balaymetadata['name'] = name
565808f684SSatish Balaymetadata['version'] = version
575808f684SSatish Balaymetadata['description'] = __doc__.strip()
585808f684SSatish Balaymetadata['long_description'] = description()
595808f684SSatish Balaymetadata['keywords'] += keywords
605808f684SSatish Balaymetadata['classifiers'] += devstat
615808f684SSatish Balaymetadata['url'] = url
625808f684SSatish Balaymetadata['download_url'] = download
635808f684SSatish Balay
645808f684SSatish Balaymetadata['provides'] = ['petsc4py']
655808f684SSatish Balaymetadata['requires'] = ['numpy']
665808f684SSatish Balay
675808f684SSatish Balay# --------------------------------------------------------------------
685808f684SSatish Balay# Extension modules
695808f684SSatish Balay# --------------------------------------------------------------------
705808f684SSatish Balay
715808f684SSatish Balaydef get_ext_modules(Extension):
725808f684SSatish Balay    from os   import walk, path
735808f684SSatish Balay    from glob import glob
745808f684SSatish Balay    depends = []
755808f684SSatish Balay    for pth, dirs, files in walk('src'):
765808f684SSatish Balay        depends += glob(path.join(pth, '*.h'))
775808f684SSatish Balay        depends += glob(path.join(pth, '*.c'))
785808f684SSatish Balay    try:
795808f684SSatish Balay        import numpy
805808f684SSatish Balay        numpy_includes = [numpy.get_include()]
815808f684SSatish Balay    except ImportError:
825808f684SSatish Balay        numpy_includes = []
835808f684SSatish Balay    return [Extension('petsc4py.lib.PETSc',
845808f684SSatish Balay                      sources=['src/PETSc.c',
855808f684SSatish Balay                               'src/libpetsc4py.c',
865808f684SSatish Balay                               ],
875808f684SSatish Balay                      include_dirs=['src/include',
885808f684SSatish Balay                                    ] + numpy_includes,
895808f684SSatish Balay                      depends=depends)]
905808f684SSatish Balay
915808f684SSatish Balay# --------------------------------------------------------------------
925808f684SSatish Balay# Setup
935808f684SSatish Balay# --------------------------------------------------------------------
945808f684SSatish Balay
955808f684SSatish Balayfrom conf.petscconf import setup, Extension
965808f684SSatish Balayfrom conf.petscconf import config, build, build_src, build_ext, install
975808f684SSatish Balayfrom conf.petscconf import clean, test, sdist
985808f684SSatish Balay
995808f684SSatish BalayCYTHON = '0.22'
1005808f684SSatish Balay
1015808f684SSatish Balaydef run_setup():
1025808f684SSatish Balay    setup_args = metadata.copy()
1035808f684SSatish Balay    if setuptools:
1045808f684SSatish Balay        setup_args['zip_safe'] = False
1055808f684SSatish Balay        setup_args['install_requires'] = ['numpy']
1065808f684SSatish Balay        PETSC_DIR = os.environ.get('PETSC_DIR')
1075808f684SSatish Balay        if not (PETSC_DIR and os.path.isdir(PETSC_DIR)):
1085808f684SSatish Balay            vstr = setup_args['version'].split('.')[:2]
1095808f684SSatish Balay            x, y = int(vstr[0]), int(vstr[1])
1105808f684SSatish Balay            PETSC = ">=%s.%s,<%s.%s" % (x, y, x, y+1)
1115808f684SSatish Balay            setup_args['install_requires'] += ['petsc'+PETSC]
1125808f684SSatish Balay    if setuptools:
1135808f684SSatish Balay        src = os.path.join('src', 'petsc4py.PETSc.c')
1145808f684SSatish Balay        has_src = os.path.exists(os.path.join(topdir, src))
1155808f684SSatish Balay        has_git = os.path.isdir(os.path.join(topdir, '.git'))
1165808f684SSatish Balay        has_hg  = os.path.isdir(os.path.join(topdir, '.hg'))
117*3594a89dSLisandro Dalcin        suffix = os.path.join('src', 'binding', 'petsc4py')
118*3594a89dSLisandro Dalcin        in_petsc = topdir.endswith(os.path.sep + suffix)
119*3594a89dSLisandro Dalcin        if not has_src or has_git or has_hg or in_petsc:
1205808f684SSatish Balay            setup_args['setup_requires'] = ['Cython>='+CYTHON]
1215808f684SSatish Balay    #
1225808f684SSatish Balay    setup(packages     = ['petsc4py',
1235808f684SSatish Balay                          'petsc4py.lib',],
1245808f684SSatish Balay          package_dir  = {'petsc4py'     : 'src',
1255808f684SSatish Balay                          'petsc4py.lib' : 'src/lib'},
1265808f684SSatish Balay          package_data = {'petsc4py'     : ['include/petsc4py/*.h',
1275808f684SSatish Balay                                            'include/petsc4py/*.i',
1285808f684SSatish Balay                                            'include/petsc4py/*.pxd',
1295808f684SSatish Balay                                            'include/petsc4py/*.pxi',
1305808f684SSatish Balay                                            'include/petsc4py/*.pyx',
1315808f684SSatish Balay                                            'PETSc.pxd',],
1325808f684SSatish Balay                          'petsc4py.lib' : ['petsc.cfg'],},
1335808f684SSatish Balay          ext_modules  = get_ext_modules(Extension),
1345808f684SSatish Balay          cmdclass     = {'config'     : config,
1355808f684SSatish Balay                          'build'      : build,
1365808f684SSatish Balay                          'build_src'  : build_src,
1375808f684SSatish Balay                          'build_ext'  : build_ext,
1385808f684SSatish Balay                          'install'    : install,
1395808f684SSatish Balay                          'clean'      : clean,
1405808f684SSatish Balay                          'test'       : test,
1415808f684SSatish Balay                          'sdist'      : sdist,
1425808f684SSatish Balay                          },
1435808f684SSatish Balay          **setup_args)
1445808f684SSatish Balay
1455808f684SSatish Balaydef chk_cython(VERSION):
1465808f684SSatish Balay    from distutils import log
1475808f684SSatish Balay    from distutils.version import LooseVersion
1485808f684SSatish Balay    from distutils.version import StrictVersion
1495808f684SSatish Balay    warn = lambda msg='': sys.stderr.write(msg+'\n')
1505808f684SSatish Balay    #
1515808f684SSatish Balay    try:
1525808f684SSatish Balay        import Cython
1535808f684SSatish Balay    except ImportError:
1545808f684SSatish Balay        warn("*"*80)
1555808f684SSatish Balay        warn()
1565808f684SSatish Balay        warn(" You need to generate C source files with Cython!!")
1575808f684SSatish Balay        warn(" Download and install Cython <http://www.cython.org>")
1585808f684SSatish Balay        warn()
1595808f684SSatish Balay        warn("*"*80)
1605808f684SSatish Balay        return False
1615808f684SSatish Balay    #
1625808f684SSatish Balay    try:
1635808f684SSatish Balay        CYTHON_VERSION = Cython.__version__
1645808f684SSatish Balay    except AttributeError:
1655808f684SSatish Balay        from Cython.Compiler.Version import version as CYTHON_VERSION
1665808f684SSatish Balay    REQUIRED = VERSION
1675808f684SSatish Balay    m = re.match(r"(\d+\.\d+(?:\.\d+)?).*", CYTHON_VERSION)
1685808f684SSatish Balay    if m:
1695808f684SSatish Balay        Version = StrictVersion
1705808f684SSatish Balay        AVAILABLE = m.groups()[0]
1715808f684SSatish Balay    else:
1725808f684SSatish Balay        Version = LooseVersion
1735808f684SSatish Balay        AVAILABLE = CYTHON_VERSION
1745808f684SSatish Balay    if (REQUIRED is not None and
1755808f684SSatish Balay        Version(AVAILABLE) < Version(REQUIRED)):
1765808f684SSatish Balay        warn("*"*80)
1775808f684SSatish Balay        warn()
1785808f684SSatish Balay        warn(" You need to install Cython %s (you have version %s)"
1795808f684SSatish Balay             % (REQUIRED, CYTHON_VERSION))
1805808f684SSatish Balay        warn(" Download and install Cython <http://www.cython.org>")
1815808f684SSatish Balay        warn()
1825808f684SSatish Balay        warn("*"*80)
1835808f684SSatish Balay        return False
1845808f684SSatish Balay    #
1855808f684SSatish Balay    return True
1865808f684SSatish Balay
1875808f684SSatish Balaydef run_cython(source, depends=(), includes=(),
1885808f684SSatish Balay               destdir_c=None, destdir_h=None,
1895808f684SSatish Balay               wdir=None, force=False, VERSION=None):
1905808f684SSatish Balay    from glob import glob
1915808f684SSatish Balay    from distutils import log
1925808f684SSatish Balay    from distutils import dep_util
1935808f684SSatish Balay    from distutils.errors import DistutilsError
1945808f684SSatish Balay    target = os.path.splitext(source)[0]+'.c'
1955808f684SSatish Balay    cwd = os.getcwd()
1965808f684SSatish Balay    try:
1975808f684SSatish Balay        if wdir: os.chdir(wdir)
1985808f684SSatish Balay        alldeps = [source]
1995808f684SSatish Balay        for dep in depends:
2005808f684SSatish Balay            alldeps += glob(dep)
2015808f684SSatish Balay        if not (force or dep_util.newer_group(alldeps, target)):
2025808f684SSatish Balay            log.debug("skipping '%s' -> '%s' (up-to-date)",
2035808f684SSatish Balay                      source, target)
2045808f684SSatish Balay            return
2055808f684SSatish Balay    finally:
2065808f684SSatish Balay        os.chdir(cwd)
2075808f684SSatish Balay    if not chk_cython(VERSION):
2085808f684SSatish Balay        raise DistutilsError("requires Cython>=%s" % VERSION)
2095808f684SSatish Balay    log.info("cythonizing '%s' -> '%s'", source, target)
2105808f684SSatish Balay    from conf.cythonize import cythonize
2115808f684SSatish Balay    err = cythonize(source,
2125808f684SSatish Balay                    includes=includes,
2135808f684SSatish Balay                    destdir_c=destdir_c,
2145808f684SSatish Balay                    destdir_h=destdir_h,
2155808f684SSatish Balay                    wdir=wdir)
2165808f684SSatish Balay    if err:
2175808f684SSatish Balay        raise DistutilsError(
2185808f684SSatish Balay            "Cython failure: '%s' -> '%s'" % (source, target))
2195808f684SSatish Balay
2205808f684SSatish Balaydef build_sources(cmd):
2215808f684SSatish Balay    from os.path import exists, isdir, join
2225808f684SSatish Balay    if (exists(join('src', 'petsc4py.PETSc.c')) and
2235808f684SSatish Balay        not (isdir('.hg') or isdir('.git')) and
2245808f684SSatish Balay        not cmd.force): return
2255808f684SSatish Balay    # petsc4py.PETSc
2265808f684SSatish Balay    source = 'petsc4py.PETSc.pyx'
2275808f684SSatish Balay    depends = ('include/*/*.pxd',
2285808f684SSatish Balay               'PETSc/*.pyx',
2295808f684SSatish Balay               'PETSc/*.pxi',)
2305808f684SSatish Balay    includes = ['include']
2315808f684SSatish Balay    destdir_h = os.path.join('include', 'petsc4py')
2325808f684SSatish Balay    run_cython(source, depends, includes,
2335808f684SSatish Balay               destdir_c=None, destdir_h=destdir_h, wdir='src',
2345808f684SSatish Balay               force=cmd.force, VERSION=CYTHON)
2355808f684SSatish Balay    # libpetsc4py
2365808f684SSatish Balay    source = os.path.join('libpetsc4py', 'libpetsc4py.pyx')
2375808f684SSatish Balay    depends = ['include/petsc4py/*.pxd',
2385808f684SSatish Balay               'libpetsc4py/*.pyx',
2395808f684SSatish Balay               'libpetsc4py/*.pxi']
2405808f684SSatish Balay    includes = ['include']
2415808f684SSatish Balay    run_cython(source, depends, includes,
2425808f684SSatish Balay               destdir_c=None, destdir_h=None, wdir='src',
2435808f684SSatish Balay               force=cmd.force, VERSION=CYTHON)
2445808f684SSatish Balay
2455808f684SSatish Balaybuild_src.run = build_sources
2465808f684SSatish Balay
2475808f684SSatish Balaydef run_testsuite(cmd):
2485808f684SSatish Balay    from distutils.errors import DistutilsError
2495808f684SSatish Balay    sys.path.insert(0, 'test')
2505808f684SSatish Balay    try:
2515808f684SSatish Balay        from runtests import main
2525808f684SSatish Balay    finally:
2535808f684SSatish Balay        del sys.path[0]
2545808f684SSatish Balay    if cmd.dry_run:
2555808f684SSatish Balay        return
2565808f684SSatish Balay    args = cmd.args[:] or []
2575808f684SSatish Balay    if cmd.verbose < 1:
2585808f684SSatish Balay        args.insert(0,'-q')
2595808f684SSatish Balay    if cmd.verbose > 1:
2605808f684SSatish Balay        args.insert(0,'-v')
2615808f684SSatish Balay    err = main(args)
2625808f684SSatish Balay    if err:
2635808f684SSatish Balay        raise DistutilsError("test")
2645808f684SSatish Balay
2655808f684SSatish Balaytest.run = run_testsuite
2665808f684SSatish Balay
2675808f684SSatish Balay# --------------------------------------------------------------------
2685808f684SSatish Balay
2695808f684SSatish Balaydef main():
2705808f684SSatish Balay    run_setup()
2715808f684SSatish Balay
2725808f684SSatish Balayif __name__ == '__main__':
2735808f684SSatish Balay    main()
2745808f684SSatish Balay
2755808f684SSatish Balay# --------------------------------------------------------------------
276