xref: /petsc/src/binding/petsc4py/setup.py (revision 9fb6d20cdf3c0d158c59c8394c1a6c992d58ec7a)
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
8*9fb6d20cSLisandro Dalcinimport warnings
95808f684SSatish Balay
105808f684SSatish Balaytry:
115808f684SSatish Balay    import setuptools
125808f684SSatish Balayexcept ImportError:
135808f684SSatish Balay    setuptools = None
145808f684SSatish Balay
15f46a955bSLisandro Dalcintopdir = os.path.abspath(os.path.dirname(__file__))
16f46a955bSLisandro Dalcinsys.path.insert(0, os.path.join(topdir, 'conf'))
17f46a955bSLisandro Dalcin
185808f684SSatish Balaypyver = sys.version_info[:2]
19aab42556SSatish Balayif pyver < (3, 6):
20aab42556SSatish Balay    raise RuntimeError('Python version 3.6 or higher is required')
211e83877aSSatish Balay
22f46a955bSLisandro DalcinPNAME = 'PETSc'
23f46a955bSLisandro DalcinEMAIL = 'petsc-maint@mcs.anl.gov'
24f46a955bSLisandro DalcinPLIST = [PNAME]
25fb83dddaSLisandro Dalcin
265808f684SSatish Balay# --------------------------------------------------------------------
275808f684SSatish Balay# Metadata
285808f684SSatish Balay# --------------------------------------------------------------------
295808f684SSatish Balay
306f336411SStefano Zampini
31f46a955bSLisandro Dalcindef F(string):
32f46a955bSLisandro Dalcin    return string.format(
33f46a955bSLisandro Dalcin        Name=PNAME,
34f46a955bSLisandro Dalcin        name=PNAME.lower(),
35f46a955bSLisandro Dalcin        pyname=PNAME.lower() + '4py',
36f46a955bSLisandro Dalcin    )
375808f684SSatish Balay
386f336411SStefano Zampini
39f46a955bSLisandro Dalcindef get_name():
40f46a955bSLisandro Dalcin    return F('{pyname}')
415808f684SSatish Balay
426f336411SStefano Zampini
43f46a955bSLisandro Dalcindef get_version():
44f46a955bSLisandro Dalcin    try:
45f46a955bSLisandro Dalcin        return get_version.result
46f46a955bSLisandro Dalcin    except AttributeError:
47f46a955bSLisandro Dalcin        pass
48f46a955bSLisandro Dalcin    pkg_init_py = os.path.join(F('{pyname}'), '__init__.py')
49f46a955bSLisandro Dalcin    with open(os.path.join(topdir, 'src', pkg_init_py)) as f:
505808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
51f46a955bSLisandro Dalcin    version = m.groups()[0]
52f46a955bSLisandro Dalcin    get_version.result = version
53f46a955bSLisandro Dalcin    return version
545808f684SSatish Balay
556f336411SStefano Zampini
565808f684SSatish Balaydef description():
57f46a955bSLisandro Dalcin    return F('{Name} for Python')
58fb83dddaSLisandro Dalcin
596f336411SStefano Zampini
60fb83dddaSLisandro Dalcindef long_description():
615808f684SSatish Balay    with open(os.path.join(topdir, 'DESCRIPTION.rst')) as f:
625808f684SSatish Balay        return f.read()
635808f684SSatish Balay
646f336411SStefano Zampini
65f46a955bSLisandro Dalcinurl = F('https://gitlab.com/{name}/{name}')
66f46a955bSLisandro Dalcinpypiroot = F('https://pypi.io/packages/source')
67f46a955bSLisandro Dalcinpypislug = F('{pyname}')[0] + F('/{pyname}')
68f46a955bSLisandro Dalcintarball = F('{pyname}-%s.tar.gz' % get_version())
69f46a955bSLisandro Dalcindownload = '/'.join([pypiroot, pypislug, tarball])
705808f684SSatish Balay
71fb83dddaSLisandro Dalcinclassifiers = """
72fb83dddaSLisandro DalcinOperating System :: POSIX
73fb83dddaSLisandro DalcinIntended Audience :: Developers
74fb83dddaSLisandro DalcinIntended Audience :: Science/Research
75fb83dddaSLisandro DalcinProgramming Language :: C
76fb83dddaSLisandro DalcinProgramming Language :: C++
77fb83dddaSLisandro DalcinProgramming Language :: Cython
78fb83dddaSLisandro DalcinProgramming Language :: Python
79fb83dddaSLisandro DalcinProgramming Language :: Python :: 3
80fb83dddaSLisandro DalcinProgramming Language :: Python :: Implementation :: CPython
81fb83dddaSLisandro DalcinTopic :: Scientific/Engineering
82fb83dddaSLisandro DalcinTopic :: Software Development :: Libraries :: Python Modules
83fb83dddaSLisandro DalcinDevelopment Status :: 5 - Production/Stable
84f46a955bSLisandro Dalcin""".strip().split('\n')
855808f684SSatish Balay
86fb83dddaSLisandro Dalcinkeywords = """
87fb83dddaSLisandro Dalcinscientific computing
88fb83dddaSLisandro Dalcinparallel computing
89fb83dddaSLisandro DalcinMPI
90f46a955bSLisandro Dalcin""".strip().split('\n')
915808f684SSatish Balay
92fb83dddaSLisandro Dalcinplatforms = """
93fb83dddaSLisandro DalcinPOSIX
94fb83dddaSLisandro DalcinLinux
95fb83dddaSLisandro DalcinmacOS
96fb83dddaSLisandro DalcinFreeBSD
97f46a955bSLisandro Dalcin""".strip().split('\n')
98fb83dddaSLisandro Dalcin
99fb83dddaSLisandro Dalcinmetadata = {
100f46a955bSLisandro Dalcin    'name': get_name(),
101f46a955bSLisandro Dalcin    'version': get_version(),
102fb83dddaSLisandro Dalcin    'description': description(),
103fb83dddaSLisandro Dalcin    'long_description': long_description(),
104fb83dddaSLisandro Dalcin    'url': url,
105fb83dddaSLisandro Dalcin    'download_url': download,
106f46a955bSLisandro Dalcin    'classifiers': classifiers,
107f46a955bSLisandro Dalcin    'keywords': keywords + PLIST,
108fb83dddaSLisandro Dalcin    'license': 'BSD-2-Clause',
109f46a955bSLisandro Dalcin    'platforms': platforms,
110fb83dddaSLisandro Dalcin    'author': 'Lisandro Dalcin',
111fb83dddaSLisandro Dalcin    'author_email': 'dalcinl@gmail.com',
112f46a955bSLisandro Dalcin    'maintainer': F('{Name} Team'),
113f46a955bSLisandro Dalcin    'maintainer_email': EMAIL,
114fb83dddaSLisandro Dalcin}
1156f336411SStefano Zampinimetadata.update(
1166f336411SStefano Zampini    {
117fb83dddaSLisandro Dalcin        'requires': ['numpy'],
1186f336411SStefano Zampini    }
1196f336411SStefano Zampini)
120fb83dddaSLisandro Dalcin
121fb83dddaSLisandro Dalcinmetadata_extra = {
122833126bdSLisandro Dalcin    'long_description_content_type': 'text/x-rst',
123fb83dddaSLisandro Dalcin}
1245808f684SSatish Balay
1255808f684SSatish Balay# --------------------------------------------------------------------
1265808f684SSatish Balay# Extension modules
1275808f684SSatish Balay# --------------------------------------------------------------------
1285808f684SSatish Balay
1296f336411SStefano Zampini
130f46a955bSLisandro Dalcindef sources():
1316f336411SStefano Zampini    src = {
1326f336411SStefano Zampini        'source': F('{pyname}/{Name}.pyx'),
1336f336411SStefano Zampini        'depends': [
134f46a955bSLisandro Dalcin            F('{pyname}/*.pyx'),
135f46a955bSLisandro Dalcin            F('{pyname}/*.pxd'),
136f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pyx'),
137f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxd'),
138f46a955bSLisandro Dalcin            F('{pyname}/{Name}/*.pxi'),
139f46a955bSLisandro Dalcin        ],
1406f336411SStefano Zampini        'workdir': 'src',
1416f336411SStefano Zampini    }
142f46a955bSLisandro Dalcin    return [src]
143f46a955bSLisandro Dalcin
1446f336411SStefano Zampini
145fb83dddaSLisandro Dalcindef extensions():
1468885bf16SLisandro Dalcin    from os import walk
1475808f684SSatish Balay    from glob import glob
1488885bf16SLisandro Dalcin    from os.path import join
1496f336411SStefano Zampini
150f46a955bSLisandro Dalcin    #
1515808f684SSatish Balay    depends = []
152f46a955bSLisandro Dalcin    glob_join = lambda *args: glob(join(*args))
1536f336411SStefano Zampini    for pth, _, _ in walk('src'):
1548885bf16SLisandro Dalcin        depends += glob_join(pth, '*.h')
1558885bf16SLisandro Dalcin        depends += glob_join(pth, '*.c')
156f46a955bSLisandro Dalcin    for pkg in map(str.lower, reversed(PLIST)):
157f46a955bSLisandro Dalcin        if (pkg.upper() + '_DIR') in os.environ:
158f46a955bSLisandro Dalcin            pd = os.environ[pkg.upper() + '_DIR']
1598885bf16SLisandro Dalcin            pa = os.environ.get('PETSC_ARCH', '')
1608885bf16SLisandro Dalcin            depends += glob_join(pd, 'include', '*.h')
161f46a955bSLisandro Dalcin            depends += glob_join(pd, 'include', pkg, 'private', '*.h')
162f46a955bSLisandro Dalcin            depends += glob_join(pd, pa, 'include', '%sconf.h' % pkg)
163f46a955bSLisandro Dalcin    #
164f46a955bSLisandro Dalcin    include_dirs = []
1650f51ee0fSAlexei Colin    numpy_include = os.environ.get('NUMPY_INCLUDE')
1660f51ee0fSAlexei Colin    if numpy_include is not None:
1670f51ee0fSAlexei Colin        numpy_includes = [numpy_include]
1680f51ee0fSAlexei Colin    else:
1695808f684SSatish Balay        try:
1705808f684SSatish Balay            import numpy
1716f336411SStefano Zampini
1725808f684SSatish Balay            numpy_includes = [numpy.get_include()]
1735808f684SSatish Balay        except ImportError:
1745808f684SSatish Balay            numpy_includes = []
175f46a955bSLisandro Dalcin    include_dirs.extend(numpy_includes)
176f46a955bSLisandro Dalcin    if F('{pyname}') != 'petsc4py':
177f46a955bSLisandro Dalcin        try:
178f46a955bSLisandro Dalcin            import petsc4py
1796f336411SStefano Zampini
180f46a955bSLisandro Dalcin            petsc4py_includes = [petsc4py.get_include()]
181f46a955bSLisandro Dalcin        except ImportError:
182f46a955bSLisandro Dalcin            petsc4py_includes = []
183f46a955bSLisandro Dalcin        include_dirs.extend(petsc4py_includes)
184f46a955bSLisandro Dalcin    #
1856f336411SStefano Zampini    ext = {
1866f336411SStefano Zampini        'name': F('{pyname}.lib.{Name}'),
1876f336411SStefano Zampini        'sources': [F('src/{pyname}/{Name}.c')],
1886f336411SStefano Zampini        'depends': depends,
1896f336411SStefano Zampini        'include_dirs': [
190f46a955bSLisandro Dalcin            'src',
191f46a955bSLisandro Dalcin            F('src/{pyname}/include'),
1926f336411SStefano Zampini        ]
1936f336411SStefano Zampini        + include_dirs,
1946f336411SStefano Zampini        'define_macros': [
195fb83dddaSLisandro Dalcin            ('MPICH_SKIP_MPICXX', 1),
196fb83dddaSLisandro Dalcin            ('OMPI_SKIP_MPICXX', 1),
197f46a955bSLisandro Dalcin            ('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'),
198fb83dddaSLisandro Dalcin        ],
1996f336411SStefano Zampini    }
200f46a955bSLisandro Dalcin    return [ext]
2015808f684SSatish Balay
2026f336411SStefano Zampini
2035808f684SSatish Balay# --------------------------------------------------------------------
2045808f684SSatish Balay# Setup
2055808f684SSatish Balay# --------------------------------------------------------------------
2065808f684SSatish Balay
2076f336411SStefano Zampini
208f8c80548SLisandro Dalcindef get_release():
209f46a955bSLisandro Dalcin    suffix = os.path.join('src', 'binding', F('{pyname}'))
210f46a955bSLisandro Dalcin    if not topdir.endswith(os.path.join(os.path.sep, suffix)):
211f09792b6SLisandro Dalcin        return True
212f8c80548SLisandro Dalcin    release = 1
213f8c80548SLisandro Dalcin    rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir] * 3))
214f46a955bSLisandro Dalcin    version_h = os.path.join(rootdir, 'include', F('{name}version.h'))
215f46a955bSLisandro Dalcin    release_macro = '%s_VERSION_RELEASE' % F('{name}').upper()
2166f336411SStefano Zampini    version_re = re.compile(r'#define\s+%s\s+([-]*\d+)' % release_macro)
217f8c80548SLisandro Dalcin    if os.path.exists(version_h) and os.path.isfile(version_h):
218f8c80548SLisandro Dalcin        with open(version_h, 'r') as f:
219f8c80548SLisandro Dalcin            release = int(version_re.search(f.read()).groups()[0])
220f8c80548SLisandro Dalcin    return bool(release)
221f8c80548SLisandro Dalcin
2226f336411SStefano Zampini
223f8c80548SLisandro Dalcindef requires(pkgname, major, minor, release=True):
224f8c80548SLisandro Dalcin    minor = minor + int(not release)
225f8c80548SLisandro Dalcin    devel = '' if release else '.dev0'
2266f336411SStefano Zampini    vmin = f'{major}.{minor}{devel}'
2276f336411SStefano Zampini    vmax = f'{major}.{minor+1}'
2286f336411SStefano Zampini    return f'{pkgname}>={vmin},<{vmax}'
2296f336411SStefano Zampini
230f8c80548SLisandro Dalcin
2315808f684SSatish Balaydef run_setup():
2322149b0eaSStefano Zampini    is_sdist = 'sdist' in sys.argv
2335808f684SSatish Balay    setup_args = metadata.copy()
234f8c80548SLisandro Dalcin    vstr = setup_args['version'].split('.')[:2]
235f8c80548SLisandro Dalcin    x, y = tuple(map(int, vstr))
236f8c80548SLisandro Dalcin    release = get_release()
237f8c80548SLisandro Dalcin    if not release:
2386f336411SStefano Zampini        setup_args['version'] = '%d.%d.0.dev0' % (x, y + 1)
2395808f684SSatish Balay    if setuptools:
240*9fb6d20cSLisandro Dalcin        warnings.filterwarnings(
241*9fb6d20cSLisandro Dalcin            'ignore', message=r'.*fetch_build_eggs', module='setuptools'
242*9fb6d20cSLisandro Dalcin        )
2435808f684SSatish Balay        setup_args['zip_safe'] = False
2442149b0eaSStefano Zampini        numpy_pin = 'numpy'
2452149b0eaSStefano Zampini        if not is_sdist:
24630eefebbSLisandro Dalcin            try:
24730eefebbSLisandro Dalcin                import numpy
2486f336411SStefano Zampini
24930eefebbSLisandro Dalcin                major = int(numpy.__version__.partition('.')[0])
250f566d949SLisandro Dalcin                numpy_pin = 'numpy>=1.19' if major >= 2 else 'numpy<2'
25130eefebbSLisandro Dalcin            except ImportError:
2522149b0eaSStefano Zampini                pass
253693647e8SLisandro Dalcin        setup_args['setup_requires'] = ['numpy']
25430eefebbSLisandro Dalcin        setup_args['install_requires'] = [numpy_pin]
255f46a955bSLisandro Dalcin        for pkg in map(str.lower, PLIST):
256f46a955bSLisandro Dalcin            PKG_DIR = os.environ.get(pkg.upper() + '_DIR')
257f46a955bSLisandro Dalcin            if not (PKG_DIR and os.path.isdir(PKG_DIR)):
258f46a955bSLisandro Dalcin                package = requires(pkg, x, y, release)
259693647e8SLisandro Dalcin                setup_args['setup_requires'] += [package]
260f46a955bSLisandro Dalcin                setup_args['install_requires'] += [package]
261f46a955bSLisandro Dalcin        if F('{pyname}') != 'petsc4py':
262f46a955bSLisandro Dalcin            package = requires('petsc4py', x, y, release)
263693647e8SLisandro Dalcin            setup_args['setup_requires'] += [package]
264f46a955bSLisandro Dalcin            setup_args['install_requires'] += [package]
265fb83dddaSLisandro Dalcin        setup_args.update(metadata_extra)
2665808f684SSatish Balay    #
267f46a955bSLisandro Dalcin    conf = __import__(F('conf{name}'))
268f46a955bSLisandro Dalcin    conf.setup(
269fb83dddaSLisandro Dalcin        packages=[
270f46a955bSLisandro Dalcin            F('{pyname}'),
271f46a955bSLisandro Dalcin            F('{pyname}.lib'),
27222d6dc08SStefano Zampini            F('{pyname}.lib._pytypes'),
27322d6dc08SStefano Zampini            F('{pyname}.lib._pytypes.viewer'),
274fb83dddaSLisandro Dalcin        ],
275f46a955bSLisandro Dalcin        package_dir={'': 'src'},
276fb83dddaSLisandro Dalcin        package_data={
277f46a955bSLisandro Dalcin            F('{pyname}'): [
278f46a955bSLisandro Dalcin                F('{Name}.pxd'),
279f46a955bSLisandro Dalcin                F('{Name}*.h'),
280f46a955bSLisandro Dalcin                F('include/{pyname}/*.h'),
281f46a955bSLisandro Dalcin                F('include/{pyname}/*.i'),
28255a74a43SLisandro Dalcin                'py.typed',
28355a74a43SLisandro Dalcin                '*.pyi',
28455a74a43SLisandro Dalcin                '*/*.pyi',
285fb83dddaSLisandro Dalcin            ],
286f46a955bSLisandro Dalcin            F('{pyname}.lib'): [
287f46a955bSLisandro Dalcin                F('{name}.cfg'),
288fb83dddaSLisandro Dalcin            ],
289fb83dddaSLisandro Dalcin        },
2906f336411SStefano Zampini        cython_sources=[src for src in sources()],  # noqa: C416
2916f336411SStefano Zampini        ext_modules=[conf.Extension(**ext) for ext in extensions()],
2926f336411SStefano Zampini        **setup_args,
293fb83dddaSLisandro Dalcin    )
2945808f684SSatish Balay
2956f336411SStefano Zampini
296fb83dddaSLisandro Dalcin# --------------------------------------------------------------------
297fb83dddaSLisandro Dalcin
2986f336411SStefano Zampini
2995808f684SSatish Balaydef main():
3005808f684SSatish Balay    run_setup()
3015808f684SSatish Balay
3026f336411SStefano Zampini
3035808f684SSatish Balayif __name__ == '__main__':
3045808f684SSatish Balay    main()
3055808f684SSatish Balay
3065808f684SSatish Balay# --------------------------------------------------------------------
307