mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
This version properly exports all necessary DLL symbols, eliminating the need to embed it separately in the Cython module.
141 lines
5.9 KiB
Python
141 lines
5.9 KiB
Python
"""Cython-based Python Module"""
|
|
import re
|
|
from pathlib import Path
|
|
from buildutils import *
|
|
|
|
Import('env', 'build', 'install')
|
|
|
|
localenv = env.Clone()
|
|
|
|
dataFiles = localenv.RecursiveInstall("cantera/data", "#build/data")
|
|
build(dataFiles)
|
|
|
|
# Install Python samples
|
|
install(localenv.RecursiveInstall, "$inst_sampledir/python", "#samples/python")
|
|
|
|
setup_python_env(localenv)
|
|
# Python module shouldn't explicitly link to Python library (added in other cases to
|
|
# support Python-based extensions), except when using MinGW
|
|
if localenv["toolchain"] != "mingw":
|
|
localenv["LIBS"] = [lib for lib in localenv["LIBS"] if not lib.startswith("python")]
|
|
|
|
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"])
|
|
|
|
directives = {"binding": True}
|
|
if env["coverage"]:
|
|
directives["linetrace"] = True
|
|
localenv.Append(CPPDEFINES={"CYTHON_TRACE": 1})
|
|
|
|
# Build the Python module
|
|
cython_obj = []
|
|
for pyxfile in multi_glob(localenv, "cantera", "pyx"):
|
|
cythonized = localenv.Command(
|
|
f"cantera/{pyxfile.name.replace('.pyx', '.cpp')}", pyxfile,
|
|
f'''${{python_cmd}} -c "import Cython.Build; Cython.Build.cythonize(r'${{SOURCE}}', compiler_directives={directives!r})"'''
|
|
)
|
|
for pxd in multi_glob(localenv, "cantera", "pxd"):
|
|
localenv.Depends(cythonized, pxd)
|
|
|
|
obj = localenv.SharedObject(
|
|
f"#build/temp-py/{pyxfile.name.split('.')[0]}", cythonized)
|
|
cython_obj.append(obj)
|
|
cython_obj.extend(env['python_ext_objects'])
|
|
|
|
module_ext = localenv["py_module_ext"]
|
|
ext = localenv.LoadableModule(f"cantera/_cantera{module_ext}",
|
|
cython_obj, LIBPREFIX="", SHLIBSUFFIX=module_ext,
|
|
SHLIBPREFIX="", LIBSUFFIXES=[module_ext])
|
|
|
|
build_cmd = ("$python_cmd_esc -m pip wheel -v --no-build-isolation --no-deps "
|
|
"--wheel-dir=build/python/dist build/python")
|
|
wheel_name = ("Cantera-${cantera_version}-cp${py_version_nodot}"
|
|
"-cp${py_version_nodot}-${py_plat}.whl")
|
|
mod = build(localenv.Command(f"#build/python/dist/{wheel_name}", "setup.cfg",
|
|
build_cmd))
|
|
env['python_module'] = mod
|
|
env['python_extension'] = ext
|
|
|
|
localenv.Depends(mod, [ext, dataFiles, setup_cfg, readme, license,
|
|
"setup.py", "pyproject.toml",
|
|
"cantera/test/README.txt", "cantera/examples/README.txt"])
|
|
|
|
if env['OS'] == 'Windows':
|
|
# On Windows, the cantera library directory is likely not to be on the path.
|
|
# However, Windows does search the directory containing a library (i.e. the
|
|
# Python extension module) for DLL dependencies.
|
|
dll = [f for f in localenv['cantera_shlib'] if f.name.endswith('.dll')][0]
|
|
copy_dll = localenv.Command(f'cantera/{dll.name}', dll, Copy("$TARGET", "$SOURCE"))
|
|
localenv.Depends(ext, copy_dll)
|
|
else:
|
|
localenv.Depends(ext, localenv['cantera_shlib'])
|
|
|
|
for f in (multi_glob(localenv, 'cantera', 'py') +
|
|
multi_glob(localenv, 'cantera/*', 'py')):
|
|
localenv.Depends(mod, f)
|
|
|
|
# Determine installation path and install the Python module
|
|
install_cmd = ["$python_cmd_esc", "-m", "pip", "install"]
|
|
user_install = False
|
|
python_prefix = None
|
|
if localenv['python_prefix'] == 'USER':
|
|
# Install to the OS-dependent user site-packages directory
|
|
install_cmd.append("--user")
|
|
user_install = True
|
|
elif localenv["python_prefix"]:
|
|
# A specific location for the Cantera python module has been given
|
|
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"]
|
|
|
|
# Check for existing Python module installation. Allow pip to remove an existing
|
|
# installation only if we're installing to the same location. Also disable
|
|
# uninstallation if we're installing to a staging directory.
|
|
if env["stage_dir"]:
|
|
install_cmd.append("--ignore-installed")
|
|
else:
|
|
info = get_command_output(localenv["python_cmd"], "-m", "pip", "show", "cantera",
|
|
ignore_errors=True)
|
|
|
|
if user_install:
|
|
test_prefix = Path(localenv["user_site_packages"]).parents[2]
|
|
elif python_prefix is None:
|
|
test_prefix = Path(localenv["site_packages"][0]).parents[2]
|
|
else:
|
|
test_prefix = Path(python_prefix)
|
|
|
|
match = re.search(r"Location: (.*)\n", info, re.MULTILINE)
|
|
existing_prefix = Path(match.group(1)).parents[2] if match else None
|
|
if existing_prefix and existing_prefix != test_prefix:
|
|
install_cmd.append("--ignore-installed")
|
|
|
|
if env["stage_dir"]:
|
|
# Get the absolute path to the stage directory. If the stage directory is a relative
|
|
# 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()}")
|
|
|
|
install_cmd.extend(("--no-build-isolation", "--no-deps", "-v", "--force-reinstall",
|
|
"build/python"))
|
|
if localenv['PYTHON_INSTALLER'] == 'direct':
|
|
mod_inst = install(localenv.Command, "dummy", mod, " ".join(install_cmd))
|
|
env["install_python_action"] = mod_inst
|
|
install_locs = get_pip_install_location(localenv["python_cmd"], user_install,
|
|
python_prefix)
|
|
env["python_module_loc"] = Path(install_locs["platlib"]).as_posix()
|
|
env["ct_pyscriptdir"] = Path(install_locs["scripts"]).as_posix()
|
|
elif localenv['PYTHON_INSTALLER'] == 'debian':
|
|
install(localenv.Command, 'dummy', mod,
|
|
'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>"
|