Skip to content

Commit

Permalink
esmf package: add (optional) Python bindings (spack#45504)
Browse files Browse the repository at this point in the history
* 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).
  • Loading branch information
Chrismarsh authored Aug 16, 2024
1 parent 9ec8eaa commit f0f9a16
Showing 1 changed file with 64 additions and 18 deletions.
82 changes: 64 additions & 18 deletions var/spack/repos/builtin/packages/esmf/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from spack.package import *


class Esmf(MakefilePackage):
class Esmf(MakefilePackage, PythonExtension):
"""The Earth System Modeling Framework (ESMF) is high-performance, flexible
software infrastructure for building and coupling weather, climate, and
related Earth science applications. The ESMF defines an architecture for
Expand Down Expand Up @@ -97,6 +97,10 @@ class Esmf(MakefilePackage):
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
depends_on("mpi", when="+mpi")
depends_on("lapack@3:", when="+external-lapack")
Expand All @@ -112,6 +116,20 @@ class Esmf(MakefilePackage):
depends_on("[email protected]: ~mpi", when="@8.5:+external-parallelio~mpi")
depends_on("[email protected]:", 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 [email protected], 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
depends_on("perl", type="test")

Expand Down Expand Up @@ -143,6 +161,29 @@ class Esmf(MakefilePackage):
# https://github.com/spack/spack/issues/35957
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
# the Cray compiler wrappers, where we need to swap
# out the spack compiler wrappers in esmf.mk with the
Expand Down Expand Up @@ -214,38 +255,38 @@ def setup_build_environment(self, env):
# ESMF_COMPILER must be set to select which Fortran and
# 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")
with self.compiler.compiler_environment():
with self.pkg.compiler.compiler_environment():
gfortran_major_version = int(
spack.compiler.get_compiler_version_output(
self.compiler.fc, "-dumpversion"
self.pkg.compiler.fc, "-dumpversion"
).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")
elif self.compiler.name in ["clang", "apple-clang"]:
elif self.pkg.compiler.name in ["clang", "apple-clang"]:
env.set("ESMF_COMPILER", "gfortranclang")
with self.compiler.compiler_environment():
with self.pkg.compiler.compiler_environment():
gfortran_major_version = int(
spack.compiler.get_compiler_version_output(
self.compiler.fc, "-dumpversion"
self.pkg.compiler.fc, "-dumpversion"
).split(".")[0]
)
elif self.compiler.name == "nag":
elif self.pkg.compiler.name == "nag":
env.set("ESMF_COMPILER", "nag")
elif self.compiler.name == "pgi":
elif self.pkg.compiler.name == "pgi":
env.set("ESMF_COMPILER", "pgi")
elif self.compiler.name == "nvhpc":
elif self.pkg.compiler.name == "nvhpc":
env.set("ESMF_COMPILER", "nvhpc")
elif self.compiler.name == "cce":
elif self.pkg.compiler.name == "cce":
env.set("ESMF_COMPILER", "cce")
elif self.compiler.name == "aocc":
elif self.pkg.compiler.name == "aocc":
env.set("ESMF_COMPILER", "aocc")
else:
msg = "The compiler you are building with, "
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:
env.set("ESMF_CXX", spec["mpi"].mpicxx)
Expand All @@ -265,7 +306,7 @@ def setup_build_environment(self, env):
env.set("ESMF_BOPT", "O")

if (
self.compiler.name in ["gcc", "clang", "apple-clang"]
self.pkg.compiler.name in ["gcc", "clang", "apple-clang"]
and gfortran_major_version >= 10
and (self.spec.satisfies("@:8.2.99") or self.spec.satisfies("@8.3.0b09"))
):
Expand All @@ -277,7 +318,7 @@ def setup_build_environment(self, env):

# ESMF_OS must be set for Cray systems
# 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")

# Allow override of ESMF_OS:
Expand Down Expand Up @@ -430,5 +471,10 @@ def check(self):
def setup_dependent_build_environment(self, env, dependent_spec):
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))

def setup_run_environment(self, env):
env.set("ESMFMKFILE", os.path.join(self.prefix.lib, "esmf.mk"))
def install(self, pkg, spec, prefix):
make("install")

if "+python" in spec:
# build the python library
python_builder = PythonPipBuilder(pkg)
python_builder.install(pkg, spec, prefix)

0 comments on commit f0f9a16

Please sign in to comment.