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 89fb6d20cSLisandro 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 307b8d1e39SLisandro Dalcinpy_limited_api = (3, 10) 317b8d1e39SLisandro Dalcin 326f336411SStefano Zampini 33f46a955bSLisandro Dalcindef F(string): 34f46a955bSLisandro Dalcin return string.format( 35f46a955bSLisandro Dalcin Name=PNAME, 36f46a955bSLisandro Dalcin name=PNAME.lower(), 37f46a955bSLisandro Dalcin pyname=PNAME.lower() + '4py', 38f46a955bSLisandro Dalcin ) 395808f684SSatish Balay 406f336411SStefano Zampini 41f46a955bSLisandro Dalcindef get_name(): 42f46a955bSLisandro Dalcin return F('{pyname}') 435808f684SSatish Balay 446f336411SStefano Zampini 45f46a955bSLisandro Dalcindef get_version(): 46f46a955bSLisandro Dalcin try: 47f46a955bSLisandro Dalcin return get_version.result 48f46a955bSLisandro Dalcin except AttributeError: 49f46a955bSLisandro Dalcin pass 50f46a955bSLisandro Dalcin pkg_init_py = os.path.join(F('{pyname}'), '__init__.py') 51f46a955bSLisandro Dalcin with open(os.path.join(topdir, 'src', pkg_init_py)) as f: 525808f684SSatish Balay m = re.search(r"__version__\s*=\s*'(.*)'", f.read()) 53f46a955bSLisandro Dalcin version = m.groups()[0] 54f46a955bSLisandro Dalcin get_version.result = version 55f46a955bSLisandro Dalcin return version 565808f684SSatish Balay 576f336411SStefano Zampini 585808f684SSatish Balaydef description(): 59f46a955bSLisandro Dalcin return F('{Name} for Python') 60fb83dddaSLisandro Dalcin 616f336411SStefano Zampini 62fb83dddaSLisandro Dalcindef long_description(): 635808f684SSatish Balay with open(os.path.join(topdir, 'DESCRIPTION.rst')) as f: 645808f684SSatish Balay return f.read() 655808f684SSatish Balay 666f336411SStefano Zampini 67f46a955bSLisandro Dalcinurl = F('https://gitlab.com/{name}/{name}') 68f46a955bSLisandro Dalcinpypiroot = F('https://pypi.io/packages/source') 69f46a955bSLisandro Dalcinpypislug = F('{pyname}')[0] + F('/{pyname}') 70f46a955bSLisandro Dalcintarball = F('{pyname}-%s.tar.gz' % get_version()) 71f46a955bSLisandro Dalcindownload = '/'.join([pypiroot, pypislug, tarball]) 725808f684SSatish Balay 73fb83dddaSLisandro Dalcinclassifiers = """ 74fb83dddaSLisandro DalcinOperating System :: POSIX 75fb83dddaSLisandro DalcinIntended Audience :: Developers 76fb83dddaSLisandro DalcinIntended Audience :: Science/Research 77fb83dddaSLisandro DalcinProgramming Language :: C 78fb83dddaSLisandro DalcinProgramming Language :: C++ 79fb83dddaSLisandro DalcinProgramming Language :: Cython 80fb83dddaSLisandro DalcinProgramming Language :: Python 81fb83dddaSLisandro DalcinProgramming Language :: Python :: 3 82fb83dddaSLisandro DalcinProgramming Language :: Python :: Implementation :: CPython 83fb83dddaSLisandro DalcinTopic :: Scientific/Engineering 84fb83dddaSLisandro DalcinTopic :: Software Development :: Libraries :: Python Modules 85fb83dddaSLisandro DalcinDevelopment Status :: 5 - Production/Stable 86f46a955bSLisandro Dalcin""".strip().split('\n') 875808f684SSatish Balay 88fb83dddaSLisandro Dalcinkeywords = """ 89fb83dddaSLisandro Dalcinscientific computing 90fb83dddaSLisandro Dalcinparallel computing 91fb83dddaSLisandro DalcinMPI 92f46a955bSLisandro Dalcin""".strip().split('\n') 935808f684SSatish Balay 94fb83dddaSLisandro Dalcinplatforms = """ 95fb83dddaSLisandro DalcinPOSIX 96fb83dddaSLisandro DalcinLinux 97fb83dddaSLisandro DalcinmacOS 98fb83dddaSLisandro DalcinFreeBSD 99f46a955bSLisandro Dalcin""".strip().split('\n') 100fb83dddaSLisandro Dalcin 101fb83dddaSLisandro Dalcinmetadata = { 102f46a955bSLisandro Dalcin 'name': get_name(), 103f46a955bSLisandro Dalcin 'version': get_version(), 104fb83dddaSLisandro Dalcin 'description': description(), 105fb83dddaSLisandro Dalcin 'long_description': long_description(), 106fb83dddaSLisandro Dalcin 'url': url, 107fb83dddaSLisandro Dalcin 'download_url': download, 108f46a955bSLisandro Dalcin 'classifiers': classifiers, 109f46a955bSLisandro Dalcin 'keywords': keywords + PLIST, 110fb83dddaSLisandro Dalcin 'license': 'BSD-2-Clause', 111f46a955bSLisandro Dalcin 'platforms': platforms, 112fb83dddaSLisandro Dalcin 'author': 'Lisandro Dalcin', 113fb83dddaSLisandro Dalcin 'author_email': 'dalcinl@gmail.com', 114f46a955bSLisandro Dalcin 'maintainer': F('{Name} Team'), 115f46a955bSLisandro Dalcin 'maintainer_email': EMAIL, 116fb83dddaSLisandro Dalcin} 1176f336411SStefano Zampinimetadata.update( 1186f336411SStefano Zampini { 119fb83dddaSLisandro Dalcin 'requires': ['numpy'], 1206f336411SStefano Zampini } 1216f336411SStefano Zampini) 122fb83dddaSLisandro Dalcin 123fb83dddaSLisandro Dalcinmetadata_extra = { 124833126bdSLisandro Dalcin 'long_description_content_type': 'text/x-rst', 125fb83dddaSLisandro Dalcin} 1265808f684SSatish Balay 1277b8d1e39SLisandro Dalcindef get_build_pysabi(): 128*30ff0ac2SLisandro Dalcin abi = os.environ.get("PETSC4PY_BUILD_PYSABI", "").lower() 1297b8d1e39SLisandro Dalcin if abi and sys.implementation.name == "cpython": 130*30ff0ac2SLisandro Dalcin if abi in {"false", "no", "off", "n", "0"}: 131*30ff0ac2SLisandro Dalcin return None 132*30ff0ac2SLisandro Dalcin if abi in {"true", "yes", "on", "y", "1"} | {"abi3"}: 1337b8d1e39SLisandro Dalcin return py_limited_api 1347b8d1e39SLisandro Dalcin if abi.startswith("cp"): 1357b8d1e39SLisandro Dalcin abi = abi[2:] 1367b8d1e39SLisandro Dalcin if "." in abi: 1377b8d1e39SLisandro Dalcin x, y = abi.split(".") 1387b8d1e39SLisandro Dalcin else: 1397b8d1e39SLisandro Dalcin x, y = abi[0], abi[1:] 1407b8d1e39SLisandro Dalcin return (int(x), int(y)) 1417b8d1e39SLisandro Dalcin return None 1427b8d1e39SLisandro Dalcin 1435808f684SSatish Balay# -------------------------------------------------------------------- 1445808f684SSatish Balay# Extension modules 1455808f684SSatish Balay# -------------------------------------------------------------------- 1465808f684SSatish Balay 1476f336411SStefano Zampini 148f46a955bSLisandro Dalcindef sources(): 1496f336411SStefano Zampini src = { 1506f336411SStefano Zampini 'source': F('{pyname}/{Name}.pyx'), 1516f336411SStefano Zampini 'depends': [ 152f46a955bSLisandro Dalcin F('{pyname}/*.pyx'), 153f46a955bSLisandro Dalcin F('{pyname}/*.pxd'), 154f46a955bSLisandro Dalcin F('{pyname}/{Name}/*.pyx'), 155f46a955bSLisandro Dalcin F('{pyname}/{Name}/*.pxd'), 156f46a955bSLisandro Dalcin F('{pyname}/{Name}/*.pxi'), 157f46a955bSLisandro Dalcin ], 1586f336411SStefano Zampini 'workdir': 'src', 1596f336411SStefano Zampini } 160f46a955bSLisandro Dalcin return [src] 161f46a955bSLisandro Dalcin 1626f336411SStefano Zampini 163fb83dddaSLisandro Dalcindef extensions(): 1648885bf16SLisandro Dalcin from os import walk 1655808f684SSatish Balay from glob import glob 1668885bf16SLisandro Dalcin from os.path import join 1676f336411SStefano Zampini 168f46a955bSLisandro Dalcin # 1695808f684SSatish Balay depends = [] 170f46a955bSLisandro Dalcin glob_join = lambda *args: glob(join(*args)) 1716f336411SStefano Zampini for pth, _, _ in walk('src'): 1728885bf16SLisandro Dalcin depends += glob_join(pth, '*.h') 1738885bf16SLisandro Dalcin depends += glob_join(pth, '*.c') 174f46a955bSLisandro Dalcin for pkg in map(str.lower, reversed(PLIST)): 175f46a955bSLisandro Dalcin if (pkg.upper() + '_DIR') in os.environ: 176f46a955bSLisandro Dalcin pd = os.environ[pkg.upper() + '_DIR'] 1778885bf16SLisandro Dalcin pa = os.environ.get('PETSC_ARCH', '') 1788885bf16SLisandro Dalcin depends += glob_join(pd, 'include', '*.h') 179f46a955bSLisandro Dalcin depends += glob_join(pd, 'include', pkg, 'private', '*.h') 180f46a955bSLisandro Dalcin depends += glob_join(pd, pa, 'include', '%sconf.h' % pkg) 181f46a955bSLisandro Dalcin # 182f46a955bSLisandro Dalcin include_dirs = [] 1830f51ee0fSAlexei Colin numpy_include = os.environ.get('NUMPY_INCLUDE') 1840f51ee0fSAlexei Colin if numpy_include is not None: 1850f51ee0fSAlexei Colin numpy_includes = [numpy_include] 1860f51ee0fSAlexei Colin else: 1875808f684SSatish Balay try: 1885808f684SSatish Balay import numpy 1896f336411SStefano Zampini 1905808f684SSatish Balay numpy_includes = [numpy.get_include()] 1915808f684SSatish Balay except ImportError: 1925808f684SSatish Balay numpy_includes = [] 193f46a955bSLisandro Dalcin include_dirs.extend(numpy_includes) 194f46a955bSLisandro Dalcin if F('{pyname}') != 'petsc4py': 195f46a955bSLisandro Dalcin try: 196f46a955bSLisandro Dalcin import petsc4py 1976f336411SStefano Zampini 198f46a955bSLisandro Dalcin petsc4py_includes = [petsc4py.get_include()] 199f46a955bSLisandro Dalcin except ImportError: 200f46a955bSLisandro Dalcin petsc4py_includes = [] 201f46a955bSLisandro Dalcin include_dirs.extend(petsc4py_includes) 202f46a955bSLisandro Dalcin # 2036f336411SStefano Zampini ext = { 2046f336411SStefano Zampini 'name': F('{pyname}.lib.{Name}'), 2056f336411SStefano Zampini 'sources': [F('src/{pyname}/{Name}.c')], 2066f336411SStefano Zampini 'depends': depends, 2076f336411SStefano Zampini 'include_dirs': [ 208f46a955bSLisandro Dalcin 'src', 209f46a955bSLisandro Dalcin F('src/{pyname}/include'), 2106f336411SStefano Zampini ] 2116f336411SStefano Zampini + include_dirs, 2126f336411SStefano Zampini 'define_macros': [ 213fb83dddaSLisandro Dalcin ('MPICH_SKIP_MPICXX', 1), 214fb83dddaSLisandro Dalcin ('OMPI_SKIP_MPICXX', 1), 215f46a955bSLisandro Dalcin ('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'), 216fb83dddaSLisandro Dalcin ], 2176f336411SStefano Zampini } 218f46a955bSLisandro Dalcin return [ext] 2195808f684SSatish Balay 2206f336411SStefano Zampini 2215808f684SSatish Balay# -------------------------------------------------------------------- 2225808f684SSatish Balay# Setup 2235808f684SSatish Balay# -------------------------------------------------------------------- 2245808f684SSatish Balay 2256f336411SStefano Zampini 226f8c80548SLisandro Dalcindef get_release(): 227f46a955bSLisandro Dalcin suffix = os.path.join('src', 'binding', F('{pyname}')) 228f46a955bSLisandro Dalcin if not topdir.endswith(os.path.join(os.path.sep, suffix)): 229f09792b6SLisandro Dalcin return True 230f8c80548SLisandro Dalcin release = 1 231f8c80548SLisandro Dalcin rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir] * 3)) 232f46a955bSLisandro Dalcin version_h = os.path.join(rootdir, 'include', F('{name}version.h')) 233f46a955bSLisandro Dalcin release_macro = '%s_VERSION_RELEASE' % F('{name}').upper() 2346f336411SStefano Zampini version_re = re.compile(r'#define\s+%s\s+([-]*\d+)' % release_macro) 235f8c80548SLisandro Dalcin if os.path.exists(version_h) and os.path.isfile(version_h): 236f8c80548SLisandro Dalcin with open(version_h, 'r') as f: 237f8c80548SLisandro Dalcin release = int(version_re.search(f.read()).groups()[0]) 238f8c80548SLisandro Dalcin return bool(release) 239f8c80548SLisandro Dalcin 2406f336411SStefano Zampini 241f8c80548SLisandro Dalcindef requires(pkgname, major, minor, release=True): 242f8c80548SLisandro Dalcin minor = minor + int(not release) 243f8c80548SLisandro Dalcin devel = '' if release else '.dev0' 2446f336411SStefano Zampini vmin = f'{major}.{minor}{devel}' 2456f336411SStefano Zampini vmax = f'{major}.{minor+1}' 2466f336411SStefano Zampini return f'{pkgname}>={vmin},<{vmax}' 2476f336411SStefano Zampini 248f8c80548SLisandro Dalcin 2495808f684SSatish Balaydef run_setup(): 2502149b0eaSStefano Zampini is_sdist = 'sdist' in sys.argv 2515808f684SSatish Balay setup_args = metadata.copy() 252f8c80548SLisandro Dalcin vstr = setup_args['version'].split('.')[:2] 253f8c80548SLisandro Dalcin x, y = tuple(map(int, vstr)) 254f8c80548SLisandro Dalcin release = get_release() 255f8c80548SLisandro Dalcin if not release: 2566f336411SStefano Zampini setup_args['version'] = '%d.%d.0.dev0' % (x, y + 1) 2575808f684SSatish Balay if setuptools: 2589fb6d20cSLisandro Dalcin warnings.filterwarnings( 2599fb6d20cSLisandro Dalcin 'ignore', message=r'.*fetch_build_eggs', module='setuptools' 2609fb6d20cSLisandro Dalcin ) 2615808f684SSatish Balay setup_args['zip_safe'] = False 2622149b0eaSStefano Zampini numpy_pin = 'numpy' 2632149b0eaSStefano Zampini if not is_sdist: 26430eefebbSLisandro Dalcin try: 26530eefebbSLisandro Dalcin import numpy 2666f336411SStefano Zampini 26730eefebbSLisandro Dalcin major = int(numpy.__version__.partition('.')[0]) 268f566d949SLisandro Dalcin numpy_pin = 'numpy>=1.19' if major >= 2 else 'numpy<2' 26930eefebbSLisandro Dalcin except ImportError: 2702149b0eaSStefano Zampini pass 271693647e8SLisandro Dalcin setup_args['setup_requires'] = ['numpy'] 27230eefebbSLisandro Dalcin setup_args['install_requires'] = [numpy_pin] 273f46a955bSLisandro Dalcin for pkg in map(str.lower, PLIST): 274f46a955bSLisandro Dalcin PKG_DIR = os.environ.get(pkg.upper() + '_DIR') 275f46a955bSLisandro Dalcin if not (PKG_DIR and os.path.isdir(PKG_DIR)): 276f46a955bSLisandro Dalcin package = requires(pkg, x, y, release) 277693647e8SLisandro Dalcin setup_args['setup_requires'] += [package] 278f46a955bSLisandro Dalcin setup_args['install_requires'] += [package] 279f46a955bSLisandro Dalcin if F('{pyname}') != 'petsc4py': 280f46a955bSLisandro Dalcin package = requires('petsc4py', x, y, release) 281693647e8SLisandro Dalcin setup_args['setup_requires'] += [package] 282f46a955bSLisandro Dalcin setup_args['install_requires'] += [package] 283fb83dddaSLisandro Dalcin setup_args.update(metadata_extra) 2845808f684SSatish Balay # 285f46a955bSLisandro Dalcin conf = __import__(F('conf{name}')) 2867b8d1e39SLisandro Dalcin cython_sources = [src for src in sources()] # noqa: C416 2877b8d1e39SLisandro Dalcin ext_modules = [conf.Extension(**ext) for ext in extensions()] 2887b8d1e39SLisandro Dalcin # 2897b8d1e39SLisandro Dalcin sabi = get_build_pysabi() 2907b8d1e39SLisandro Dalcin if sabi and setuptools: 2917b8d1e39SLisandro Dalcin api_tag = "cp{}{}".format(*sabi) 2927b8d1e39SLisandro Dalcin options = {"bdist_wheel": {"py_limited_api": api_tag}} 2937b8d1e39SLisandro Dalcin setup_args["options"] = options 2947b8d1e39SLisandro Dalcin api_ver = "0x{:02X}{:02X}0000".format(*sabi) 2957b8d1e39SLisandro Dalcin defines = [("Py_LIMITED_API", api_ver)] 2967b8d1e39SLisandro Dalcin for ext in ext_modules: 2977b8d1e39SLisandro Dalcin ext.define_macros.extend(defines) 2987b8d1e39SLisandro Dalcin ext.py_limited_api = True 2997b8d1e39SLisandro Dalcin # 300f46a955bSLisandro Dalcin conf.setup( 301fb83dddaSLisandro Dalcin packages=[ 302f46a955bSLisandro Dalcin F('{pyname}'), 303f46a955bSLisandro Dalcin F('{pyname}.lib'), 30422d6dc08SStefano Zampini F('{pyname}.lib._pytypes'), 30522d6dc08SStefano Zampini F('{pyname}.lib._pytypes.viewer'), 306fb83dddaSLisandro Dalcin ], 307f46a955bSLisandro Dalcin package_dir={'': 'src'}, 308fb83dddaSLisandro Dalcin package_data={ 309f46a955bSLisandro Dalcin F('{pyname}'): [ 310f46a955bSLisandro Dalcin F('{Name}.pxd'), 311f46a955bSLisandro Dalcin F('{Name}*.h'), 312f46a955bSLisandro Dalcin F('include/{pyname}/*.h'), 313f46a955bSLisandro Dalcin F('include/{pyname}/*.i'), 31455a74a43SLisandro Dalcin 'py.typed', 31555a74a43SLisandro Dalcin '*.pyi', 31655a74a43SLisandro Dalcin '*/*.pyi', 317fb83dddaSLisandro Dalcin ], 318f46a955bSLisandro Dalcin F('{pyname}.lib'): [ 319f46a955bSLisandro Dalcin F('{name}.cfg'), 320fb83dddaSLisandro Dalcin ], 321fb83dddaSLisandro Dalcin }, 3227b8d1e39SLisandro Dalcin cython_sources=cython_sources, 3237b8d1e39SLisandro Dalcin ext_modules=ext_modules, 3246f336411SStefano Zampini **setup_args, 325fb83dddaSLisandro Dalcin ) 3265808f684SSatish Balay 3276f336411SStefano Zampini 328fb83dddaSLisandro Dalcin# -------------------------------------------------------------------- 329fb83dddaSLisandro Dalcin 3306f336411SStefano Zampini 3315808f684SSatish Balaydef main(): 3325808f684SSatish Balay run_setup() 3335808f684SSatish Balay 3346f336411SStefano Zampini 3355808f684SSatish Balayif __name__ == '__main__': 3365808f684SSatish Balay main() 3375808f684SSatish Balay 3385808f684SSatish Balay# -------------------------------------------------------------------- 339