xref: /petsc/src/binding/petsc4py/setup.py (revision f09792b67b5e11667c1bd39897f59ceef2b02fe1)
15808f684SSatish Balay#!/usr/bin/env python
25808f684SSatish Balay# Author:  Lisandro Dalcin
35808f684SSatish Balay# Contact: dalcinl@gmail.com
45808f684SSatish Balay
55808f684SSatish Balayimport re
6fb83dddaSLisandro Dalcinimport os
7fb83dddaSLisandro Dalcinimport sys
85808f684SSatish Balay
95808f684SSatish Balaytry:
105808f684SSatish Balay    import setuptools
115808f684SSatish Balayexcept ImportError:
125808f684SSatish Balay    setuptools = None
135808f684SSatish Balay
14f46a955bSLisandro Dalcintopdir = os.path.abspath(os.path.dirname(__file__))
15f46a955bSLisandro Dalcinsys.path.insert(0, os.path.join(topdir, 'conf'))
16f46a955bSLisandro Dalcin
175808f684SSatish Balaypyver = sys.version_info[:2]
181e83877aSSatish Balayif pyver < (2, 6) or (3, 0) <= pyver < (3, 2):
191e83877aSSatish Balay    raise RuntimeError("Python version 2.6, 2.7 or >= 3.2 required")
201e83877aSSatish Balayif pyver == (2, 6) or pyver == (3, 2):
211e83877aSSatish Balay    sys.stderr.write(
221e83877aSSatish Balay        "WARNING: Python %d.%d is not supported.\n" % pyver)
231e83877aSSatish Balay
24f46a955bSLisandro DalcinPNAME = 'PETSc'
25f46a955bSLisandro DalcinEMAIL = 'petsc-maint@mcs.anl.gov'
26f46a955bSLisandro DalcinPLIST = [PNAME]
27fb83dddaSLisandro Dalcin
285808f684SSatish Balay# --------------------------------------------------------------------
295808f684SSatish Balay# Metadata
305808f684SSatish Balay# --------------------------------------------------------------------
315808f684SSatish Balay
32f46a955bSLisandro Dalcindef F(string):
33f46a955bSLisandro Dalcin    return string.format(
34f46a955bSLisandro Dalcin        Name=PNAME,
35f46a955bSLisandro Dalcin        name=PNAME.lower(),
36f46a955bSLisandro Dalcin        pyname=PNAME.lower()+'4py',
37f46a955bSLisandro Dalcin    )
385808f684SSatish Balay
39f46a955bSLisandro Dalcindef get_name():
40f46a955bSLisandro Dalcin    return F('{pyname}')
415808f684SSatish Balay
42f46a955bSLisandro Dalcindef get_version():
43f46a955bSLisandro Dalcin    try:
44f46a955bSLisandro Dalcin        return get_version.result
45f46a955bSLisandro Dalcin    except AttributeError:
46f46a955bSLisandro Dalcin        pass
47f46a955bSLisandro Dalcin    pkg_init_py = os.path.join(F('{pyname}'), '__init__.py')
48f46a955bSLisandro Dalcin    with open(os.path.join(topdir, 'src', pkg_init_py)) as f:
495808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
50f46a955bSLisandro Dalcin    version = m.groups()[0]
51f46a955bSLisandro Dalcin    get_version.result = version
52f46a955bSLisandro Dalcin    return version
535808f684SSatish Balay
545808f684SSatish Balaydef description():
55f46a955bSLisandro Dalcin    return F('{Name} for Python')
56fb83dddaSLisandro Dalcin
57fb83dddaSLisandro Dalcindef long_description():
585808f684SSatish Balay    with open(os.path.join(topdir, 'DESCRIPTION.rst')) as f:
595808f684SSatish Balay        return f.read()
605808f684SSatish Balay
61f46a955bSLisandro Dalcinurl      = F('https://gitlab.com/{name}/{name}')
62f46a955bSLisandro Dalcinpypiroot = F('https://pypi.io/packages/source')
63f46a955bSLisandro Dalcinpypislug = F('{pyname}')[0] + F('/{pyname}')
64f46a955bSLisandro Dalcintarball  = F('{pyname}-%s.tar.gz' % get_version())
65f46a955bSLisandro Dalcindownload = '/'.join([pypiroot, pypislug, tarball])
665808f684SSatish Balay
67fb83dddaSLisandro Dalcinclassifiers = """
68fb83dddaSLisandro DalcinLicense :: OSI Approved :: BSD License
69fb83dddaSLisandro DalcinOperating System :: POSIX
70fb83dddaSLisandro DalcinIntended Audience :: Developers
71fb83dddaSLisandro DalcinIntended Audience :: Science/Research
72fb83dddaSLisandro DalcinProgramming Language :: C
73fb83dddaSLisandro DalcinProgramming Language :: C++
74fb83dddaSLisandro DalcinProgramming Language :: Cython
75fb83dddaSLisandro DalcinProgramming Language :: Python
76fb83dddaSLisandro DalcinProgramming Language :: Python :: 2
77fb83dddaSLisandro DalcinProgramming Language :: Python :: 3
78fb83dddaSLisandro DalcinProgramming Language :: Python :: Implementation :: CPython
79fb83dddaSLisandro DalcinTopic :: Scientific/Engineering
80fb83dddaSLisandro DalcinTopic :: Software Development :: Libraries :: Python Modules
81fb83dddaSLisandro DalcinDevelopment Status :: 5 - Production/Stable
82f46a955bSLisandro Dalcin""".strip().split('\n')
835808f684SSatish Balay
84fb83dddaSLisandro Dalcinkeywords = """
85fb83dddaSLisandro Dalcinscientific computing
86fb83dddaSLisandro Dalcinparallel computing
87fb83dddaSLisandro DalcinMPI
88f46a955bSLisandro Dalcin""".strip().split('\n')
895808f684SSatish Balay
90fb83dddaSLisandro Dalcinplatforms = """
91fb83dddaSLisandro DalcinPOSIX
92fb83dddaSLisandro DalcinLinux
93fb83dddaSLisandro DalcinmacOS
94fb83dddaSLisandro DalcinFreeBSD
95f46a955bSLisandro Dalcin""".strip().split('\n')
96fb83dddaSLisandro Dalcin
97fb83dddaSLisandro Dalcinmetadata = {
98f46a955bSLisandro Dalcin    'name'             : get_name(),
99f46a955bSLisandro Dalcin    'version'          : get_version(),
100fb83dddaSLisandro Dalcin    'description'      : description(),
101fb83dddaSLisandro Dalcin    'long_description' : long_description(),
102fb83dddaSLisandro Dalcin    'url'              : url,
103fb83dddaSLisandro Dalcin    'download_url'     : download,
104f46a955bSLisandro Dalcin    'classifiers'      : classifiers,
105f46a955bSLisandro Dalcin    'keywords'         : keywords + PLIST,
106fb83dddaSLisandro Dalcin    'license'          : 'BSD-2-Clause',
107f46a955bSLisandro Dalcin    'platforms'        : platforms,
108fb83dddaSLisandro Dalcin    'author'           : 'Lisandro Dalcin',
109fb83dddaSLisandro Dalcin    'author_email'     : 'dalcinl@gmail.com',
110f46a955bSLisandro Dalcin    'maintainer'       : F('{Name} Team'),
111f46a955bSLisandro Dalcin    'maintainer_email' : EMAIL,
112fb83dddaSLisandro Dalcin}
113fb83dddaSLisandro Dalcinmetadata.update({
114fb83dddaSLisandro Dalcin    'requires': ['numpy'],
115fb83dddaSLisandro Dalcin})
116fb83dddaSLisandro Dalcin
117fb83dddaSLisandro Dalcinmetadata_extra = {
118833126bdSLisandro Dalcin    'long_description_content_type': 'text/x-rst',
119fb83dddaSLisandro Dalcin}
1205808f684SSatish Balay
1215808f684SSatish Balay# --------------------------------------------------------------------
1225808f684SSatish Balay# Extension modules
1235808f684SSatish Balay# --------------------------------------------------------------------
1245808f684SSatish Balay
125f46a955bSLisandro Dalcindef sources():
126f46a955bSLisandro Dalcin    src = dict(
127f46a955bSLisandro Dalcin        source=F('{pyname}/{Name}.pyx'),
128f46a955bSLisandro Dalcin        depends=[
129f46a955bSLisandro Dalcin            F('{pyname}/*.pyx'),
130f46a955bSLisandro Dalcin            F('{pyname}/*.pxd'),
131f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pyx'),
132f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxd'),
133f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxi'),
134f46a955bSLisandro Dalcin        ],
135f46a955bSLisandro Dalcin        workdir='src',
136f46a955bSLisandro Dalcin    )
137f46a955bSLisandro Dalcin    return [src]
138f46a955bSLisandro Dalcin
139fb83dddaSLisandro Dalcindef extensions():
1408885bf16SLisandro Dalcin    from os import walk
1415808f684SSatish Balay    from glob import glob
1428885bf16SLisandro Dalcin    from os.path import join
143f46a955bSLisandro Dalcin    #
1445808f684SSatish Balay    depends = []
145f46a955bSLisandro Dalcin    glob_join = lambda *args: glob(join(*args))
1465808f684SSatish Balay    for pth, dirs, files in walk('src'):
1478885bf16SLisandro Dalcin        depends += glob_join(pth, '*.h')
1488885bf16SLisandro Dalcin        depends += glob_join(pth, '*.c')
149f46a955bSLisandro Dalcin    for pkg in map(str.lower, reversed(PLIST)):
150f46a955bSLisandro Dalcin        if (pkg.upper()+'_DIR') in os.environ:
151f46a955bSLisandro Dalcin            pd = os.environ[pkg.upper()+'_DIR']
1528885bf16SLisandro Dalcin            pa = os.environ.get('PETSC_ARCH', '')
1538885bf16SLisandro Dalcin            depends += glob_join(pd, 'include', '*.h')
154f46a955bSLisandro Dalcin            depends += glob_join(pd, 'include', pkg, 'private', '*.h')
155f46a955bSLisandro Dalcin            depends += glob_join(pd, pa, 'include', '%sconf.h' % pkg)
156f46a955bSLisandro Dalcin    #
157f46a955bSLisandro Dalcin    include_dirs = []
1580f51ee0fSAlexei Colin    numpy_include = os.environ.get('NUMPY_INCLUDE')
1590f51ee0fSAlexei Colin    if numpy_include is not None:
1600f51ee0fSAlexei Colin        numpy_includes = [numpy_include]
1610f51ee0fSAlexei Colin    else:
1625808f684SSatish Balay        try:
1635808f684SSatish Balay            import numpy
1645808f684SSatish Balay            numpy_includes = [numpy.get_include()]
1655808f684SSatish Balay        except ImportError:
1665808f684SSatish Balay            numpy_includes = []
167f46a955bSLisandro Dalcin    include_dirs.extend(numpy_includes)
168f46a955bSLisandro Dalcin    if F('{pyname}') != 'petsc4py':
169f46a955bSLisandro Dalcin        try:
170f46a955bSLisandro Dalcin            import petsc4py
171f46a955bSLisandro Dalcin            petsc4py_includes = [petsc4py.get_include()]
172f46a955bSLisandro Dalcin        except ImportError:
173f46a955bSLisandro Dalcin            petsc4py_includes = []
174f46a955bSLisandro Dalcin        include_dirs.extend(petsc4py_includes)
175f46a955bSLisandro Dalcin    #
176f46a955bSLisandro Dalcin    ext = dict(
177f46a955bSLisandro Dalcin        name=F('{pyname}.lib.{Name}'),
178f46a955bSLisandro Dalcin        sources=[F('src/{pyname}/{Name}.c')],
179fb83dddaSLisandro Dalcin        depends=depends,
180fb83dddaSLisandro Dalcin        include_dirs=[
181f46a955bSLisandro Dalcin            'src',
182f46a955bSLisandro Dalcin            F('src/{pyname}/include'),
183f46a955bSLisandro Dalcin        ] + include_dirs,
184fb83dddaSLisandro Dalcin        define_macros=[
185fb83dddaSLisandro Dalcin            ('MPICH_SKIP_MPICXX', 1),
186fb83dddaSLisandro Dalcin            ('OMPI_SKIP_MPICXX', 1),
187f46a955bSLisandro Dalcin            ('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'),
188fb83dddaSLisandro Dalcin        ],
189fb83dddaSLisandro Dalcin    )
190f46a955bSLisandro Dalcin    return [ext]
1915808f684SSatish Balay
1925808f684SSatish Balay# --------------------------------------------------------------------
1935808f684SSatish Balay# Setup
1945808f684SSatish Balay# --------------------------------------------------------------------
1955808f684SSatish Balay
196f8c80548SLisandro Dalcindef get_release():
197f46a955bSLisandro Dalcin    suffix = os.path.join('src', 'binding', F('{pyname}'))
198f46a955bSLisandro Dalcin    if not topdir.endswith(os.path.join(os.path.sep, suffix)):
199*f09792b6SLisandro Dalcin        return True
200f8c80548SLisandro Dalcin    release = 1
201f8c80548SLisandro Dalcin    rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir]*3))
202f46a955bSLisandro Dalcin    version_h = os.path.join(rootdir, 'include', F('{name}version.h'))
203f46a955bSLisandro Dalcin    release_macro = '%s_VERSION_RELEASE' % F('{name}').upper()
204f8c80548SLisandro Dalcin    version_re = re.compile(r"#define\s+%s\s+([-]*\d+)" % release_macro)
205f8c80548SLisandro Dalcin    if os.path.exists(version_h) and os.path.isfile(version_h):
206f8c80548SLisandro Dalcin        with open(version_h, 'r') as f:
207f8c80548SLisandro Dalcin            release = int(version_re.search(f.read()).groups()[0])
208f8c80548SLisandro Dalcin    return bool(release)
209f8c80548SLisandro Dalcin
210f8c80548SLisandro Dalcindef requires(pkgname, major, minor, release=True):
211f8c80548SLisandro Dalcin    minor = minor + int(not release)
212f8c80548SLisandro Dalcin    devel = '' if release else '.dev0'
213f8c80548SLisandro Dalcin    vmin = "%s.%s%s" % (major, minor, devel)
214f8c80548SLisandro Dalcin    vmax = "%s.%s" % (major, minor + 1)
215f8c80548SLisandro Dalcin    return "%s>=%s,<%s" % (pkgname, vmin, vmax)
216f8c80548SLisandro Dalcin
2175808f684SSatish Balaydef run_setup():
2185808f684SSatish Balay    setup_args = metadata.copy()
219f8c80548SLisandro Dalcin    vstr = setup_args['version'].split('.')[:2]
220f8c80548SLisandro Dalcin    x, y = tuple(map(int, vstr))
221f8c80548SLisandro Dalcin    release = get_release()
222f8c80548SLisandro Dalcin    if not release:
223f8c80548SLisandro Dalcin        setup_args['version'] = "%d.%d.0.dev0" %(x, y+1)
2245808f684SSatish Balay    if setuptools:
2255808f684SSatish Balay        setup_args['zip_safe'] = False
2265808f684SSatish Balay        setup_args['install_requires'] = ['numpy']
227f46a955bSLisandro Dalcin        for pkg in map(str.lower, PLIST):
228f46a955bSLisandro Dalcin            PKG_DIR = os.environ.get(pkg.upper() + '_DIR')
229f46a955bSLisandro Dalcin            if not (PKG_DIR and os.path.isdir(PKG_DIR)):
230f46a955bSLisandro Dalcin                package = requires(pkg, x, y, release)
231f46a955bSLisandro Dalcin                setup_args['install_requires'] += [package]
232f46a955bSLisandro Dalcin        if F('{pyname}') != 'petsc4py':
233f46a955bSLisandro Dalcin            package = requires('petsc4py', x, y, release)
234f46a955bSLisandro Dalcin            setup_args['install_requires'] += [package]
235fb83dddaSLisandro Dalcin        setup_args.update(metadata_extra)
2365808f684SSatish Balay    #
237f46a955bSLisandro Dalcin    conf = __import__(F('conf{name}'))
238f46a955bSLisandro Dalcin    conf.setup(
239fb83dddaSLisandro Dalcin        packages=[
240f46a955bSLisandro Dalcin            F('{pyname}'),
241f46a955bSLisandro Dalcin            F('{pyname}.lib'),
242fb83dddaSLisandro Dalcin        ],
243f46a955bSLisandro Dalcin        package_dir={'' : 'src'},
244fb83dddaSLisandro Dalcin        package_data={
245f46a955bSLisandro Dalcin            F('{pyname}'): [
246f46a955bSLisandro Dalcin                F('{Name}.pxd'),
247f46a955bSLisandro Dalcin                F('{Name}*.h'),
248f46a955bSLisandro Dalcin                F('include/{pyname}/*.h'),
249f46a955bSLisandro Dalcin                F('include/{pyname}/*.i'),
250fb83dddaSLisandro Dalcin            ],
251f46a955bSLisandro Dalcin            F('{pyname}.lib'): [
252f46a955bSLisandro Dalcin                F('{name}.cfg'),
253fb83dddaSLisandro Dalcin            ],
254fb83dddaSLisandro Dalcin        },
255f46a955bSLisandro Dalcin        cython_sources=[
256f46a955bSLisandro Dalcin            src for src in sources()
257f46a955bSLisandro Dalcin        ],
258f46a955bSLisandro Dalcin        ext_modules=[
259f46a955bSLisandro Dalcin            conf.Extension(**ext) for ext in extensions()
260f46a955bSLisandro Dalcin        ],
261f46a955bSLisandro Dalcin        **setup_args
262fb83dddaSLisandro Dalcin    )
2635808f684SSatish Balay
264fb83dddaSLisandro Dalcin# --------------------------------------------------------------------
265fb83dddaSLisandro Dalcin
2665808f684SSatish Balaydef main():
2675808f684SSatish Balay    run_setup()
2685808f684SSatish Balay
2695808f684SSatish Balayif __name__ == '__main__':
2705808f684SSatish Balay    main()
2715808f684SSatish Balay
2725808f684SSatish Balay# --------------------------------------------------------------------
273