xref: /petsc/src/binding/petsc4py/setup.py (revision aab425562e7c2c7b86a9faf80f0fb20ca1581317) !
11b37a2a7SPierre Jolivet#!/usr/bin/env python3
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]
18*aab42556SSatish Balayif pyver < (3, 6):
19*aab42556SSatish Balay    raise RuntimeError('Python version 3.6 or higher is required')
201e83877aSSatish Balay
21f46a955bSLisandro DalcinPNAME = 'PETSc'
22f46a955bSLisandro DalcinEMAIL = 'petsc-maint@mcs.anl.gov'
23f46a955bSLisandro DalcinPLIST = [PNAME]
24fb83dddaSLisandro Dalcin
255808f684SSatish Balay# --------------------------------------------------------------------
265808f684SSatish Balay# Metadata
275808f684SSatish Balay# --------------------------------------------------------------------
285808f684SSatish Balay
296f336411SStefano Zampini
30f46a955bSLisandro Dalcindef F(string):
31f46a955bSLisandro Dalcin    return string.format(
32f46a955bSLisandro Dalcin        Name=PNAME,
33f46a955bSLisandro Dalcin        name=PNAME.lower(),
34f46a955bSLisandro Dalcin        pyname=PNAME.lower() + '4py',
35f46a955bSLisandro Dalcin    )
365808f684SSatish Balay
376f336411SStefano Zampini
38f46a955bSLisandro Dalcindef get_name():
39f46a955bSLisandro Dalcin    return F('{pyname}')
405808f684SSatish Balay
416f336411SStefano Zampini
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
546f336411SStefano Zampini
555808f684SSatish Balaydef description():
56f46a955bSLisandro Dalcin    return F('{Name} for Python')
57fb83dddaSLisandro Dalcin
586f336411SStefano Zampini
59fb83dddaSLisandro Dalcindef long_description():
605808f684SSatish Balay    with open(os.path.join(topdir, 'DESCRIPTION.rst')) as f:
615808f684SSatish Balay        return f.read()
625808f684SSatish Balay
636f336411SStefano Zampini
64f46a955bSLisandro Dalcinurl = F('https://gitlab.com/{name}/{name}')
65f46a955bSLisandro Dalcinpypiroot = F('https://pypi.io/packages/source')
66f46a955bSLisandro Dalcinpypislug = F('{pyname}')[0] + F('/{pyname}')
67f46a955bSLisandro Dalcintarball = F('{pyname}-%s.tar.gz' % get_version())
68f46a955bSLisandro Dalcindownload = '/'.join([pypiroot, pypislug, tarball])
695808f684SSatish Balay
70fb83dddaSLisandro Dalcinclassifiers = """
71fb83dddaSLisandro DalcinOperating System :: POSIX
72fb83dddaSLisandro DalcinIntended Audience :: Developers
73fb83dddaSLisandro DalcinIntended Audience :: Science/Research
74fb83dddaSLisandro DalcinProgramming Language :: C
75fb83dddaSLisandro DalcinProgramming Language :: C++
76fb83dddaSLisandro DalcinProgramming Language :: Cython
77fb83dddaSLisandro DalcinProgramming Language :: Python
78fb83dddaSLisandro DalcinProgramming Language :: Python :: 3
79fb83dddaSLisandro DalcinProgramming Language :: Python :: Implementation :: CPython
80fb83dddaSLisandro DalcinTopic :: Scientific/Engineering
81fb83dddaSLisandro DalcinTopic :: Software Development :: Libraries :: Python Modules
82fb83dddaSLisandro DalcinDevelopment Status :: 5 - Production/Stable
83f46a955bSLisandro Dalcin""".strip().split('\n')
845808f684SSatish Balay
85fb83dddaSLisandro Dalcinkeywords = """
86fb83dddaSLisandro Dalcinscientific computing
87fb83dddaSLisandro Dalcinparallel computing
88fb83dddaSLisandro DalcinMPI
89f46a955bSLisandro Dalcin""".strip().split('\n')
905808f684SSatish Balay
91fb83dddaSLisandro Dalcinplatforms = """
92fb83dddaSLisandro DalcinPOSIX
93fb83dddaSLisandro DalcinLinux
94fb83dddaSLisandro DalcinmacOS
95fb83dddaSLisandro DalcinFreeBSD
96f46a955bSLisandro Dalcin""".strip().split('\n')
97fb83dddaSLisandro Dalcin
98fb83dddaSLisandro Dalcinmetadata = {
99f46a955bSLisandro Dalcin    'name': get_name(),
100f46a955bSLisandro Dalcin    'version': get_version(),
101fb83dddaSLisandro Dalcin    'description': description(),
102fb83dddaSLisandro Dalcin    'long_description': long_description(),
103fb83dddaSLisandro Dalcin    'url': url,
104fb83dddaSLisandro Dalcin    'download_url': download,
105f46a955bSLisandro Dalcin    'classifiers': classifiers,
106f46a955bSLisandro Dalcin    'keywords': keywords + PLIST,
107fb83dddaSLisandro Dalcin    'license': 'BSD-2-Clause',
108f46a955bSLisandro Dalcin    'platforms': platforms,
109fb83dddaSLisandro Dalcin    'author': 'Lisandro Dalcin',
110fb83dddaSLisandro Dalcin    'author_email': 'dalcinl@gmail.com',
111f46a955bSLisandro Dalcin    'maintainer': F('{Name} Team'),
112f46a955bSLisandro Dalcin    'maintainer_email': EMAIL,
113fb83dddaSLisandro Dalcin}
1146f336411SStefano Zampinimetadata.update(
1156f336411SStefano Zampini    {
116fb83dddaSLisandro Dalcin        'requires': ['numpy'],
1176f336411SStefano Zampini    }
1186f336411SStefano Zampini)
119fb83dddaSLisandro Dalcin
120fb83dddaSLisandro Dalcinmetadata_extra = {
121833126bdSLisandro Dalcin    'long_description_content_type': 'text/x-rst',
122fb83dddaSLisandro Dalcin}
1235808f684SSatish Balay
1245808f684SSatish Balay# --------------------------------------------------------------------
1255808f684SSatish Balay# Extension modules
1265808f684SSatish Balay# --------------------------------------------------------------------
1275808f684SSatish Balay
1286f336411SStefano Zampini
129f46a955bSLisandro Dalcindef sources():
1306f336411SStefano Zampini    src = {
1316f336411SStefano Zampini        'source': F('{pyname}/{Name}.pyx'),
1326f336411SStefano Zampini        'depends': [
133f46a955bSLisandro Dalcin            F('{pyname}/*.pyx'),
134f46a955bSLisandro Dalcin            F('{pyname}/*.pxd'),
135f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pyx'),
136f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxd'),
137f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxi'),
138f46a955bSLisandro Dalcin        ],
1396f336411SStefano Zampini        'workdir': 'src',
1406f336411SStefano Zampini    }
141f46a955bSLisandro Dalcin    return [src]
142f46a955bSLisandro Dalcin
1436f336411SStefano Zampini
144fb83dddaSLisandro Dalcindef extensions():
1458885bf16SLisandro Dalcin    from os import walk
1465808f684SSatish Balay    from glob import glob
1478885bf16SLisandro Dalcin    from os.path import join
1486f336411SStefano Zampini
149f46a955bSLisandro Dalcin    #
1505808f684SSatish Balay    depends = []
151f46a955bSLisandro Dalcin    glob_join = lambda *args: glob(join(*args))
1526f336411SStefano Zampini    for pth, _, _ in walk('src'):
1538885bf16SLisandro Dalcin        depends += glob_join(pth, '*.h')
1548885bf16SLisandro Dalcin        depends += glob_join(pth, '*.c')
155f46a955bSLisandro Dalcin    for pkg in map(str.lower, reversed(PLIST)):
156f46a955bSLisandro Dalcin        if (pkg.upper() + '_DIR') in os.environ:
157f46a955bSLisandro Dalcin            pd = os.environ[pkg.upper() + '_DIR']
1588885bf16SLisandro Dalcin            pa = os.environ.get('PETSC_ARCH', '')
1598885bf16SLisandro Dalcin            depends += glob_join(pd, 'include', '*.h')
160f46a955bSLisandro Dalcin            depends += glob_join(pd, 'include', pkg, 'private', '*.h')
161f46a955bSLisandro Dalcin            depends += glob_join(pd, pa, 'include', '%sconf.h' % pkg)
162f46a955bSLisandro Dalcin    #
163f46a955bSLisandro Dalcin    include_dirs = []
1640f51ee0fSAlexei Colin    numpy_include = os.environ.get('NUMPY_INCLUDE')
1650f51ee0fSAlexei Colin    if numpy_include is not None:
1660f51ee0fSAlexei Colin        numpy_includes = [numpy_include]
1670f51ee0fSAlexei Colin    else:
1685808f684SSatish Balay        try:
1695808f684SSatish Balay            import numpy
1706f336411SStefano Zampini
1715808f684SSatish Balay            numpy_includes = [numpy.get_include()]
1725808f684SSatish Balay        except ImportError:
1735808f684SSatish Balay            numpy_includes = []
174f46a955bSLisandro Dalcin    include_dirs.extend(numpy_includes)
175f46a955bSLisandro Dalcin    if F('{pyname}') != 'petsc4py':
176f46a955bSLisandro Dalcin        try:
177f46a955bSLisandro Dalcin            import petsc4py
1786f336411SStefano Zampini
179f46a955bSLisandro Dalcin            petsc4py_includes = [petsc4py.get_include()]
180f46a955bSLisandro Dalcin        except ImportError:
181f46a955bSLisandro Dalcin            petsc4py_includes = []
182f46a955bSLisandro Dalcin        include_dirs.extend(petsc4py_includes)
183f46a955bSLisandro Dalcin    #
1846f336411SStefano Zampini    ext = {
1856f336411SStefano Zampini        'name': F('{pyname}.lib.{Name}'),
1866f336411SStefano Zampini        'sources': [F('src/{pyname}/{Name}.c')],
1876f336411SStefano Zampini        'depends': depends,
1886f336411SStefano Zampini        'include_dirs': [
189f46a955bSLisandro Dalcin            'src',
190f46a955bSLisandro Dalcin            F('src/{pyname}/include'),
1916f336411SStefano Zampini        ]
1926f336411SStefano Zampini        + include_dirs,
1936f336411SStefano Zampini        'define_macros': [
194fb83dddaSLisandro Dalcin            ('MPICH_SKIP_MPICXX', 1),
195fb83dddaSLisandro Dalcin            ('OMPI_SKIP_MPICXX', 1),
196f46a955bSLisandro Dalcin            ('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'),
197fb83dddaSLisandro Dalcin        ],
1986f336411SStefano Zampini    }
199f46a955bSLisandro Dalcin    return [ext]
2005808f684SSatish Balay
2016f336411SStefano Zampini
2025808f684SSatish Balay# --------------------------------------------------------------------
2035808f684SSatish Balay# Setup
2045808f684SSatish Balay# --------------------------------------------------------------------
2055808f684SSatish Balay
2066f336411SStefano Zampini
207f8c80548SLisandro Dalcindef get_release():
208f46a955bSLisandro Dalcin    suffix = os.path.join('src', 'binding', F('{pyname}'))
209f46a955bSLisandro Dalcin    if not topdir.endswith(os.path.join(os.path.sep, suffix)):
210f09792b6SLisandro Dalcin        return True
211f8c80548SLisandro Dalcin    release = 1
212f8c80548SLisandro Dalcin    rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir] * 3))
213f46a955bSLisandro Dalcin    version_h = os.path.join(rootdir, 'include', F('{name}version.h'))
214f46a955bSLisandro Dalcin    release_macro = '%s_VERSION_RELEASE' % F('{name}').upper()
2156f336411SStefano Zampini    version_re = re.compile(r'#define\s+%s\s+([-]*\d+)' % release_macro)
216f8c80548SLisandro Dalcin    if os.path.exists(version_h) and os.path.isfile(version_h):
217f8c80548SLisandro Dalcin        with open(version_h, 'r') as f:
218f8c80548SLisandro Dalcin            release = int(version_re.search(f.read()).groups()[0])
219f8c80548SLisandro Dalcin    return bool(release)
220f8c80548SLisandro Dalcin
2216f336411SStefano Zampini
222f8c80548SLisandro Dalcindef requires(pkgname, major, minor, release=True):
223f8c80548SLisandro Dalcin    minor = minor + int(not release)
224f8c80548SLisandro Dalcin    devel = '' if release else '.dev0'
2256f336411SStefano Zampini    vmin = f'{major}.{minor}{devel}'
2266f336411SStefano Zampini    vmax = f'{major}.{minor+1}'
2276f336411SStefano Zampini    return f'{pkgname}>={vmin},<{vmax}'
2286f336411SStefano Zampini
229f8c80548SLisandro Dalcin
2305808f684SSatish Balaydef run_setup():
2312149b0eaSStefano Zampini    is_sdist = 'sdist' in sys.argv
2325808f684SSatish Balay    setup_args = metadata.copy()
233f8c80548SLisandro Dalcin    vstr = setup_args['version'].split('.')[:2]
234f8c80548SLisandro Dalcin    x, y = tuple(map(int, vstr))
235f8c80548SLisandro Dalcin    release = get_release()
236f8c80548SLisandro Dalcin    if not release:
2376f336411SStefano Zampini        setup_args['version'] = '%d.%d.0.dev0' % (x, y + 1)
2385808f684SSatish Balay    if setuptools:
2395808f684SSatish Balay        setup_args['zip_safe'] = False
2402149b0eaSStefano Zampini        numpy_pin = 'numpy'
2412149b0eaSStefano Zampini        if not is_sdist:
24230eefebbSLisandro Dalcin            try:
24330eefebbSLisandro Dalcin                import numpy
2446f336411SStefano Zampini
24530eefebbSLisandro Dalcin                major = int(numpy.__version__.partition('.')[0])
246f566d949SLisandro Dalcin                numpy_pin = 'numpy>=1.19' if major >= 2 else 'numpy<2'
24730eefebbSLisandro Dalcin            except ImportError:
2482149b0eaSStefano Zampini                pass
249693647e8SLisandro Dalcin        setup_args['setup_requires'] = ['numpy']
25030eefebbSLisandro Dalcin        setup_args['install_requires'] = [numpy_pin]
251f46a955bSLisandro Dalcin        for pkg in map(str.lower, PLIST):
252f46a955bSLisandro Dalcin            PKG_DIR = os.environ.get(pkg.upper() + '_DIR')
253f46a955bSLisandro Dalcin            if not (PKG_DIR and os.path.isdir(PKG_DIR)):
254f46a955bSLisandro Dalcin                package = requires(pkg, x, y, release)
255693647e8SLisandro Dalcin                setup_args['setup_requires'] += [package]
256f46a955bSLisandro Dalcin                setup_args['install_requires'] += [package]
257f46a955bSLisandro Dalcin        if F('{pyname}') != 'petsc4py':
258f46a955bSLisandro Dalcin            package = requires('petsc4py', x, y, release)
259693647e8SLisandro Dalcin            setup_args['setup_requires'] += [package]
260f46a955bSLisandro Dalcin            setup_args['install_requires'] += [package]
261fb83dddaSLisandro Dalcin        setup_args.update(metadata_extra)
2625808f684SSatish Balay    #
263f46a955bSLisandro Dalcin    conf = __import__(F('conf{name}'))
264f46a955bSLisandro Dalcin    conf.setup(
265fb83dddaSLisandro Dalcin        packages=[
266f46a955bSLisandro Dalcin            F('{pyname}'),
267f46a955bSLisandro Dalcin            F('{pyname}.lib'),
26822d6dc08SStefano Zampini            F('{pyname}.lib._pytypes'),
26922d6dc08SStefano Zampini            F('{pyname}.lib._pytypes.viewer'),
270fb83dddaSLisandro Dalcin        ],
271f46a955bSLisandro Dalcin        package_dir={'': 'src'},
272fb83dddaSLisandro Dalcin        package_data={
273f46a955bSLisandro Dalcin            F('{pyname}'): [
274f46a955bSLisandro Dalcin                F('{Name}.pxd'),
275f46a955bSLisandro Dalcin                F('{Name}*.h'),
276f46a955bSLisandro Dalcin                F('include/{pyname}/*.h'),
277f46a955bSLisandro Dalcin                F('include/{pyname}/*.i'),
27855a74a43SLisandro Dalcin                'py.typed',
27955a74a43SLisandro Dalcin                '*.pyi',
28055a74a43SLisandro Dalcin                '*/*.pyi',
281fb83dddaSLisandro Dalcin            ],
282f46a955bSLisandro Dalcin            F('{pyname}.lib'): [
283f46a955bSLisandro Dalcin                F('{name}.cfg'),
284fb83dddaSLisandro Dalcin            ],
285fb83dddaSLisandro Dalcin        },
2866f336411SStefano Zampini        cython_sources=[src for src in sources()],  # noqa: C416
2876f336411SStefano Zampini        ext_modules=[conf.Extension(**ext) for ext in extensions()],
2886f336411SStefano Zampini        **setup_args,
289fb83dddaSLisandro Dalcin    )
2905808f684SSatish Balay
2916f336411SStefano Zampini
292fb83dddaSLisandro Dalcin# --------------------------------------------------------------------
293fb83dddaSLisandro Dalcin
2946f336411SStefano Zampini
2955808f684SSatish Balaydef main():
2965808f684SSatish Balay    run_setup()
2975808f684SSatish Balay
2986f336411SStefano Zampini
2995808f684SSatish Balayif __name__ == '__main__':
3005808f684SSatish Balay    main()
3015808f684SSatish Balay
3025808f684SSatish Balay# --------------------------------------------------------------------
303