Chapel package: major update (#42197)

* add cray detection taken from upcxx
* add CUDA/ROCm support
* add numerous pass-through options to Chapel build,
  like gpu_mem_strategy, comm_substrate, etc.; all variants are
  translated to analogous CHPL_* environment variables. As a side
  effect, this defines a number of environment variables that are
  not actually used by Chapel.
* Define LD_LIBRARY_PATH, LIBRARY_PATH, and PKG_CONFIG_PATH to
  help programs built with Chapel properly locate needed runtime
  dependencies

---------

Co-authored-by: bonachea <dobonachea@lbl.gov>
This commit is contained in:
arezaii 2024-06-17 18:09:05 -06:00 committed by Harmen Stoppels
parent f339225d22
commit 03c22f403f
2 changed files with 827 additions and 12 deletions

View file

@ -0,0 +1,22 @@
diff --git a/util/chplenv/chpl_llvm.py b/util/chplenv/chpl_llvm.py
index f0fd495f28..95dc9c3f67 100755
--- a/util/chplenv/chpl_llvm.py
+++ b/util/chplenv/chpl_llvm.py
@@ -866,13 +866,14 @@ def get_clang_prgenv_args():
os.environ['PE_CHAPEL_PKGCONFIG_LIBS'] = gather_pe_chpl_pkgconfig_libs()
# Use cc --cray-print-opts=... to get arguments from compiler driver
-
+ # find the actual cc in case something like spack has wrapped it
+ real_cc = os.path.join(os.environ["CRAYPE_DIR"], "bin", "cc")
# Get compilation arguments
- opts = run_command(['cc', '--cray-print-opts=cflags'])
+ opts = run_command([real_cc, '--cray-print-opts=cflags'])
comp_args.extend(opts.split())
# Get link arguments
- opts = run_command(['cc', '--cray-print-opts=libs'])
+ opts = run_command([real_cc, '--cray-print-opts=libs'])
link_args.extend(opts.split())
return (comp_args, link_args)

View file

@ -3,24 +3,817 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import subprocess
from spack.package import *
from spack.util.environment import is_system_path, set_env
class Chapel(AutotoolsPackage):
@llnl.util.lang.memoized
def is_CrayEX():
# Credit to upcxx package for this hpe-cray-ex detection function
if spack.platforms.host().name == "linux":
target = os.environ.get("CRAYPE_NETWORK_TARGET")
if target in ["ofi", "ucx"]: # normal case
return True
elif target is None: # but some systems lack Cray PrgEnv
fi_info = which("fi_info")
if (
fi_info
and fi_info("-l", output=str, error=str, fail_on_error=False).find("cxi") >= 0
):
return True
return False
class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage):
"""Chapel is a modern programming language that is parallel, productive,
portable, scalable and open-source."""
portable, scalable and open-source. The Chapel package comes with many
options in the form of variants, most of which can be left unset to allow
Chapel's built-in scripts to determine the proper values based on the environment."""
homepage = "https://chapel-lang.org/"
url = "https://github.com/chapel-lang/chapel/releases/download/1.24.1/chapel-1.24.1.tar.gz"
url = "https://github.com/chapel-lang/chapel/archive/refs/tags/2.0.0.tar.gz"
git = "https://github.com/chapel-lang/chapel.git"
test_requires_compiler = True
# TODO: Re-enable these once we add determine_version and determine_variants
# executables = ["^chpl$", "^chpldoc$"]
# A list of GitHub accounts to notify when the package is updated.
# TODO: add chapel-project github account
maintainers("arezaii", "bonachea")
# See https://spdx.org/licenses/ for a list.
license("Apache-2.0")
version("1.24.1", sha256="f898f266fccaa34d937b38730a361d42efb20753ba43a95e5682816e008ce5e4")
version("1.24.0", sha256="77c6087f3e0837268470915f2ad260d49cf7ac4adf16f5b44862ae624c1be801")
version("1.23.0", sha256="7ae2c8f17a7b98ac68378e94a842cf16d4ab0bcfeabc0fee5ab4aaa07b205661")
version("1.22.1", sha256="8235eb0869c9b04256f2e5ce3ac4f9eff558401582fba0eba05f254449a24989")
version("1.22.0", sha256="57ba6ee5dfc36efcd66854ecb4307e1c054700ea201eff73012bd8b4572c2ce6")
version("1.21.0", sha256="886f7ba0e0e86c86dba99417e3165f90b1d3eca59c8cd5a7f645ce28cb5d82a0")
version("1.20.0", sha256="08bc86df13e4ad56d0447f52628b0f8e36b0476db4e19a90eeb2bd5f260baece")
version("1.19.0", sha256="c2b68a20d87cc382c2f73dd1ecc6a4f42fb2f590b0b10fbc577382dd35c9e9bd")
version("1.18.0", sha256="68471e1f398b074edcc28cae0be26a481078adc3edea4df663f01c6bd3b6ae0d")
version("main", branch="main")
version("2.0.1", sha256="47e1f3789478ea870bd4ecdf52acbe469d171b89b663309325431f3da7c75008")
version("2.0.0", sha256="a8cab99fd034c7b7229be8d4626ec95cf02072646fb148c74b4f48c460c6059c")
patch("fix_spack_cc_wrapper_in_cray_prgenv.patch", when="@2.0.0:")
launcher_names = (
"amudprun",
"aprun",
"gasnetrun_ibv",
"gasnetrun_mpi",
"mpirun4ofi",
"lsf-gasnetrun_ibv",
"pals",
"pbs-aprun",
"pbs-gasnetrun_ibv",
"slurm-gasnetrun_ibv",
"slurm-gasnetrun_mpi",
"slurm-gasnetrun_ofi",
"slurm-srun",
"smp",
"none",
"unset",
)
# TODO: revise this list of mappings, probably need more logic for cce, see upc++
compiler_map = {
"aocc": "clang",
"apple-clang": "clang",
"arm": "clang",
"clang": "clang",
"cce": "cray-prgenv-cray",
"dpcpp": "intel",
"gcc": "gnu",
"intel": "intel",
"llvm": "llvm",
"oneapi": "intel",
"pgi": "pgi",
"rocmcc": "clang",
"unset": "unset",
}
cpu_options = (
"native",
"none",
"unknown",
"unset",
"aarch64",
"barcelona",
"bdver1",
"bdver2",
"bdver3",
"bdver4",
"broadwell",
"core2",
"haswell",
"ivybridge",
"k8",
"k8sse3",
"nehalem",
"sandybridge",
"skylake",
"thunderx",
"thunderx2t99",
"westmere",
)
# TODO: add other package dependencies
package_module_dict = {
"curl": "curl",
"hdf5": "hdf5+hl~mpi",
"libevent": "libevent",
"protobuf": "py-protobuf",
"ssl": "openssl",
"yaml": "libyaml@0.1",
"zmq": "libzmq",
}
platform_opts = (
"cray-cs",
"cray-xc",
"cygwin32",
"cygwin64",
"darwin",
"hpe-apollo",
"hpe-cray-ex",
"linux32",
"linux64",
"netbsd32",
"netbsd64",
"pwr6",
"unset",
)
variant(
"atomics",
values=("unset", "cstdlib", "intrinsics", "locks"),
default="unset",
description="Select atomics implementation",
multi=False,
)
# TODO: refactor this somehow, this is a separate documentation tool, not a variant of chapel
variant("chpldoc", default=False, description="Build chpldoc in addition to chpl")
variant("developer", default=False, description="Enable Chapel developer mode")
variant(
"comm",
default="none",
description="Build Chapel with multi-locale support",
values=("gasnet", "none", "ofi", "ugni"),
)
variant(
"comm_substrate",
default="unset",
description="Build Chapel with GASNet multi-locale support using the "
"supplied CHPL_COMM_SUBSTRATE",
values=("ibv", "ofi", "udp", "smp", "unset"),
multi=False,
sticky=True, # never allow the concretizer to choose this
)
# Chapel depends on GASNet whenever comm=gasnet.
# The default (and recommendation) is to use the embedded copy of GASNet.
# This variant allows overriding with a particular version of GASNet sources,
# although this is not officially supported and some combinations might be rejected.
variant(
"gasnet",
description="Control the GASNet library version used",
default="bundled",
values=("bundled", "spack"),
multi=False,
)
variant(
"gasnet_segment",
default="unset",
description="Build Chapel with multi-locale support using the "
"supplied CHPL_GASNET_SEGMENT",
values=("everything", "fast", "large", "unset"),
multi=False,
)
variant(
"gmp",
description="Build with gmp support",
default="spack",
values=("bundled", "none", "spack"),
multi=False,
)
variant(
"gpu_mem_strategy",
description="The memory allocation strategy for GPU data",
values=("array_on_device", "unified_memory"),
default="array_on_device",
multi=False,
)
variant(
"host_arch",
description="Host architecture of the build machine",
values=("x86_64", "aarch64", "arm64", "unset"),
default="unset",
multi=False,
)
variant(
"host_jemalloc",
values=("bundled", "none", "spack", "unset"),
default="unset",
multi=False,
description="Selects between no jemalloc, bundled jemalloc, or spack supplied jemalloc",
)
variant(
"host_mem",
values=("cstdlib", "jemalloc"),
default="jemalloc",
description="Memory management layer for the chpl compiler",
multi=False,
)
variant(
"host_platform",
description="Host platform",
default="unset",
values=platform_opts,
multi=False,
)
variant(
"hwloc",
description="Build with hwloc support",
default="bundled",
values=(
"bundled",
"none",
# CHPL_HWLOC=system existed back to at least 2017,
# but it was buggy and unsupported until version 2.1
conditional("spack", when="@2.1:"),
),
multi=False,
)
variant(
"launcher",
values=launcher_names,
default="unset",
description="Launcher to use for running Chapel programs",
multi=False,
)
variant(
"lib_pic",
values=("none", "pic"),
default="none",
description="Build position-independent code suitable for shared libraries",
)
variant(
"libfabric",
default="unset",
description="When building with ofi support, specify libfabric option",
values=("bundled", "spack", "unset"),
multi=False,
)
variant(
"llvm",
default="spack",
description="LLVM backend type. The 'spack' value can use an external "
"source of LLVM or let spack build a version if no LLVM installs were "
"previously detected by 'spack external find'",
values=("bundled", "none", "spack"),
)
variant(
"re2",
description="Build with re2 support",
default="bundled",
values=("bundled", "none"),
multi=False,
)
variant(
"target_arch",
description="Target architecture for cross compilation",
default="unset",
values=("x86_64", "aarch64", "arm64", "unset"),
multi=False,
)
variant(
"target_cpu",
values=cpu_options,
description="Indicate that the target executable should be specialized "
"to the given architecture when using --specialize (and --fast).",
default="unset",
multi=False,
)
variant(
"target_platform",
description="Target platform for cross compilation",
default="unset",
values=platform_opts,
multi=False,
)
variant(
"tasks",
description="Select tasking layer for intra-locale parallelism",
default="qthreads",
values=("fifo", "qthreads"),
multi=False,
)
variant(
"timers",
description="Select timers implementation",
default="unset",
values=("generic", "unset"),
multi=False,
)
variant(
"unwind",
description="Build with unwind library for stack tracing",
default="none",
values=("bundled", "none", "spack"),
multi=False,
)
# Add dependencies for package modules
for variant_name, dep in package_module_dict.items():
variant(
variant_name,
description="Build with support for the Chapel {0} package module".format(
variant_name
),
default=True,
)
depends_on(dep, when="+{0}".format(variant_name))
# TODO: for CHPL_X_CC and CHPL_X_CXX, can we capture an arbitrary path, possibly
# with arguments?
chpl_env_vars = [
"CHPL_ATOMICS",
"CHPL_AUX_FILESYS",
"CHPL_COMM",
"CHPL_COMM_SUBSTRATE",
"CHPL_DEVELOPER",
"CHPL_GASNET_SEGMENT",
"CHPL_GMP",
"CHPL_GPU",
"CHPL_GPU_ARCH",
"CHPL_GPU_MEM_STRATEGY",
"CHPL_HOST_ARCH",
# "CHPL_HOST_CC",
"CHPL_HOST_COMPILER",
# "CHPL_HOST_CXX",
"CHPL_HOST_JEMALLOC",
"CHPL_HOST_MEM",
"CHPL_HOST_PLATFORM",
"CHPL_HWLOC",
"CHPL_LAUNCHER",
"CHPL_LIB_PIC",
"CHPL_LIBFABRIC",
"CHPL_LLVM",
"CHPL_LLVM_CONFIG",
"CHPL_LLVM_SUPPORT",
"CHPL_LLVM_VERSION",
"CHPL_LOCALE_MODEL",
"CHPL_MEM",
"CHPL_RE2",
"CHPL_SANITIZE",
"CHPL_SANITIZE_EXE",
"CHPL_TARGET_ARCH",
# "CHPL_TARGET_CC",
"CHPL_TARGET_COMPILER",
"CHPL_TARGET_CPU",
# "CHPL_TARGET_CXX",
"CHPL_TARGET_PLATFORM",
"CHPL_TASKS",
"CHPL_TIMERS",
"CHPL_UNWIND",
]
conflicts("platform=windows") # Support for windows is through WSL only
conflicts("+rocm", when="+cuda", msg="Chapel must be built with either CUDA or ROCm, not both")
conflicts("+rocm", when="@:2.0.0", msg="ROCm support in spack requires Chapel 2.0.0 or later")
conflicts(
"comm_substrate=unset",
when="comm=gasnet",
msg="comm=gasnet requires you to also set comm_substrate= to the appropriate network",
)
conflicts(
"^python@3.12:",
when="@:2.1.0",
msg="Chapel versions prior to 2.1.0 may produce SyntaxWarnings with Python >= 3.12",
)
conflicts(
"host_jemalloc=spack",
when="platform=linux",
msg="Only bundled jemalloc may be used on Linux systems, see "
"https://chapel-lang.org/docs/usingchapel/chplenv.html#chpl-host-jemalloc",
)
conflicts(
"host_jemalloc=bundled",
when="platform=darwin",
msg="Only system jemalloc may be used on Darwin (MacOS) systems, see "
"https://chapel-lang.org/docs/usingchapel/chplenv.html#chpl-host-jemalloc",
)
with when("llvm=none"):
conflicts("+cuda", msg="Cuda support requires building with LLVM")
conflicts("+rocm", msg="ROCm support requires building with LLVM")
# Add dependencies
depends_on("doxygen@1.8.17:", when="+chpldoc")
# TODO: keep up to date with util/chplenv/chpl_llvm.py
with when("llvm=spack"):
depends_on("llvm@11:17", when="@:2.0.1")
depends_on("llvm@11:18", when="@2.1.0:")
# Based on docs https://chapel-lang.org/docs/technotes/gpu.html#requirements
depends_on("llvm@16:", when="llvm=spack ^cuda@12:")
requires(
"^llvm targets=all",
msg="llvm=spack +cuda requires LLVM support the nvptx target",
when="llvm=spack +cuda",
)
depends_on("cuda@11:", when="+cuda", type=("build", "link", "run", "test"))
# This is because certain systems have binutils installed as a system package
# but do not include the headers. Spack incorrectly supplies those external
# packages as proper dependencies for LLVM, but then LLVM will fail to build
# with an error about missing plugin-api.h
depends_on("binutils+gold+ld+plugins+headers", when="llvm=bundled")
depends_on("m4")
depends_on("gmp", when="gmp=spack", type=("build", "link", "run", "test"))
depends_on("hwloc", when="hwloc=spack", type=("build", "link", "run", "test"))
depends_on("libfabric", when="libfabric=spack", type=("build", "link", "run", "test"))
depends_on("libunwind", when="unwind=spack", type=("build", "link", "run", "test"))
depends_on("jemalloc", when="host_jemalloc=spack", type=("build", "link", "run", "test"))
depends_on("gasnet conduits=none", when="gasnet=spack")
depends_on("gasnet@2024.5.0: conduits=none", when="@2.1.0: gasnet=spack")
depends_on("python@3.7:")
depends_on("cmake@3.16:")
# ensure we can map the spack compiler name to one of the ones we recognize
requires(
"%aocc",
"%apple-clang",
"%arm",
"%clang",
"%cce",
"%cray-prgenv-cray",
"%cray-prgenv-gnu",
"%cray-prgenv-intel",
"%cray-prgenv-pgi",
"%dpcpp",
"%gcc",
"%intel",
"%llvm",
"%oneapi",
"%pgi",
"%rocmcc",
policy="one_of",
)
def unset_chpl_env_vars(self, env):
# Clean the environment from any pre-set CHPL_ variables that affect the build
for var in self.chpl_env_vars:
env.unset(var)
def build(self, spec, prefix):
make()
if spec.variants["chpldoc"].value:
make("chpldoc")
def setup_chpl_platform(self, env):
if self.spec.variants["host_platform"].value == "unset":
if is_CrayEX():
env.set("CHPL_HOST_PLATFORM", "hpe-cray-ex")
def setup_chpl_compilers(self, env):
env.set("CHPL_HOST_COMPILER", self.compiler_map[self.spec.compiler.name])
env.set("CHPL_TARGET_COMPILER", self.compiler_map[self.spec.compiler.name])
# Undo spack compiler wrappers:
# the C/C++ compilers must work post-install
if self.spec.satisfies("+cuda") or self.spec.satisfies("+rocm"):
env.set("CHPL_TARGET_COMPILER", "llvm")
real_cc = join_path(self.spec["llvm"].prefix, "bin", "clang")
real_cxx = join_path(self.spec["llvm"].prefix, "bin", "clang++")
elif is_CrayEX() and os.environ.get("CRAYPE_DIR"):
real_cc = join_path(os.environ["CRAYPE_DIR"], "bin", "cc")
real_cxx = join_path(os.environ["CRAYPE_DIR"], "bin", "CC")
else:
real_cc = self.compiler.cc
real_cxx = self.compiler.cxx
env.set("CHPL_TARGET_CC", real_cc)
env.set("CHPL_TARGET_CXX", real_cxx)
def setup_chpl_comm(self, env, spec):
env.set("CHPL_COMM", spec.variants["comm"].value)
@run_before("configure", when="gasnet=spack")
def setup_gasnet(self):
dst = join_path(self.stage.source_path, "third-party", "gasnet", "gasnet-src")
remove_directory_contents(dst)
os.rmdir(dst)
symlink(self.spec["gasnet"].prefix.src, dst)
def setup_chpl_llvm(self, env):
if self.spec.variants["llvm"].value == "spack":
env.set(
"CHPL_LLVM_CONFIG", "{0}/{1}".format(self.spec["llvm"].prefix, "bin/llvm-config")
)
def setup_if_not_unset(self, env, var, value):
if value != "unset":
if value == "spack":
value = "system"
env.set(var, value)
def prepend_cpath_include(self, env, prefix):
if not is_system_path(prefix):
env.prepend_path("CPATH", prefix.include)
def setup_env_vars(self, env):
# variants that appear unused by Spack typically correspond directly to
# a CHPL_<variant> variable which will be used by the Chapel build system
for v in self.spec.variants.keys():
self.setup_if_not_unset(env, "CHPL_" + v.upper(), self.spec.variants[v].value)
self.setup_chpl_llvm(env)
self.setup_chpl_compilers(env)
self.setup_chpl_platform(env)
# TODO: a function to set defaults for things where we removed variants
# We'll set to GPU later if +rocm or +cuda requested
env.set("CHPL_LOCALE_MODEL", "flat")
if self.spec.satisfies("+developer"):
env.set("CHPL_DEVELOPER", "true")
if self.spec.variants["gmp"].value == "spack":
# TODO: why must we add to CPATH to find gmp.h
# TODO: why must we add to LIBRARY_PATH to find lgmp
self.prepend_cpath_include(env, self.spec["gmp"].prefix)
env.prepend_path("LIBRARY_PATH", self.spec["gmp"].prefix.lib)
# Need this for the test env, where it does not appear automatic:
env.prepend_path("PKG_CONFIG_PATH", self.spec["gmp"].prefix.lib.pkgconfig)
if self.spec.variants["hwloc"].value == "spack":
env.prepend_path("LD_LIBRARY_PATH", self.spec["hwloc"].prefix.lib)
# Need this for the test env, where it does not appear automatic:
env.prepend_path("PKG_CONFIG_PATH", self.spec["hwloc"].prefix.lib.pkgconfig)
env.prepend_path("PKG_CONFIG_PATH", self.spec["libpciaccess"].prefix.lib.pkgconfig)
if self.spec.variants["unwind"].value == "spack":
# chapel package would not build without cpath, missing libunwind.h
self.prepend_cpath_include(env, self.spec["libunwind"].prefix)
env.prepend_path("LD_LIBRARY_PATH", self.spec["libunwind"].prefix.lib)
if self.spec.satisfies("+yaml"):
env.prepend_path("PKG_CONFIG_PATH", self.spec["libyaml"].prefix.lib.pkgconfig)
self.prepend_cpath_include(env, self.spec["libyaml"].prefix)
# could not compile test/library/packages/Yaml/writeAndParse.chpl without this
env.prepend_path("LIBRARY_PATH", self.spec["libyaml"].prefix.lib)
if self.spec.satisfies("+zmq"):
self.prepend_cpath_include(env, self.spec["libzmq"].prefix)
# could not compile test/library/packages/ZMQ/hello.chpl without this
env.prepend_path("LIBRARY_PATH", self.spec["libzmq"].prefix.lib)
env.prepend_path("LD_LIBRARY_PATH", self.spec["libzmq"].prefix.lib)
# could not compile test/library/packages/ZMQ/hello.chpl without this
env.prepend_path("LIBRARY_PATH", self.spec["libzmq"].prefix.lib)
env.prepend_path("PKG_CONFIG_PATH", self.spec["libzmq"].prefix.lib.pkgconfig)
env.prepend_path("PKG_CONFIG_PATH", self.spec["libsodium"].prefix.lib.pkgconfig)
if self.spec.satisfies("+curl"):
self.prepend_cpath_include(env, self.spec["curl"].prefix)
# could not compile test/library/packages/Curl/check-http.chpl without this
env.prepend_path("LIBRARY_PATH", self.spec["curl"].prefix.lib)
env.prepend_path("LD_LIBRARY_PATH", self.spec["curl"].prefix.lib)
env.prepend_path("PKG_CONFIG_PATH", self.spec["curl"].prefix.lib.pkgconfig)
if self.spec.satisfies("+cuda"):
# TODO: why must we add to LD_LIBRARY_PATH to find libcudart?
env.prepend_path("LD_LIBRARY_PATH", self.spec["cuda"].prefix.lib64)
env.set("CHPL_LOCALE_MODEL", "gpu")
env.set("CHPL_GPU", "nvidia")
if self.spec.satisfies("+rocm"):
env.set("CHPL_LOCALE_MODEL", "gpu")
env.set("CHPL_GPU", "amd")
env.set("CHPL_HOST_COMPILER", "llvm")
env.set("CHPL_GPU_ARCH", self.spec.variants["amdgpu_target"].value[0])
env.set(
"CHPL_LLVM_CONFIG",
"{0}/{1}".format(self.spec["llvm-amdgpu"].prefix, "bin/llvm-config"),
)
self.prepend_cpath_include(env, self.spec["hip"].prefix)
env.set("CHPL_ROCM_PATH", self.spec["llvm-amdgpu"].prefix)
env.prepend_path("LIBRARY_PATH", self.spec["hip"].prefix.lib)
env.prepend_path("LIBRARY_PATH", self.spec["hsa-rocr-dev"].prefix.lib)
env.prepend_path("LD_LIBRARY_PATH", self.spec["hip"].prefix.lib)
env.prepend_path("LD_LIBRARY_PATH", self.spec["hsa-rocr-dev"].prefix.lib)
self.setup_chpl_comm(env, self.spec)
def setup_build_environment(self, env):
self.unset_chpl_env_vars(env)
self.setup_env_vars(env)
def setup_run_environment(self, env):
self.setup_env_vars(env)
env.prepend_path(
"PATH", join_path(self.prefix.share, "chapel", self._output_version_short, "util")
)
@property
@llnl.util.lang.memoized
def _output_version_long(self):
if str(self.spec.version).lower() == "main":
return "2.1.0"
spec_vers_str = str(self.spec.version.up_to(3))
return spec_vers_str
@property
@llnl.util.lang.memoized
def _output_version_short(self):
if str(self.spec.version).lower() == "main":
return "2.1"
spec_vers_str = str(self.spec.version.up_to(2))
return spec_vers_str
def test_version(self):
"""Perform version checks on selected installed package binaries."""
expected = f"version {self._output_version_long}"
exes = ["chpl"]
if self.spec.satisfies("+chpldoc"):
exes.append("chpldoc")
for exe in exes:
reason = f"ensure version of {exe} is {self._output_version_long}"
with test_part(self, f"test_version_{exe}", purpose=reason):
path = join_path(self.prefix.bin, exe)
if not os.path.isfile(path):
raise SkipTest(f"{path} is not installed")
prog = which(path)
if prog is None:
raise RuntimeError(f"Could not find {path}")
output = prog("--version", output=str.split, error=str.split)
assert expected in output
def check(self):
# TODO: we skip the self-check because it's ran by default but:
# - make check doesn't work at build time b/c the PATH isn't yet updated
# - make test is a long running operation
pass
def check_chpl_install_gasnet(self):
"""Setup env to run self-test after installing the package with gasnet"""
with set_env(
GASNET_SPAWNFN="L",
GASNET_QUIET="yes",
GASNET_ROUTE_OUTPUT="0",
QT_AFFINITY="no",
CHPL_QTHREAD_ENABLE_OVERSUBSCRIPTION="1",
CHPL_RT_MASTERIP="127.0.0.1",
CHPL_RT_WORKERIP="127.0.0.0",
CHPL_LAUNCHER="",
):
return subprocess.run(["util/test/checkChplInstall"])
def check_chpl_install(self):
if self.spec.variants["comm"].value != "none":
return self.check_chpl_install_gasnet()
else:
return subprocess.run(["util/test/checkChplInstall"])
def test_hello(self):
"""Run the hello world test"""
with working_dir(self.test_suite.current_test_cache_dir):
with set_env(CHPL_CHECK_HOME=self.test_suite.current_test_cache_dir):
with test_part(self, "test_hello", purpose="test hello world"):
if self.spec.satisfies("+cuda") or self.spec.satisfies("+rocm"):
with set_env(COMP_FLAGS="--no-checks --no-compiler-driver"):
res = self.check_chpl_install()
assert res and res.returncode == 0
else:
res = self.check_chpl_install()
assert res and res.returncode == 0
# TODO: This is a pain because the checkChplDoc script doesn't have the same
# support for CHPL_CHECK_HOME and chpldoc is finicky about CHPL_HOME
def test_chpldoc(self):
"""Run the chpldoc test"""
if not self.spec.satisfies("+chpldoc"):
print("Skipping chpldoc test as chpldoc variant is not set")
return
with working_dir(self.test_suite.current_test_cache_dir):
with set_env(CHPL_HOME=self.test_suite.current_test_cache_dir):
with test_part(self, "test_chpldoc", purpose="test chpldoc"):
res = subprocess.run(["util/test/checkChplDoc"])
assert res.returncode == 0
# TODO: In order to run these tests, there's a lot of infrastructure to copy
# from the Chapel test suite and there are conflicts with CHPL_HOME needing
# to match the compiler's directory and the test suite's directory
# def test_package_modules(self):
# """Test that the package modules are available"""
# # if not self.spec.satisfies("+module_tests"):
# # print("Skipping module tests as module_tests variant is not set")
# # return
# tests_to_run = []
# with working_dir(self.test_suite.current_test_cache_dir):
# with set_env(CHPL_HOME=join_path(self.spec.prefix.share,
# "chapel", self._output_version_short)):
# with test_part(self, "test_package_modules", purpose="test package modules"):
# if self.spec.satisfies("+yaml"):
# tests_to_run.append("test/library/packages/Yaml/writeAndParse.chpl")
# if self.spec.satisfies("+zmq"):
# tests_to_run.append("test/library/packages/ZMQ/weather.chpl")
# if self.spec.satisfies("+ssl"):
# tests_to_run.append("test/library/packages/Crypto/")
# # TODO: These tests fail with llvm, unable to find C variable CURLPAUSE_CONT
# if (
# self.spec.satisfies("+curl")
# and self.spec.variants["llvm"].value == "none"
# ):
# with set_env(CHPL_NIGHTLY_TEST_CONFIG_NAME="networking-packages"):
# print("Running package module test for package 'curl'")
# res = subprocess.run(
# ["util/start_test", "test/library/packages/Curl/"]
# )
# assert res.returncode == 0
# print("Running package module test for package 'url'")
# res = subprocess.run(["util/start_test",
# "test/library/packages/URL/"])
# assert res.returncode == 0
# if self.spec.satisfies("+hdf5"):
# tests_to_run.append("test/library/packages/HDF5/")
# if self.spec.satisfies("+protobuf"):
# tests_to_run.append("test/library/packages/ProtobufProtocolSupport/")
# if len(tests_to_run) > 0:
# with set_env(CHPL_HOME=self.test_suite.current_test_cache_dir):
# compiler = join_path(self.spec.prefix.bin,'chpl')
# print("Running package module tests for packages...")
# print(f" command to run: util/start_test --compiler {compiler}")
# tests_to_run.insert(0, "util/start_test")
# tests_to_run.insert(1, "--compiler")
# tests_to_run.insert(2, compiler)
# res = subprocess.run([t for t in tests_to_run])
# assert res.returncode == 0
@run_after("install")
def copy_test_files(self):
"""Copy test files to the install directory"""
test_files = [
"test/release/examples",
"util/start_test",
"util/test",
"util/chplenv",
"util/config",
# "test/library/packages/Curl",
# "test/library/packages/URL/",
# "test/library/packages/ProtobufProtocolSupport/",
# "test/library/packages/Crypto/",
# "test/library/packages/Yaml/",
# "test/library/packages/ZMQ/",
# "test/library/packages/HDF5/",
"chplconfig",
"make",
"third-party/chpl-venv/",
]
cache_extra_test_sources(self, test_files)
# @run_after("install")
# @on_package_attributes(run_tests=True)
# def self_check(self):
# """Run the self-check after installing the package"""
# path_put_first("PATH", [self.prefix.bin])
# self.test_version()
# self.test_hello()
# if self.spec.satisfies("+chpldoc"):
# make("check-chpldoc")
# self.test_package_modules()