Skip to content
Merged
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
162 changes: 130 additions & 32 deletions repos/spack_repo/builtin/packages/axom/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import shutil
import socket
import tempfile
from os.path import join as pjoin

from spack_repo.builtin.build_systems.cached_cmake import (
Expand Down Expand Up @@ -113,8 +114,11 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage):
variant("tools", default=True, description="Build tools")
variant("tutorials", default=True, description="Build tutorials")

# Hard requirement after Axom 0.6.1
variant("cpp14", default=True, description="Build with C++14 support")
variant(
"cpp14",
default=False,
description="Build with C++14 support. Deprecated -- use the cxxstd variant version.",
)

variant("fortran", default=True, description="Build with Fortran support")

Expand Down Expand Up @@ -150,20 +154,30 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage):
variant("adiak", default=False, when="@0.13:", description="Build with adiak")
variant("caliper", default=False, when="@0.13:", description="Build with caliper")
variant("conduit", default=True, description="Build with conduit")

variant("opencascade", default=False, description="Build with opencascade")

variant("mfem", default=False, description="Build with mfem")
variant("hdf5", default=True, description="Build with hdf5")
variant("lua", default=True, description="Build with Lua")
variant("mfem", default=False, description="Build with mfem")
variant("opencascade", default=False, description="Build with opencascade")
variant("raja", default=True, description="Build with raja")
variant("scr", default=False, description="Build with SCR")
variant("umpire", default=True, description="Build with umpire")

variant("raja", default=True, description="Build with raja")

varmsg = "Build development tools (such as Sphinx, Doxygen, etc...)"
variant("devtools", default=False, description=varmsg)

variant(
"cxxstd",
default="20",
values=(
conditional("11", when="@:0.6.1"),
conditional("14", when="@:0.11.0"),
conditional("17", when="@:0.14.0"),
"20",
),
multi=False,
description="C++ standard to build with",
)

# -----------------------------------------------------------------------
Comment thread
becker33 marked this conversation as resolved.
# Dependencies
# -----------------------------------------------------------------------
Expand Down Expand Up @@ -278,14 +292,20 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage):
depends_on("mfem~mpi", when="~mpi")
depends_on("mfem@4.5.0:", when="@0.7.0:")

depends_on("python", when="+python")

# Python
with when("+python"):
depends_on("python")

# extending python allows spack environment views to import axom from python
extends("python")

depends_on("py-nanobind@2.7.0:")
depends_on("py-pytest")
depends_on("py-packaging")
depends_on("py-pygments")
depends_on("py-numpy")
depends_on("conduit+python")
depends_on("py-mpi4py", when="+mpi")
depends_on("conduit+python", when="+conduit")

# Devtools
with when("+devtools"):
Expand All @@ -302,6 +322,7 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage):
# (ENABLE_CLANGFORMAT will be OFF if not the exact version)
depends_on("llvm+clang@19", type="build")

# -----------------------------------------------------------------------
# Component requirements
# -----------------------------------------------------------------------
# Hard inter-component dependencies taken from Axom's dependency graph.
Expand Down Expand Up @@ -329,8 +350,6 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage):
# -----------------------------------------------------------------------
# Conflicts
# -----------------------------------------------------------------------
# Hard requirement after Axom 0.6.1
conflicts("~cpp14", when="@0.6.2:")

# Conduit's cmake config files moved and < 0.4.0 can't find it
conflicts("^conduit@0.7.2:", when="@:0.4.0")
Expand Down Expand Up @@ -388,6 +407,10 @@ def cache_name(self):
special_case,
)

@property
def cxx_std(self):
return self.spec.variants.get("cxxstd").value

def initconfig_compiler_entries(self):
spec = self.spec
entries = super().initconfig_compiler_entries()
Expand All @@ -409,8 +432,10 @@ def initconfig_compiler_entries(self):
else:
entries.append(cmake_cache_option("ENABLE_FORTRAN", False))

if spec.satisfies("+cpp14") and spec.satisfies("@:0.6.1"):
if (spec.satisfies("+cpp14") or self.cxx_std == "14") and spec.satisfies("@:0.6.1"):
entries.append(cmake_cache_string("BLT_CXX_STD", "c++14", ""))
else:
entries.append(cmake_cache_string("BLT_CXX_STD", f"c++{self.cxx_std}"))

# Add optimization flag workaround for builds with cray compiler
if spec.satisfies("%cce"):
Expand Down Expand Up @@ -449,7 +474,7 @@ def initconfig_hardware_entries(self):

if spec.satisfies("^blt@:0.5.1"):
# This is handled internally by BLT now
if spec.satisfies("+cpp14"):
if spec.satisfies("+cpp14") or self.cxx_std == "14":
cudaflags += " -std=c++14"
else:
cudaflags += " -std=c++11"
Expand Down Expand Up @@ -499,25 +524,26 @@ def initconfig_hardware_entries(self):
hip_link_flags += "-lflang -lflangrti "

# Additional library path for cray compiler
if self.spec.satisfies("%cce"):
lib_path = "/opt/cray/pe/cce/{0}/cce/x86_64/lib".format(self.spec.compiler.version)
if spec.satisfies("%cce"):
lib_path = "/opt/cray/pe/cce/{0}/cce/x86_64/lib".format(spec.compiler.version)
hip_link_flags += "-L{0} -Wl,-rpath,{0}".format(lib_path)

if spec.satisfies("+fortran"):
link_remove_list = []
link_lib_remove_list = []

# Remove extra link library for crayftn
if self.is_fortran_compiler("crayftn"):
link_remove_list += ["unwind"]
link_lib_remove_list += ["unwind"]

# Remove injected OpenMP stub library
if spec.satisfies("+openmp"):
link_remove_list += ["ompstub"]
link_lib_remove_list += ["ompstub"]

if link_remove_list:
if link_lib_remove_list:
entries.append(
cmake_cache_string(
"BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE", ";".join(link_remove_list)
"BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE",
";".join(link_lib_remove_list),
)
)

Expand Down Expand Up @@ -579,7 +605,8 @@ def initconfig_hardware_entries(self):
cmake_cache_string("BLT_OPENMP_LINK_FLAGS", openmp_gen_exp, description)
)

if spec.satisfies("+openmp") and spec.satisfies("+rocm") and self.spec.satisfies("%cce"):
# For cce up to version 20.0.0
if spec.satisfies("+openmp") and spec.satisfies("+rocm") and spec.satisfies("%cce@:20"):
openmp_gen_exp = (
"$<$<NOT:$<COMPILE_LANGUAGE:Fortran>>:"
"-fopenmp=libomp>;$<$<COMPILE_LANGUAGE:"
Expand Down Expand Up @@ -697,9 +724,9 @@ def initconfig_package_entries(self):
for dep in variant_deps:
if spec.satisfies(f"^{dep}"):
dep_dir = get_spec_path(spec, dep, path_replacements)
entries.append(cmake_cache_path("%s_DIR" % dep.upper(), dep_dir))
entries.append(cmake_cache_path(f"{dep.upper()}_DIR", dep_dir))
else:
entries.append("# %s not built\n" % dep.upper())
entries.append(f"# {dep.upper()} not built\n")

if (spec.satisfies("+raja") or spec.satisfies("+umpire")) and spec.satisfies("^camp"):
dep_dir = get_spec_path(spec, "camp", path_replacements)
Expand Down Expand Up @@ -756,6 +783,15 @@ def initconfig_package_entries(self):
python_bin_dir = get_spec_path(spec, "python", path_replacements, use_bin=True)
entries.append(cmake_cache_path("Python_EXECUTABLE", pjoin(python_bin_dir, "python3")))

if spec.satisfies("+python"):
# Install Axom's Python package(s) so a spack environment view merges them into
# a single site-packages and `import axom.sidre` works without updating PYTHONPATH
entries.append(
cmake_cache_path(
"AXOM_PYTHON_MODULE_INSTALL_PREFIX", spec["python"].package.platlib
)
)

if spec.satisfies("^py-jsonschema"):
jsonschema_dir = get_spec_path(spec, "py-jsonschema", path_replacements, use_bin=True)
jsonschema_path = os.path.join(jsonschema_dir, "jsonschema")
Expand Down Expand Up @@ -786,13 +822,23 @@ def initconfig_package_entries(self):
)

if spec.satisfies("+python"):
python_platlib = spec["python"].package.platlib

# pytest requires pluggy and iniconfig
for dep in ("py-nanobind", "py-pytest", "py-numpy", "py-pluggy", "py-iniconfig"):
# newer pytest releases also import packaging/pygments from separate Spack prefixes.
for dep in (
"py-nanobind",
"py-pytest",
"py-numpy",
"py-pluggy",
"py-iniconfig",
"py-packaging",
"py-pygments",
"py-mpi4py",
):
if spec.satisfies("^{0}".format(dep)):
dep_dir = get_spec_path(spec, dep, path_replacements, use_lib=True)
py_libdir = join_path(
dep_dir, f"python{spec['python'].version.up_to(2)}", "site-packages"
)
dep_dir = get_spec_path(spec, dep, path_replacements)
py_libdir = join_path(dep_dir, python_platlib)
entries.append(
cmake_cache_path("%s_DIR" % dep.upper().replace("-", "_"), py_libdir)
)
Expand Down Expand Up @@ -837,7 +883,8 @@ def build_test(self):
def test_install_using_cmake(self):
"""build example with cmake and run"""
example_src_dir = join_path(self.prefix.examples.axom, "using-with-cmake")
example_stage_dir = "./cmake"
example_test_dir = tempfile.mkdtemp(prefix="axom-cmake-example-")
example_stage_dir = join_path(example_test_dir, "using-with-cmake")
shutil.copytree(example_src_dir, example_stage_dir)
with working_dir(join_path(example_stage_dir, "build"), create=True):
cmake_args = ["-C ../host-config.cmake", example_src_dir]
Expand All @@ -853,10 +900,61 @@ def test_install_using_cmake(self):
def test_install_using_make(self):
"""build example with make and run"""
example_src_dir = join_path(self.prefix.examples.axom, "using-with-make")
example_stage_dir = "./make"
example_test_dir = tempfile.mkdtemp(prefix="axom-make-example-")
example_stage_dir = join_path(example_test_dir, "using-with-make")
shutil.copytree(example_src_dir, example_stage_dir)
with working_dir(example_stage_dir, create=True):
make(f"AXOM_DIR={self.prefix}")
example = Executable("./example")
example()
make("clean")

@run_after("install", when="+examples+python+tools components=sidre")
@on_package_attributes(run_tests=True)
def test_install_using_python(self):
"""run python example against installed axom"""
example = join_path(self.prefix.examples.axom, "using-with-python", "example.py")
python_runner = join_path(self.prefix.bin, "run_python_with_axom.sh")
if not os.path.isfile(example):
raise RuntimeError("Missing installed python example: {0}".format(example))
if not os.path.isfile(python_runner):
raise RuntimeError("Missing installed python runner: {0}".format(python_runner))
run_python = Executable(python_runner)
run_python(example)

@run_after("install", when="+python components=sidre")
@on_package_attributes(run_tests=True)
def test_axom_sidre_installed_into_site_packages(self):
"""Check axom.sidre installed into a site-packages-shaped prefix
and imports from view-shaped site-packages paths.
"""
python_pkg = self.spec["python"].package
python_platlib = python_pkg.platlib
site_packages = join_path(self.prefix, python_platlib)
sidre_pkg_dir = join_path(site_packages, "axom", "sidre")
if not os.path.isdir(sidre_pkg_dir):
raise RuntimeError(
"axom.sidre was not installed under the interpreter platlib: {0}".format(
sidre_pkg_dir
)
)

# Assemble the Python package directories a view would merge into site-packages.
import_path = [site_packages]
if self.spec.satisfies("+conduit"):
for conduit_py in (
join_path(self.spec["conduit"].prefix, python_platlib),
join_path(self.spec["conduit"].prefix, "python-modules"),
):
if os.path.isdir(conduit_py):
import_path.append(conduit_py)

for dep in ("py-numpy", "py-mpi4py"):
if self.spec.satisfies("^{0}".format(dep)):
dep_py = join_path(self.spec[dep].prefix, python_platlib)
if os.path.isdir(dep_py):
import_path.append(dep_py)

imports = "import axom.sidre as s; import numpy; print('axom.sidre', s.__version__)"
python = self["python"].command
python("-c", imports, extra_env={"PYTHONPATH": ":".join(import_path)})
Loading