Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
04602c8
Add py-proteus
cekees Jul 31, 2026
227b098
Merge branch 'develop' into py-proteus
cekees Aug 10, 2026
c5a7d41
py-proteus: add scorec variant wiring PUMI in instead of skipping it
cekees Aug 10, 2026
f35726e
Merge branch 'develop' into py-proteus
cekees Aug 10, 2026
8b26624
py-proteus: drop split-pumi-chrono-skip.patch, now upstream on torino…
cekees Aug 11, 2026
5917fbd
Merge remote-tracking branch 'origin/develop' into py-proteus
cekees Aug 11, 2026
d257f3d
py-proteus: trim comments to essentials
cekees Aug 11, 2026
44ba7f2
triangle: fix macOS build (-DLINUX hardcoded) and install a header+li…
cekees Aug 11, 2026
929d7d4
zoltan: fix gfortran linking and self-declared dylib ID on macOS
cekees Aug 11, 2026
9163e5c
py-proteus: link metis (needed by SuperLU's ordering), revert local-t…
cekees Aug 11, 2026
62701cb
py-proteus: build petsc with +hypre+superlu-dist to match other insta…
cekees Aug 11, 2026
bee21a2
pumi: patch the _vert_id int/long SCOREC bug; triangle: fix showme's …
cekees Aug 13, 2026
32a9637
py_proteus: track main instead of stale torino_narwhal; pumi: add 4.1.0
cekees Aug 14, 2026
41c1e99
petsc: add +superlu variant (sequential SuperLU, distinct from +super…
cekees Aug 14, 2026
d00426c
py-proteus: add +superlu/+tetgen, pin pumi@4.1.0 explicitly, fix MPI …
cekees Aug 14, 2026
1034532
triangle: fix K&R-style implicit-declaration build failure on modern GCC
cekees Aug 14, 2026
fdc3154
Merge branch 'develop' into py-proteus
cekees Aug 18, 2026
9fd3d46
Cleaned up wordy comments and proteus-pumi dep
cekees Aug 18, 2026
616604d
Merge branch 'develop' into py-proteus
cekees Aug 18, 2026
0d57bf6
Update repos/spack_repo/builtin/packages/petsc/package.py
balay Aug 18, 2026
089388d
Update repos/spack_repo/builtin/packages/petsc/package.py
balay Aug 18, 2026
4818467
Apply suggestions from code review
balay Aug 18, 2026
42a0672
[@spackbot] updating style on behalf of cekees
cekees Aug 18, 2026
75c3720
pumi: add missing 4.2.1 version tag (same commit as 4.2.0, includes a…
cekees Aug 18, 2026
e1368f7
chrono: new package
cekees Aug 27, 2026
18cb545
Merge remote-tracking branch 'upstream/develop' into py-proteus
cekees Aug 28, 2026
1521f6d
Merge branch 'chrono-new-package' into py-proteus
cekees Aug 28, 2026
e3e8626
py-proteus: build against chrono instead of disabling it
cekees Aug 28, 2026
0cf11cb
chrono: satisfy ruff-format
cekees Aug 28, 2026
757663a
py-proteus: depend on gmsh~fltk~med
cekees Aug 28, 2026
8c18197
openblas: build only the library targets, not the test suite
cekees Aug 28, 2026
b9c72ea
openblas: build the library targets sequentially, not as one make
cekees Aug 28, 2026
fbde1c1
Apply suggestion from @balay
cekees Aug 29, 2026
525d1f7
clean up pumi, chrono, and triangle dependencies
cekees Aug 29, 2026
36cec8a
Merge branch 'develop' into py-proteus
cekees Aug 29, 2026
c0b936a
[@spackbot] updating style on behalf of cekees
cekees Aug 29, 2026
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
149 changes: 149 additions & 0 deletions repos/spack_repo/builtin/packages/chrono/package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os

from spack_repo.builtin.build_systems.cmake import CMakePackage

from spack.package import *


class Chrono(CMakePackage):
"""Project Chrono is an open-source multi-physics simulation engine for
rigid and flexible multibody dynamics, collision detection, granular
material, fluid-solid interaction and vehicle dynamics.

The ``+python`` variant additionally builds ``pychrono``, the SWIG-generated
Python module, which Chrono builds from the same tree rather than shipping
as a separate project.
"""

homepage = "https://projectchrono.org/"
url = "https://github.com/projectchrono/chrono/archive/refs/tags/10.0.0.tar.gz"
git = "https://github.com/projectchrono/chrono.git"

maintainers("cekees")

license("BSD-3-Clause")

version("main", branch="main")
version("10.0.0", sha256="806e5e24a06f26bbd42344dd1f13d75e3214c9eb29901553574b9c87217d8722")

variant("python", default=False, description="Build the pychrono Python module")
variant("openmp", default=True, description="Enable OpenMP parallelism")
variant("shared", default=True, description="Build shared libraries")
variant("simd", default=False, description="Enable SIMD vectorization")

# Chrono compiles C as well as C++ (e.g. chrono_thirdparty/libstl/stlfile.c),
# so both must be declared -- omitting "c" fails at cmake time with
# "[spack cc]: Error: SPACK_CC_* variables not set".
depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("cmake@3.18:", type="build")

# Chrono's core headers include Eigen directly, so it is a link-time
# dependency of every consumer, not just a build-time one.
depends_on("eigen@3.3.0:")

# The Python module is generated with SWIG at build time
# (src/chrono_swig/chrono_python/CMakeLists.txt does find_package(SWIG)).
with when("+python"):
# NOT extends("python"): Chrono installs pychrono into
# share/chrono/python, never into site-packages -- verified on an actual
# install, whose prefix contains only include/ lib/ share/
# importer_blender/. extends() would promise spack a layout that does not
# exist. PYTHONPATH is set for this package and its dependents below,
# which is the same thing PETSc's own proteus build does
# (PYTHONPATH="$PREFIX/share/chrono/python").
depends_on("python@3.8:", type=("build", "run"))
depends_on("swig@4:", type="build")

depends_on("llvm-openmp", when="+openmp platform=darwin")

# ------------------------------------------------------------------
# ChClassFactory.h uses std::enable_if, std::is_polymorphic and
# std::is_abstract but includes only <cstdio> <string> <functional>
# <typeindex> <unordered_map> <memory>, relying on one of those to pull in
# <type_traits> transitively. libstdc++ and Apple's libc++ still do;
# newer libc++ (e.g. conda-forge's) does not, and Chrono_core then fails
# with 14 errors of the form
#
# ChClassFactory.h:48:53: error: no member named 'is_polymorphic' in
# namespace 'std'
#
# Belongs upstream in projectchrono/chrono; done here as a filter_file
# rather than a patch so it stays a no-op once upstream adds the include.
# ------------------------------------------------------------------
@run_before("cmake")
def add_missing_type_traits_include(self):
header = join_path(self.stage.source_path, "src", "chrono", "core", "ChClassFactory.h")
if not os.path.exists(header):
return
with open(header) as f:
if "#include <type_traits>" in f.read():
return
filter_file(r"^#include <cstdio>$", "#include <cstdio>\n#include <type_traits>", header)

def cmake_args(self):
args = [
self.define_from_variant("BUILD_SHARED_LIBS", "shared"),
self.define("BUILD_TESTING", False),
self.define("BUILD_DEMOS", False),
# Optional modules, each pulling dependencies Chrono does not need
# for multibody dynamics. Option names carry the CH_ prefix as of
# 10.0.0 (confirmed against the tag's own CMakeLists.txt).
self.define("CH_ENABLE_MODULE_CASCADE", False),
self.define("CH_ENABLE_MODULE_IRRLICHT", False),
self.define("CH_ENABLE_MODULE_MATLAB", False),
self.define("CH_ENABLE_MODULE_POSTPROCESS", False),
self.define("CH_ENABLE_MODULE_ROS", False),
self.define("CH_ENABLE_MODULE_VEHICLE", False),
self.define_from_variant("CH_ENABLE_MODULE_PYTHON", "python"),
self.define_from_variant("CH_ENABLE_OPENMP", "openmp"),
self.define_from_variant("CH_USE_SIMD", "simd"),
# Chrono appends CH_DEBUG_POSTFIX ("_d") to every library name in a
# Debug build, but consumers link the unsuffixed name. Force it
# empty so a Debug build keeps -g without renaming the libraries.
self.define("CH_DEBUG_POSTFIX", ""),
]

if self.spec.satisfies("+python"):
# Chrono's find_package(Python3 ... COMPONENTS Development) has been
# observed to populate only Python3_EXECUTABLE, after which the SWIG
# module links without libpython and fails on every CPython symbol.
# Point CMake at the library and headers directly.
python = self.spec["python"]
args += [
self.define("Python3_EXECUTABLE", python.command.path),
self.define("Python3_INCLUDE_DIR", python.headers.directories[0]),
self.define("Python3_LIBRARY", python.libs[0]),
]
if self.spec.satisfies("platform=darwin"):
# chrono_python's _core module target neither links -lpython nor
# passes -undefined dynamic_lookup. Unresolved symbols in a
# shared object are fine on Linux and resolve at dlopen time,
# but are a hard link error for a macOS bundle.
args.append(self.define("CMAKE_MODULE_LINKER_FLAGS", "-undefined dynamic_lookup"))

return args

# pychrono lives in share/chrono/python, so nothing finds it by default.
# Setting CH_INSTALL_PYTHON does not move it (tried against 10.0.0: the
# module still installed to share/chrono/python), so expose it explicitly --
# for this package's own run environment and for anything depending on it.
@property
def _pychrono_dir(self):
return join_path(self.prefix, "share", "chrono", "python")

def setup_run_environment(self, env):
if self.spec.satisfies("+python"):
env.prepend_path("PYTHONPATH", self._pychrono_dir)

def setup_dependent_build_environment(self, env, dependent_spec):
if self.spec.satisfies("+python"):
env.prepend_path("PYTHONPATH", self._pychrono_dir)

def setup_dependent_run_environment(self, env, dependent_spec):
if self.spec.satisfies("+python"):
env.prepend_path("PYTHONPATH", self._pychrono_dir)
21 changes: 20 additions & 1 deletion repos/spack_repo/builtin/packages/openblas/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,26 @@ def build(self, pkg: MakefilePackage, spec: Spec, prefix: Prefix) -> None:
with working_dir(self.build_directory):
# Due to the verbosity of the command line and number of object
# files created, we suppress makefile command echoing via `-s`.
make("-s", *self.make_defs)
# Build the library targets only, ONE AT A TIME. A bare "make" is
# OpenBLAS's default "all" -- "libs netlib $(RELA) tests shared" -- so
# the test suite is built AND RUN by an ordinary install. That defeats
# the check_build/check_install hooks below, which are guarded by
# @on_package_attributes(run_tests=True) and are the intended opt-in,
# and it turns any test failure into a hard build failure: on macOS
# x86_64 (TARGET=SKYLAKEX NO_AVX512=1 DYNAMIC_ARCH=1) "TEST 1/125
# min:smin_negative" dies with "Bus error: 10" though the library
# itself builds cleanly.
#
# The invocations must stay SEPARATE. Passing "libs netlib shared" as
# three goals to one make lets them run concurrently, which races:
# "ar: libopenblas-r0.3.34.a: error reading zlatm5.o: file truncated"
# on linux-alderlake/gcc. That is the race this method's docstring is
# about, and the reason it overrides 'make all' in the first place.
#
# TEMPORARY: carried on this branch pending an upstream fix; drop it
# once spack/spack-packages takes the change.
for target in ("libs", "netlib", "shared"):
make("-s", target, *self.make_defs)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this comment to remind that it's under discussion in #6278 @haampie


def edit(self, pkg, spec, prefix):
# https://github.com/spack/spack-packages/pull/5883#issuecomment-5189054355
Expand Down
7 changes: 7 additions & 0 deletions repos/spack_repo/builtin/packages/petsc/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class Petsc(Package, CudaPackage, ROCmPackage):
when="+fortran",
description="Activates support for superlu-dist (only parallel)",
)
variant("superlu", default=False, description="Activates support for superlu (sequential)")
variant("strumpack", default=False, description="Activates support for Strumpack")
variant(
"scalapack", default=False, when="+fortran", description="Activates support for Scalapack"
Expand Down Expand Up @@ -366,6 +367,11 @@ class Petsc(Package, CudaPackage, ROCmPackage):
depends_on("mkl", when="+mkl-pardiso")
depends_on("fftw+mpi", when="+fftw+mpi")
depends_on("suite-sparse", when="+suite-sparse")
depends_on("superlu", when="+superlu")
conflicts(
"+superlu+int64",
msg="SuperLU has no support for 64-bit integers, use superlu-dist instead",
)
depends_on("libx11", when="+X")
depends_on("mpfr", when="+mpfr")
depends_on("gmp", when="+mpfr")
Expand Down Expand Up @@ -549,6 +555,7 @@ def configure_options(self):
("kokkos", "kokkos", False, False),
("kokkos-kernels", "kokkos-kernels", False, False),
("superlu-dist", "superlu_dist", True, True),
"superlu",
("scotch", "ptscotch", True, True),
(
"suite-sparse:umfpack,klu,cholmod,btf,ccolamd,colamd,camd,amd,"
Expand Down
6 changes: 6 additions & 0 deletions repos/spack_repo/builtin/packages/pumi/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class Pumi(CMakePackage):
# scorec/core develop branch and we prefer not to expose spack users
# to the added instability.
version("master", submodules=True, branch="master")
version(
"4.2.1", submodules=True, commit="a40922de30f09af63a0251a0d53f95c6cadd9199"
) # tag 4.2.1 (same commit as 4.2.0 -- retag only, includes the apfMDS.cc int/long fix)
version(
"4.1.0", submodules=True, commit="a8e3aef58bfe86790782c4ae5e5c1bb5f232ff30"
) # tag 4.1.0
version(
"2.2.9", submodules=True, commit="f87525cae7597322edfb2ccf1c7d4437402d9481"
) # tag 2.2.9
Expand Down
99 changes: 99 additions & 0 deletions repos/spack_repo/builtin/packages/py_proteus/package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import glob
import os

from spack_repo.builtin.build_systems.python import PythonPackage

from spack.package import *


class PyProteus(PythonPackage):
"""Proteus: Computational Methods and Simulation Toolkit. Python tools
for rapidly developing computer models and numerical methods"""

homepage = "http://proteustoolkit.org"
git = "https://github.com/cekees/proteus.git"

maintainers("cekees")

license("MIT")

version("main", branch="main")

variant("pumi", default=True, description="Enable PUMI mesh adaptation support")
variant("chrono", default=True, description="Enable Chrono modeling support")

depends_on("c", type="build")
depends_on("cxx", type="build")
depends_on("fortran", type="build") # remove in future not a direct proteus dep
depends_on("python@3.9:", type=("build", "run"))
depends_on("py-setuptools@61:", type="build")
depends_on("py-cython@3:", type="build")
depends_on("py-pybind11@2.11:2", type="build") # xtensor@0.27.1 *= overload issue
depends_on("py-numpy@1.25:", type=("build", "run"))
depends_on("py-scipy", type=("build", "run"))
depends_on("py-mpi4py", type=("build", "run"))
depends_on("py-petsc4py", type=("build", "run"))
depends_on("py-h5py+mpi", type=("build", "run"))
depends_on("mpi")
depends_on("petsc+mpi+hypre+superlu-dist+superlu")
depends_on("hdf5+mpi+hl")
depends_on("openblas") # should relax to generic blas in future
depends_on("metis") # through several dependencies
depends_on("superlu")
depends_on("triangle") # shells out but has linked in past
depends_on("tetgen") # shells out
depends_on("gmsh~fltk~med") # shells out to the gmsh, no fltk/med needed
depends_on("ncurses") # Fenton waves as text gui, generally not used
# run type matters: chrono exports PYTHONPATH for share/chrono/python
# (pychrono is not installed into site-packages) via
# setup_dependent_run_environment, which spack only applies to run deps.
depends_on("chrono+python", when="+chrono", type=("build", "link", "run"))
depends_on("pumi@4.2.1:+zoltan+shared", when="+pumi") # <4.2.1 requires patch
depends_on("zoltan+parmetis~fortran", when="+pumi")
depends_on("parmetis")
depends_on("eigen@3.4") # xtensor dep
depends_on("xtensor@0.26.0")
depends_on("xtensor-python@0.28.0:")
depends_on("xtl")

def _mpi_dir(self):
# try to find the right mpi.h as it's not always in self.spec["mpi"]
mpi_prefix = self.spec["mpi"].prefix
if os.path.isfile(os.path.join(mpi_prefix, "include", "mpi.h")):
return mpi_prefix
for candidate in glob.glob(os.path.join(mpi_prefix, "lib", "*", "mpich")):
if os.path.isfile(os.path.join(candidate, "include", "mpi.h")):
return candidate
for candidate in glob.glob(os.path.join(mpi_prefix, "lib", "*", "openmpi")):
if os.path.isfile(os.path.join(candidate, "include", "mpi.h")):
return candidate
return mpi_prefix

def setup_build_environment(self, env):
if self.spec.satisfies("~pumi"):
env.set("PROTEUS_SKIP_PUMI", "1")
Comment thread
cekees marked this conversation as resolved.
if self.spec.satisfies("~chrono"):
env.set("PROTEUS_SKIP_CHRONO", "1")
env.set("PETSC_DIR", self.spec["petsc"].prefix)
env.set("MPI_DIR", self._mpi_dir())
env.set("HDF5_DIR", self.spec["hdf5"].prefix)
env.set("BLAS_DIR", self.spec["openblas"].prefix)
env.set("LAPACK_DIR", self.spec["openblas"].prefix)
env.set("SUPERLU_DIR", self.spec["superlu"].prefix)
env.set("NCURSES_DIR", self.spec["ncurses"].prefix)
env.set("METIS_DIR", self.spec["metis"].prefix)

if self.spec.satisfies("+pumi"):
env.set("SCOREC_DIR", self.spec["pumi"].prefix)
env.set("ZOLTAN_DIR", self.spec["zoltan"].prefix)
env.set("PARMETIS_DIR", self.spec["parmetis"].prefix)

if self.spec.satisfies("+chrono"):
env.set("CHRONO_DIR", self.spec["chrono"].prefix)

for dep in ("eigen", "xtensor", "xtensor-python", "xtl"):
env.prepend_path("CPATH", self.spec[dep].prefix.include)
10 changes: 8 additions & 2 deletions repos/spack_repo/builtin/packages/triangle/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ class Triangle(Package):

version("1.6", sha256="1766327add038495fa3499e9b7cc642179229750f7201b94f8e1b7bee76f8480")

depends_on("libx11", type="link")
depends_on("libx11", type=("build", "link"))
depends_on("xproto", type="build")
depends_on("gmake", type="build")

def install(self, spec, prefix):
make()
x11 = spec["libx11"].prefix
xproto = spec["xproto"].prefix
cswitches = "-O -std=gnu17 -I{0} -I{1} -L{2}".format(x11.include, xproto.include, x11.lib)
if not spec.satisfies("platform=darwin"):
cswitches = "-DLINUX " + cswitches
make("CSWITCHES=" + cswitches)
mkdirp(prefix.bin)

install("triangle", prefix.bin)
Expand Down
13 changes: 13 additions & 0 deletions repos/spack_repo/builtin/packages/zoltan/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os
import re

from spack_repo.builtin.build_systems.autotools import AutotoolsPackage
Expand Down Expand Up @@ -119,6 +120,11 @@ def configure_args(self):
# Although adding to config_libs _should_ suffice, it does not
# Add to ldflags as well
config_ldflags.append("-lgfortran")
gfortran_lib = Executable(self.compiler.fc)(
"-print-file-name=libgfortran." + dso_suffix, output=str
).strip()
if gfortran_lib and gfortran_lib != "libgfortran." + dso_suffix:
config_ldflags.append("-L" + os.path.dirname(gfortran_lib))
if spec.satisfies("%intel") or spec.satisfies("%oneapi"):
config_libs.append("-lifcore")

Expand Down Expand Up @@ -211,3 +217,10 @@ def solib_install(self):
for lib_path in find(self.spec.prefix.lib, "lib*.a"):
lib_shared_name = re.sub(r"\.a$", f".{dso_suffix}", lib_path)
move(lib_path, lib_shared_name)
if dso_suffix == "dylib":
install_name_tool = which("install_name_tool", required=True)
install_name_tool(
"-id",
"@rpath/" + os.path.basename(lib_shared_name),
lib_shared_name,
)
Loading