esmf package: add (optional) Python bindings (#45504)
* Add `+python` variant * `esmf` package installs Python bindings when `+python` is set Note: this does not inherit `PythonPackage`, which force an either/or choice between the Makefile and Pip builder: it instantiates a `PythonPipBuilder` as needed (when `+python` is set).
This commit is contained in:
parent
9ec8eaa0d3
commit
f0f9a16e4f
@ -10,7 +10,7 @@
|
|||||||
from spack.package import *
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
class Esmf(MakefilePackage):
|
class Esmf(MakefilePackage, PythonExtension):
|
||||||
"""The Earth System Modeling Framework (ESMF) is high-performance, flexible
|
"""The Earth System Modeling Framework (ESMF) is high-performance, flexible
|
||||||
software infrastructure for building and coupling weather, climate, and
|
software infrastructure for building and coupling weather, climate, and
|
||||||
related Earth science applications. The ESMF defines an architecture for
|
related Earth science applications. The ESMF defines an architecture for
|
||||||
@ -97,6 +97,10 @@ class Esmf(MakefilePackage):
|
|||||||
description="Named variant for snapshots versions (e.g., 'b09')",
|
description="Named variant for snapshots versions (e.g., 'b09')",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The way python is handled here is only avialable >=8.4.0
|
||||||
|
# https://github.com/esmf-org/esmf/releases/tag/v8.4.0
|
||||||
|
variant("python", default=False, description="Build python bindings", when="@8.4.0:")
|
||||||
|
|
||||||
# Optional dependencies
|
# Optional dependencies
|
||||||
depends_on("mpi", when="+mpi")
|
depends_on("mpi", when="+mpi")
|
||||||
depends_on("lapack@3:", when="+external-lapack")
|
depends_on("lapack@3:", when="+external-lapack")
|
||||||
@ -112,6 +116,20 @@ class Esmf(MakefilePackage):
|
|||||||
depends_on("parallelio@2.5.10: ~mpi", when="@8.5:+external-parallelio~mpi")
|
depends_on("parallelio@2.5.10: ~mpi", when="@8.5:+external-parallelio~mpi")
|
||||||
depends_on("cmake@3.5.2:", type="build", when="~external-parallelio")
|
depends_on("cmake@3.5.2:", type="build", when="~external-parallelio")
|
||||||
|
|
||||||
|
# python library
|
||||||
|
with when("+python"):
|
||||||
|
extends("python")
|
||||||
|
depends_on("py-pip")
|
||||||
|
depends_on("py-setuptools", type="build")
|
||||||
|
depends_on("py-wheel", type="build")
|
||||||
|
depends_on("py-mpi4py", when="+mpi")
|
||||||
|
depends_on("py-numpy")
|
||||||
|
|
||||||
|
# In esmf@8.4.0, esmx was introduced which depends on py-pyyaml
|
||||||
|
with when("@8.4.0:"):
|
||||||
|
depends_on("python", type="run")
|
||||||
|
depends_on("py-pyyaml", type="run")
|
||||||
|
|
||||||
# Testing dependencies
|
# Testing dependencies
|
||||||
depends_on("perl", type="test")
|
depends_on("perl", type="test")
|
||||||
|
|
||||||
@ -143,6 +161,29 @@ class Esmf(MakefilePackage):
|
|||||||
# https://github.com/spack/spack/issues/35957
|
# https://github.com/spack/spack/issues/35957
|
||||||
patch("esmf_cpp_info.patch")
|
patch("esmf_cpp_info.patch")
|
||||||
|
|
||||||
|
@when("+python")
|
||||||
|
def patch(self):
|
||||||
|
# The pyproject.toml file uses a dynamically generated version from git
|
||||||
|
# However, this results in a version of 0.0.0 and a mismatch with the loaded version
|
||||||
|
# so this hardcodes it to match the library's version
|
||||||
|
filter_file(
|
||||||
|
"""dynamic = \\[\\s+"version"\\s+\\]""",
|
||||||
|
f"""version = "{self.version}" """,
|
||||||
|
os.path.join("src/addon/esmpy/pyproject.toml"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup_run_environment(self, env):
|
||||||
|
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))
|
||||||
|
|
||||||
|
|
||||||
|
class PythonPipBuilder(spack.build_systems.python.PythonPipBuilder):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def build_directory(self):
|
||||||
|
return os.path.join(self.stage.source_path, "src/addon/esmpy")
|
||||||
|
|
||||||
|
|
||||||
|
class MakefileBuilder(spack.build_systems.makefile.MakefileBuilder):
|
||||||
# This is strictly required on Cray systems that use
|
# This is strictly required on Cray systems that use
|
||||||
# the Cray compiler wrappers, where we need to swap
|
# the Cray compiler wrappers, where we need to swap
|
||||||
# out the spack compiler wrappers in esmf.mk with the
|
# out the spack compiler wrappers in esmf.mk with the
|
||||||
@ -214,38 +255,38 @@ def setup_build_environment(self, env):
|
|||||||
# ESMF_COMPILER must be set to select which Fortran and
|
# ESMF_COMPILER must be set to select which Fortran and
|
||||||
# C++ compilers are being used to build the ESMF library.
|
# C++ compilers are being used to build the ESMF library.
|
||||||
|
|
||||||
if self.compiler.name == "gcc":
|
if self.pkg.compiler.name == "gcc":
|
||||||
env.set("ESMF_COMPILER", "gfortran")
|
env.set("ESMF_COMPILER", "gfortran")
|
||||||
with self.compiler.compiler_environment():
|
with self.pkg.compiler.compiler_environment():
|
||||||
gfortran_major_version = int(
|
gfortran_major_version = int(
|
||||||
spack.compiler.get_compiler_version_output(
|
spack.compiler.get_compiler_version_output(
|
||||||
self.compiler.fc, "-dumpversion"
|
self.pkg.compiler.fc, "-dumpversion"
|
||||||
).split(".")[0]
|
).split(".")[0]
|
||||||
)
|
)
|
||||||
elif self.compiler.name == "intel" or self.compiler.name == "oneapi":
|
elif self.pkg.compiler.name == "intel" or self.pkg.compiler.name == "oneapi":
|
||||||
env.set("ESMF_COMPILER", "intel")
|
env.set("ESMF_COMPILER", "intel")
|
||||||
elif self.compiler.name in ["clang", "apple-clang"]:
|
elif self.pkg.compiler.name in ["clang", "apple-clang"]:
|
||||||
env.set("ESMF_COMPILER", "gfortranclang")
|
env.set("ESMF_COMPILER", "gfortranclang")
|
||||||
with self.compiler.compiler_environment():
|
with self.pkg.compiler.compiler_environment():
|
||||||
gfortran_major_version = int(
|
gfortran_major_version = int(
|
||||||
spack.compiler.get_compiler_version_output(
|
spack.compiler.get_compiler_version_output(
|
||||||
self.compiler.fc, "-dumpversion"
|
self.pkg.compiler.fc, "-dumpversion"
|
||||||
).split(".")[0]
|
).split(".")[0]
|
||||||
)
|
)
|
||||||
elif self.compiler.name == "nag":
|
elif self.pkg.compiler.name == "nag":
|
||||||
env.set("ESMF_COMPILER", "nag")
|
env.set("ESMF_COMPILER", "nag")
|
||||||
elif self.compiler.name == "pgi":
|
elif self.pkg.compiler.name == "pgi":
|
||||||
env.set("ESMF_COMPILER", "pgi")
|
env.set("ESMF_COMPILER", "pgi")
|
||||||
elif self.compiler.name == "nvhpc":
|
elif self.pkg.compiler.name == "nvhpc":
|
||||||
env.set("ESMF_COMPILER", "nvhpc")
|
env.set("ESMF_COMPILER", "nvhpc")
|
||||||
elif self.compiler.name == "cce":
|
elif self.pkg.compiler.name == "cce":
|
||||||
env.set("ESMF_COMPILER", "cce")
|
env.set("ESMF_COMPILER", "cce")
|
||||||
elif self.compiler.name == "aocc":
|
elif self.pkg.compiler.name == "aocc":
|
||||||
env.set("ESMF_COMPILER", "aocc")
|
env.set("ESMF_COMPILER", "aocc")
|
||||||
else:
|
else:
|
||||||
msg = "The compiler you are building with, "
|
msg = "The compiler you are building with, "
|
||||||
msg += '"{0}", is not supported by ESMF.'
|
msg += '"{0}", is not supported by ESMF.'
|
||||||
raise InstallError(msg.format(self.compiler.name))
|
raise InstallError(msg.format(self.pkg.compiler.name))
|
||||||
|
|
||||||
if "+mpi" in spec:
|
if "+mpi" in spec:
|
||||||
env.set("ESMF_CXX", spec["mpi"].mpicxx)
|
env.set("ESMF_CXX", spec["mpi"].mpicxx)
|
||||||
@ -265,7 +306,7 @@ def setup_build_environment(self, env):
|
|||||||
env.set("ESMF_BOPT", "O")
|
env.set("ESMF_BOPT", "O")
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.compiler.name in ["gcc", "clang", "apple-clang"]
|
self.pkg.compiler.name in ["gcc", "clang", "apple-clang"]
|
||||||
and gfortran_major_version >= 10
|
and gfortran_major_version >= 10
|
||||||
and (self.spec.satisfies("@:8.2.99") or self.spec.satisfies("@8.3.0b09"))
|
and (self.spec.satisfies("@:8.2.99") or self.spec.satisfies("@8.3.0b09"))
|
||||||
):
|
):
|
||||||
@ -277,7 +318,7 @@ def setup_build_environment(self, env):
|
|||||||
|
|
||||||
# ESMF_OS must be set for Cray systems
|
# ESMF_OS must be set for Cray systems
|
||||||
# But spack no longer gives arch == cray
|
# But spack no longer gives arch == cray
|
||||||
if self.compiler.name == "cce" or "^cray-mpich" in self.spec:
|
if self.pkg.compiler.name == "cce" or "^cray-mpich" in self.spec:
|
||||||
env.set("ESMF_OS", "Unicos")
|
env.set("ESMF_OS", "Unicos")
|
||||||
|
|
||||||
# Allow override of ESMF_OS:
|
# Allow override of ESMF_OS:
|
||||||
@ -430,5 +471,10 @@ def check(self):
|
|||||||
def setup_dependent_build_environment(self, env, dependent_spec):
|
def setup_dependent_build_environment(self, env, dependent_spec):
|
||||||
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))
|
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))
|
||||||
|
|
||||||
def setup_run_environment(self, env):
|
def install(self, pkg, spec, prefix):
|
||||||
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))
|
make("install")
|
||||||
|
|
||||||
|
if "+python" in spec:
|
||||||
|
# build the python library
|
||||||
|
python_builder = PythonPipBuilder(pkg)
|
||||||
|
python_builder.install(pkg, spec, prefix)
|
||||||
|
Loading…
Reference in New Issue
Block a user