mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
[SCons] Extract Python module-building environment setup
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
"""Cython-based Python Module"""
|
||||
import re
|
||||
from pathlib import Path
|
||||
from pkg_resources import parse_version
|
||||
import json
|
||||
from buildutils import *
|
||||
|
||||
Import('env', 'build', 'install')
|
||||
@@ -15,70 +13,8 @@ build(dataFiles)
|
||||
# Install Python samples
|
||||
install(localenv.RecursiveInstall, "$inst_sampledir/python", "#samples/python")
|
||||
|
||||
# Get information needed to build the Python module
|
||||
script = """\
|
||||
from sysconfig import *
|
||||
import numpy
|
||||
import json
|
||||
import site
|
||||
vars = get_config_vars()
|
||||
vars["plat"] = get_platform()
|
||||
vars["numpy_include"] = numpy.get_include()
|
||||
vars["site_packages"] = [d for d in site.getsitepackages() if d.endswith("-packages")]
|
||||
vars["user_site_packages"] = site.getusersitepackages()
|
||||
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"])
|
||||
py_version_nodot = info["py_version_nodot"]
|
||||
numpy_include = info["numpy_include"]
|
||||
site_packages = info["site_packages"]
|
||||
user_site_packages = info["user_site_packages"]
|
||||
localenv.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
|
||||
localenv.Prepend(LIBS=localenv['cantera_libs'])
|
||||
setup_python_env(localenv)
|
||||
|
||||
# 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"
|
||||
):
|
||||
module_ext = f".cp{py_version_nodot}-{info['plat'].replace('-', '_')}.pyd"
|
||||
|
||||
# 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.
|
||||
if localenv["HAS_CLANG"] and py_version_short == parse_version("3.8"):
|
||||
localenv.Append(CXXFLAGS='-Wno-deprecated-declarations')
|
||||
|
||||
if "icc" in localenv["CC"]:
|
||||
localenv.Append(CPPDEFINES={"CYTHON_FALLTHROUGH": " __attribute__((fallthrough))"})
|
||||
|
||||
if localenv['OS'] == 'Darwin':
|
||||
localenv.Append(LINKFLAGS='-undefined dynamic_lookup')
|
||||
elif localenv['OS'] == 'Windows':
|
||||
localenv.Append(LIBPATH=prefix + '/libs')
|
||||
if localenv['toolchain'] == 'mingw':
|
||||
localenv.Append(LIBS=f"python{py_version_nodot}")
|
||||
if localenv['OS_BITS'] == 64:
|
||||
localenv.Append(CPPDEFINES='MS_WIN64')
|
||||
# Fix for https://bugs.python.org/issue11566. Fixed in 3.7.3 and higher.
|
||||
# See https://github.com/python/cpython/pull/11283
|
||||
if py_version_full < parse_version("3.7.3"):
|
||||
localenv.Append(CPPDEFINES={"_hypot": "hypot"})
|
||||
|
||||
if "numpy_1_7_API" in localenv:
|
||||
localenv.Append(CPPDEFINES="NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION")
|
||||
|
||||
localenv["module_ext"] = module_ext
|
||||
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",
|
||||
@@ -104,15 +40,15 @@ for pyxfile in multi_glob(localenv, "cantera", "pyx"):
|
||||
f"#build/temp-py/{pyxfile.name.split('.')[0]}", cythonized)
|
||||
cython_obj.append(obj)
|
||||
|
||||
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")
|
||||
plat = info['plat'].replace('-', '_').replace('.', '_')
|
||||
wheel_name = (f"Cantera-{env['cantera_version']}-cp{py_version_nodot}"
|
||||
f"-cp{py_version_nodot}-{plat}.whl")
|
||||
wheel_name = ("Cantera-${cantera_version}-cp${py_version_nodot}"
|
||||
"-cp${py_version_nodot}-${plat}.whl")
|
||||
mod = build(localenv.Command(f"#build/python/dist/{wheel_name}", "setup.cfg",
|
||||
build_cmd))
|
||||
env['python_module'] = mod
|
||||
@@ -153,9 +89,9 @@ else:
|
||||
ignore_errors=True)
|
||||
|
||||
if user_install:
|
||||
test_prefix = Path(user_site_packages).parents[2]
|
||||
test_prefix = Path(localenv["user_site_packages"]).parents[2]
|
||||
elif python_prefix is None:
|
||||
test_prefix = Path(site_packages[0]).parents[2]
|
||||
test_prefix = Path(localenv["site_packages"][0]).parents[2]
|
||||
else:
|
||||
test_prefix = Path(python_prefix)
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ packages =
|
||||
# The module extension needs to be here since we don't want setuptools to compile
|
||||
# the extension, so there are no ``source`` files in the setup.py ``extension`` and
|
||||
# we have to treat the module as package data.
|
||||
cantera = *.pxd, *@module_ext@, test/*.txt, examples/*.txt, data/*.*
|
||||
cantera = *.pxd, *@py_module_ext@, test/*.txt, examples/*.txt, data/*.*
|
||||
|
||||
[options.extras_require]
|
||||
hdf5 = h5py
|
||||
|
||||
@@ -11,10 +11,12 @@ import time
|
||||
import shutil
|
||||
import enum
|
||||
from pathlib import Path
|
||||
from pkg_resources import parse_version
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
from collections.abc import Mapping as MappingABC
|
||||
from SCons.Variables import PathVariable, EnumVariable, BoolVariable
|
||||
from SCons.Script import Dir
|
||||
|
||||
try:
|
||||
import numpy as np
|
||||
@@ -25,7 +27,7 @@ __all__ = ("Option", "PathOption", "BoolOption", "EnumOption", "Configuration",
|
||||
"logger", "remove_directory", "remove_file", "test_results",
|
||||
"add_RegressionTest", "get_command_output", "listify", "which",
|
||||
"ConfigBuilder", "multi_glob", "get_spawn", "quoted",
|
||||
"get_pip_install_location", "compiler_flag_list")
|
||||
"get_pip_install_location", "compiler_flag_list", "setup_python_env")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Iterable, TypeVar, Union, List, Dict, Tuple, Optional, \
|
||||
@@ -1246,6 +1248,83 @@ def get_command_output(cmd: str, *args: str, ignore_errors=False):
|
||||
)
|
||||
return data.stdout.strip()
|
||||
|
||||
_python_info = None
|
||||
def setup_python_env(env):
|
||||
"""Set up an environment for compiling Python extension modules"""
|
||||
|
||||
global _python_info
|
||||
if _python_info is None:
|
||||
# Get information needed to build the Python module
|
||||
script = textwrap.dedent("""\
|
||||
from sysconfig import *
|
||||
import numpy
|
||||
import json
|
||||
import site
|
||||
vars = get_config_vars()
|
||||
vars["plat"] = get_platform()
|
||||
vars["numpy_include"] = numpy.get_include()
|
||||
vars["site_packages"] = [d for d in site.getsitepackages() if d.endswith("-packages")]
|
||||
vars["user_site_packages"] = site.getusersitepackages()
|
||||
print(json.dumps(vars))
|
||||
""")
|
||||
_python_info = json.loads(get_command_output(env["python_cmd"], "-c", script))
|
||||
|
||||
info = _python_info
|
||||
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"])
|
||||
py_version_nodot = info["py_version_nodot"]
|
||||
plat = info['plat'].replace('-', '_').replace('.', '_')
|
||||
numpy_include = info["numpy_include"]
|
||||
env.Prepend(CPPPATH=[Dir('#include'), inc, numpy_include])
|
||||
env.Prepend(LIBS=env['cantera_libs'])
|
||||
|
||||
# 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 env["OS"] == "Windows"
|
||||
and module_ext == ".pyd"
|
||||
):
|
||||
module_ext = f".cp{py_version_nodot}-{info['plat'].replace('-', '_')}.pyd"
|
||||
|
||||
env["py_module_ext"] = module_ext
|
||||
env["py_version_nodot"] = py_version_nodot
|
||||
env["py_plat"] = plat
|
||||
env["site_packages"] = info["site_packages"]
|
||||
env["user_site_packages"] = info["user_site_packages"]
|
||||
|
||||
# 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.
|
||||
if env["HAS_CLANG"] and py_version_short == parse_version("3.8"):
|
||||
env.Append(CXXFLAGS='-Wno-deprecated-declarations')
|
||||
|
||||
if "icc" in env["CC"]:
|
||||
env.Append(CPPDEFINES={"CYTHON_FALLTHROUGH": " __attribute__((fallthrough))"})
|
||||
|
||||
if env['OS'] == 'Darwin':
|
||||
env.Append(LINKFLAGS='-undefined dynamic_lookup')
|
||||
elif env['OS'] == 'Windows':
|
||||
env.Append(LIBPATH=prefix + '/libs')
|
||||
if env['toolchain'] == 'mingw':
|
||||
env.Append(LIBS=f"python{py_version_nodot}")
|
||||
if env['OS_BITS'] == 64:
|
||||
env.Append(CPPDEFINES='MS_WIN64')
|
||||
# Fix for https://bugs.python.org/issue11566. Fixed in 3.7.3 and higher.
|
||||
# See https://github.com/python/cpython/pull/11283
|
||||
if py_version_full < parse_version("3.7.3"):
|
||||
env.Append(CPPDEFINES={"_hypot": "hypot"})
|
||||
|
||||
if "numpy_1_7_API" in env:
|
||||
env.Append(CPPDEFINES="NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION")
|
||||
|
||||
|
||||
return env
|
||||
|
||||
def get_pip_install_location(
|
||||
python_cmd: str,
|
||||
|
||||
Reference in New Issue
Block a user