Skip to content
55 changes: 55 additions & 0 deletions packages/issm/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack.package import *
import os
Comment thread
lawrenceabird marked this conversation as resolved.
Outdated
import zipfile


class Issm(AutotoolsPackage):
Expand Down Expand Up @@ -61,6 +63,12 @@ class Issm(AutotoolsPackage):
description="Propagate OpenMP flags so threaded deps link cleanly",
)

variant(
"py-tools",
default=False,
description="Install ISSM python files under <prefix>/python-tools",
)

# --------------------------------------------------------------------
# Dependencies
# --------------------------------------------------------------------
Expand Down Expand Up @@ -94,10 +102,20 @@ class Issm(AutotoolsPackage):
depends_on("access-triangle", when="+wrappers")
depends_on("[email protected]:", when="+wrappers", type=("build", "run"))
depends_on("py-numpy", when="+wrappers", type=("build", "run"))

# --------------------------------------------------------------------
# Conflicts
# --------------------------------------------------------------------

# GCC 14 breaks on several C++17 constructs used in ISSM
conflicts("%gcc@14:", msg="ISSM cannot be built with GCC versions above 13")

# +wrappers requires +py-tools to access the wrappers
conflicts("+wrappers", when="~py-tools", msg="The +wrappers variant requires +py-tools")
Comment thread
lawrenceabird marked this conversation as resolved.

# +py-tools requires +wrappers for full Python functionality
conflicts("+py-tools", when="~wrappers", msg="The +py-tools variant requires +wrappers for full functionality")

# --------------------------------------------------------------------
# Helper functions
# --------------------------------------------------------------------
Expand Down Expand Up @@ -198,7 +216,44 @@ def configure_args(self):
def install(self, spec, prefix):
make("install", parallel=False)

# Optionally install examples directory
if "+examples" in self.spec:
examples_src = join_path(self.stage.source_path, "examples")
examples_dst = join_path(prefix, "examples")
install_tree(examples_src, examples_dst)

# Optionally install Python (.py) files as a zip archive
if "+py-tools" in spec:
py_src = join_path(self.stage.source_path, "src", "m")
py_dst = join_path(prefix, "python-tools.zip")

# Recursively copy all .py files from src/m to python-tools.zip
# Exclude contrib directory which contains working files
exclude_dirs = {'contrib'}

# Create a zip file and add *.py files, excluding exclude_dirs
with zipfile.ZipFile(py_dst, 'w', zipfile.ZIP_DEFLATED) as zf:
for root, dirs, files in os.walk(py_src):
Comment thread
lawrenceabird marked this conversation as resolved.
Outdated
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for file in files:
if file.endswith('.py'):
src_path = os.path.join(root, file)
Comment thread
lawrenceabird marked this conversation as resolved.
Outdated
zf.write(src_path, arcname=file)

# --------------------------------------------------------------------
# Run environment - set ISSM_DIR and PYTHONPATH
# --------------------------------------------------------------------
def setup_run_environment(self, env):
"""Set ISSM_DIR to the install root."""

# Get the prefix path (install root)
issm_dir = self.prefix

# Set environment variable
env.set('ISSM_DIR', issm_dir)

# Add ISSM python files (and shared libraries) to PYTHONPATH if +py-tools
if "+py-tools" in self.spec:
env.prepend_path("PYTHONPATH", join_path(self.prefix, "python-tools.zip"))
env.prepend_path("PYTHONPATH", join_path(self.prefix, "lib"))