2017-11-08 16:19:53 -05:00
|
|
|
"""Cython-based Python Module"""
|
2021-04-15 11:52:16 -04:00
|
|
|
import re
|
2021-09-17 16:50:14 -04:00
|
|
|
from pathlib import Path
|
2021-04-15 11:52:16 -04:00
|
|
|
from pkg_resources import parse_version
|
2021-07-17 09:42:01 -04:00
|
|
|
import json
|
2012-09-06 19:58:03 +00:00
|
|
|
from buildutils import *
|
|
|
|
|
|
|
|
|
|
Import('env', 'build', 'install')
|
|
|
|
|
|
|
|
|
|
localenv = env.Clone()
|
|
|
|
|
|
2018-09-09 22:44:46 -04:00
|
|
|
cythonized = localenv.Command(
|
|
|
|
|
'cantera/_cantera.cpp',
|
|
|
|
|
'cantera/_cantera.pyx',
|
|
|
|
|
'''${python_cmd} -c "import Cython.Build; Cython.Build.cythonize('${SOURCE}')"''')
|
2014-01-31 23:15:17 +00:00
|
|
|
|
2021-04-18 22:22:48 -04:00
|
|
|
for f in multi_glob(localenv, 'cantera', 'pyx', 'pxd'):
|
2014-01-31 23:15:17 +00:00
|
|
|
localenv.Depends(cythonized, f)
|
|
|
|
|
|
2022-02-06 20:34:07 -05:00
|
|
|
# This must be the path to the real pxd file, not a file node pointing at the
|
|
|
|
|
# possibly non-existent file in the build directory
|
|
|
|
|
pxd_file = File("#interfaces/cython/cantera/_cantera.pxd").abspath
|
|
|
|
|
for line in Path(pxd_file).read_text().splitlines():
|
2014-10-29 15:36:28 +00:00
|
|
|
m = re.search(r'from "(cantera.*?)"', line)
|
|
|
|
|
if m:
|
|
|
|
|
localenv.Depends('cantera/_cantera.cpp', '#include/' + m.group(1))
|
|
|
|
|
|
2022-02-06 20:34:07 -05:00
|
|
|
dataFiles = localenv.RecursiveInstall("cantera/data", "#build/data")
|
2012-09-06 19:58:03 +00:00
|
|
|
build(dataFiles)
|
|
|
|
|
|
2022-02-06 20:34:07 -05:00
|
|
|
testFiles = localenv.RecursiveInstall("cantera/test/data", "#test/data")
|
2012-09-06 19:58:32 +00:00
|
|
|
build(testFiles)
|
|
|
|
|
|
2018-09-09 22:19:34 -04:00
|
|
|
# Get information needed to build the Python module
|
2021-07-17 09:42:01 -04:00
|
|
|
script = """\
|
|
|
|
|
from sysconfig import *
|
|
|
|
|
import numpy
|
|
|
|
|
import json
|
|
|
|
|
vars = get_config_vars()
|
|
|
|
|
vars["plat"] = get_platform()
|
|
|
|
|
vars["numpy_include"] = numpy.get_include()
|
|
|
|
|
print(json.dumps(vars))
|
|
|
|
|
"""
|
|
|
|
|
info = json.loads(get_command_output(localenv["python_cmd"], "-c", script))
|
|
|
|
|
module_ext = info["EXT_SUFFIX"]
|
|
|
|
|
inc = info["INCLUDEPY"]
|
|
|
|
|
pylib = info.get("LDLIBRARY")
|
|
|
|
|
prefix = info["prefix"]
|
|
|
|
|
py_version_short = parse_version(info["py_version_short"])
|
|
|
|
|
py_version_full = parse_version(info["py_version"])
|
2022-02-06 20:34:07 -05:00
|
|
|
py_version_nodot = info["py_version_nodot"]
|
2021-07-17 09:42:01 -04:00
|
|
|
numpy_include = info["numpy_include"]
|
2018-09-09 22:19:34 -04:00
|
|
|
localenv.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
|
|
|
|
|
localenv.Prepend(LIBS=localenv['cantera_libs'])
|
2021-02-04 17:31:51 -05:00
|
|
|
|
2021-07-17 09:42:01 -04:00
|
|
|
# Fix the module extension for Windows from the sysconfig library.
|
|
|
|
|
# See https://github.com/python/cpython/pull/22088 and
|
|
|
|
|
# https://bugs.python.org/issue39825
|
|
|
|
|
if (
|
|
|
|
|
py_version_full < parse_version("3.8.7")
|
|
|
|
|
and localenv["OS"] == "Windows"
|
|
|
|
|
and module_ext == ".pyd"
|
|
|
|
|
):
|
2022-01-17 21:39:30 -05:00
|
|
|
module_ext = f".cp{py_version_nodot}-{info['plat'].replace('-', '_')}.pyd"
|
2021-07-17 09:42:01 -04:00
|
|
|
|
2021-02-04 17:31:51 -05:00
|
|
|
# Don't print deprecation warnings for internal Python changes.
|
|
|
|
|
# Only applies to Python 3.8. The field that is deprecated in Python 3.8
|
|
|
|
|
# and causes the warnings to appear will be removed in Python 3.9 so no
|
|
|
|
|
# further warnings should be issued.
|
2021-07-17 09:42:01 -04:00
|
|
|
if localenv["HAS_CLANG"] and py_version_short == parse_version("3.8"):
|
2021-02-04 17:31:51 -05:00
|
|
|
localenv.Append(CXXFLAGS='-Wno-deprecated-declarations')
|
|
|
|
|
|
2021-11-26 10:02:29 -06:00
|
|
|
if "icc" in localenv["CC"]:
|
2022-02-06 20:34:07 -05:00
|
|
|
localenv.Append(CPPDEFINES={"CYTHON_FALLTHROUGH": " __attribute__((fallthrough))"})
|
2021-11-26 10:02:29 -06:00
|
|
|
|
2018-09-09 22:19:34 -04:00
|
|
|
if localenv['OS'] == 'Darwin':
|
|
|
|
|
localenv.Append(LINKFLAGS='-undefined dynamic_lookup')
|
|
|
|
|
elif localenv['OS'] == 'Windows':
|
2022-02-06 20:34:07 -05:00
|
|
|
localenv.Append(LIBPATH=prefix + '/libs')
|
2018-09-09 22:19:34 -04:00
|
|
|
if localenv['toolchain'] == 'mingw':
|
2022-01-17 21:39:30 -05:00
|
|
|
localenv.Append(LIBS=f"python{py_version_nodot}")
|
2018-09-09 22:19:34 -04:00
|
|
|
if localenv['OS_BITS'] == 64:
|
|
|
|
|
localenv.Append(CPPDEFINES='MS_WIN64')
|
2021-07-17 09:42:01 -04:00
|
|
|
# Fix for https://bugs.python.org/issue11566. Fixed in 3.7.3 and higher.
|
2021-07-16 15:08:48 -04:00
|
|
|
# See https://github.com/python/cpython/pull/11283
|
2021-07-17 09:42:01 -04:00
|
|
|
if py_version_full < parse_version("3.7.3"):
|
2021-07-16 15:08:48 -04:00
|
|
|
localenv.Append(CPPDEFINES={"_hypot": "hypot"})
|
2018-09-09 22:19:34 -04:00
|
|
|
elif localenv['OS'] == 'Cygwin':
|
|
|
|
|
# extract 'pythonX.Y' from 'libpythonX.Y.dll.a'
|
|
|
|
|
localenv.Append(LIBS=pylib[3:-6])
|
|
|
|
|
|
2022-01-17 21:39:30 -05:00
|
|
|
localenv["module_ext"] = module_ext
|
2021-07-16 15:14:16 -04:00
|
|
|
setup_cfg = localenv.SubstFile("setup.cfg", "setup.cfg.in")
|
|
|
|
|
readme = localenv.Command("README.rst", "#README.rst", Copy("$TARGET", "$SOURCE"))
|
|
|
|
|
license = localenv.Command("LICENSE.txt", "#build/ext/LICENSE.txt",
|
|
|
|
|
Copy("$TARGET", "$SOURCE"))
|
|
|
|
|
localenv.Depends(license, localenv["license_target"])
|
2022-01-17 21:39:30 -05:00
|
|
|
|
|
|
|
|
# Build the Python module
|
|
|
|
|
obj = localenv.SharedObject('#build/temp-py/_cantera', 'cantera/_cantera.cpp')
|
|
|
|
|
ext = localenv.LoadableModule(f"cantera/_cantera{module_ext}",
|
|
|
|
|
obj, LIBPREFIX="", SHLIBSUFFIX=module_ext,
|
|
|
|
|
SHLIBPREFIX="", LIBSUFFIXES=[module_ext])
|
|
|
|
|
|
2022-03-29 08:59:42 -04:00
|
|
|
build_cmd = ("$python_cmd_esc -m pip wheel -v --no-build-isolation --no-deps "
|
2022-01-17 21:39:30 -05:00
|
|
|
"--wheel-dir=build/python/dist build/python")
|
2022-03-26 16:53:20 -04:00
|
|
|
plat = info['plat'].replace('-', '_').replace('.', '_')
|
2022-01-17 21:39:30 -05:00
|
|
|
wheel_name = (f"Cantera-{env['cantera_version']}-cp{py_version_nodot}"
|
2022-03-26 16:53:20 -04:00
|
|
|
f"-cp{py_version_nodot}-{plat}.whl")
|
2022-02-06 20:34:07 -05:00
|
|
|
mod = build(localenv.Command(f"#build/python/dist/{wheel_name}", "setup.cfg",
|
|
|
|
|
build_cmd))
|
2018-09-09 22:19:34 -04:00
|
|
|
env['python_module'] = mod
|
|
|
|
|
env['python_extension'] = ext
|
|
|
|
|
|
2022-01-17 21:39:30 -05:00
|
|
|
localenv.Depends(mod, [ext, dataFiles, testFiles, setup_cfg, readme, license,
|
|
|
|
|
"setup.py", "pyproject.toml"])
|
2018-09-09 22:19:34 -04:00
|
|
|
localenv.Depends(ext, localenv['cantera_staticlib'])
|
|
|
|
|
|
2021-04-18 22:22:48 -04:00
|
|
|
for f in (multi_glob(localenv, 'cantera', 'py') +
|
2022-01-17 21:39:30 -05:00
|
|
|
multi_glob(localenv, 'cantera/*', 'py') +
|
|
|
|
|
multi_glob(localenv, 'cantera/*/*', 'py')):
|
2018-09-09 22:19:34 -04:00
|
|
|
localenv.Depends(mod, f)
|
|
|
|
|
|
|
|
|
|
# Determine installation path and install the Python module
|
2022-01-17 21:39:30 -05:00
|
|
|
install_cmd = ["$python_cmd_esc", "-m", "pip", "install"]
|
|
|
|
|
user_install = False
|
|
|
|
|
python_prefix = None
|
2018-09-09 22:19:34 -04:00
|
|
|
if localenv['python_prefix'] == 'USER':
|
|
|
|
|
# Install to the OS-dependent user site-packages directory
|
2022-01-17 21:39:30 -05:00
|
|
|
install_cmd.append("--user")
|
|
|
|
|
user_install = True
|
2022-02-06 20:34:07 -05:00
|
|
|
elif localenv["python_prefix"]:
|
|
|
|
|
# A specific location for the Cantera python module has been given
|
2022-03-19 17:57:09 -04:00
|
|
|
install_cmd.append(f"--prefix={localenv.subst('$python_prefix')}")
|
|
|
|
|
python_prefix = localenv.subst("$python_prefix")
|
|
|
|
|
elif not env["default_prefix"]:
|
|
|
|
|
install_cmd.append(f"--prefix={env['prefix']}")
|
|
|
|
|
python_prefix = env["prefix"]
|
2018-09-09 22:19:34 -04:00
|
|
|
|
2021-09-17 16:50:14 -04:00
|
|
|
if env["stage_dir"]:
|
|
|
|
|
# Get the absolute path to the stage directory. If the stage directory is a relative
|
2022-01-17 21:39:30 -05:00
|
|
|
# path, consider it to be relative to the root of the Cantera source directory.
|
|
|
|
|
stage_dir = Path(env["stage_dir"])
|
|
|
|
|
if not stage_dir.is_absolute():
|
|
|
|
|
stage_dir = Path(Dir("#").abspath) / stage_dir
|
|
|
|
|
|
|
|
|
|
install_cmd.append(f"--root={stage_dir.resolve()}")
|
2021-09-17 16:50:14 -04:00
|
|
|
|
2022-02-06 20:34:07 -05:00
|
|
|
install_cmd.extend(("--no-build-isolation", "--no-deps", "-v", "--force-reinstall",
|
|
|
|
|
"build/python"))
|
2018-09-09 22:19:34 -04:00
|
|
|
if localenv['PYTHON_INSTALLER'] == 'direct':
|
|
|
|
|
mod_inst = install(localenv.Command, 'dummy', mod,
|
2022-01-17 21:39:30 -05:00
|
|
|
" ".join(install_cmd))
|
|
|
|
|
env["install_python_action"] = mod_inst
|
2022-02-06 20:24:26 -05:00
|
|
|
install_locs = get_pip_install_location(localenv["python_cmd"], user_install,
|
|
|
|
|
python_prefix)
|
2022-01-17 21:39:30 -05:00
|
|
|
env["python_module_loc"] = install_locs["platlib"]
|
|
|
|
|
env["ct_pyscriptdir"] = install_locs["scripts"]
|
2018-09-09 22:19:34 -04:00
|
|
|
elif localenv['PYTHON_INSTALLER'] == 'debian':
|
|
|
|
|
install(localenv.Command, 'dummy', mod,
|
2022-01-17 21:39:30 -05:00
|
|
|
'cd build/python && '
|
|
|
|
|
'$python_cmd_esc setup.py build --build-lib=. '
|
|
|
|
|
'install --install-layout=deb --no-compile --root=${python_prefix}')
|
|
|
|
|
env["python_module_loc"] = "<unspecified>"
|