Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix wheel builds #1484

Merged
merged 6 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
5 changes: 3 additions & 2 deletions interfaces/python_sdist/MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 6 additions & 43 deletions interfaces/python_sdist/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ from build.env import IsolatedEnvBuilder

from buildutils import logger

Import("env", "configh")
configh = configh.copy()
Import("env")

localenv = env.Clone()

Expand Down Expand Up @@ -84,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(
Expand All @@ -107,10 +108,11 @@ include_target = sdist(localenv.RecursiveInstall(
"clib$",
"ext$",
r"config\.h\.in",
r"config\.h",
r"utils_utils\.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",
Expand All @@ -122,45 +124,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",
Expand Down
8 changes: 4 additions & 4 deletions interfaces/python_sdist/pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions interfaces/python_sdist/setup.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ install_requires =
packaging
python_requires @py_requires_ver_str@
packages =
cantera
cantera.data
cantera.examples
cantera.test
Expand Down
83 changes: 46 additions & 37 deletions interfaces/python_sdist/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@
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:
"""Custom options for the install and develop commands.

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."),
Expand All @@ -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 (
Expand All @@ -62,19 +66,21 @@ 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():
p.unlink()
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")))
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -111,8 +122,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 "
Expand All @@ -125,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 = []

Expand All @@ -152,10 +159,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


Expand All @@ -166,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,
Expand Down
2 changes: 1 addition & 1 deletion test/python/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down