package_hash: add test to ensure consistency across Python versions

Our package hash is supposed to be consistent from python version to python version.
Test this by adding some known unparse inputs and ensuring that they always have the
same canonical hash.  This test relies on the fact that we run Spack's unit tests
across many python versions.  We can't compute for several python versions within the
same test run so we precompute the hashes and check them in CI.
This commit is contained in:
Todd Gamblin 2021-12-23 00:59:34 -08:00 committed by Greg Becker
parent 800229a448
commit b6dde510bd
7 changed files with 2486 additions and 0 deletions

View File

@ -0,0 +1,17 @@
# Test data for unparser
These are test packages for testing Spack's unparser. They are used to ensure that the
canonical unparser used for Spack's package hash remains consistent across Python
versions.
All of these were copied from mainline Spack packages, and they have been renamed with
`.txt` suffixes so that they're not considered proper source files by the various
checkers used in Spack CI.
These packages were chosen for various reasons, but mainly because:
1. They're some of the more complex packages in Spack, and they exercise more unparser
features than other packages.
2. Each of these packages has some interesting feature that was hard to unparse
consistently across Python versions. See docstrings in packages for details.

View File

@ -0,0 +1,266 @@
# -*- python -*-
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This is an unparser test package.
``amdfftw`` was chosen for its complexity and because it uses a negative array
index that was not being unparsed consistently from Python 2 to 3.
"""
import os
from spack import *
from spack.pkg.builtin.fftw import FftwBase
class Amdfftw(FftwBase):
"""FFTW (AMD Optimized version) is a comprehensive collection of
fast C routines for computing the Discrete Fourier Transform (DFT)
and various special cases thereof.
It is an open-source implementation of the Fast Fourier transform
algorithm. It can compute transforms of real and complex-values
arrays of arbitrary size and dimension.
AMD Optimized FFTW is the optimized FFTW implementation targeted
for AMD CPUs.
For single precision build, please use precision value as float.
Example : spack install amdfftw precision=float
"""
_name = 'amdfftw'
homepage = "https://developer.amd.com/amd-aocl/fftw/"
url = "https://github.com/amd/amd-fftw/archive/3.0.tar.gz"
git = "https://github.com/amd/amd-fftw.git"
maintainers = ['amd-toolchain-support']
version('3.1', sha256='3e777f3acef13fa1910db097e818b1d0d03a6a36ef41186247c6ab1ab0afc132')
version('3.0.1', sha256='87030c6bbb9c710f0a64f4f306ba6aa91dc4b182bb804c9022b35aef274d1a4c')
version('3.0', sha256='a69deaf45478a59a69f77c4f7e9872967f1cfe996592dd12beb6318f18ea0bcd')
version('2.2', sha256='de9d777236fb290c335860b458131678f75aa0799c641490c644c843f0e246f8')
variant('shared', default=True,
description='Builds a shared version of the library')
variant('openmp', default=True,
description='Enable OpenMP support')
variant('threads', default=False,
description='Enable SMP threads support')
variant('debug', default=False,
description='Builds a debug version of the library')
variant(
'amd-fast-planner',
default=False,
description='Option to reduce the planning time without much'
'tradeoff in the performance. It is supported for'
'Float and double precisions only.')
variant(
'amd-top-n-planner',
default=False,
description='Build with amd-top-n-planner support')
variant(
'amd-mpi-vader-limit',
default=False,
description='Build with amd-mpi-vader-limit support')
variant(
'static',
default=False,
description='Build with static suppport')
variant(
'amd-trans',
default=False,
description='Build with amd-trans suppport')
variant(
'amd-app-opt',
default=False,
description='Build with amd-app-opt suppport')
depends_on('texinfo')
provides('fftw-api@3', when='@2:')
conflicts(
'precision=quad',
when='@2.2 %aocc',
msg='Quad precision is not supported by AOCC clang version 2.2')
conflicts(
'+debug',
when='@2.2 %aocc',
msg='debug mode is not supported by AOCC clang version 2.2')
conflicts(
'%gcc@:7.2',
when='@2.2:',
msg='GCC version above 7.2 is required for AMDFFTW')
conflicts(
'+amd-fast-planner ',
when='+mpi',
msg='mpi thread is not supported with amd-fast-planner')
conflicts(
'+amd-fast-planner',
when='@2.2',
msg='amd-fast-planner is supported from 3.0 onwards')
conflicts(
'+amd-fast-planner',
when='precision=quad',
msg='Quad precision is not supported with amd-fast-planner')
conflicts(
'+amd-fast-planner',
when='precision=long_double',
msg='long_double precision is not supported with amd-fast-planner')
conflicts(
'+amd-top-n-planner',
when='@:3.0.0',
msg='amd-top-n-planner is supported from 3.0.1 onwards')
conflicts(
'+amd-top-n-planner',
when='precision=long_double',
msg='long_double precision is not supported with amd-top-n-planner')
conflicts(
'+amd-top-n-planner',
when='precision=quad',
msg='Quad precision is not supported with amd-top-n-planner')
conflicts(
'+amd-top-n-planner',
when='+amd-fast-planner',
msg='amd-top-n-planner cannot be used with amd-fast-planner')
conflicts(
'+amd-top-n-planner',
when='+threads',
msg='amd-top-n-planner works only for single thread')
conflicts(
'+amd-top-n-planner',
when='+mpi',
msg='mpi thread is not supported with amd-top-n-planner')
conflicts(
'+amd-top-n-planner',
when='+openmp',
msg='openmp thread is not supported with amd-top-n-planner')
conflicts(
'+amd-mpi-vader-limit',
when='@:3.0.0',
msg='amd-mpi-vader-limit is supported from 3.0.1 onwards')
conflicts(
'+amd-mpi-vader-limit',
when='precision=quad',
msg='Quad precision is not supported with amd-mpi-vader-limit')
conflicts(
'+amd-trans',
when='+threads',
msg='amd-trans works only for single thread')
conflicts(
'+amd-trans',
when='+mpi',
msg='mpi thread is not supported with amd-trans')
conflicts(
'+amd-trans',
when='+openmp',
msg='openmp thread is not supported with amd-trans')
conflicts(
'+amd-trans',
when='precision=long_double',
msg='long_double precision is not supported with amd-trans')
conflicts(
'+amd-trans',
when='precision=quad',
msg='Quad precision is not supported with amd-trans')
conflicts(
'+amd-app-opt',
when='@:3.0.1',
msg='amd-app-opt is supported from 3.1 onwards')
conflicts(
'+amd-app-opt',
when='+mpi',
msg='mpi thread is not supported with amd-app-opt')
conflicts(
'+amd-app-opt',
when='precision=long_double',
msg='long_double precision is not supported with amd-app-opt')
conflicts(
'+amd-app-opt',
when='precision=quad',
msg='Quad precision is not supported with amd-app-opt')
def configure(self, spec, prefix):
"""Configure function"""
# Base options
options = [
'--prefix={0}'.format(prefix),
'--enable-amd-opt'
]
# Check if compiler is AOCC
if '%aocc' in spec:
options.append('CC={0}'.format(os.path.basename(spack_cc)))
options.append('FC={0}'.format(os.path.basename(spack_fc)))
options.append('F77={0}'.format(os.path.basename(spack_fc)))
if '+debug' in spec:
options.append('--enable-debug')
if '+mpi' in spec:
options.append('--enable-mpi')
options.append('--enable-amd-mpifft')
else:
options.append('--disable-mpi')
options.append('--disable-amd-mpifft')
options.extend(self.enable_or_disable('shared'))
options.extend(self.enable_or_disable('openmp'))
options.extend(self.enable_or_disable('threads'))
options.extend(self.enable_or_disable('amd-fast-planner'))
options.extend(self.enable_or_disable('amd-top-n-planner'))
options.extend(self.enable_or_disable('amd-mpi-vader-limit'))
options.extend(self.enable_or_disable('static'))
options.extend(self.enable_or_disable('amd-trans'))
options.extend(self.enable_or_disable('amd-app-opt'))
if not self.compiler.f77 or not self.compiler.fc:
options.append('--disable-fortran')
# Cross compilation is supported in amd-fftw by making use of target
# variable to set AMD_ARCH configure option.
# Spack user can not directly use AMD_ARCH for this purpose but should
# use target variable to set appropriate -march option in AMD_ARCH.
arch = spec.architecture
options.append(
'AMD_ARCH={0}'.format(
arch.target.optimization_flags(
spec.compiler).split('=')[-1]))
# Specific SIMD support.
# float and double precisions are supported
simd_features = ['sse2', 'avx', 'avx2']
simd_options = []
for feature in simd_features:
msg = '--enable-{0}' if feature in spec.target else '--disable-{0}'
simd_options.append(msg.format(feature))
# When enabling configure option "--enable-amd-opt", do not use the
# configure option "--enable-generic-simd128" or
# "--enable-generic-simd256"
# Double is the default precision, for all the others we need
# to enable the corresponding option.
enable_precision = {
'float': ['--enable-float'],
'double': None,
'long_double': ['--enable-long-double'],
'quad': ['--enable-quad-precision']
}
# Different precisions must be configured and compiled one at a time
configure = Executable('../configure')
for precision in self.selected_precisions:
opts = (enable_precision[precision] or []) + options[:]
# SIMD optimizations are available only for float and double
if precision in ('float', 'double'):
opts += simd_options
with working_dir(precision, create=True):
configure(*opts)

View File

@ -0,0 +1,72 @@
# -*- python -*-
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This is an unparser test package.
``grads`` was chosen because it has an embedded comment that looks like a docstring,
which should be removed when doing canonical unparsing.
"""
from spack import *
class Grads(AutotoolsPackage):
"""The Grid Analysis and Display System (GrADS) is an interactive
desktop tool that is used for easy access, manipulation, and visualization
of earth science data. GrADS has two data models for handling gridded and
station data. GrADS supports many data file formats, including
binary (stream or sequential), GRIB (version 1 and 2), NetCDF,
HDF (version 4 and 5), and BUFR (for station data)."""
homepage = "http://cola.gmu.edu/grads/grads.php"
url = "ftp://cola.gmu.edu/grads/2.2/grads-2.2.1-src.tar.gz"
version('2.2.1', sha256='695e2066d7d131720d598bac0beb61ac3ae5578240a5437401dc0ffbbe516206')
variant('geotiff', default=True, description="Enable GeoTIFF support")
variant('shapefile', default=True, description="Enable Shapefile support")
"""
# FIXME: Fails with undeclared functions (tdefi, tdef, ...) in gauser.c
variant('hdf5', default=False, description="Enable HDF5 support")
variant('hdf4', default=False, description="Enable HDF4 support")
variant('netcdf', default=False, description="Enable NetCDF support")
depends_on('hdf5', when='+hdf5')
depends_on('hdf', when='+hdf4')
depends_on('netcdf-c', when='+netcdf')
"""
depends_on('libgeotiff', when='+geotiff')
depends_on('shapelib', when='+shapefile')
depends_on('udunits')
depends_on('libgd')
depends_on('libxmu')
depends_on('cairo +X +pdf +fc +ft')
depends_on('readline')
depends_on('pkgconfig', type='build')
def setup_build_environment(self, env):
env.set('SUPPLIBS', '/')
def setup_run_environment(self, env):
env.set('GADDIR', self.prefix.data)
@run_after('install')
def copy_data(self):
with working_dir(self.build_directory):
install_tree('data', self.prefix.data)
with working_dir(self.package_dir):
install('udpt', self.prefix.data)
filter_file(
r'({lib})',
self.prefix.lib,
self.prefix.data.udpt
)
def configure_args(self):
args = []
args.extend(self.with_or_without('geotiff'))
return args

View File

@ -0,0 +1,715 @@
# -*- python -*-
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This is an unparser test package.
``llvm`` was chosen because it is one of the most complex packages in Spack and it
exercises nearly all directives.
"""
import os
import os.path
import re
import sys
import llnl.util.tty as tty
import spack.build_environment
import spack.util.executable
class Llvm(CMakePackage, CudaPackage):
"""The LLVM Project is a collection of modular and reusable compiler and
toolchain technologies. Despite its name, LLVM has little to do
with traditional virtual machines, though it does provide helpful
libraries that can be used to build them. The name "LLVM" itself
is not an acronym; it is the full name of the project.
"""
homepage = "https://llvm.org/"
url = "https://github.com/llvm/llvm-project/archive/llvmorg-7.1.0.tar.gz"
list_url = "https://releases.llvm.org/download.html"
git = "https://github.com/llvm/llvm-project"
maintainers = ['trws', 'haampie']
tags = ['e4s']
generator = 'Ninja'
family = "compiler" # Used by lmod
# fmt: off
version('main', branch='main')
version('13.0.0', sha256='a1131358f1f9f819df73fa6bff505f2c49d176e9eef0a3aedd1fdbce3b4630e8')
version('12.0.1', sha256='66b64aa301244975a4aea489f402f205cde2f53dd722dad9e7b77a0459b4c8df')
version('12.0.0', sha256='8e6c99e482bb16a450165176c2d881804976a2d770e0445af4375e78a1fbf19c')
version('11.1.0', sha256='53a0719f3f4b0388013cfffd7b10c7d5682eece1929a9553c722348d1f866e79')
version('11.0.1', sha256='9c7ad8e8ec77c5bde8eb4afa105a318fd1ded7dff3747d14f012758719d7171b')
version('11.0.0', sha256='8ad4ddbafac4f2c8f2ea523c2c4196f940e8e16f9e635210537582a48622a5d5')
version('10.0.1', sha256='c7ccb735c37b4ec470f66a6c35fbae4f029c0f88038f6977180b1a8ddc255637')
version('10.0.0', sha256='b81c96d2f8f40dc61b14a167513d87c0d813aae0251e06e11ae8a4384ca15451')
version('9.0.1', sha256='be7b034641a5fda51ffca7f5d840b1a768737779f75f7c4fd18fe2d37820289a')
version('9.0.0', sha256='7807fac25330e24e9955ca46cd855dd34bbc9cc4fdba8322366206654d1036f2')
version('8.0.1', sha256='5b18f6111c7aee7c0933c355877d4abcfe6cb40c1a64178f28821849c725c841')
version('8.0.0', sha256='d81238b4a69e93e29f74ce56f8107cbfcf0c7d7b40510b7879e98cc031e25167')
version('7.1.0', sha256='71c93979f20e01f1a1cc839a247945f556fa5e63abf2084e8468b238080fd839')
version('7.0.1', sha256='f17a6cd401e8fd8f811fbfbb36dcb4f455f898c9d03af4044807ad005df9f3c0')
version('6.0.1', sha256='aefadceb231f4c195fe6d6cd3b1a010b269c8a22410f339b5a089c2e902aa177')
version('6.0.0', sha256='1946ec629c88d30122afa072d3c6a89cc5d5e4e2bb28dc63b2f9ebcc7917ee64')
version('5.0.2', sha256='fe87aa11558c08856739bfd9bd971263a28657663cb0c3a0af01b94f03b0b795')
version('5.0.1', sha256='84ca454abf262579814a2a2b846569f6e0cb3e16dc33ca3642b4f1dff6fbafd3')
version('5.0.0', sha256='1f1843315657a4371d8ca37f01265fa9aae17dbcf46d2d0a95c1fdb3c6a4bab6')
version('4.0.1', sha256='cd664fb3eec3208c08fb61189c00c9118c290b3be5adb3215a97b24255618be5')
version('4.0.0', sha256='28ca4b2fc434cb1f558e8865386c233c2a6134437249b8b3765ae745ffa56a34')
version('3.9.1', sha256='f5b6922a5c65f9232f83d89831191f2c3ccf4f41fdd8c63e6645bbf578c4ab92')
version('3.9.0', sha256='9c6563a72c8b5b79941c773937d997dd2b1b5b3f640136d02719ec19f35e0333')
version('3.8.1', sha256='69360f0648fde0dc3d3c4b339624613f3bc2a89c4858933bc3871a250ad02826')
version('3.8.0', sha256='b5cc5974cc2fd4e9e49e1bbd0700f872501a8678bd9694fa2b36c65c026df1d1')
version('3.7.1', sha256='d2cb0eb9b8eb21e07605bfe5e7a5c6c5f5f8c2efdac01ec1da6ffacaabe4195a')
version('3.7.0', sha256='dc00bc230be2006fb87b84f6fe4800ca28bc98e6692811a98195da53c9cb28c6')
version('3.6.2', sha256='f75d703a388ba01d607f9cf96180863a5e4a106827ade17b221d43e6db20778a')
version('3.5.1', sha256='5d739684170d5b2b304e4fb521532d5c8281492f71e1a8568187bfa38eb5909d')
# fmt: on
# NOTE: The debug version of LLVM is an order of magnitude larger than
# the release version, and may take up 20-30 GB of space. If you want
# to save space, build with `build_type=Release`.
variant(
"clang",
default=True,
description="Build the LLVM C/C++/Objective-C compiler frontend",
)
variant(
"flang",
default=False,
description="Build the LLVM Fortran compiler frontend "
"(experimental - parser only, needs GCC)",
)
variant(
"omp_debug",
default=False,
description="Include debugging code in OpenMP runtime libraries",
)
variant("lldb", default=True, description="Build the LLVM debugger")
variant("lld", default=True, description="Build the LLVM linker")
variant("mlir", default=False, description="Build with MLIR support")
variant(
"internal_unwind",
default=True,
description="Build the libcxxabi libunwind",
)
variant(
"polly",
default=True,
description="Build the LLVM polyhedral optimization plugin, "
"only builds for 3.7.0+",
)
variant(
"libcxx",
default=True,
description="Build the LLVM C++ standard library",
)
variant(
"compiler-rt",
default=True,
description="Build LLVM compiler runtime, including sanitizers",
)
variant(
"gold",
default=(sys.platform != "darwin"),
description="Add support for LTO with the gold linker plugin",
)
variant(
"split_dwarf",
default=False,
description="Build with split dwarf information",
)
variant(
"shared_libs",
default=False,
description="Build all components as shared libraries, faster, "
"less memory to build, less stable",
)
variant(
"llvm_dylib",
default=False,
description="Build LLVM shared library, containing all "
"components in a single shared library",
)
variant(
"link_llvm_dylib",
default=False,
description="Link LLVM tools against the LLVM shared library",
)
variant(
"all_targets",
default=False,
description="Build all supported targets, default targets "
"<current arch>,NVPTX,AMDGPU,CppBackend",
)
variant(
"build_type",
default="Release",
description="CMake build type",
values=("Debug", "Release", "RelWithDebInfo", "MinSizeRel"),
)
variant(
"omp_tsan",
default=False,
description="Build with OpenMP capable thread sanitizer",
)
variant(
"omp_as_runtime",
default=True,
description="Build OpenMP runtime via ENABLE_RUNTIME by just-built Clang",
)
variant('code_signing', default=False,
description="Enable code-signing on macOS")
variant("python", default=False, description="Install python bindings")
variant('version_suffix', default='none', description="Add a symbol suffix")
variant('z3', default=False, description='Use Z3 for the clang static analyzer')
extends("python", when="+python")
# Build dependency
depends_on("cmake@3.4.3:", type="build")
depends_on('cmake@3.13.4:', type='build', when='@12:')
depends_on("ninja", type="build")
depends_on("python@2.7:2.8", when="@:4 ~python", type="build")
depends_on("python", when="@5: ~python", type="build")
depends_on("pkgconfig", type="build")
# Universal dependency
depends_on("python@2.7:2.8", when="@:4+python")
depends_on("python", when="@5:+python")
depends_on('z3', when='@8:+clang+z3')
# openmp dependencies
depends_on("perl-data-dumper", type=("build"))
depends_on("hwloc")
depends_on("libelf", when="+cuda") # libomptarget
depends_on("libffi", when="+cuda") # libomptarget
# ncurses dependency
depends_on("ncurses+termlib")
# lldb dependencies
depends_on("swig", when="+lldb")
depends_on("libedit", when="+lldb")
depends_on("py-six", when="@5.0.0: +lldb +python")
# gold support, required for some features
depends_on("binutils+gold+ld+plugins", when="+gold")
# polly plugin
depends_on("gmp", when="@:3.6 +polly")
depends_on("isl", when="@:3.6 +polly")
conflicts("+llvm_dylib", when="+shared_libs")
conflicts("+link_llvm_dylib", when="~llvm_dylib")
conflicts("+lldb", when="~clang")
conflicts("+libcxx", when="~clang")
conflicts("+internal_unwind", when="~clang")
conflicts("+compiler-rt", when="~clang")
conflicts("+flang", when="~clang")
# Introduced in version 11 as a part of LLVM and not a separate package.
conflicts("+flang", when="@:10")
conflicts('~mlir', when='+flang', msg='Flang requires MLIR')
# Older LLVM do not build with newer compilers, and vice versa
conflicts("%gcc@8:", when="@:5")
conflicts("%gcc@:5.0", when="@8:")
# clang/lib: a lambda parameter cannot shadow an explicitly captured entity
conflicts("%clang@8:", when="@:4")
# When these versions are concretized, but not explicitly with +libcxx, these
# conflicts will enable clingo to set ~libcxx, making the build successful:
# libc++ of LLVM13, see https://libcxx.llvm.org/#platform-and-compiler-support
# @13 does not support %gcc@:10 https://bugs.llvm.org/show_bug.cgi?id=51359#c1
# GCC 11 - latest stable release per GCC release page
# Clang: 11, 12 - latest two stable releases per LLVM release page
# AppleClang 12 - latest stable release per Xcode release page
conflicts("%gcc@:10", when="@13:+libcxx")
conflicts("%clang@:10", when="@13:+libcxx")
conflicts("%apple-clang@:11", when="@13:+libcxx")
# libcxx-4 and compiler-rt-4 fail to build with "newer" clang and gcc versions:
conflicts('%gcc@7:', when='@:4+libcxx')
conflicts('%clang@6:', when='@:4+libcxx')
conflicts('%apple-clang@6:', when='@:4+libcxx')
conflicts('%gcc@7:', when='@:4+compiler-rt')
conflicts('%clang@6:', when='@:4+compiler-rt')
conflicts('%apple-clang@6:', when='@:4+compiler-rt')
# OMP TSAN exists in > 5.x
conflicts("+omp_tsan", when="@:5")
# OpenMP via ENABLE_RUNTIME restrictions
conflicts("+omp_as_runtime", when="~clang", msg="omp_as_runtime requires clang being built.")
conflicts("+omp_as_runtime", when="@:11.1", msg="omp_as_runtime works since LLVM 12.")
# cuda_arch value must be specified
conflicts("cuda_arch=none", when="+cuda", msg="A value for cuda_arch must be specified.")
# MLIR exists in > 10.x
conflicts("+mlir", when="@:9")
# code signing is only necessary on macOS",
conflicts('+code_signing', when='platform=linux')
conflicts('+code_signing', when='platform=cray')
conflicts(
'+code_signing',
when='~lldb platform=darwin',
msg="code signing is only necessary for building the "
"in-tree debug server on macOS. Turning this variant "
"off enables a build of llvm with lldb that uses the "
"system debug server",
)
# LLVM bug https://bugs.llvm.org/show_bug.cgi?id=48234
# CMake bug: https://gitlab.kitware.com/cmake/cmake/-/issues/21469
# Fixed in upstream versions of both
conflicts('^cmake@3.19.0', when='@6.0.0:11.0.0')
# Github issue #4986
patch("llvm_gcc7.patch", when="@4.0.0:4.0.1+lldb %gcc@7.0:")
# sys/ustat.h has been removed in favour of statfs from glibc-2.28. Use fixed sizes:
patch('llvm5-sanitizer-ustat.patch', when="@4:6+compiler-rt")
# Fix lld templates: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=230463
patch('llvm4-lld-ELF-Symbols.patch', when="@4+lld%clang@6:")
patch('llvm5-lld-ELF-Symbols.patch', when="@5+lld%clang@7:")
# Fix missing std:size_t in 'llvm@4:5' when built with '%clang@7:'
patch('xray_buffer_queue-cstddef.patch', when="@4:5+compiler-rt%clang@7:")
# https://github.com/llvm/llvm-project/commit/947f9692440836dcb8d88b74b69dd379d85974ce
patch('sanitizer-ipc_perm_mode.patch', when="@5:7+compiler-rt%clang@11:")
patch('sanitizer-ipc_perm_mode.patch', when="@5:9+compiler-rt%gcc@9:")
# github.com/spack/spack/issues/24270 and MicrosoftDemangle: %gcc@10: and %clang@13:
patch('missing-includes.patch', when='@8:11')
# Backport from llvm master + additional fix
# see https://bugs.llvm.org/show_bug.cgi?id=39696
# for a bug report about this problem in llvm master.
patch("constexpr_longdouble.patch", when="@6:8+libcxx")
patch("constexpr_longdouble_9.0.patch", when="@9:10.0.0+libcxx")
# Backport from llvm master; see
# https://bugs.llvm.org/show_bug.cgi?id=38233
# for a bug report about this problem in llvm master.
patch("llvm_py37.patch", when="@4:6 ^python@3.7:")
# https://bugs.llvm.org/show_bug.cgi?id=39696
patch("thread-p9.patch", when="@develop+libcxx")
# https://github.com/spack/spack/issues/19625,
# merged in llvm-11.0.0_rc2, but not found in 11.0.1
patch("lldb_external_ncurses-10.patch", when="@10.0.0:11.0.1+lldb")
# https://github.com/spack/spack/issues/19908
# merged in llvm main prior to 12.0.0
patch("llvm_python_path.patch", when="@11.0.0")
# Workaround for issue https://github.com/spack/spack/issues/18197
patch('llvm7_intel.patch', when='@7 %intel@18.0.2,19.0.4')
# Remove cyclades support to build against newer kernel headers
# https://reviews.llvm.org/D102059
patch('no_cyclades.patch', when='@10:12.0.0')
patch('no_cyclades9.patch', when='@6:9')
# The functions and attributes below implement external package
# detection for LLVM. See:
#
# https://spack.readthedocs.io/en/latest/packaging_guide.html#making-a-package-discoverable-with-spack-external-find
executables = ['clang', 'flang', 'ld.lld', 'lldb']
@classmethod
def filter_detected_exes(cls, prefix, exes_in_prefix):
result = []
for exe in exes_in_prefix:
# Executables like lldb-vscode-X are daemon listening
# on some port and would hang Spack during detection.
# clang-cl and clang-cpp are dev tools that we don't
# need to test
if any(x in exe for x in ('vscode', 'cpp', '-cl', '-gpu')):
continue
result.append(exe)
return result
@classmethod
def determine_version(cls, exe):
version_regex = re.compile(
# Normal clang compiler versions are left as-is
r'clang version ([^ )\n]+)-svn[~.\w\d-]*|'
# Don't include hyphenated patch numbers in the version
# (see https://github.com/spack/spack/pull/14365 for details)
r'clang version ([^ )\n]+?)-[~.\w\d-]*|'
r'clang version ([^ )\n]+)|'
# LLDB
r'lldb version ([^ )\n]+)|'
# LLD
r'LLD ([^ )\n]+) \(compatible with GNU linkers\)'
)
try:
compiler = Executable(exe)
output = compiler('--version', output=str, error=str)
if 'Apple' in output:
return None
match = version_regex.search(output)
if match:
return match.group(match.lastindex)
except spack.util.executable.ProcessError:
pass
except Exception as e:
tty.debug(e)
return None
@classmethod
def determine_variants(cls, exes, version_str):
variants, compilers = ['+clang'], {}
lld_found, lldb_found = False, False
for exe in exes:
if 'clang++' in exe:
compilers['cxx'] = exe
elif 'clang' in exe:
compilers['c'] = exe
elif 'flang' in exe:
variants.append('+flang')
compilers['fc'] = exe
compilers['f77'] = exe
elif 'ld.lld' in exe:
lld_found = True
compilers['ld'] = exe
elif 'lldb' in exe:
lldb_found = True
compilers['lldb'] = exe
variants.append('+lld' if lld_found else '~lld')
variants.append('+lldb' if lldb_found else '~lldb')
return ''.join(variants), {'compilers': compilers}
@classmethod
def validate_detected_spec(cls, spec, extra_attributes):
# For LLVM 'compilers' is a mandatory attribute
msg = ('the extra attribute "compilers" must be set for '
'the detected spec "{0}"'.format(spec))
assert 'compilers' in extra_attributes, msg
compilers = extra_attributes['compilers']
for key in ('c', 'cxx'):
msg = '{0} compiler not found for {1}'
assert key in compilers, msg.format(key, spec)
@property
def cc(self):
msg = "cannot retrieve C compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes['compilers'].get('c', None)
result = None
if '+clang' in self.spec:
result = os.path.join(self.spec.prefix.bin, 'clang')
return result
@property
def cxx(self):
msg = "cannot retrieve C++ compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes['compilers'].get('cxx', None)
result = None
if '+clang' in self.spec:
result = os.path.join(self.spec.prefix.bin, 'clang++')
return result
@property
def fc(self):
msg = "cannot retrieve Fortran compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes['compilers'].get('fc', None)
result = None
if '+flang' in self.spec:
result = os.path.join(self.spec.prefix.bin, 'flang')
return result
@property
def f77(self):
msg = "cannot retrieve Fortran 77 compiler [spec is not concrete]"
assert self.spec.concrete, msg
if self.spec.external:
return self.spec.extra_attributes['compilers'].get('f77', None)
result = None
if '+flang' in self.spec:
result = os.path.join(self.spec.prefix.bin, 'flang')
return result
@run_before('cmake')
def codesign_check(self):
if self.spec.satisfies("+code_signing"):
codesign = which('codesign')
mkdir('tmp')
llvm_check_file = join_path('tmp', 'llvm_check')
copy('/usr/bin/false', llvm_check_file)
try:
codesign('-f', '-s', 'lldb_codesign', '--dryrun',
llvm_check_file)
except ProcessError:
# Newer LLVM versions have a simple script that sets up
# automatically when run with sudo priviliges
setup = Executable("./lldb/scripts/macos-setup-codesign.sh")
try:
setup()
except Exception:
raise RuntimeError(
'spack was unable to either find or set up'
'code-signing on your system. Please refer to'
'https://lldb.llvm.org/resources/build.html#'
'code-signing-on-macos for details on how to'
'create this identity.'
)
def flag_handler(self, name, flags):
if name == 'cxxflags':
flags.append(self.compiler.cxx11_flag)
return(None, flags, None)
elif name == 'ldflags' and self.spec.satisfies('%intel'):
flags.append('-shared-intel')
return(None, flags, None)
return(flags, None, None)
def setup_build_environment(self, env):
"""When using %clang, add only its ld.lld-$ver and/or ld.lld to our PATH"""
if self.compiler.name in ['clang', 'apple-clang']:
for lld in 'ld.lld-{0}'.format(self.compiler.version.version[0]), 'ld.lld':
bin = os.path.join(os.path.dirname(self.compiler.cc), lld)
sym = os.path.join(self.stage.path, 'ld.lld')
if os.path.exists(bin) and not os.path.exists(sym):
mkdirp(self.stage.path)
os.symlink(bin, sym)
env.prepend_path('PATH', self.stage.path)
def setup_run_environment(self, env):
if "+clang" in self.spec:
env.set("CC", join_path(self.spec.prefix.bin, "clang"))
env.set("CXX", join_path(self.spec.prefix.bin, "clang++"))
if "+flang" in self.spec:
env.set("FC", join_path(self.spec.prefix.bin, "flang"))
env.set("F77", join_path(self.spec.prefix.bin, "flang"))
root_cmakelists_dir = "llvm"
def cmake_args(self):
spec = self.spec
define = CMakePackage.define
from_variant = self.define_from_variant
python = spec['python']
cmake_args = [
define("LLVM_REQUIRES_RTTI", True),
define("LLVM_ENABLE_RTTI", True),
define("LLVM_ENABLE_EH", True),
define("CLANG_DEFAULT_OPENMP_RUNTIME", "libomp"),
define("PYTHON_EXECUTABLE", python.command.path),
define("LIBOMP_USE_HWLOC", True),
define("LIBOMP_HWLOC_INSTALL_DIR", spec["hwloc"].prefix),
]
version_suffix = spec.variants['version_suffix'].value
if version_suffix != 'none':
cmake_args.append(define('LLVM_VERSION_SUFFIX', version_suffix))
if python.version >= Version("3"):
cmake_args.append(define("Python3_EXECUTABLE", python.command.path))
else:
cmake_args.append(define("Python2_EXECUTABLE", python.command.path))
projects = []
runtimes = []
if "+cuda" in spec:
cmake_args.extend([
define("CUDA_TOOLKIT_ROOT_DIR", spec["cuda"].prefix),
define("LIBOMPTARGET_NVPTX_COMPUTE_CAPABILITIES",
",".join(spec.variants["cuda_arch"].value)),
define("CLANG_OPENMP_NVPTX_DEFAULT_ARCH",
"sm_{0}".format(spec.variants["cuda_arch"].value[-1])),
])
if "+omp_as_runtime" in spec:
cmake_args.extend([
define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True),
# work around bad libelf detection in libomptarget
define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR",
spec["libelf"].prefix.include),
])
else:
# still build libomptarget but disable cuda
cmake_args.extend([
define("CUDA_TOOLKIT_ROOT_DIR", "IGNORE"),
define("CUDA_SDK_ROOT_DIR", "IGNORE"),
define("CUDA_NVCC_EXECUTABLE", "IGNORE"),
define("LIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES", "IGNORE"),
])
cmake_args.append(from_variant("LIBOMPTARGET_ENABLE_DEBUG", "omp_debug"))
if "+lldb" in spec:
if spec.version >= Version('10'):
cmake_args.append(from_variant("LLDB_ENABLE_PYTHON", 'python'))
else:
cmake_args.append(define("LLDB_DISABLE_PYTHON",
'~python' in spec))
if spec.satisfies("@5.0.0: +python"):
cmake_args.append(define("LLDB_USE_SYSTEM_SIX", True))
if "+gold" in spec:
cmake_args.append(
define("LLVM_BINUTILS_INCDIR", spec["binutils"].prefix.include)
)
if "+clang" in spec:
projects.append("clang")
projects.append("clang-tools-extra")
if "+omp_as_runtime" in spec:
runtimes.append("openmp")
else:
projects.append("openmp")
if self.spec.satisfies("@8"):
cmake_args.append(define('CLANG_ANALYZER_ENABLE_Z3_SOLVER',
self.spec.satisfies('@8+z3')))
if self.spec.satisfies("@9:"):
cmake_args.append(define('LLVM_ENABLE_Z3_SOLVER',
self.spec.satisfies('@9:+z3')))
if "+flang" in spec:
projects.append("flang")
if "+lldb" in spec:
projects.append("lldb")
if "+lld" in spec:
projects.append("lld")
if "+compiler-rt" in spec:
projects.append("compiler-rt")
if "+libcxx" in spec:
projects.append("libcxx")
projects.append("libcxxabi")
if "+mlir" in spec:
projects.append("mlir")
if "+internal_unwind" in spec:
projects.append("libunwind")
if "+polly" in spec:
projects.append("polly")
cmake_args.append(define("LINK_POLLY_INTO_TOOLS", True))
cmake_args.extend([
from_variant("BUILD_SHARED_LIBS", "shared_libs"),
from_variant("LLVM_BUILD_LLVM_DYLIB", "llvm_dylib"),
from_variant("LLVM_LINK_LLVM_DYLIB", "link_llvm_dylib"),
from_variant("LLVM_USE_SPLIT_DWARF", "split_dwarf"),
# By default on Linux, libc++.so is a ldscript. CMake fails to add
# CMAKE_INSTALL_RPATH to it, which fails. Statically link libc++abi.a
# into libc++.so, linking with -lc++ or -stdlib=libc++ is enough.
define('LIBCXX_ENABLE_STATIC_ABI_LIBRARY', True)
])
if "+all_targets" not in spec: # all is default on cmake
targets = ["NVPTX", "AMDGPU"]
if spec.version < Version("3.9.0"):
# Starting in 3.9.0 CppBackend is no longer a target (see
# LLVM_ALL_TARGETS in llvm's top-level CMakeLists.txt for
# the complete list of targets)
targets.append("CppBackend")
if spec.target.family in ("x86", "x86_64"):
targets.append("X86")
elif spec.target.family == "arm":
targets.append("ARM")
elif spec.target.family == "aarch64":
targets.append("AArch64")
elif spec.target.family in ("sparc", "sparc64"):
targets.append("Sparc")
elif spec.target.family in ("ppc64", "ppc64le", "ppc", "ppcle"):
targets.append("PowerPC")
cmake_args.append(define("LLVM_TARGETS_TO_BUILD", targets))
cmake_args.append(from_variant("LIBOMP_TSAN_SUPPORT", "omp_tsan"))
if self.compiler.name == "gcc":
compiler = Executable(self.compiler.cc)
gcc_output = compiler('-print-search-dirs', output=str, error=str)
for line in gcc_output.splitlines():
if line.startswith("install:"):
# Get path and strip any whitespace
# (causes oddity with ancestor)
gcc_prefix = line.split(":")[1].strip()
gcc_prefix = ancestor(gcc_prefix, 4)
break
cmake_args.append(define("GCC_INSTALL_PREFIX", gcc_prefix))
if self.spec.satisfies("~code_signing platform=darwin"):
cmake_args.append(define('LLDB_USE_SYSTEM_DEBUGSERVER', True))
# Semicolon seperated list of projects to enable
cmake_args.append(define("LLVM_ENABLE_PROJECTS", projects))
# Semicolon seperated list of runtimes to enable
if runtimes:
cmake_args.append(define("LLVM_ENABLE_RUNTIMES", runtimes))
return cmake_args
@run_after("install")
def post_install(self):
spec = self.spec
define = CMakePackage.define
# unnecessary if we build openmp via LLVM_ENABLE_RUNTIMES
if "+cuda ~omp_as_runtime" in self.spec:
ompdir = "build-bootstrapped-omp"
prefix_paths = spack.build_environment.get_cmake_prefix_path(self)
prefix_paths.append(str(spec.prefix))
# rebuild libomptarget to get bytecode runtime library files
with working_dir(ompdir, create=True):
cmake_args = [
'-G', 'Ninja',
define('CMAKE_BUILD_TYPE', spec.variants['build_type'].value),
define("CMAKE_C_COMPILER", spec.prefix.bin + "/clang"),
define("CMAKE_CXX_COMPILER", spec.prefix.bin + "/clang++"),
define("CMAKE_INSTALL_PREFIX", spec.prefix),
define('CMAKE_PREFIX_PATH', prefix_paths)
]
cmake_args.extend(self.cmake_args())
cmake_args.extend([
define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True),
define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR",
spec["libelf"].prefix.include),
self.stage.source_path + "/openmp",
])
cmake(*cmake_args)
ninja()
ninja("install")
if "+python" in self.spec:
install_tree("llvm/bindings/python", site_packages_dir)
if "+clang" in self.spec:
install_tree("clang/bindings/python", site_packages_dir)
with working_dir(self.build_directory):
install_tree("bin", join_path(self.prefix, "libexec", "llvm"))

View File

@ -0,0 +1,931 @@
# -*- python -*-
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This is an unparser test package.
``mfem`` was chosen because it's one of the most complex packages in Spack, because it
uses ``@when`` functions, because it has ``configure()`` calls with star-args in
different locations, and beacuse it has a function with embedded unicode that needs to
be unparsed consistently between Python versions.
"""
import os
import shutil
import sys
from spack import *
class Mfem(Package, CudaPackage, ROCmPackage):
"""Free, lightweight, scalable C++ library for finite element methods."""
tags = ['fem', 'finite-elements', 'high-order', 'amr', 'hpc', 'radiuss', 'e4s']
homepage = 'http://www.mfem.org'
git = 'https://github.com/mfem/mfem.git'
maintainers = ['v-dobrev', 'tzanio', 'acfisher',
'goxberry', 'markcmiller86']
test_requires_compiler = True
# Recommended mfem builds to test when updating this file: see the shell
# script 'test_builds.sh' in the same directory as this file.
# mfem is downloaded from a URL shortener at request of upstream
# author Tzanio Kolev <tzanio@llnl.gov>. See here:
# https://github.com/mfem/mfem/issues/53
#
# The following procedure should be used to verify security when a
# new version is added:
#
# 1. Verify that no checksums on old versions have changed.
#
# 2. Verify that the shortened URL for the new version is listed at:
# https://mfem.org/download/
#
# 3. Use http://getlinkinfo.com or similar to verify that the
# underling download link for the latest version comes has the
# prefix: http://mfem.github.io/releases
#
# If this quick verification procedure fails, additional discussion
# will be required to verify the new version.
# 'develop' is a special version that is always larger (or newer) than any
# other version.
version('develop', branch='master')
version('4.3.0',
sha256='3a495602121b986049286ea0b23512279cdbdfb43c15c42a1511b521051fbe38',
url='https://bit.ly/mfem-4-3', extension='tar.gz')
version('4.2.0',
'4352a225b55948d2e73a5ee88cece0e88bdbe7ba6726a23d68b2736d3221a86d',
url='https://bit.ly/mfem-4-2', extension='tar.gz')
version('4.1.0',
'4c83fdcf083f8e2f5b37200a755db843cdb858811e25a8486ad36b2cbec0e11d',
url='https://bit.ly/mfem-4-1', extension='tar.gz')
# Tagged development version used by xSDK
version('4.0.1-xsdk', commit='c55c80d17b82d80de04b849dd526e17044f8c99a')
version('4.0.0',
'df5bdac798ea84a263979f6fbf79de9013e1c55562f95f98644c3edcacfbc727',
url='https://bit.ly/mfem-4-0', extension='tar.gz')
# Tagged development version used by the laghos package:
version('3.4.1-laghos-v2.0', tag='laghos-v2.0')
version('3.4.0',
sha256='4e73e4fe0482636de3c5dc983cd395839a83cb16f6f509bd88b053e8b3858e05',
url='https://bit.ly/mfem-3-4', extension='tar.gz')
version('3.3.2',
sha256='b70fa3c5080b9ec514fc05f4a04ff74322b99ac4ecd6d99c229f0ed5188fc0ce',
url='https://goo.gl/Kd7Jk8', extension='tar.gz')
# Tagged development version used by the laghos package:
version('3.3.1-laghos-v1.0', tag='laghos-v1.0')
version('3.3',
sha256='b17bd452593aada93dc0fee748fcfbbf4f04ce3e7d77fdd0341cc9103bcacd0b',
url='http://goo.gl/Vrpsns', extension='tar.gz')
version('3.2',
sha256='2938c3deed4ec4f7fd5b5f5cfe656845282e86e2dcd477d292390058b7b94340',
url='http://goo.gl/Y9T75B', extension='tar.gz')
version('3.1',
sha256='841ea5cf58de6fae4de0f553b0e01ebaab9cd9c67fa821e8a715666ecf18fc57',
url='http://goo.gl/xrScXn', extension='tar.gz')
variant('static', default=True,
description='Build static library')
variant('shared', default=False,
description='Build shared library')
variant('mpi', default=True,
description='Enable MPI parallelism')
# Can we make the default value for 'metis' to depend on the 'mpi' value?
variant('metis', default=True,
description='Enable METIS support')
variant('openmp', default=False,
description='Enable OpenMP parallelism')
# Note: '+cuda' and 'cuda_arch' variants are added by the CudaPackage
# Note: '+rocm' and 'amdgpu_target' variants are added by the ROCmPackage
variant('occa', default=False, description='Enable OCCA backend')
variant('raja', default=False, description='Enable RAJA backend')
variant('libceed', default=False, description='Enable libCEED backend')
variant('umpire', default=False, description='Enable Umpire support')
variant('amgx', default=False, description='Enable NVIDIA AmgX solver support')
variant('threadsafe', default=False,
description=('Enable thread safe features.'
' Required for OpenMP.'
' May cause minor performance issues.'))
variant('superlu-dist', default=False,
description='Enable MPI parallel, sparse direct solvers')
variant('strumpack', default=False,
description='Enable support for STRUMPACK')
variant('suite-sparse', default=False,
description='Enable serial, sparse direct solvers')
variant('petsc', default=False,
description='Enable PETSc solvers, preconditioners, etc.')
variant('slepc', default=False,
description='Enable SLEPc integration')
variant('sundials', default=False,
description='Enable Sundials time integrators')
variant('pumi', default=False,
description='Enable functionality based on PUMI')
variant('gslib', default=False,
description='Enable functionality based on GSLIB')
variant('mpfr', default=False,
description='Enable precise, 1D quadrature rules')
variant('lapack', default=False,
description='Use external blas/lapack routines')
variant('debug', default=False,
description='Build debug instead of optimized version')
variant('netcdf', default=False,
description='Enable Cubit/Genesis reader')
variant('conduit', default=False,
description='Enable binary data I/O using Conduit')
variant('zlib', default=True,
description='Support zip\'d streams for I/O')
variant('gnutls', default=False,
description='Enable secure sockets using GnuTLS')
variant('libunwind', default=False,
description='Enable backtrace on error support using Libunwind')
# TODO: SIMD, Ginkgo, ADIOS2, HiOp, MKL CPardiso, Axom/Sidre
variant('timer', default='auto',
values=('auto', 'std', 'posix', 'mac', 'mpi'),
description='Timing functions to use in mfem::StopWatch')
variant('examples', default=False,
description='Build and install examples')
variant('miniapps', default=False,
description='Build and install miniapps')
conflicts('+shared', when='@:3.3.2')
conflicts('~static~shared')
conflicts('~threadsafe', when='@:3+openmp')
conflicts('+cuda', when='@:3')
conflicts('+rocm', when='@:4.1')
conflicts('+cuda+rocm')
conflicts('+netcdf', when='@:3.1')
conflicts('+superlu-dist', when='@:3.1')
# STRUMPACK support was added in mfem v3.3.2, however, here we allow only
# strumpack v3+ support for which is available starting with mfem v4.0:
conflicts('+strumpack', when='@:3')
conflicts('+gnutls', when='@:3.1')
conflicts('+zlib', when='@:3.2')
conflicts('+mpfr', when='@:3.2')
conflicts('+petsc', when='@:3.2')
conflicts('+slepc', when='@:4.1')
conflicts('+sundials', when='@:3.2')
conflicts('+pumi', when='@:3.3.2')
conflicts('+gslib', when='@:4.0')
conflicts('timer=mac', when='@:3.3.0')
conflicts('timer=mpi', when='@:3.3.0')
conflicts('~metis+mpi', when='@:3.3.0')
conflicts('+metis~mpi', when='@:3.3.0')
conflicts('+conduit', when='@:3.3.2')
conflicts('+occa', when='mfem@:3')
conflicts('+raja', when='mfem@:3')
conflicts('+libceed', when='mfem@:4.0')
conflicts('+umpire', when='mfem@:4.0')
conflicts('+amgx', when='mfem@:4.1')
conflicts('+amgx', when='~cuda')
conflicts('+mpi~cuda ^hypre+cuda')
conflicts('+superlu-dist', when='~mpi')
conflicts('+strumpack', when='~mpi')
conflicts('+petsc', when='~mpi')
conflicts('+slepc', when='~petsc')
conflicts('+pumi', when='~mpi')
conflicts('timer=mpi', when='~mpi')
depends_on('mpi', when='+mpi')
depends_on('hypre@2.10.0:2.13', when='@:3.3+mpi')
depends_on('hypre@:2.20.0', when='@3.4:4.2+mpi')
depends_on('hypre@:2.23.0', when='@4.3.0+mpi')
depends_on('hypre', when='+mpi')
depends_on('metis', when='+metis')
depends_on('blas', when='+lapack')
depends_on('lapack@3.0:', when='+lapack')
depends_on('sundials@2.7.0', when='@:3.3.0+sundials~mpi')
depends_on('sundials@2.7.0+mpi+hypre', when='@:3.3.0+sundials+mpi')
depends_on('sundials@2.7.0:', when='@3.3.2:+sundials~mpi')
depends_on('sundials@2.7.0:+mpi+hypre', when='@3.3.2:+sundials+mpi')
depends_on('sundials@5.0.0:', when='@4.0.1-xsdk:+sundials~mpi')
depends_on('sundials@5.0.0:+mpi+hypre', when='@4.0.1-xsdk:+sundials+mpi')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('sundials@5.4.0:+cuda cuda_arch={0}'.format(sm_),
when='@4.2.0:+sundials+cuda cuda_arch={0}'.format(sm_))
depends_on('pumi@2.2.3:', when='@4.2.0:+pumi')
depends_on('pumi', when='+pumi~shared')
depends_on('pumi+shared', when='+pumi+shared')
depends_on('gslib@1.0.5:+mpi', when='+gslib+mpi')
depends_on('gslib@1.0.5:~mpi~mpiio', when='+gslib~mpi')
depends_on('suite-sparse', when='+suite-sparse')
depends_on('superlu-dist', when='+superlu-dist')
depends_on('strumpack@3.0.0:', when='+strumpack~shared')
depends_on('strumpack@3.0.0:+shared', when='+strumpack+shared')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('strumpack+cuda cuda_arch={0}'.format(sm_),
when='+strumpack+cuda cuda_arch={0}'.format(sm_))
# The PETSc tests in MFEM will fail if PETSc is not configured with
# SuiteSparse and MUMPS. On the other hand, if we require the variants
# '+suite-sparse+mumps' of PETSc, the xsdk package concretization fails.
depends_on('petsc@3.8:+mpi+double+hypre', when='+petsc')
depends_on('slepc@3.8.0:', when='+slepc')
# Recommended when building outside of xsdk:
# depends_on('petsc@3.8:+mpi+double+hypre+suite-sparse+mumps',
# when='+petsc')
depends_on('mpfr', when='+mpfr')
depends_on('netcdf-c@4.1.3:', when='+netcdf')
depends_on('unwind', when='+libunwind')
depends_on('zlib', when='+zlib')
depends_on('gnutls', when='+gnutls')
depends_on('conduit@0.3.1:,master:', when='+conduit')
depends_on('conduit+mpi', when='+conduit+mpi')
# The MFEM 4.0.0 SuperLU interface fails when using hypre@2.16.0 and
# superlu-dist@6.1.1. See https://github.com/mfem/mfem/issues/983.
# This issue was resolved in v4.1.
conflicts('+superlu-dist',
when='mfem@:4.0 ^hypre@2.16.0: ^superlu-dist@6:')
# The STRUMPACK v3 interface in MFEM seems to be broken as of MFEM v4.1
# when using hypre version >= 2.16.0.
# This issue is resolved in v4.2.
conflicts('+strumpack', when='mfem@4.0.0:4.1 ^hypre@2.16.0:')
conflicts('+strumpack ^strumpack+cuda', when='~cuda')
depends_on('occa@1.0.8:', when='@:4.1+occa')
depends_on('occa@1.1.0:', when='@4.2.0:+occa')
depends_on('occa+cuda', when='+occa+cuda')
# TODO: propagate '+rocm' variant to occa when it is supported
depends_on('raja@0.10.0:', when='@4.0.1:+raja')
depends_on('raja@0.7.0:0.9.0', when='@4.0.0+raja')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('raja+cuda cuda_arch={0}'.format(sm_),
when='+raja+cuda cuda_arch={0}'.format(sm_))
for gfx in ROCmPackage.amdgpu_targets:
depends_on('raja+rocm amdgpu_target={0}'.format(gfx),
when='+raja+rocm amdgpu_target={0}'.format(gfx))
depends_on('libceed@0.6:', when='@:4.1+libceed')
depends_on('libceed@0.7:', when='@4.2.0:+libceed')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('libceed+cuda cuda_arch={0}'.format(sm_),
when='+libceed+cuda cuda_arch={0}'.format(sm_))
for gfx in ROCmPackage.amdgpu_targets:
depends_on('libceed+rocm amdgpu_target={0}'.format(gfx),
when='+libceed+rocm amdgpu_target={0}'.format(gfx))
depends_on('umpire@2.0.0:', when='+umpire')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('umpire+cuda cuda_arch={0}'.format(sm_),
when='+umpire+cuda cuda_arch={0}'.format(sm_))
for gfx in ROCmPackage.amdgpu_targets:
depends_on('umpire+rocm amdgpu_target={0}'.format(gfx),
when='+umpire+rocm amdgpu_target={0}'.format(gfx))
# AmgX: propagate the cuda_arch and mpi settings:
for sm_ in CudaPackage.cuda_arch_values:
depends_on('amgx+mpi cuda_arch={0}'.format(sm_),
when='+amgx+mpi cuda_arch={0}'.format(sm_))
depends_on('amgx~mpi cuda_arch={0}'.format(sm_),
when='+amgx~mpi cuda_arch={0}'.format(sm_))
patch('mfem_ppc_build.patch', when='@3.2:3.3.0 arch=ppc64le')
patch('mfem-3.4.patch', when='@3.4.0')
patch('mfem-3.3-3.4-petsc-3.9.patch',
when='@3.3.0:3.4.0 +petsc ^petsc@3.9.0:')
patch('mfem-4.2-umpire.patch', when='@4.2.0+umpire')
patch('mfem-4.2-slepc.patch', when='@4.2.0+slepc')
patch('mfem-4.2-petsc-3.15.0.patch', when='@4.2.0+petsc ^petsc@3.15.0:')
patch('mfem-4.3-hypre-2.23.0.patch', when='@4.3.0')
patch('mfem-4.3-cusparse-11.4.patch', when='@4.3.0+cuda')
# Patch to fix MFEM makefile syntax error. See
# https://github.com/mfem/mfem/issues/1042 for the bug report and
# https://github.com/mfem/mfem/pull/1043 for the bugfix contributed
# upstream.
patch('mfem-4.0.0-makefile-syntax-fix.patch', when='@4.0.0')
phases = ['configure', 'build', 'install']
def setup_build_environment(self, env):
env.unset('MFEM_DIR')
env.unset('MFEM_BUILD_DIR')
#
# Note: Although MFEM does support CMake configuration, MFEM
# development team indicates that vanilla GNU Make is the
# preferred mode of configuration of MFEM and the mode most
# likely to be up to date in supporting *all* of MFEM's
# configuration options. So, don't use CMake
#
def configure(self, spec, prefix):
def yes_no(varstr):
return 'YES' if varstr in self.spec else 'NO'
# See also find_system_libraries in lib/spack/llnl/util/filesystem.py
# where the same list of paths is used.
sys_lib_paths = [
'/lib64',
'/lib',
'/usr/lib64',
'/usr/lib',
'/usr/local/lib64',
'/usr/local/lib']
def is_sys_lib_path(dir):
return dir in sys_lib_paths
xcompiler = ''
xlinker = '-Wl,'
if '+cuda' in spec:
xcompiler = '-Xcompiler='
xlinker = '-Xlinker='
cuda_arch = None if '~cuda' in spec else spec.variants['cuda_arch'].value
# We need to add rpaths explicitly to allow proper export of link flags
# from within MFEM.
# Similar to spec[pkg].libs.ld_flags but prepends rpath flags too.
# Also does not add system library paths as defined by 'sys_lib_paths'
# above -- this is done to avoid issues like this:
# https://github.com/mfem/mfem/issues/1088.
def ld_flags_from_library_list(libs_list):
flags = ['%s-rpath,%s' % (xlinker, dir)
for dir in libs_list.directories
if not is_sys_lib_path(dir)]
flags += ['-L%s' % dir for dir in libs_list.directories
if not is_sys_lib_path(dir)]
flags += [libs_list.link_flags]
return ' '.join(flags)
def ld_flags_from_dirs(pkg_dirs_list, pkg_libs_list):
flags = ['%s-rpath,%s' % (xlinker, dir) for dir in pkg_dirs_list
if not is_sys_lib_path(dir)]
flags += ['-L%s' % dir for dir in pkg_dirs_list
if not is_sys_lib_path(dir)]
flags += ['-l%s' % lib for lib in pkg_libs_list]
return ' '.join(flags)
def find_optional_library(name, prefix):
for shared in [True, False]:
for path in ['lib64', 'lib']:
lib = find_libraries(name, join_path(prefix, path),
shared=shared, recursive=False)
if lib:
return lib
return LibraryList([])
# Determine how to run MPI tests, e.g. when using '--test=root', when
# Spack is run inside a batch system job.
mfem_mpiexec = 'mpirun'
mfem_mpiexec_np = '-np'
if 'SLURM_JOBID' in os.environ:
mfem_mpiexec = 'srun'
mfem_mpiexec_np = '-n'
elif 'LSB_JOBID' in os.environ:
if 'LLNL_COMPUTE_NODES' in os.environ:
mfem_mpiexec = 'lrun'
mfem_mpiexec_np = '-n'
else:
mfem_mpiexec = 'jsrun'
mfem_mpiexec_np = '-p'
metis5_str = 'NO'
if ('+metis' in spec) and spec['metis'].satisfies('@5:'):
metis5_str = 'YES'
zlib_var = 'MFEM_USE_ZLIB' if (spec.satisfies('@4.1.0:')) else \
'MFEM_USE_GZSTREAM'
options = [
'PREFIX=%s' % prefix,
'MFEM_USE_MEMALLOC=YES',
'MFEM_DEBUG=%s' % yes_no('+debug'),
# NOTE: env['CXX'] is the spack c++ compiler wrapper. The real
# compiler is defined by env['SPACK_CXX'].
'CXX=%s' % env['CXX'],
'MFEM_USE_LIBUNWIND=%s' % yes_no('+libunwind'),
'%s=%s' % (zlib_var, yes_no('+zlib')),
'MFEM_USE_METIS=%s' % yes_no('+metis'),
'MFEM_USE_METIS_5=%s' % metis5_str,
'MFEM_THREAD_SAFE=%s' % yes_no('+threadsafe'),
'MFEM_USE_MPI=%s' % yes_no('+mpi'),
'MFEM_USE_LAPACK=%s' % yes_no('+lapack'),
'MFEM_USE_SUPERLU=%s' % yes_no('+superlu-dist'),
'MFEM_USE_STRUMPACK=%s' % yes_no('+strumpack'),
'MFEM_USE_SUITESPARSE=%s' % yes_no('+suite-sparse'),
'MFEM_USE_SUNDIALS=%s' % yes_no('+sundials'),
'MFEM_USE_PETSC=%s' % yes_no('+petsc'),
'MFEM_USE_SLEPC=%s' % yes_no('+slepc'),
'MFEM_USE_PUMI=%s' % yes_no('+pumi'),
'MFEM_USE_GSLIB=%s' % yes_no('+gslib'),
'MFEM_USE_NETCDF=%s' % yes_no('+netcdf'),
'MFEM_USE_MPFR=%s' % yes_no('+mpfr'),
'MFEM_USE_GNUTLS=%s' % yes_no('+gnutls'),
'MFEM_USE_OPENMP=%s' % yes_no('+openmp'),
'MFEM_USE_CONDUIT=%s' % yes_no('+conduit'),
'MFEM_USE_CUDA=%s' % yes_no('+cuda'),
'MFEM_USE_HIP=%s' % yes_no('+rocm'),
'MFEM_USE_OCCA=%s' % yes_no('+occa'),
'MFEM_USE_RAJA=%s' % yes_no('+raja'),
'MFEM_USE_AMGX=%s' % yes_no('+amgx'),
'MFEM_USE_CEED=%s' % yes_no('+libceed'),
'MFEM_USE_UMPIRE=%s' % yes_no('+umpire'),
'MFEM_MPIEXEC=%s' % mfem_mpiexec,
'MFEM_MPIEXEC_NP=%s' % mfem_mpiexec_np]
cxxflags = spec.compiler_flags['cxxflags']
if cxxflags:
# Add opt/debug flags if they are not present in global cxx flags
opt_flag_found = any(f in self.compiler.opt_flags
for f in cxxflags)
debug_flag_found = any(f in self.compiler.debug_flags
for f in cxxflags)
if '+debug' in spec:
if not debug_flag_found:
cxxflags.append('-g')
if not opt_flag_found:
cxxflags.append('-O0')
else:
if not opt_flag_found:
cxxflags.append('-O2')
cxxflags = [(xcompiler + flag) for flag in cxxflags]
if '+cuda' in spec:
cxxflags += [
'-x=cu --expt-extended-lambda -arch=sm_%s' % cuda_arch,
'-ccbin %s' % (spec['mpi'].mpicxx if '+mpi' in spec
else env['CXX'])]
if self.spec.satisfies('@4.0.0:'):
cxxflags.append(self.compiler.cxx11_flag)
# The cxxflags are set by the spack c++ compiler wrapper. We also
# set CXXFLAGS explicitly, for clarity, and to properly export the
# cxxflags in the variable MFEM_CXXFLAGS in config.mk.
options += ['CXXFLAGS=%s' % ' '.join(cxxflags)]
if '~static' in spec:
options += ['STATIC=NO']
if '+shared' in spec:
options += [
'SHARED=YES',
'PICFLAG=%s' % (xcompiler + self.compiler.cxx_pic_flag)]
if '+mpi' in spec:
options += ['MPICXX=%s' % spec['mpi'].mpicxx]
hypre = spec['hypre']
# The hypre package always links with 'blas' and 'lapack'.
all_hypre_libs = hypre.libs + hypre['lapack'].libs + \
hypre['blas'].libs
options += [
'HYPRE_OPT=-I%s' % hypre.prefix.include,
'HYPRE_LIB=%s' % ld_flags_from_library_list(all_hypre_libs)]
if '+metis' in spec:
options += [
'METIS_OPT=-I%s' % spec['metis'].prefix.include,
'METIS_LIB=%s' %
ld_flags_from_library_list(spec['metis'].libs)]
if '+lapack' in spec:
lapack_blas = spec['lapack'].libs + spec['blas'].libs
options += [
# LAPACK_OPT is not used
'LAPACK_LIB=%s' % ld_flags_from_library_list(lapack_blas)]
if '+superlu-dist' in spec:
lapack_blas = spec['lapack'].libs + spec['blas'].libs
options += [
'SUPERLU_OPT=-I%s -I%s' %
(spec['superlu-dist'].prefix.include,
spec['parmetis'].prefix.include),
'SUPERLU_LIB=%s %s' %
(ld_flags_from_dirs([spec['superlu-dist'].prefix.lib,
spec['parmetis'].prefix.lib],
['superlu_dist', 'parmetis']),
ld_flags_from_library_list(lapack_blas))]
if '+strumpack' in spec:
strumpack = spec['strumpack']
sp_opt = ['-I%s' % strumpack.prefix.include]
sp_lib = [ld_flags_from_library_list(strumpack.libs)]
# Parts of STRUMPACK use fortran, so we need to link with the
# fortran library and also the MPI fortran library:
if '~shared' in strumpack:
if os.path.basename(env['FC']) == 'gfortran':
gfortran = Executable(env['FC'])
libext = 'dylib' if sys.platform == 'darwin' else 'so'
libfile = os.path.abspath(gfortran(
'-print-file-name=libgfortran.%s' % libext,
output=str).strip())
gfortran_lib = LibraryList(libfile)
sp_lib += [ld_flags_from_library_list(gfortran_lib)]
if ('^mpich' in strumpack) or ('^mvapich2' in strumpack):
sp_lib += ['-lmpifort']
elif '^openmpi' in strumpack:
sp_lib += ['-lmpi_mpifh']
elif '^spectrum-mpi' in strumpack:
sp_lib += ['-lmpi_ibm_mpifh']
if '+openmp' in strumpack:
# The '+openmp' in the spec means strumpack will TRY to find
# OpenMP; if not found, we should not add any flags -- how do
# we figure out if strumpack found OpenMP?
if not self.spec.satisfies('%apple-clang'):
sp_opt += [xcompiler + self.compiler.openmp_flag]
if '^parmetis' in strumpack:
parmetis = strumpack['parmetis']
sp_opt += [parmetis.headers.cpp_flags]
sp_lib += [ld_flags_from_library_list(parmetis.libs)]
if '^netlib-scalapack' in strumpack:
scalapack = strumpack['scalapack']
sp_opt += ['-I%s' % scalapack.prefix.include]
sp_lib += [ld_flags_from_dirs([scalapack.prefix.lib],
['scalapack'])]
elif '^scalapack' in strumpack:
scalapack = strumpack['scalapack']
sp_opt += [scalapack.headers.cpp_flags]
sp_lib += [ld_flags_from_library_list(scalapack.libs)]
if '+butterflypack' in strumpack:
bp = strumpack['butterflypack']
sp_opt += ['-I%s' % bp.prefix.include]
sp_lib += [ld_flags_from_dirs([bp.prefix.lib],
['dbutterflypack',
'zbutterflypack'])]
if '+zfp' in strumpack:
zfp = strumpack['zfp']
sp_opt += ['-I%s' % zfp.prefix.include]
sp_lib += [ld_flags_from_dirs([zfp.prefix.lib], ['zfp'])]
if '+cuda' in strumpack:
# assuming also ('+cuda' in spec)
sp_lib += ['-lcusolver', '-lcublas']
options += [
'STRUMPACK_OPT=%s' % ' '.join(sp_opt),
'STRUMPACK_LIB=%s' % ' '.join(sp_lib)]
if '+suite-sparse' in spec:
ss_spec = 'suite-sparse:' + self.suitesparse_components
options += [
'SUITESPARSE_OPT=-I%s' % spec[ss_spec].prefix.include,
'SUITESPARSE_LIB=%s' %
ld_flags_from_library_list(spec[ss_spec].libs)]
if '+sundials' in spec:
sun_spec = 'sundials:' + self.sundials_components
options += [
'SUNDIALS_OPT=%s' % spec[sun_spec].headers.cpp_flags,
'SUNDIALS_LIB=%s' %
ld_flags_from_library_list(spec[sun_spec].libs)]
if '+petsc' in spec:
petsc = spec['petsc']
if '+shared' in petsc:
options += [
'PETSC_OPT=%s' % petsc.headers.cpp_flags,
'PETSC_LIB=%s' % ld_flags_from_library_list(petsc.libs)]
else:
options += ['PETSC_DIR=%s' % petsc.prefix]
if '+slepc' in spec:
slepc = spec['slepc']
options += [
'SLEPC_OPT=%s' % slepc.headers.cpp_flags,
'SLEPC_LIB=%s' % ld_flags_from_library_list(slepc.libs)]
if '+pumi' in spec:
pumi_libs = ['pumi', 'crv', 'ma', 'mds', 'apf', 'pcu', 'gmi',
'parma', 'lion', 'mth', 'apf_zoltan', 'spr']
options += [
'PUMI_OPT=-I%s' % spec['pumi'].prefix.include,
'PUMI_LIB=%s' %
ld_flags_from_dirs([spec['pumi'].prefix.lib], pumi_libs)]
if '+gslib' in spec:
options += [
'GSLIB_OPT=-I%s' % spec['gslib'].prefix.include,
'GSLIB_LIB=%s' %
ld_flags_from_dirs([spec['gslib'].prefix.lib], ['gs'])]
if '+netcdf' in spec:
lib_flags = ld_flags_from_dirs([spec['netcdf-c'].prefix.lib],
['netcdf'])
hdf5 = spec['hdf5:hl']
if hdf5.satisfies('~shared'):
hdf5_libs = hdf5.libs
hdf5_libs += LibraryList(find_system_libraries('libdl'))
lib_flags += " " + ld_flags_from_library_list(hdf5_libs)
options += [
'NETCDF_OPT=-I%s' % spec['netcdf-c'].prefix.include,
'NETCDF_LIB=%s' % lib_flags]
if '+zlib' in spec:
if "@:3.3.2" in spec:
options += ['ZLIB_DIR=%s' % spec['zlib'].prefix]
else:
options += [
'ZLIB_OPT=-I%s' % spec['zlib'].prefix.include,
'ZLIB_LIB=%s' %
ld_flags_from_library_list(spec['zlib'].libs)]
if '+mpfr' in spec:
options += [
'MPFR_OPT=-I%s' % spec['mpfr'].prefix.include,
'MPFR_LIB=%s' %
ld_flags_from_dirs([spec['mpfr'].prefix.lib], ['mpfr'])]
if '+gnutls' in spec:
options += [
'GNUTLS_OPT=-I%s' % spec['gnutls'].prefix.include,
'GNUTLS_LIB=%s' %
ld_flags_from_dirs([spec['gnutls'].prefix.lib], ['gnutls'])]
if '+libunwind' in spec:
libunwind = spec['unwind']
headers = find_headers('libunwind', libunwind.prefix.include)
headers.add_macro('-g')
libs = find_optional_library('libunwind', libunwind.prefix)
# When mfem uses libunwind, it also needs 'libdl'.
libs += LibraryList(find_system_libraries('libdl'))
options += [
'LIBUNWIND_OPT=%s' % headers.cpp_flags,
'LIBUNWIND_LIB=%s' % ld_flags_from_library_list(libs)]
if '+openmp' in spec:
options += [
'OPENMP_OPT=%s' % (xcompiler + self.compiler.openmp_flag)]
if '+cuda' in spec:
options += [
'CUDA_CXX=%s' % join_path(spec['cuda'].prefix, 'bin', 'nvcc'),
'CUDA_ARCH=sm_%s' % cuda_arch]
if '+rocm' in spec:
amdgpu_target = ','.join(spec.variants['amdgpu_target'].value)
options += [
'HIP_CXX=%s' % spec['hip'].hipcc,
'HIP_ARCH=%s' % amdgpu_target]
if '+occa' in spec:
options += ['OCCA_OPT=-I%s' % spec['occa'].prefix.include,
'OCCA_LIB=%s' %
ld_flags_from_dirs([spec['occa'].prefix.lib],
['occa'])]
if '+raja' in spec:
options += ['RAJA_OPT=-I%s' % spec['raja'].prefix.include,
'RAJA_LIB=%s' %
ld_flags_from_dirs([spec['raja'].prefix.lib],
['RAJA'])]
if '+amgx' in spec:
amgx = spec['amgx']
if '+shared' in amgx:
options += ['AMGX_OPT=-I%s' % amgx.prefix.include,
'AMGX_LIB=%s' %
ld_flags_from_library_list(amgx.libs)]
else:
options += ['AMGX_DIR=%s' % amgx.prefix]
if '+libceed' in spec:
options += ['CEED_OPT=-I%s' % spec['libceed'].prefix.include,
'CEED_LIB=%s' %
ld_flags_from_dirs([spec['libceed'].prefix.lib],
['ceed'])]
if '+umpire' in spec:
options += ['UMPIRE_OPT=-I%s' % spec['umpire'].prefix.include,
'UMPIRE_LIB=%s' %
ld_flags_from_library_list(spec['umpire'].libs)]
timer_ids = {'std': '0', 'posix': '2', 'mac': '4', 'mpi': '6'}
timer = spec.variants['timer'].value
if timer != 'auto':
options += ['MFEM_TIMER_TYPE=%s' % timer_ids[timer]]
if '+conduit' in spec:
conduit = spec['conduit']
headers = HeaderList(find(conduit.prefix.include, 'conduit.hpp',
recursive=True))
conduit_libs = ['libconduit', 'libconduit_relay',
'libconduit_blueprint']
libs = find_libraries(conduit_libs, conduit.prefix.lib,
shared=('+shared' in conduit))
libs += LibraryList(find_system_libraries('libdl'))
if '+hdf5' in conduit:
hdf5 = conduit['hdf5']
headers += find_headers('hdf5', hdf5.prefix.include)
libs += hdf5.libs
##################
# cyrush note:
##################
# spack's HeaderList is applying too much magic, undermining us:
#
# It applies a regex to strip back to the last "include" dir
# in the path. In our case we need to pass the following
# as part of the CONDUIT_OPT flags:
#
# -I<install_path>/include/conduit
#
# I tried several ways to present this path to the HeaderList,
# but the regex always kills the trailing conduit dir
# breaking build.
#
# To resolve the issue, we simply join our own string with
# the headers results (which are important b/c they handle
# hdf5 paths when enabled).
##################
# construct proper include path
conduit_include_path = conduit.prefix.include.conduit
# add this path to the found flags
conduit_opt_flags = "-I{0} {1}".format(conduit_include_path,
headers.cpp_flags)
options += [
'CONDUIT_OPT=%s' % conduit_opt_flags,
'CONDUIT_LIB=%s' % ld_flags_from_library_list(libs)]
make('config', *options, parallel=False)
make('info', parallel=False)
def build(self, spec, prefix):
make('lib')
@run_after('build')
def check_or_test(self):
# Running 'make check' or 'make test' may fail if MFEM_MPIEXEC or
# MFEM_MPIEXEC_NP are not set appropriately.
if not self.run_tests:
# check we can build ex1 (~mpi) or ex1p (+mpi).
make('-C', 'examples', 'ex1p' if ('+mpi' in self.spec) else 'ex1',
parallel=False)
# make('check', parallel=False)
else:
make('all')
make('test', parallel=False)
def install(self, spec, prefix):
make('install', parallel=False)
# TODO: The way the examples and miniapps are being installed is not
# perfect. For example, the makefiles do not work.
install_em = ('+examples' in spec) or ('+miniapps' in spec)
if install_em and ('+shared' in spec):
make('examples/clean', 'miniapps/clean')
# This is a hack to get the examples and miniapps to link with the
# installed shared mfem library:
with working_dir('config'):
os.rename('config.mk', 'config.mk.orig')
copy(str(self.config_mk), 'config.mk')
shutil.copystat('config.mk.orig', 'config.mk')
prefix_share = join_path(prefix, 'share', 'mfem')
if '+examples' in spec:
make('examples')
install_tree('examples', join_path(prefix_share, 'examples'))
if '+miniapps' in spec:
make('miniapps')
install_tree('miniapps', join_path(prefix_share, 'miniapps'))
if install_em:
install_tree('data', join_path(prefix_share, 'data'))
examples_src_dir = 'examples'
examples_data_dir = 'data'
@run_after('install')
def cache_test_sources(self):
"""Copy the example source files after the package is installed to an
install test subdirectory for use during `spack test run`."""
self.cache_extra_test_sources([self.examples_src_dir,
self.examples_data_dir])
def test(self):
test_dir = join_path(
self.test_suite.current_test_cache_dir,
self.examples_src_dir
)
# MFEM has many examples to serve as a suitable smoke check. ex10
# was chosen arbitrarily among the examples that work both with
# MPI and without it
test_exe = 'ex10p' if ('+mpi' in self.spec) else 'ex10'
self.run_test(
'make',
[
'CONFIG_MK={0}/share/mfem/config.mk'.format(self.prefix),
test_exe,
'parallel=False'
],
purpose='test: building {0}'.format(test_exe),
skip_missing=False,
work_dir=test_dir,
)
self.run_test(
'./{0}'.format(test_exe),
[
'--mesh',
'../{0}/beam-quad.mesh'.format(self.examples_data_dir)
],
[],
installed=False,
purpose='test: running {0}'.format(test_exe),
skip_missing=False,
work_dir=test_dir,
)
# this patch is only needed for mfem 4.1, where a few
# released files include byte order marks
@when('@4.1.0')
def patch(self):
# Remove the byte order mark since it messes with some compilers
files_with_bom = [
'fem/gslib.hpp', 'fem/gslib.cpp', 'linalg/hiop.hpp',
'miniapps/gslib/field-diff.cpp', 'miniapps/gslib/findpts.cpp',
'miniapps/gslib/pfindpts.cpp']
bom = '\xef\xbb\xbf' if sys.version_info < (3,) else u'\ufeff'
for f in files_with_bom:
filter_file(bom, '', f)
@property
def suitesparse_components(self):
"""Return the SuiteSparse components needed by MFEM."""
ss_comps = 'umfpack,cholmod,colamd,amd,camd,ccolamd,suitesparseconfig'
if self.spec.satisfies('@3.2:'):
ss_comps = 'klu,btf,' + ss_comps
return ss_comps
@property
def sundials_components(self):
"""Return the SUNDIALS components needed by MFEM."""
spec = self.spec
sun_comps = 'arkode,cvodes,nvecserial,kinsol'
if '+mpi' in spec:
if spec.satisfies('@4.2:'):
sun_comps += ',nvecparallel,nvecmpiplusx'
else:
sun_comps += ',nvecparhyp,nvecparallel'
if '+cuda' in spec and '+cuda' in spec['sundials']:
sun_comps += ',nveccuda'
return sun_comps
@property
def headers(self):
"""Export the main mfem header, mfem.hpp.
"""
hdrs = HeaderList(find(self.prefix.include, 'mfem.hpp',
recursive=False))
return hdrs or None
@property
def libs(self):
"""Export the mfem library file.
"""
libs = find_libraries('libmfem', root=self.prefix.lib,
shared=('+shared' in self.spec), recursive=False)
return libs or None
@property
def config_mk(self):
"""Export the location of the config.mk file.
This property can be accessed using spec['mfem'].package.config_mk
"""
dirs = [self.prefix, self.prefix.share.mfem]
for d in dirs:
f = join_path(d, 'config.mk')
if os.access(f, os.R_OK):
return FileList(f)
return FileList(find(self.prefix, 'config.mk', recursive=True))
@property
def test_mk(self):
"""Export the location of the test.mk file.
This property can be accessed using spec['mfem'].package.test_mk.
In version 3.3.2 and newer, the location of test.mk is also defined
inside config.mk, variable MFEM_TEST_MK.
"""
dirs = [self.prefix, self.prefix.share.mfem]
for d in dirs:
f = join_path(d, 'test.mk')
if os.access(f, os.R_OK):
return FileList(f)
return FileList(find(self.prefix, 'test.mk', recursive=True))

View File

@ -0,0 +1,448 @@
# -*- python -*-
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This is an unparser test package.
``py-torch`` was chosen for its complexity and because it has an ``@when`` function
that can be removed statically, as well as several decorated @run_after functions
that should be preserved.
"""
import os
import sys
from spack import *
class PyTorch(PythonPackage, CudaPackage):
"""Tensors and Dynamic neural networks in Python
with strong GPU acceleration."""
homepage = "https://pytorch.org/"
git = "https://github.com/pytorch/pytorch.git"
maintainers = ['adamjstewart']
# Exact set of modules is version- and variant-specific, just attempt to import the
# core libraries to ensure that the package was successfully installed.
import_modules = ['torch', 'torch.autograd', 'torch.nn', 'torch.utils']
version('master', branch='master', submodules=True)
version('1.10.1', tag='v1.10.1', submodules=True)
version('1.10.0', tag='v1.10.0', submodules=True)
version('1.9.1', tag='v1.9.1', submodules=True)
version('1.9.0', tag='v1.9.0', submodules=True)
version('1.8.2', tag='v1.8.2', submodules=True)
version('1.8.1', tag='v1.8.1', submodules=True)
version('1.8.0', tag='v1.8.0', submodules=True)
version('1.7.1', tag='v1.7.1', submodules=True)
version('1.7.0', tag='v1.7.0', submodules=True)
version('1.6.0', tag='v1.6.0', submodules=True)
version('1.5.1', tag='v1.5.1', submodules=True)
version('1.5.0', tag='v1.5.0', submodules=True)
version('1.4.1', tag='v1.4.1', submodules=True)
version('1.4.0', tag='v1.4.0', submodules=True, deprecated=True,
submodules_delete=['third_party/fbgemm'])
version('1.3.1', tag='v1.3.1', submodules=True)
version('1.3.0', tag='v1.3.0', submodules=True)
version('1.2.0', tag='v1.2.0', submodules=True)
version('1.1.0', tag='v1.1.0', submodules=True)
version('1.0.1', tag='v1.0.1', submodules=True)
version('1.0.0', tag='v1.0.0', submodules=True)
version('0.4.1', tag='v0.4.1', submodules=True, deprecated=True,
submodules_delete=['third_party/nervanagpu'])
version('0.4.0', tag='v0.4.0', submodules=True, deprecated=True)
version('0.3.1', tag='v0.3.1', submodules=True, deprecated=True)
is_darwin = sys.platform == 'darwin'
# All options are defined in CMakeLists.txt.
# Some are listed in setup.py, but not all.
variant('caffe2', default=True, description='Build Caffe2')
variant('test', default=False, description='Build C++ test binaries')
variant('cuda', default=not is_darwin, description='Use CUDA')
variant('rocm', default=False, description='Use ROCm')
variant('cudnn', default=not is_darwin, description='Use cuDNN')
variant('fbgemm', default=True, description='Use FBGEMM (quantized 8-bit server operators)')
variant('kineto', default=True, description='Use Kineto profiling library')
variant('magma', default=not is_darwin, description='Use MAGMA')
variant('metal', default=is_darwin, description='Use Metal for Caffe2 iOS build')
variant('nccl', default=not is_darwin, description='Use NCCL')
variant('nnpack', default=True, description='Use NNPACK')
variant('numa', default=not is_darwin, description='Use NUMA')
variant('numpy', default=True, description='Use NumPy')
variant('openmp', default=True, description='Use OpenMP for parallel code')
variant('qnnpack', default=True, description='Use QNNPACK (quantized 8-bit operators)')
variant('valgrind', default=not is_darwin, description='Use Valgrind')
variant('xnnpack', default=True, description='Use XNNPACK')
variant('mkldnn', default=True, description='Use MKLDNN')
variant('distributed', default=not is_darwin, description='Use distributed')
variant('mpi', default=not is_darwin, description='Use MPI for Caffe2')
variant('gloo', default=not is_darwin, description='Use Gloo')
variant('tensorpipe', default=not is_darwin, description='Use TensorPipe')
variant('onnx_ml', default=True, description='Enable traditional ONNX ML API')
variant('breakpad', default=True, description='Enable breakpad crash dump library')
conflicts('+cuda', when='+rocm')
conflicts('+cudnn', when='~cuda')
conflicts('+magma', when='~cuda')
conflicts('+nccl', when='~cuda~rocm')
conflicts('+nccl', when='platform=darwin')
conflicts('+numa', when='platform=darwin', msg='Only available on Linux')
conflicts('+valgrind', when='platform=darwin', msg='Only available on Linux')
conflicts('+mpi', when='~distributed')
conflicts('+gloo', when='~distributed')
conflicts('+tensorpipe', when='~distributed')
conflicts('+kineto', when='@:1.7')
conflicts('+valgrind', when='@:1.7')
conflicts('~caffe2', when='@0.4.0:1.6') # no way to disable caffe2?
conflicts('+caffe2', when='@:0.3.1') # caffe2 did not yet exist?
conflicts('+tensorpipe', when='@:1.5')
conflicts('+xnnpack', when='@:1.4')
conflicts('~onnx_ml', when='@:1.4') # no way to disable ONNX?
conflicts('+rocm', when='@:0.4')
conflicts('+cudnn', when='@:0.4')
conflicts('+fbgemm', when='@:0.4,1.4.0')
conflicts('+qnnpack', when='@:0.4')
conflicts('+mkldnn', when='@:0.4')
conflicts('+breakpad', when='@:1.9') # Option appeared in 1.10.0
conflicts('+breakpad', when='target=ppc64:', msg='Unsupported')
conflicts('+breakpad', when='target=ppc64le:', msg='Unsupported')
conflicts('cuda_arch=none', when='+cuda',
msg='Must specify CUDA compute capabilities of your GPU, see '
'https://developer.nvidia.com/cuda-gpus')
# Required dependencies
depends_on('cmake@3.5:', type='build')
# Use Ninja generator to speed up build times, automatically used if found
depends_on('ninja@1.5:', when='@1.1.0:', type='build')
# See python_min_version in setup.py
depends_on('python@3.6.2:', when='@1.7.1:', type=('build', 'link', 'run'))
depends_on('python@3.6.1:', when='@1.6.0:1.7.0', type=('build', 'link', 'run'))
depends_on('python@3.5:', when='@1.5.0:1.5', type=('build', 'link', 'run'))
depends_on('python@2.7:2.8,3.5:', when='@1.4.0:1.4', type=('build', 'link', 'run'))
depends_on('python@2.7:2.8,3.5:3.7', when='@:1.3', type=('build', 'link', 'run'))
depends_on('py-setuptools', type=('build', 'run'))
depends_on('py-future', when='@1.5:', type=('build', 'run'))
depends_on('py-future', when='@1.1: ^python@:2', type=('build', 'run'))
depends_on('py-pyyaml', type=('build', 'run'))
depends_on('py-typing', when='@0.4: ^python@:3.4', type=('build', 'run'))
depends_on('py-typing-extensions', when='@1.7:', type=('build', 'run'))
depends_on('py-pybind11@2.6.2', when='@1.8.0:', type=('build', 'link', 'run'))
depends_on('py-pybind11@2.3.0', when='@1.1.0:1.7', type=('build', 'link', 'run'))
depends_on('py-pybind11@2.2.4', when='@1.0.0:1.0', type=('build', 'link', 'run'))
depends_on('py-pybind11@2.2.2', when='@0.4.0:0.4', type=('build', 'link', 'run'))
depends_on('py-dataclasses', when='@1.7: ^python@3.6.0:3.6', type=('build', 'run'))
depends_on('py-tqdm', type='run')
depends_on('py-protobuf', when='@0.4:', type=('build', 'run'))
depends_on('protobuf', when='@0.4:')
depends_on('blas')
depends_on('lapack')
depends_on('eigen', when='@0.4:')
# https://github.com/pytorch/pytorch/issues/60329
# depends_on('cpuinfo@2020-12-17', when='@1.8.0:')
# depends_on('cpuinfo@2020-06-11', when='@1.6.0:1.7')
# https://github.com/shibatch/sleef/issues/427
# depends_on('sleef@3.5.1_2020-12-22', when='@1.8.0:')
# https://github.com/pytorch/pytorch/issues/60334
# depends_on('sleef@3.4.0_2019-07-30', when='@1.6.0:1.7')
# https://github.com/Maratyszcza/FP16/issues/18
# depends_on('fp16@2020-05-14', when='@1.6.0:')
depends_on('pthreadpool@2021-04-13', when='@1.9.0:')
depends_on('pthreadpool@2020-10-05', when='@1.8.0:1.8')
depends_on('pthreadpool@2020-06-15', when='@1.6.0:1.7')
depends_on('psimd@2020-05-17', when='@1.6.0:')
depends_on('fxdiv@2020-04-17', when='@1.6.0:')
depends_on('benchmark', when='@1.6:+test')
# Optional dependencies
depends_on('cuda@7.5:', when='+cuda', type=('build', 'link', 'run'))
depends_on('cuda@9:', when='@1.1:+cuda', type=('build', 'link', 'run'))
depends_on('cuda@9.2:', when='@1.6:+cuda', type=('build', 'link', 'run'))
depends_on('cudnn@6.0:7', when='@:1.0+cudnn')
depends_on('cudnn@7.0:7', when='@1.1.0:1.5+cudnn')
depends_on('cudnn@7.0:', when='@1.6.0:+cudnn')
depends_on('magma', when='+magma')
depends_on('nccl', when='+nccl')
depends_on('numactl', when='+numa')
depends_on('py-numpy', when='+numpy', type=('build', 'run'))
depends_on('llvm-openmp', when='%apple-clang +openmp')
depends_on('valgrind', when='+valgrind')
# https://github.com/pytorch/pytorch/issues/60332
# depends_on('xnnpack@2021-02-22', when='@1.8.0:+xnnpack')
# depends_on('xnnpack@2020-03-23', when='@1.6.0:1.7+xnnpack')
depends_on('mpi', when='+mpi')
# https://github.com/pytorch/pytorch/issues/60270
# depends_on('gloo@2021-05-04', when='@1.9.0:+gloo')
# depends_on('gloo@2020-09-18', when='@1.7.0:1.8+gloo')
# depends_on('gloo@2020-03-17', when='@1.6.0:1.6+gloo')
# https://github.com/pytorch/pytorch/issues/60331
# depends_on('onnx@1.8.0_2020-11-03', when='@1.8.0:+onnx_ml')
# depends_on('onnx@1.7.0_2020-05-31', when='@1.6.0:1.7+onnx_ml')
depends_on('mkl', when='+mkldnn')
# Test dependencies
depends_on('py-hypothesis', type='test')
depends_on('py-six', type='test')
depends_on('py-psutil', type='test')
# Fix BLAS being overridden by MKL
# https://github.com/pytorch/pytorch/issues/60328
patch('https://patch-diff.githubusercontent.com/raw/pytorch/pytorch/pull/59220.patch',
sha256='e37afffe45cf7594c22050109942370e49983ad772d12ebccf508377dc9dcfc9',
when='@1.2.0:')
# Fixes build on older systems with glibc <2.12
patch('https://patch-diff.githubusercontent.com/raw/pytorch/pytorch/pull/55063.patch',
sha256='e17eaa42f5d7c18bf0d7c37d7b0910127a01ad53fdce3e226a92893356a70395',
when='@1.1.0:1.8.1')
# Fixes CMake configuration error when XNNPACK is disabled
# https://github.com/pytorch/pytorch/pull/35607
# https://github.com/pytorch/pytorch/pull/37865
patch('xnnpack.patch', when='@1.5.0:1.5')
# Fixes build error when ROCm is enabled for pytorch-1.5 release
patch('rocm.patch', when='@1.5.0:1.5+rocm')
# Fixes fatal error: sleef.h: No such file or directory
# https://github.com/pytorch/pytorch/pull/35359
# https://github.com/pytorch/pytorch/issues/26555
# patch('sleef.patch', when='@1.0.0:1.5')
# Fixes compilation with Clang 9.0.0 and Apple Clang 11.0.3
# https://github.com/pytorch/pytorch/pull/37086
patch('https://github.com/pytorch/pytorch/commit/e921cd222a8fbeabf5a3e74e83e0d8dfb01aa8b5.patch',
sha256='17561b16cd2db22f10c0fe1fdcb428aecb0ac3964ba022a41343a6bb8cba7049',
when='@1.1:1.5')
# Removes duplicate definition of getCusparseErrorString
# https://github.com/pytorch/pytorch/issues/32083
patch('cusparseGetErrorString.patch', when='@0.4.1:1.0^cuda@10.1.243:')
# Fixes 'FindOpenMP.cmake'
# to detect openmp settings used by Fujitsu compiler.
patch('detect_omp_of_fujitsu_compiler.patch', when='%fj')
# Fix compilation of +distributed~tensorpipe
# https://github.com/pytorch/pytorch/issues/68002
patch('https://github.com/pytorch/pytorch/commit/c075f0f633fa0136e68f0a455b5b74d7b500865c.patch',
sha256='e69e41b5c171bfb00d1b5d4ee55dd5e4c8975483230274af4ab461acd37e40b8', when='@1.10.0+distributed~tensorpipe')
# Both build and install run cmake/make/make install
# Only run once to speed up build times
phases = ['install']
@property
def libs(self):
root = join_path(self.prefix, self.spec['python'].package.site_packages_dir,
'torch', 'lib')
return find_libraries('libtorch', root)
@property
def headers(self):
root = join_path(self.prefix, self.spec['python'].package.site_packages_dir,
'torch', 'include')
headers = find_all_headers(root)
headers.directories = [root]
return headers
@when('@1.5.0:')
def patch(self):
# https://github.com/pytorch/pytorch/issues/52208
filter_file('torch_global_deps PROPERTIES LINKER_LANGUAGE C',
'torch_global_deps PROPERTIES LINKER_LANGUAGE CXX',
'caffe2/CMakeLists.txt')
def setup_build_environment(self, env):
"""Set environment variables used to control the build.
PyTorch's ``setup.py`` is a thin wrapper around ``cmake``.
In ``tools/setup_helpers/cmake.py``, you can see that all
environment variables that start with ``BUILD_``, ``USE_``,
or ``CMAKE_``, plus a few more explicitly specified variable
names, are passed directly to the ``cmake`` call. Therefore,
most flags defined in ``CMakeLists.txt`` can be specified as
environment variables.
"""
def enable_or_disable(variant, keyword='USE', var=None, newer=False):
"""Set environment variable to enable or disable support for a
particular variant.
Parameters:
variant (str): the variant to check
keyword (str): the prefix to use for enabling/disabling
var (str): CMake variable to set. Defaults to variant.upper()
newer (bool): newer variants that never used NO_*
"""
if var is None:
var = variant.upper()
# Version 1.1.0 switched from NO_* to USE_* or BUILD_*
# But some newer variants have always used USE_* or BUILD_*
if self.spec.satisfies('@1.1:') or newer:
if '+' + variant in self.spec:
env.set(keyword + '_' + var, 'ON')
else:
env.set(keyword + '_' + var, 'OFF')
else:
if '+' + variant in self.spec:
env.unset('NO_' + var)
else:
env.set('NO_' + var, 'ON')
# Build in parallel to speed up build times
env.set('MAX_JOBS', make_jobs)
# Spack logs have trouble handling colored output
env.set('COLORIZE_OUTPUT', 'OFF')
if self.spec.satisfies('@0.4:'):
enable_or_disable('test', keyword='BUILD')
if self.spec.satisfies('@1.7:'):
enable_or_disable('caffe2', keyword='BUILD')
enable_or_disable('cuda')
if '+cuda' in self.spec:
# cmake/public/cuda.cmake
# cmake/Modules_CUDA_fix/upstream/FindCUDA.cmake
env.unset('CUDA_ROOT')
torch_cuda_arch = ';'.join('{0:.1f}'.format(float(i) / 10.0) for i
in
self.spec.variants['cuda_arch'].value)
env.set('TORCH_CUDA_ARCH_LIST', torch_cuda_arch)
enable_or_disable('rocm')
enable_or_disable('cudnn')
if '+cudnn' in self.spec:
# cmake/Modules_CUDA_fix/FindCUDNN.cmake
env.set('CUDNN_INCLUDE_DIR', self.spec['cudnn'].prefix.include)
env.set('CUDNN_LIBRARY', self.spec['cudnn'].libs[0])
enable_or_disable('fbgemm')
if self.spec.satisfies('@1.8:'):
enable_or_disable('kineto')
enable_or_disable('magma')
enable_or_disable('metal')
if self.spec.satisfies('@1.10:'):
enable_or_disable('breakpad')
enable_or_disable('nccl')
if '+nccl' in self.spec:
env.set('NCCL_LIB_DIR', self.spec['nccl'].libs.directories[0])
env.set('NCCL_INCLUDE_DIR', self.spec['nccl'].prefix.include)
# cmake/External/nnpack.cmake
enable_or_disable('nnpack')
enable_or_disable('numa')
if '+numa' in self.spec:
# cmake/Modules/FindNuma.cmake
env.set('NUMA_ROOT_DIR', self.spec['numactl'].prefix)
# cmake/Modules/FindNumPy.cmake
enable_or_disable('numpy')
# cmake/Modules/FindOpenMP.cmake
enable_or_disable('openmp', newer=True)
enable_or_disable('qnnpack')
if self.spec.satisfies('@1.3:'):
enable_or_disable('qnnpack', var='PYTORCH_QNNPACK')
if self.spec.satisfies('@1.8:'):
enable_or_disable('valgrind')
if self.spec.satisfies('@1.5:'):
enable_or_disable('xnnpack')
enable_or_disable('mkldnn')
enable_or_disable('distributed')
enable_or_disable('mpi')
# cmake/Modules/FindGloo.cmake
enable_or_disable('gloo', newer=True)
if self.spec.satisfies('@1.6:'):
enable_or_disable('tensorpipe')
if '+onnx_ml' in self.spec:
env.set('ONNX_ML', 'ON')
else:
env.set('ONNX_ML', 'OFF')
if not self.spec.satisfies('@master'):
env.set('PYTORCH_BUILD_VERSION', self.version)
env.set('PYTORCH_BUILD_NUMBER', 0)
# BLAS to be used by Caffe2
# Options defined in cmake/Dependencies.cmake and cmake/Modules/FindBLAS.cmake
if self.spec['blas'].name == 'atlas':
env.set('BLAS', 'ATLAS')
env.set('WITH_BLAS', 'atlas')
elif self.spec['blas'].name in ['blis', 'amdblis']:
env.set('BLAS', 'BLIS')
env.set('WITH_BLAS', 'blis')
elif self.spec['blas'].name == 'eigen':
env.set('BLAS', 'Eigen')
elif self.spec['lapack'].name in ['libflame', 'amdlibflame']:
env.set('BLAS', 'FLAME')
env.set('WITH_BLAS', 'FLAME')
elif self.spec['blas'].name in [
'intel-mkl', 'intel-parallel-studio', 'intel-oneapi-mkl']:
env.set('BLAS', 'MKL')
env.set('WITH_BLAS', 'mkl')
elif self.spec['blas'].name == 'openblas':
env.set('BLAS', 'OpenBLAS')
env.set('WITH_BLAS', 'open')
elif self.spec['blas'].name == 'veclibfort':
env.set('BLAS', 'vecLib')
env.set('WITH_BLAS', 'veclib')
else:
env.set('BLAS', 'Generic')
env.set('WITH_BLAS', 'generic')
# Don't use vendored third-party libraries when possible
env.set('BUILD_CUSTOM_PROTOBUF', 'OFF')
env.set('USE_SYSTEM_NCCL', 'ON')
env.set('USE_SYSTEM_EIGEN_INSTALL', 'ON')
if self.spec.satisfies('@0.4:'):
env.set('pybind11_DIR', self.spec['py-pybind11'].prefix)
env.set('pybind11_INCLUDE_DIR',
self.spec['py-pybind11'].prefix.include)
if self.spec.satisfies('@1.10:'):
env.set('USE_SYSTEM_PYBIND11', 'ON')
# https://github.com/pytorch/pytorch/issues/60334
# if self.spec.satisfies('@1.8:'):
# env.set('USE_SYSTEM_SLEEF', 'ON')
if self.spec.satisfies('@1.6:'):
# env.set('USE_SYSTEM_LIBS', 'ON')
# https://github.com/pytorch/pytorch/issues/60329
# env.set('USE_SYSTEM_CPUINFO', 'ON')
# https://github.com/pytorch/pytorch/issues/60270
# env.set('USE_SYSTEM_GLOO', 'ON')
# https://github.com/Maratyszcza/FP16/issues/18
# env.set('USE_SYSTEM_FP16', 'ON')
env.set('USE_SYSTEM_PTHREADPOOL', 'ON')
env.set('USE_SYSTEM_PSIMD', 'ON')
env.set('USE_SYSTEM_FXDIV', 'ON')
env.set('USE_SYSTEM_BENCHMARK', 'ON')
# https://github.com/pytorch/pytorch/issues/60331
# env.set('USE_SYSTEM_ONNX', 'ON')
# https://github.com/pytorch/pytorch/issues/60332
# env.set('USE_SYSTEM_XNNPACK', 'ON')
@run_before('install')
def build_amd(self):
if '+rocm' in self.spec:
python(os.path.join('tools', 'amd_build', 'build_amd.py'))
@run_after('install')
@on_package_attributes(run_tests=True)
def install_test(self):
with working_dir('test'):
python('run_test.py')
# Tests need to be re-added since `phases` was overridden
run_after('install')(
PythonPackage._run_default_install_time_test_callbacks)
run_after('install')(PythonPackage.sanity_check_prefix)

View File

@ -4,6 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import ast
import os
import pytest
import spack.directives
import spack.paths
@ -11,6 +14,8 @@
from spack.spec import Spec
from spack.util.unparse import unparse
datadir = os.path.join(spack.paths.test_path, "data", "unparse")
def test_hash(tmpdir, mock_packages, config):
ph.package_hash("hash-test1@1.2")
@ -152,6 +157,38 @@ def test_remove_directives():
assert name not in unparsed
@pytest.mark.parametrize("package_spec,expected_hash", [
("amdfftw", "nfrk76xyu6wxs4xb4nyichm3om3kb7yp"),
("grads", "rrlmwml3f2frdnqavmro3ias66h5b2ce"),
("llvm", "ngact4ds3xwgsbn5bruxpfs6f4u4juba"),
# has @when("@4.1.0")
("mfem", "65xryd5zxarwzqlh2pojq7ykohpod4xz"),
("mfem@4.0.0", "65xryd5zxarwzqlh2pojq7ykohpod4xz"),
("mfem@4.1.0", "2j655nix3oe57iwvs2mlgx2mresk7czl"),
# has @when("@1.5.0:")
("py-torch", "lnwmqk4wadtlsc2badrt7foid5tl5vaw"),
("py-torch@1.0", "lnwmqk4wadtlsc2badrt7foid5tl5vaw"),
("py-torch@1.6", "5nwndnknxdfs5or5nrl4pecvw46xc5i2"),
])
def test_package_hash_consistency(package_spec, expected_hash):
"""Ensure that that package hash is consistent python version to version.
We assume these tests run across all supported Python versions in CI, and we ensure
consistency with recorded hashes for some well known inputs.
If this fails, then something about the way the python AST works has likely changed.
If Spack is running in a new python version, we might need to modify the unparser to
handle it. If not, then something has become inconsistent about the way we unparse
Python code across versions.
"""
spec = Spec(package_spec)
filename = os.path.join(datadir, "%s.txt" % spec.name)
print(ph.canonical_source(spec, filename))
h = ph.canonical_source_hash(spec, filename)
assert expected_hash == h
many_multimethods = """\
class Pkg:
def foo(self):