From 8e7cd2a2530dbf8d1c2ea90be1c0100be4c063f8 Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 13:26:57 -0400 Subject: [PATCH 1/6] Clean up the Python extensions manager objects --- SConstruct | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SConstruct b/SConstruct index 11ed47d564..000c4e149b 100644 --- a/SConstruct +++ b/SConstruct @@ -126,6 +126,8 @@ if "clean" in COMMAND_LINE_TARGETS: remove_directory("test/work") remove_file(".sconsign.dblite") remove_file("include/cantera/base/config.h") + remove_file("src/extensions/PythonExtensionManager.os") + remove_file("src/extensions/delegator.h") remove_file("src/pch/system.h.gch") remove_directory("include/cantera/ext") remove_file("config.log") From 82b905f75fdbd97ba944089acc9a84976ddc992a Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 13:28:19 -0400 Subject: [PATCH 2/6] Remove special config.h handling in the sdist config.h no longer requires system-specific setup, so it can be generated at sdist build time with no problem. --- interfaces/python_sdist/SConscript | 44 ++---------------------------- interfaces/python_sdist/setup.py | 6 ---- 2 files changed, 2 insertions(+), 48 deletions(-) diff --git a/interfaces/python_sdist/SConscript b/interfaces/python_sdist/SConscript index 0aaf71b7e3..c4aa2d2211 100644 --- a/interfaces/python_sdist/SConscript +++ b/interfaces/python_sdist/SConscript @@ -9,8 +9,7 @@ from build.env import IsolatedEnvBuilder from buildutils import logger -Import("env", "configh") -configh = configh.copy() +Import("env") localenv = env.Clone() @@ -107,10 +106,10 @@ include_target = sdist(localenv.RecursiveInstall( "clib$", "ext$", r"config\.h\.in", - r"config\.h", ], )) localenv.Depends(clib_defs_target, include_target) +localenv.Depends(include_target, env["config_h_target"]) ext_include_target = sdist(localenv.Command( "include/cantera/ext", @@ -122,45 +121,6 @@ localenv.Depends(ext_include_target, include_target) ext_target = sdist(localenv.Command("ext", "#ext", copy_ext_src)) -# Disable Lapack for the sdist -configh["CT_USE_LAPACK"] = None -configh["CT_SUNDIALS_USE_LAPACK"] = None - - -class DefineDict: - """dict-like class used to fill config.h.in partially. - - We cannot use buildutils.DefineDict because missing keys in self.data are replaced - with /* #undef {key} */, but here we want to leave those as template strings for - setup.py to fill in on the final build machine. - """ - - def __init__(self, data): - self.data = data - - def __getitem__(self, key): - if key not in self.data: - return f"{{{key!s}!s}}" - elif self.data[key] is None: - return f"/* #undef {key!s} */" - else: - return f"#define {key!s} {self.data[key]!s}" - - -def config_builder(target, source, env): - configh = env["configh"] - config_h = Path(str(target[0])) - config_h_in = Path(str(source[0])).read_text() - config_h.write_text(config_h_in.format_map(configh)) - - -localenv["configh"] = DefineDict(configh) -config_h_in_target = sdist(localenv.Command( - "config.h.in", - "#include/cantera/base/config.h.in", - config_builder, -)) - sdist(localenv.UnitsInterfaceBuilder( "cantera/with_units/solution.py", "#interfaces/cython/cantera/with_units/solution.py.in", diff --git a/interfaces/python_sdist/setup.py b/interfaces/python_sdist/setup.py index 127297a178..10cd082739 100644 --- a/interfaces/python_sdist/setup.py +++ b/interfaces/python_sdist/setup.py @@ -111,8 +111,6 @@ def configure_build(): boost_version = boost_lib_version.group(1) break - config_h = {} - if not boost_version: raise ValueError( "Could not find Boost headers. Please set an environment variable called " @@ -152,10 +150,6 @@ def configure_build(): shutil.copy2(sun_config_h, EXT_SRC / "sundials" / "sundials") shutil.copy2(sun_config_h, CT_INCLUDE / "cantera" / "ext" / "sundials") - config_h_in = Path("config.h.in").read_text() - ct_config_h = Path("include") / "cantera" / "base" / "config.h" - ct_config_h.write_text(config_h_in.format_map(config_h)) - return extra_compile_flags, sundials_cflags, sundials_macros From ea1721f46bb33c32c13f24a75c0131bfe4eaf675 Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 13:28:59 -0400 Subject: [PATCH 3/6] Update the Cantera data folder in tests Since the data folder is no longer in a fixed location relative to the tests, after moving the tests out of the package, we need to use the import location of the Cantera package to find the installed data files. --- test/python/utilities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/utilities.py b/test/python/utilities.py index 52d8a2b09e..9682d82448 100644 --- a/test/python/utilities.py +++ b/test/python/utilities.py @@ -16,7 +16,7 @@ slow_test = unittest.skipIf(environ.get("CT_SKIP_SLOW", "0") == "1", "slow test") TEST_DATA_PATH = Path(__file__).parents[1] / "data" -CANTERA_DATA_PATH = Path(__file__).parents[2] / "data" +CANTERA_DATA_PATH = Path(cantera.__file__).parent / "data" cantera.add_directory(TEST_DATA_PATH) cantera.add_directory(CANTERA_DATA_PATH) From ce98a45f74267134e9034a66fff07e94887b2a77 Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 14:27:31 -0400 Subject: [PATCH 4/6] Fixes after splitting the Cython module --- interfaces/python_sdist/MANIFEST.in | 5 +- interfaces/python_sdist/setup.cfg.in | 1 + interfaces/python_sdist/setup.py | 77 +++++++++++++++++----------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/interfaces/python_sdist/MANIFEST.in b/interfaces/python_sdist/MANIFEST.in index 9b1ae04f48..78bbd163b7 100644 --- a/interfaces/python_sdist/MANIFEST.in +++ b/interfaces/python_sdist/MANIFEST.in @@ -2,10 +2,11 @@ # the wheel file if they are also listed in setup.cfg:options.package_data and not # listed in setup.cfg:options.exclude_package_data. -include cantera/_cantera.cpp +recursive-include cantera *.cpp +recursive-include cantera *.h recursive-include cantera *.pyx +recursive-include cantera *.pxd include sundials_config.h.in -include config.h.in graft include # The C/C++ files in these folders are included automatically because they're in diff --git a/interfaces/python_sdist/setup.cfg.in b/interfaces/python_sdist/setup.cfg.in index 77aa5557b7..219e53a3f0 100644 --- a/interfaces/python_sdist/setup.cfg.in +++ b/interfaces/python_sdist/setup.cfg.in @@ -45,6 +45,7 @@ install_requires = packaging python_requires @py_requires_ver_str@ packages = + cantera cantera.data cantera.examples cantera.test diff --git a/interfaces/python_sdist/setup.py b/interfaces/python_sdist/setup.py index 10cd082739..f6a7e6b2eb 100644 --- a/interfaces/python_sdist/setup.py +++ b/interfaces/python_sdist/setup.py @@ -8,13 +8,14 @@ import numpy import shutil +PY_SRC = Path("cantera") CT_SRC = Path("src") EXT_SRC = Path("ext") CT_INCLUDE = Path("include") BOOST_INCLUDE = None FORCE_CYTHON_COMPILE = False -CYTHON_BUILT_FILES = [Path("cantera") / f"_cantera.{ext}" for ext in ("cpp", "h")] +CYTHON_BUILT_FILES = [pth.with_suffix(".cpp") for pth in PY_SRC.glob("*.pyx")] class CanteraOptionsMixin: @@ -22,6 +23,7 @@ class CanteraOptionsMixin: Modeled after https://stackoverflow.com/a/53833930 """ + user_options = [ ("force-cython-compile", None, "Force compilation of .pyx files via Cython"), ("boost-include", None, "Location of the Boost header files."), @@ -46,13 +48,15 @@ def run(self): class InstallCommand(CanteraOptionsMixin, install): - user_options = (getattr(install, "user_options", []) - + CanteraOptionsMixin.user_options) + user_options = ( + getattr(install, "user_options", []) + CanteraOptionsMixin.user_options + ) class DevelopCommand(CanteraOptionsMixin, develop): - user_options = (getattr(develop, "user_options", []) - + CanteraOptionsMixin.user_options) + user_options = ( + getattr(develop, "user_options", []) + CanteraOptionsMixin.user_options + ) if ( @@ -62,6 +66,7 @@ class DevelopCommand(CanteraOptionsMixin, develop): or os.environ.get("FORCE_CYTHON_COMPILE", False) ): from Cython.Build import cythonize + CYTHON_EXT = ".pyx" for p in CYTHON_BUILT_FILES: if p.exists(): @@ -69,12 +74,13 @@ class DevelopCommand(CanteraOptionsMixin, develop): else: CYTHON_EXT = ".cpp" - def cythonize(extensions): + def cythonize(extensions, **kwargs): """Define a no-op for when we're not using Cython.""" return extensions -source_files = ["cantera/_cantera" + CYTHON_EXT] -source_files += list(map(str, CT_SRC.glob("**/*.cpp"))) + +ct_sources = list(map(str, CT_SRC.glob("**/*.cpp"))) +py_sources = list(map(str, PY_SRC.glob(f"*{CYTHON_EXT}"))) sundials_sources = list(map(str, EXT_SRC.glob("sundials/**/*.c"))) yaml_cpp_sources = list(map(str, EXT_SRC.glob("yaml-cpp/**/*.cpp"))) fmt_sources = list(map(str, EXT_SRC.glob("fmt/*.cc"))) @@ -83,7 +89,8 @@ def cythonize(extensions): str(CT_INCLUDE), str(CT_INCLUDE / "cantera" / "ext"), str(CT_SRC), - numpy.get_include() + "cantera", + numpy.get_include(), ] if "BOOST_INCLUDE" in os.environ: @@ -94,8 +101,12 @@ def cythonize(extensions): def configure_build(): boost_version = "" - boost_locs = (os.environ.get("BOOST_INCLUDE", None), BOOST_INCLUDE, "/usr/include", - "/usr/local/include") + boost_locs = ( + os.environ.get("BOOST_INCLUDE", None), + BOOST_INCLUDE, + "/usr/include", + "/usr/local/include", + ) for boost_dir in boost_locs: if boost_dir is None: continue @@ -123,24 +134,22 @@ def configure_build(): f"Could not convert Boost minor version to integer: '{boost_version}'" ) from None if boost_minor_version < 61: - raise ValueError( - "Cantera requires Boost version 1.61 or newer." - ) + raise ValueError("Cantera requires Boost version 1.61 or newer.") if sys.platform != "win32": extra_compile_flags = ["-std=c++17", "-g0"] sundials_configh = { "SUNDIALS_USE_GENERIC_MATH": "#define SUNDIALS_USE_GENERIC_MATH 1", - "SUNDIALS_BLAS_LAPACK": "/* #undef SUNDIALS_BLAS_LAPACK */" + "SUNDIALS_BLAS_LAPACK": "/* #undef SUNDIALS_BLAS_LAPACK */", } sundials_cflags = ["-w"] sundials_macros = [] else: - extra_compile_flags = [] + extra_compile_flags = ["/EHsc", "/std:c++17"] sundials_macros = [("_CRT_SECURE_NO_WARNINGS", None)] sundials_configh = { "SUNDIALS_USE_GENERIC_MATH": "/* #undef SUNDIALS_USE_GENERIC_MATH */", - "SUNDIALS_BLAS_LAPACK": "/* #undef SUNDIALS_BLAS_LAPACK */" + "SUNDIALS_BLAS_LAPACK": "/* #undef SUNDIALS_BLAS_LAPACK */", } sundials_cflags = [] @@ -160,31 +169,37 @@ def configure_build(): sundials_cflags = [] sundials_macros = [] -extensions = cythonize([ - Extension( - "cantera._cantera", - source_files, - include_dirs=include_dirs, - extra_compile_args=extra_compile_flags, - language="c++", - ), -]) - def lib_def(sources, cflags, include_dirs, macros): """Convenience factory to create the dictionary for a Setuptools library build.""" - return dict(sources=sources, cflags=cflags, include_dirs=include_dirs, - macros=macros) + return dict( + sources=sources, cflags=cflags, include_dirs=include_dirs, macros=macros + ) sundials_inc_dir = include_dirs + [str(EXT_SRC / "sundials" / "sundials")] libraries = [ - ("sundials", lib_def(sundials_sources, sundials_cflags, sundials_inc_dir, - sundials_macros)), + ( + "sundials", + lib_def(sundials_sources, sundials_cflags, sundials_inc_dir, sundials_macros), + ), ("yaml-cpp", lib_def(yaml_cpp_sources, extra_compile_flags, include_dirs, [])), ("fmtlib", lib_def(fmt_sources, extra_compile_flags, include_dirs, [])), ] +extensions = cythonize( + [ + Extension( + name=f"cantera._cantera", + sources=py_sources + ct_sources, + include_dirs=include_dirs, + extra_compile_args=extra_compile_flags, + language="c++", + ) + ], + compiler_directives={"binding": True, "language_level": 3}, +) + setup( ext_modules=extensions, libraries=libraries, From 17bdbb32f793a11c21a6ccb429568fd9728c42b9 Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 14:28:14 -0400 Subject: [PATCH 5/6] Update build package versions --- interfaces/python_sdist/pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interfaces/python_sdist/pyproject.toml b/interfaces/python_sdist/pyproject.toml index 1bb9493c62..b16f5851bb 100644 --- a/interfaces/python_sdist/pyproject.toml +++ b/interfaces/python_sdist/pyproject.toml @@ -1,10 +1,10 @@ [build-system] -# These versions are pinned to the latest versions at the time of this commit. -# Feel free to update as required. +# These versions are updated to the latest versions supported in cibuildwheel +# at the time of this commit. Feel free to update as required. requires = [ - "setuptools==67.7.1", + "setuptools>=67.6.1", "wheel", "oldest-supported-numpy", - "Cython==0.29.34", + "Cython>=0.29.34", ] build-backend = "setuptools.build_meta" From 1723bd7a1f565e5ed0d23a090a41beab7f057fef Mon Sep 17 00:00:00 2001 From: Bryan Weber Date: Sun, 7 May 2023 14:28:25 -0400 Subject: [PATCH 6/6] Fix commit version in Cython package --- interfaces/python_sdist/SConscript | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interfaces/python_sdist/SConscript b/interfaces/python_sdist/SConscript index c4aa2d2211..d9a8c16766 100644 --- a/interfaces/python_sdist/SConscript +++ b/interfaces/python_sdist/SConscript @@ -83,11 +83,13 @@ def replace_git_hash(target, source, env): sdist(localenv.RecursiveInstall( "src", "#src", - exclude=["fortran", "matlab", "clib", r"global\.cpp", "SCons.*"], + exclude=["fortran", "matlab", "clib", r"global\.cpp", "SCons.*", r"canteraStatic\.cpp"], )) sdist(localenv.Command("src/base/global.cpp", "#src/base/global.cpp", replace_git_hash)) +sdist(localenv.Command("include/cantera/cython/utils_utils.h", "#include/cantera/cython/utils_utils.h", + replace_git_hash)) # This is the only bit of the clib that we need for the Python interface clib_defs_target = sdist(localenv.Command( @@ -106,6 +108,7 @@ include_target = sdist(localenv.RecursiveInstall( "clib$", "ext$", r"config\.h\.in", + r"utils_utils\.h", ], )) localenv.Depends(clib_defs_target, include_target)