Compare commits

...
Author SHA1 Message Date
Bernede 1d7f160b8c Set Petsc arch to _empty_ 2021-01-21 12:25:11 -08:00
Bernede 4882f02d1c Clean up comments 2021-01-21 12:25:11 -08:00
Adrien M. Bernede c008eafb2f Convert to _DIR for cmake 2021-01-21 12:25:11 -08:00
Adrien M. Bernede 1f9c0f6271 Minor fix 2021-01-21 12:25:11 -08:00
Adrien M. Bernede 6e86a1cdb7 Add uberenv temporarily 2021-01-21 12:25:04 -08:00
Adrien M. Bernede 22229e3674 DO NOT FETCH REMOTE UBERENV 2021-01-21 12:22:26 -08:00
Adrien M. Bernede 1a24d3df39 Useful??? 2021-01-21 12:21:22 -08:00
Adrien M. Bernede e10ffc39e0 update mfem-uberenv 2021-01-21 12:21:22 -08:00
Adrien M. Bernede 9461b55c7e Install MFEM with spack in CI 2021-01-21 12:21:16 -08:00
Adrien M. Bernede 15343b874b Use specific uberenv config 2021-01-21 12:19:56 -08:00
26 changed files with 4050 additions and 73 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/config/XSDKDefaults.cmake")
# Enable languages.
enable_language(CXX)
enable_language(CXX C Fortran)
if (MFEM_USE_CUDA)
# MFEM_USE_CUDA requires CMake 3.8 or newer (for direct CUDA support)
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
+71 -71
View File
@@ -45,78 +45,78 @@ then
prefix_opt="--prefix=${prefix}"
fi
tests/gitlab/get_mfem_uberenv.sh || ( echo "Error fetching Uberenv" && exit 1 );
#tests/gitlab/get_mfem_uberenv.sh || ( echo "Error fetching Uberenv" && exit 1 );
python tests/uberenv/uberenv.py --spec="${spec}" "${upstream_opt}" "${prefix_opt}"
python tests/uberenv/uberenv.py --install --spec="${spec}" "${upstream_opt}" "${prefix_opt}"
fi
# Host config file
if [[ -z ${hostconfig} ]]
then
# If no host config file was provided, we assume it was generated.
# This means we are looking of a unique one in project dir.
hostconfigs=( $( ls "${project_dir}/"hc-*.mk ) )
if [[ ${#hostconfigs[@]} == 1 ]]
then
hostconfig_path=${hostconfigs[0]}
echo "Found host config file: ${hostconfig_path}"
elif [[ ${#hostconfigs[@]} == 0 ]]
then
echo "No result for: ${project_dir}/hc-*.mk"
echo "Spack generated host-config not found."
exit 1
else
echo "More than one result for: ${project_dir}/hc-*.mk"
echo "${hostconfigs[@]}"
echo "Please specify one with HOST_CONFIG variable"
exit 1
fi
else
# Using provided host-config file.
hostconfig_path="${project_dir}/host-configs/${hostconfig}"
fi
# Build Directory
if [[ -z ${build_root} ]]
then
build_root=$(pwd)
fi
build_dir="${build_root}/build_${hostconfig//.mk/}"
# Build
if [[ "${option}" != "--deps-only" && "${option}" != "--test-only" ]]
then
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~ Host-config: ${hostconfig_path}"
echo "~ Build Dir: ${build_dir}"
echo "~ Project Dir: ${project_dir}"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~~~ Building MFEM"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
cp ${hostconfig_path} ${project_dir}/config/
make all -j ${threads}
fi
# Test
if [[ "${option}" != "--build-only" ]]
then
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~~~ Testing MFEM"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
return_code=0
make test 2>&1 | tee tests_output.txt || return_code=${?}
if grep -q "All tests passed." ./tests_output.txt
then
echo "SUCCESS: No error during tests" && exit 0
else
echo "ERROR: failure(s) while running MFEM tests" && exit 1
fi
fi
## Host config file
#if [[ -z ${hostconfig} ]]
#then
# # If no host config file was provided, we assume it was generated.
# # This means we are looking of a unique one in project dir.
# hostconfigs=( $( ls "${project_dir}/"hc-*.mk ) )
# if [[ ${#hostconfigs[@]} == 1 ]]
# then
# hostconfig_path=${hostconfigs[0]}
# echo "Found host config file: ${hostconfig_path}"
# elif [[ ${#hostconfigs[@]} == 0 ]]
# then
# echo "No result for: ${project_dir}/hc-*.mk"
# echo "Spack generated host-config not found."
# exit 1
# else
# echo "More than one result for: ${project_dir}/hc-*.mk"
# echo "${hostconfigs[@]}"
# echo "Please specify one with HOST_CONFIG variable"
# exit 1
# fi
#else
# # Using provided host-config file.
# hostconfig_path="${project_dir}/host-configs/${hostconfig}"
#fi
#
## Build Directory
#if [[ -z ${build_root} ]]
#then
# build_root=$(pwd)
#fi
#
#build_dir="${build_root}/build_${hostconfig//.mk/}"
#
## Build
#if [[ "${option}" != "--deps-only" && "${option}" != "--test-only" ]]
#then
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
# echo "~ Host-config: ${hostconfig_path}"
# echo "~ Build Dir: ${build_dir}"
# echo "~ Project Dir: ${project_dir}"
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
# echo "~~~~~ Building MFEM"
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#
# cp ${hostconfig_path} ${project_dir}/config/
#
# make all -j ${threads}
#fi
#
## Test
#if [[ "${option}" != "--build-only" ]]
#then
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
# echo "~~~~~ Testing MFEM"
# echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#
# return_code=0
# make test 2>&1 | tee tests_output.txt || return_code=${?}
#
# if grep -q "All tests passed." ./tests_output.txt
# then
# echo "SUCCESS: No error during tests" && exit 0
# else
# echo "ERROR: failure(s) while running MFEM tests" && exit 1
# fi
#fi
+1 -1
View File
@@ -4,7 +4,7 @@ set -o errexit
set -o nounset
uberenv_url="https://github.com/mfem/mfem-uberenv.git"
uberenv_ref="c9f95ab4d51c283a5e18d8f850a52935a402f679"
uberenv_ref="1012c077d22161d96e1da3ae70dc5a5e872de4e6"
[[ ! -d scripts/uberenv ]] && git clone ${uberenv_url} tests/uberenv
+19
View File
@@ -0,0 +1,19 @@
# uberenv
Automates using Spack (https://www.spack.io/) to build and deploy software.
Uberenv is a short python script that helps automate using Spack to build
third-party dependencies for development and to deploy Spack packages.
Uberenv was released as part of the Conduit (https://github.com/LLNL/conduit/). It is included in-source in several projects, this repo is used to hold the latest reference version.
For more details, see Uberenv's documention:
https://uberenv.readthedocs.io
You can also find details about how it is used in Conduit's documentation:
https://llnl-conduit.readthedocs.io/en/latest/building.html#building-conduit-and-third-party-dependencies
Conduit's source repo also serves as an example for uberenv and spack configuration files, etc:
https://github.com/LLNL/conduit/tree/master/scripts/uberenv
@@ -0,0 +1,71 @@
diff --git a/examples/petsc/rc_ex3p b/examples/petsc/rc_ex3p
index 2cbe07ef2..c585d9b52 100644
--- a/examples/petsc/rc_ex3p
+++ b/examples/petsc/rc_ex3p
@@ -6,4 +6,4 @@
# it needs PETSc configured with MUMPS
-solver_pc_type cholesky
--solver_pc_factor_mat_solver_package mumps
+-solver_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex3p_bddc b/examples/petsc/rc_ex3p_bddc
index ea887bb29..2e1eba0d5 100644
--- a/examples/petsc/rc_ex3p_bddc
+++ b/examples/petsc/rc_ex3p_bddc
@@ -16,7 +16,7 @@
#-pc_bddc_adaptive_threshold 10
# Customization of the local solvers
-#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
-#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
+#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
+#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
#-pc_bddc_coarse_pc_type cholesky
-#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
+#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex4p b/examples/petsc/rc_ex4p
index f734f35fe..64fbe9427 100644
--- a/examples/petsc/rc_ex4p
+++ b/examples/petsc/rc_ex4p
@@ -2,4 +2,4 @@
# it needs PETSc configured with MUMPS
-solver_pc_type cholesky
--solver_pc_factor_mat_solver_package mumps
+-solver_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex4p_bddc b/examples/petsc/rc_ex4p_bddc
index 9507ad431..e8ef99db7 100644
--- a/examples/petsc/rc_ex4p_bddc
+++ b/examples/petsc/rc_ex4p_bddc
@@ -13,7 +13,7 @@
#-pc_bddc_adaptive_threshold 10
# Customization of the local solvers
-#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
-#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
+#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
+#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
#-pc_bddc_coarse_pc_type cholesky
-#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
+#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex5p_bddc b/examples/petsc/rc_ex5p_bddc
index b243c53c8..a4bc899c3 100644
--- a/examples/petsc/rc_ex5p_bddc
+++ b/examples/petsc/rc_ex5p_bddc
@@ -28,13 +28,13 @@
# local solvers (needs PETSc compiled with support for SuiteSparse)
# default solvers will fail
-prec_pc_bddc_neumann_pc_type lu
--prec_pc_bddc_neumann_pc_factor_mat_solver_package umfpack
+-prec_pc_bddc_neumann_pc_factor_mat_solver_type umfpack
-prec_pc_bddc_dirichlet_pc_type lu
--prec_pc_bddc_dirichlet_pc_factor_mat_solver_package umfpack
+-prec_pc_bddc_dirichlet_pc_factor_mat_solver_type umfpack
# coarse solver (needs PETSc compiled with support for MUMPS)
# default solver may fail
--prec_pc_bddc_coarse_pc_factor_mat_solver_package mumps
+-prec_pc_bddc_coarse_pc_factor_mat_solver_type mumps
-prec_pc_bddc_coarse_pc_type cholesky
# deluxe scaling (needs PETSc compiled with support for MUMPS)
@@ -0,0 +1,36 @@
diff --git a/config/test.mk b/config/test.mk
index 4821b084d..62479fc63 100644
--- a/config/test.mk
+++ b/config/test.mk
@@ -14,11 +14,13 @@
# Colors used below:
# green '\033[0;32m'
# red '\033[0;31m'
+# yellow '\033[0;33m'
# no color '\033[0m'
COLOR_PRINT = if [ -t 1 ]; then \
printf $(1)$(2)'\033[0m'$(3); else printf $(2)$(3); fi
PRINT_OK = $(call COLOR_PRINT,'\033[0;32m',OK," ($$1 $$2)\n")
PRINT_FAILED = $(call COLOR_PRINT,'\033[0;31m',FAILED," ($$1 $$2)\n")
+PRINT_SKIP = $(call COLOR_PRINT,'\033[0;33m',SKIP,"\n")
# Timing support
define TIMECMD_detect
diff --git a/examples/pumi/makefile b/examples/pumi/makefile
index 2f98eeca7..5ff652aca 100644
--- a/examples/pumi/makefile
+++ b/examples/pumi/makefile
@@ -51,6 +51,13 @@ endif
MFEM_TESTS = EXAMPLES
include $(MFEM_TEST_MK)
+ifneq (,$(filter test%,$(MAKECMDGOALS)))
+ ifeq (,$(wildcard ../../data/pumi))
+ $(info PUMI data directory not found. The PUMI tests will be SKIPPED.)
+ mfem-test = printf " $(3) [$(2) $(1) ... ]: "; $(PRINT_SKIP)
+ endif
+endif
+
# Testing: Parallel vs. serial runs
RUN_MPI_NP = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP)
RUN_MPI = $(RUN_MPI_NP) $(MFEM_MPI_NP)
@@ -0,0 +1,27 @@
From e2147e51e2bff8907207036557bb9f45d45baaf8 Mon Sep 17 00:00:00 2001
From: Geoffrey M Oxberry <goxberry@gmail.com>
Date: Sun, 25 Aug 2019 00:30:15 -0700
Subject: [PATCH] makefile: add missing parenthesis to conditional
This commit adds a missing parenthesis to a conditional in the MFEM
makefile that checks if PREFIX is set when MFEM_USE_OCCA equals YES.
---
makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/makefile b/makefile
index 98a29f3c9..22a9b5bac 100644
--- a/makefile
+++ b/makefile
@@ -346,7 +346,7 @@ ifneq (,$(filter install,$(MAKECMDGOALS)))
@MFEM_EXT_LIBS@
MFEM_LIB_FILE = @MFEM_LIB_DIR@/libmfem.$(if $(shared),$(SO_VER),a)
ifeq ($(MFEM_USE_OCCA),YES)
- ifneq ($(MFEM_INSTALL_DIR),$(abspath $(PREFIX))
+ ifneq ($(MFEM_INSTALL_DIR),$(abspath $(PREFIX)))
$(error OCCA is enabled: PREFIX must be set during configuration!)
endif
endif
--
2.23.0
@@ -0,0 +1,24 @@
diff --git a/general/mem_manager.cpp b/general/mem_manager.cpp
index ff4a03465..748f6e673 100644
--- a/general/mem_manager.cpp
+++ b/general/mem_manager.cpp
@@ -482,7 +482,8 @@ public:
HostMemorySpace(),
name(mm.GetUmpireAllocatorHostName()),
rm(umpire::ResourceManager::getInstance()),
- h_allocator(rm.isAllocator(name)? rm.getAllocator(name):
+ h_allocator((!std::strcmp(name, "HOST") || rm.isAllocator(name)) ?
+ rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("HOST"))),
strat(h_allocator.getAllocationStrategy()) { }
@@ -506,7 +507,8 @@ public:
DeviceMemorySpace(),
name(mm.GetUmpireAllocatorDeviceName()),
rm(umpire::ResourceManager::getInstance()),
- d_allocator(rm.isAllocator(name)? rm.getAllocator(name):
+ d_allocator((!std::strcmp(name, "DEVICE") || rm.isAllocator(name)) ?
+ rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("DEVICE"))) { }
void Alloc(Memory &base) { base.d_ptr = d_allocator.allocate(base.bytes); }
@@ -0,0 +1,10 @@
--- mfem/miniapps/performance/makefile 2017-06-07 13:51:29.366596901 -0700
+++ mfem/miniapps/performance/makefile.new 2017-06-07 13:51:57.087104178 -0700
@@ -26,7 +26,6 @@
# Compiler specific optimizations.
# For best performance, GCC 5 (or newer) is recommended.
ifneq (,$(findstring $(MFEM_CXX),g++ mpicxx))
- MFEM_CXXFLAGS += -march=native
# MFEM_CXXFLAGS += -std=c++03
MFEM_CXXFLAGS += -std=c++11
MFEM_CXXFLAGS += -pedantic -Wall
@@ -0,0 +1,881 @@
# Copyright 2013-2020 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)
from spack import *
import socket
import os
import shutil
from os import environ as env
from os.path import join as pjoin
#TODO (bernede1@llnl.gov):
# - no mesquite dep
# - no direct parmetis
# - no mumps
# - no direct scotch
# - no direct scalapack
def cmake_cache_entry(name, value, comment=""):
"""Generate a string for a cmake cache variable"""
return 'set(%s "%s" CACHE PATH "%s")\n\n' % (name,value,comment)
def cmake_cache_string(name, string, comment=""):
"""Generate a string for a cmake cache variable"""
return 'set(%s "%s" CACHE STRING "%s")\n\n' % (name,string,comment)
def cmake_cache_option(name, boolean_value, comment=""):
"""Generate a string for a cmake configuration option"""
value = "ON" if boolean_value else "OFF"
return 'set(%s %s CACHE BOOL "%s")\n\n' % (name,value,comment)
def get_spec_path(spec, package_name, path_replacements = {}, use_bin = False) :
"""Extracts the prefix path for the given spack package
path_replacements is a dictionary with string replacements for the path.
"""
if not use_bin:
path = spec[package_name].prefix
else:
path = spec[package_name].prefix.bin
path = os.path.realpath(path)
for key in path_replacements:
path = path.replace(key, path_replacements[key])
return path
def path_replace(path, path_replacements):
"""Replaces path key/value pairs from path_replacements in path"""
for key in path_replacements:
path = path.replace(key,path_replacements[key])
return path
class MfemCmake(CMakePackage, CudaPackage):
"""Free, lightweight, scalable C++ library for finite element methods."""
tags = ['FEM', 'finite elements', 'high-order', 'AMR', 'HPC']
homepage = 'http://www.mfem.org'
git = 'https://github.com/mfem/mfem.git'
maintainers = ['v-dobrev', 'tzanio', 'acfisher',
'goxberry', 'markcmiller86']
# 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:
# http://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.2.0',
'4352a225b55948d2e73a5ee88cece0e88bdbe7ba6726a23d68b2736d3221a86d',
url='https://bit.ly/mfem-4-2', extension='tar.gz',
preferred=True)
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')
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('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: HIP, SIMD, Ginkgo, SLEPc, 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.99.99+openmp')
conflicts('+cuda', when='@:3.99.99')
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.99.99')
conflicts('+gnutls', when='@:3.1')
conflicts('+zlib', when='@:3.2')
conflicts('+mpfr', when='@:3.2')
conflicts('+petsc', when='@:3.2')
conflicts('+sundials', when='@:3.2')
conflicts('+pumi', when='@:3.3.2')
conflicts('+gslib', when='@:4.0.99')
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.99.99')
conflicts('+raja', when='mfem@:3.99.99')
conflicts('+libceed', when='mfem@:4.0.99')
conflicts('+umpire', when='mfem@:4.0.99')
conflicts('+amgx', when='mfem@:4.1.99')
conflicts('+amgx', when='~cuda')
conflicts('+superlu-dist', when='~mpi')
conflicts('+strumpack', when='~mpi')
conflicts('+petsc', when='~mpi')
conflicts('+pumi', when='~mpi')
conflicts('timer=mpi', when='~mpi')
depends_on('mpi', when='+mpi')
depends_on('hypre@2.10.0:2.13.99', when='@:3.3.99+mpi')
depends_on('hypre', when='@3.4:+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')
depends_on('sundials@5.4.0:+cuda', when='@4.2.0:+sundials+cuda')
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')
# 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')
# 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.99 ^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.99 ^hypre@2.16.0:')
conflicts('+strumpack ^strumpack+cuda', when='~cuda')
depends_on('occa@1.0.8:', when='@:4.1.99+occa')
depends_on('occa@1.1.0:', when='@4.2.0:+occa')
depends_on('occa+cuda', when='+occa+cuda')
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')
depends_on('raja+cuda', when='+raja+cuda')
depends_on('libceed@0.6:', when='@:4.1.99+libceed')
depends_on('libceed@0.7:', when='@4.2.0:+libceed')
depends_on('libceed+cuda', when='+libceed+cuda')
depends_on('umpire@2.0.0:', when='+umpire')
depends_on('umpire+cuda', when='+umpire+cuda')
depends_on('amgx', when='+amgx')
# MPI is enabled by default
depends_on('amgx~mpi', when='+amgx~mpi')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('amgx cuda_arch={0}'.format(sm_),
when='+amgx cuda_arch=sm_{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 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')
# OLD phases = ['configure', 'build', 'install']
phases = ['hostconfig', 'cmake', 'build', 'install']
def setup_build_environment(self, env):
env.unset('MFEM_DIR')
env.unset('MFEM_BUILD_DIR')
def _get_sys_type(self, spec):
sys_type = str(spec.architecture)
# if on llnl systems, we can use the SYS_TYPE
if "SYS_TYPE" in env:
sys_type = env["SYS_TYPE"]
return sys_type
def _get_host_config_path(self, spec):
host_config_path = "hc-%s-%s-%s.cmake" % (socket.gethostname().rstrip('1234567890'),
self._get_sys_type(spec),
spec.format('{name}-{version}-{compiler}-{hash:8}'))
dest_dir = self.stage.source_path
host_config_path = os.path.abspath(pjoin(dest_dir, host_config_path))
return host_config_path
#
# 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 hostconfig(self, spec, prefix):
def on_off(varstr):
return True if varstr in spec else False
# 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
# 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([])
metis5_str = False
if ('+metis' in spec) and spec['metis'].satisfies('@5:'):
metis5_str = True
zlib_var = 'MFEM_USE_ZLIB' if (spec.satisfies('@4.1.0:')) else \
'MFEM_USE_GZSTREAM'
#######################
# Compiler Info
#######################
# By directly fetching the names of the actual compilers we appear
# to doing something evil here, but this is necessary to create a
# 'host config' file that works outside of the spack install env.
c_compiler = env["SPACK_CC"]
cpp_compiler = env["SPACK_CXX"]
sys_type = spec.architecture
# if on llnl systems, we can use the SYS_TYPE
if "SYS_TYPE" in env:
sys_type = env["SYS_TYPE"]
##############################################
# Find and record what CMake is used
##############################################
cmake_exe = spec['cmake'].command.path
cmake_exe = os.path.realpath(cmake_exe)
host_config_path = self._get_host_config_path(spec)
cfg = open(host_config_path, "w")
cfg.write("####################################################################\n")
cfg.write("# Generated host-config - Edit at own risk!\n")
cfg.write("####################################################################\n")
cfg.write("# Copyright (c) 2019-2020, Lawrence Livermore National Security, LLC and\n")
cfg.write("# other Serac Project Developers. See the top-level LICENSE file for\n")
cfg.write("# details.\n")
cfg.write("#\n")
cfg.write("# SPDX-License-Identifier: (BSD-3-Clause) \n")
cfg.write("####################################################################\n\n")
cfg.write("#---------------------------------------\n")
cfg.write("# SYS_TYPE: {0}\n".format(sys_type))
cfg.write("# Compiler Spec: {0}\n".format(spec.compiler))
cfg.write("# CMake executable path: %s\n" % cmake_exe)
cfg.write("#---------------------------------------\n\n")
#######################
# Compiler Settings
#######################
cfg.write("#---------------------------------------\n")
cfg.write("# Compilers\n")
cfg.write("#---------------------------------------\n")
if '+mpi' in spec:
cfg.write(cmake_cache_entry("CMAKE_C_COMPILER", spec['mpi'].mpicc))
cfg.write(cmake_cache_entry("CMAKE_CXX_COMPILER", spec['mpi'].mpicxx))
else:
cfg.write(cmake_cache_entry("CMAKE_C_COMPILER", c_compiler))
cfg.write(cmake_cache_entry("CMAKE_CXX_COMPILER", cpp_compiler))
cflags = ' '.join(spec.compiler_flags['cflags'])
cxxflags = ' '.join(spec.compiler_flags['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 = ' '.join([cxxflags,'-g'])
if not opt_flag_found:
cxxflags = ' '.join([cxxflags,'-O0'])
else:
if not opt_flag_found:
cxxflags = ' '.join([cxxflags,'-O2'])
if self.spec.satisfies('@4.0.0:'):
cxxflags = ' '.join([cxxflags,self.compiler.cxx11_flag])
if cflags:
cfg.write(cmake_cache_entry("CMAKE_C_FLAGS", cflags))
if cxxflags:
cfg.write(cmake_cache_entry("CMAKE_CXX_FLAGS", cxxflags))
#######################
# CUDA
#######################
if "+cuda" in spec:
cfg.write("#------------------{0}\n".format("-" * 60))
cfg.write("# Cuda\n")
cfg.write("#------------------{0}\n\n".format("-" * 60))
cfg.write(cmake_cache_option("MFEM_USE_CUDA", True))
cudatoolkitdir = spec['cuda'].prefix
cfg.write(cmake_cache_entry("CUDA_TOOLKIT_ROOT_DIR",
cudatoolkitdir))
cudacompiler = "${CUDA_TOOLKIT_ROOT_DIR}/bin/nvcc"
cfg.write(cmake_cache_entry("CMAKE_CUDA_COMPILER",
cudacompiler))
if spec.satisfies('cuda_arch=none'):
cfg.write("# No cuda_arch specified in Spack spec, this is likely to fail\n\n")
else:
cuda_arch = spec.variants['cuda_arch'].value
flag = '-arch sm_{0}'.format(cuda_arch[0])
# CXX flags will be propagated to the host compiler
cuda_flags = ' '.join([flag, cxxflags])
cfg.write(cmake_cache_string("CMAKE_CUDA_FLAGS", cuda_flags))
cfg.write(cmake_cache_string("CMAKE_CUDA_ARCHITECTURES", ' '.join(cuda_arch)))
else:
cfg.write(cmake_cache_option("MFEM_USE_CUDA", False))
xcompiler = ''
xlinker = '-Wl,'
#if '+cuda' in spec:
# xcompiler = '-Xcompiler='
# xlinker = '-Xlinker='
#cxxflags = [(xcompiler + flag) for flag in cxxflags]
#if '+cuda' in spec:
# cxxflags += [
# '-x=cu --expt-extended-lambda -arch=%s' % cuda_arch,
# '-ccbin %s' % (spec['mpi'].mpicxx if '+mpi' in spec
# else env['CXX'])]
#######################
# MPI
#######################
# 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'
cfg.write("#---------------------------------------\n")
cfg.write("# MPI\n")
cfg.write("#---------------------------------------\n")
if '+mpi' in spec:
cfg.write(cmake_cache_option("MFEM_USE_MPI", True))
# cfg.write(cmake_cache_entry("MPI_C_COMPILER", spec['mpi'].mpicc))
# cfg.write(cmake_cache_entry("MPI_CXX_COMPILER",
# spec['mpi'].mpicxx))
# if os.path.isfile(mfem_mpiexec):
# # starting with cmake 3.10, FindMPI expects MPIEXEC_EXECUTABLE
# # vs the older versions which expect MPIEXEC
# if self.spec["cmake"].satisfies('@3.10:'):
# cfg.write(cmake_cache_string("MPIEXEC_EXECUTABLE", mfem_mpiexec))
# else:
# cfg.write(cmake_cache_string("MPIEXEC", mfem_mpiexec))
#else:
# cfg.write(cmake_cache_option("MFEM_USE_MPI", False))
cfg.write(cmake_cache_entry("PREFIX", prefix)),
cfg.write(cmake_cache_option("MFEM_USE_MEMALLOC", True))
cfg.write(cmake_cache_option("MFEM_DEBUG", on_off('+debug')))
# NOTE: env['CXX'] is the spack c++ compiler wrapper. The real
# compiler is defined by env['SPACK_CXX'].
cfg.write(cmake_cache_string("CXX", env['SPACK_CXX'])),
cfg.write(cmake_cache_option("MFEM_USE_LIBUNWIND", on_off('+libunwind')))
cfg.write(cmake_cache_option(zlib_var, on_off('+zlib')))
cfg.write(cmake_cache_option("MFEM_USE_METIS", on_off('+metis')))
cfg.write(cmake_cache_option("MFEM_USE_METIS_5", metis5_str))
cfg.write(cmake_cache_option("MFEM_THREAD_SAFE", on_off('+threadsafe')))
cfg.write(cmake_cache_option("MFEM_USE_LAPACK", on_off('+lapack')))
cfg.write(cmake_cache_option("MFEM_USE_SUPERLU", on_off('+superlu-dist')))
cfg.write(cmake_cache_option("MFEM_USE_STRUMPACK", on_off('+strumpack')))
cfg.write(cmake_cache_option("MFEM_USE_SUITESPARSE", on_off('+suite-sparse')))
cfg.write(cmake_cache_option("MFEM_USE_SUNDIALS", on_off('+sundials')))
cfg.write(cmake_cache_option("MFEM_USE_PETSC", on_off('+petsc')))
cfg.write(cmake_cache_option("MFEM_USE_PUMI", on_off('+pumi')))
cfg.write(cmake_cache_option("MFEM_USE_GSLIB", on_off('+gslib')))
cfg.write(cmake_cache_option("MFEM_USE_NETCDF", on_off('+netcdf')))
cfg.write(cmake_cache_option("MFEM_USE_MPFR", on_off('+mpfr')))
cfg.write(cmake_cache_option("MFEM_USE_GNUTLS", on_off('+gnutls')))
cfg.write(cmake_cache_option("MFEM_USE_OPENMP", on_off('+openmp')))
cfg.write(cmake_cache_option("MFEM_USE_CONDUIT", on_off('+conduit')))
cfg.write(cmake_cache_option("MFEM_USE_OCCA", on_off('+occa')))
cfg.write(cmake_cache_option("MFEM_USE_RAJA", on_off('+raja')))
cfg.write(cmake_cache_option("MFEM_USE_AMGX", on_off('+amgx')))
cfg.write(cmake_cache_option("MFEM_USE_CEED", on_off('+libceed')))
cfg.write(cmake_cache_option("MFEM_USE_UMPIRE", on_off('+umpire')))
if '~static' in spec:
cfg.write(cmake_cache_option("STATIC", False))
if '+shared' in spec:
cfg.write(cmake_cache_option("SHARED", True))
cfg.write(cmake_cache_string("PICFLAG", self.compiler.cxx_pic_flag))
if '+mpi' in spec:
hypre_dir = get_spec_path(spec, "hypre")
cfg.write(cmake_cache_entry("HYPRE_DIR", hypre_dir))
if '+metis' in spec:
metis_dir = get_spec_path(spec, "metis")
cfg.write(cmake_cache_entry("METIS_DIR", metis_dir))
if '+lapack' in spec:
lapack = spec['lapack'].libs
lapack_inc = spec['lapack'].prefix.includes
lapack_lib = ld_flags_from_library_list(lapack)
cfg.write(cmake_cache_string("LAPACK_LIBRARIES",lapack_lib))
cfg.write(cmake_cache_string("LAPACK_INCLUDE_DIRS",lapack_inc))
blas = spec['blas'].libs
blas_inc = spec['blas'].prefix.includes
blas_lib = ld_flags_from_library_list(blas)
cfg.write(cmake_cache_string("BLAS_LIBRARIES",blas_inc))
cfg.write(cmake_cache_string("BLAS_INCLUDE_DIRS",blas_inc))
if '+superlu-dist' in spec:
superludist_dir = get_spec_path(spec, "superlu-dist", path_replacements)
cfg.write(cmake_cache_entry("SUPERLUDIST_DIR", superludist_dir))
#TODO (bernede1@llnl.gov): what about SUPERLUDIST_REQUIRED_PACKAGES
# see MFEM config/defaults.cmake
if '+strumpack' in spec:
strumpack_dir = get_spec_path(spec, "strumpack", path_replacements)
cfg.write(cmake_cache_entry("STRUMPACK_DIR", strumpack_dir))
#TODO (bernede1@llnl.gov): what about STRUMPACK_REQUIRED_PACKAGES
# see MFEM config/defaults.cmake
if '+suite-sparse' in spec:
suitesparse_dir = get_spec_path(spec, "suitesparse")
cfg.write(cmake_cache_entry("SUITESPARSE_DIR", suitesparse_dir))
if '+sundials' in spec:
sundials_dir = get_spec_path(spec, "sundials")
cfg.write(cmake_cache_entry("SUNDIALS_DIR", sundials_dir))
if '+petsc' in spec:
petsc_dir = get_spec_path(spec, "petsc")
cfg.write(cmake_cache_entry("PETSC_DIR", petsc_dir))
cfg.write(cmake_cache_entry("PETSC_ARCH", ""))
#TODO (bernede1@llnl.gov): what about PETSC_REQUIRED_PACKAGES
# see MFEM config/defaults.cmake
#petsc = spec['petsc']
#if '+shared' in petsc:
# petsc_opt = petsc.headers.cpp_flags
# petsc_lib = ld_flags_from_library_list(petsc.libs)
# cfg.write(cmake_cache_string("PETSC_OPT", petsc_opt))
# cfg.write(cmake_cache_string("PETSC_LIB", petsc_lib))
#else:
# cfg.write(cmake_cache_string("PETSC_DIR", petsc.prefix))
if '+pumi' in spec:
pumi_dir = get_spec_path(spec, "pumi")
cfg.write(cmake_cache_entry("PUMI_DIR", pumi_dir))
if '+gslib' in spec:
gslib_dir = get_spec_path(spec, "gslib")
cfg.write(cmake_cache_entry("GSLIB_DIR", gslib_dir))
if '+netcdf' in spec:
netcdf_dir = get_spec_path(spec, "netcdf")
cfg.write(cmake_cache_entry("NETCDF_DIR", netcdf_dir))
#TODO (bernede1@llnl.gov): what about NETCDF_REQUIRED_PACKAGES
# see MFEM config/defaults.cmake
if '+zlib' in spec:
if "@:3.3.2" in spec:
zlib_dir = spec['zlib'].prefix
cfg.write(cmake_cache_entry("ZLIB_DIR", zlib_dir))
else:
zlib_opt = '-I%s' % spec['zlib'].prefix.include
zlib_lib = ld_flags_from_library_list(spec['zlib'].libs)
cfg.write(cmake_cache_string("ZLIB_OPT", zlib_opt))
cfg.write(cmake_cache_string("ZLIB_LIB", zlib_lib))
if '+mpfr' in spec:
mpfr_dir = get_spec_path(spec, "mpfr")
cfg.write(cmake_cache_entry("MPFR_DIR", mpfr_dir))
if '+gnutls' in spec:
gnutls_dir = get_spec_path(spec, "gnutls")
cfg.write(cmake_cache_entry("GNUTLS_DIR", gnutls_dir))
if '+libunwind' in spec:
libunwind_dir = get_spec_path(spec, "libunwind")
cfg.write(cmake_cache_entry("LIBUNWIND_DIR", libunwind_dir))
if '+openmp' in spec:
cfg.write(cmake_cache_string("OPENMP_OPT", self.compiler.openmp_flag))
if '+cuda' in spec:
cuda_cxx = join_path(spec['cuda'].prefix, 'bin', 'nvcc')
cfg.write(cmake_cache_string("CUDA_CXX", cuda_cxx))
cfg.write(cmake_cache_string("CUDA_ARCH", cuda_arch))
if '+occa' in spec:
occa_dir = get_spec_path(spec, "occa")
cfg.write(cmake_cache_entry("OCCA_DIR", occa_dir))
if '+raja' in spec:
raja_dir = get_spec_path(spec, "raja")
cfg.write(cmake_cache_entry("RAJA_DIR", raja_dir))
if '+amgx' in spec:
amgx_dir = get_spec_path(spec, "amgx")
cfg.write(cmake_cache_string("AMGX_DIR", amgx.prefix))
if '+libceed' in spec:
ceed_dir = get_spec_path(spec, "libceed")
cfg.write(cmake_cache_entry("CEED_DIR", ceed_dir))
if '+umpire' in spec:
umpire_dir = get_spec_path(spec, "umpire")
cfg.write(cmake_cache_entry("UMPIRE_DIR", umpire_dir))
timer_ids = {'std': '0', 'posix': '2', 'mac': '4', 'mpi': '6'}
timer = spec.variants['timer'].value
if timer != 'auto':
cfg.write(cmake_cache_string("MFEM_TIMER_TYPE",timer_ids[timer]))
if '+conduit' in spec:
conduit_dir = get_spec_path(spec, "conduit")
cfg.write(cmake_cache_entry("CONDUIT_DIR", conduit_dir))
#######################
# Close and save
#######################
cfg.write("\n")
cfg.close()
def cmake_args(self):
host_config_path = self._get_host_config_path(self.spec)
options = []
options.extend(['-C', host_config_path])
return options
# 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'))
@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))
+112
View File
@@ -0,0 +1,112 @@
#!/bin/bash
# Set a compiler to test with, e.g. '%gcc', '%clang', etc.
compiler=''
mfem='mfem'${compiler}
mfem_dev='mfem@develop'${compiler}
backends='+occa+raja+libceed'
backends_specs='^occa~cuda ^raja~openmp'
# Help the concrtizer find suitable hdf5 version (conduit constraint)
full_mpi_specs='^hdf5@1.8.19:1.8.999'
full_ser_specs='^hdf5@1.8.19:1.8.999'
# Restrict strumpack build
full_mpi_specs+=' ^strumpack~cuda'
builds=(
# preferred version:
${mfem}
${mfem}'~mpi~metis~zlib'
${mfem}"$backends"'+superlu-dist+strumpack+suite-sparse+petsc \
+sundials+pumi+gslib+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
^petsc+suite-sparse+mumps'" $backends_specs"" $full_mpi_specs"
${mfem}'~mpi \
'"$backends"'+suite-sparse+sundials+gslib+mpfr+netcdf \
+zlib+gnutls+libunwind+conduit'" $backends_specs"" $full_ser_specs"
# develop version:
${mfem_dev}'+shared~static'
${mfem_dev}'+shared~static~mpi~metis~zlib'
# NOTE: Shared build with +gslib works on mac but not on linux
# FIXME: As of 2020/11/03 the next config fails in PETSc ex5p:
# ${mfem_dev}'+shared~static \
# '"$backends"'+superlu-dist+strumpack+suite-sparse+petsc \
# +sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
# ^petsc+suite-sparse+mumps'" $backends_specs"" $full_mpi_specs"
# Removing just petsc works:
${mfem_dev}'+shared~static \
'"$backends"'+superlu-dist+strumpack+suite-sparse \
+sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
'" $backends_specs"" $full_mpi_specs"
# Removing just strumpack works on linux, fails on mac:
# ${mfem_dev}'+shared~static \
# '"$backends"'+superlu-dist+suite-sparse+petsc \
# +sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
# ^petsc+suite-sparse+mumps'" $backends_specs"" ^hdf5@1.8.19:1.8.999"
# Petsc and strumpack: fails on linux and mac in PETSc ex5p:
# ${mfem_dev}'+shared~static +strumpack+petsc \
# ^petsc+suite-sparse+mumps ^strumpack~cuda'
${mfem_dev}'+shared~static~mpi \
'"$backends"'+suite-sparse+sundials+mpfr+netcdf \
+zlib+gnutls+libunwind+conduit'" $backends_specs"" $full_ser_specs"
)
builds2=(
# preferred version
${mfem}"$backends $backends_specs"
${mfem}'+superlu-dist'
${mfem}'+strumpack ^strumpack~cuda'
${mfem}'+suite-sparse~mpi'
${mfem}'+suite-sparse'
${mfem}'+sundials~mpi'
${mfem}'+sundials'
${mfem}'+pumi'
${mfem}'+gslib'
${mfem}'+netcdf~mpi'
${mfem}'+netcdf'
${mfem}'+mpfr'
${mfem}'+gnutls'
${mfem}'+conduit~mpi'
${mfem}'+conduit'
${mfem}'+umpire'
${mfem}'+petsc ^petsc+suite-sparse+mumps'
# develop version
${mfem_dev}"$backends $backends_specs"
${mfem_dev}'+superlu-dist'
${mfem_dev}'+strumpack ^strumpack~cuda'
${mfem_dev}'+suite-sparse~mpi'
${mfem_dev}'+suite-sparse'
${mfem_dev}'+sundials~mpi'
${mfem_dev}'+sundials'
${mfem_dev}'+pumi'
${mfem_dev}'+gslib'
${mfem_dev}'+netcdf~mpi'
${mfem_dev}'+netcdf'
${mfem_dev}'+mpfr'
${mfem_dev}'+gnutls'
${mfem_dev}'+conduit~mpi'
${mfem_dev}'+conduit'
${mfem_dev}'+umpire'
${mfem_dev}'+petsc ^petsc+suite-sparse+mumps'
)
trap 'printf "\nScript interrupted.\n"; exit 33' INT
SEP='=========================================================================='
sep='--------------------------------------------------------------------------'
for bld in "${builds[@]}" "${builds2[@]}"; do
printf "\n%s\n" "${SEP}"
printf " %s\n" "${bld}"
printf "%s\n" "${SEP}"
eval bbb="\"${bld}\""
spack spec -I $bbb || exit 1
printf "%s\n" "${sep}"
spack install --test=root $bbb || exit 2
done
# Uninstall all mfem builds:
# spack uninstall --all mfem
@@ -0,0 +1,71 @@
diff --git a/examples/petsc/rc_ex3p b/examples/petsc/rc_ex3p
index 2cbe07ef2..c585d9b52 100644
--- a/examples/petsc/rc_ex3p
+++ b/examples/petsc/rc_ex3p
@@ -6,4 +6,4 @@
# it needs PETSc configured with MUMPS
-solver_pc_type cholesky
--solver_pc_factor_mat_solver_package mumps
+-solver_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex3p_bddc b/examples/petsc/rc_ex3p_bddc
index ea887bb29..2e1eba0d5 100644
--- a/examples/petsc/rc_ex3p_bddc
+++ b/examples/petsc/rc_ex3p_bddc
@@ -16,7 +16,7 @@
#-pc_bddc_adaptive_threshold 10
# Customization of the local solvers
-#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
-#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
+#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
+#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
#-pc_bddc_coarse_pc_type cholesky
-#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
+#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex4p b/examples/petsc/rc_ex4p
index f734f35fe..64fbe9427 100644
--- a/examples/petsc/rc_ex4p
+++ b/examples/petsc/rc_ex4p
@@ -2,4 +2,4 @@
# it needs PETSc configured with MUMPS
-solver_pc_type cholesky
--solver_pc_factor_mat_solver_package mumps
+-solver_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex4p_bddc b/examples/petsc/rc_ex4p_bddc
index 9507ad431..e8ef99db7 100644
--- a/examples/petsc/rc_ex4p_bddc
+++ b/examples/petsc/rc_ex4p_bddc
@@ -13,7 +13,7 @@
#-pc_bddc_adaptive_threshold 10
# Customization of the local solvers
-#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
-#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
+#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
+#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
#-pc_bddc_coarse_pc_type cholesky
-#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
+#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
diff --git a/examples/petsc/rc_ex5p_bddc b/examples/petsc/rc_ex5p_bddc
index b243c53c8..a4bc899c3 100644
--- a/examples/petsc/rc_ex5p_bddc
+++ b/examples/petsc/rc_ex5p_bddc
@@ -28,13 +28,13 @@
# local solvers (needs PETSc compiled with support for SuiteSparse)
# default solvers will fail
-prec_pc_bddc_neumann_pc_type lu
--prec_pc_bddc_neumann_pc_factor_mat_solver_package umfpack
+-prec_pc_bddc_neumann_pc_factor_mat_solver_type umfpack
-prec_pc_bddc_dirichlet_pc_type lu
--prec_pc_bddc_dirichlet_pc_factor_mat_solver_package umfpack
+-prec_pc_bddc_dirichlet_pc_factor_mat_solver_type umfpack
# coarse solver (needs PETSc compiled with support for MUMPS)
# default solver may fail
--prec_pc_bddc_coarse_pc_factor_mat_solver_package mumps
+-prec_pc_bddc_coarse_pc_factor_mat_solver_type mumps
-prec_pc_bddc_coarse_pc_type cholesky
# deluxe scaling (needs PETSc compiled with support for MUMPS)
@@ -0,0 +1,36 @@
diff --git a/config/test.mk b/config/test.mk
index 4821b084d..62479fc63 100644
--- a/config/test.mk
+++ b/config/test.mk
@@ -14,11 +14,13 @@
# Colors used below:
# green '\033[0;32m'
# red '\033[0;31m'
+# yellow '\033[0;33m'
# no color '\033[0m'
COLOR_PRINT = if [ -t 1 ]; then \
printf $(1)$(2)'\033[0m'$(3); else printf $(2)$(3); fi
PRINT_OK = $(call COLOR_PRINT,'\033[0;32m',OK," ($$1 $$2)\n")
PRINT_FAILED = $(call COLOR_PRINT,'\033[0;31m',FAILED," ($$1 $$2)\n")
+PRINT_SKIP = $(call COLOR_PRINT,'\033[0;33m',SKIP,"\n")
# Timing support
define TIMECMD_detect
diff --git a/examples/pumi/makefile b/examples/pumi/makefile
index 2f98eeca7..5ff652aca 100644
--- a/examples/pumi/makefile
+++ b/examples/pumi/makefile
@@ -51,6 +51,13 @@ endif
MFEM_TESTS = EXAMPLES
include $(MFEM_TEST_MK)
+ifneq (,$(filter test%,$(MAKECMDGOALS)))
+ ifeq (,$(wildcard ../../data/pumi))
+ $(info PUMI data directory not found. The PUMI tests will be SKIPPED.)
+ mfem-test = printf " $(3) [$(2) $(1) ... ]: "; $(PRINT_SKIP)
+ endif
+endif
+
# Testing: Parallel vs. serial runs
RUN_MPI_NP = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP)
RUN_MPI = $(RUN_MPI_NP) $(MFEM_MPI_NP)
@@ -0,0 +1,27 @@
From e2147e51e2bff8907207036557bb9f45d45baaf8 Mon Sep 17 00:00:00 2001
From: Geoffrey M Oxberry <goxberry@gmail.com>
Date: Sun, 25 Aug 2019 00:30:15 -0700
Subject: [PATCH] makefile: add missing parenthesis to conditional
This commit adds a missing parenthesis to a conditional in the MFEM
makefile that checks if PREFIX is set when MFEM_USE_OCCA equals YES.
---
makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/makefile b/makefile
index 98a29f3c9..22a9b5bac 100644
--- a/makefile
+++ b/makefile
@@ -346,7 +346,7 @@ ifneq (,$(filter install,$(MAKECMDGOALS)))
@MFEM_EXT_LIBS@
MFEM_LIB_FILE = @MFEM_LIB_DIR@/libmfem.$(if $(shared),$(SO_VER),a)
ifeq ($(MFEM_USE_OCCA),YES)
- ifneq ($(MFEM_INSTALL_DIR),$(abspath $(PREFIX))
+ ifneq ($(MFEM_INSTALL_DIR),$(abspath $(PREFIX)))
$(error OCCA is enabled: PREFIX must be set during configuration!)
endif
endif
--
2.23.0
@@ -0,0 +1,24 @@
diff --git a/general/mem_manager.cpp b/general/mem_manager.cpp
index ff4a03465..748f6e673 100644
--- a/general/mem_manager.cpp
+++ b/general/mem_manager.cpp
@@ -482,7 +482,8 @@ public:
HostMemorySpace(),
name(mm.GetUmpireAllocatorHostName()),
rm(umpire::ResourceManager::getInstance()),
- h_allocator(rm.isAllocator(name)? rm.getAllocator(name):
+ h_allocator((!std::strcmp(name, "HOST") || rm.isAllocator(name)) ?
+ rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("HOST"))),
strat(h_allocator.getAllocationStrategy()) { }
@@ -506,7 +507,8 @@ public:
DeviceMemorySpace(),
name(mm.GetUmpireAllocatorDeviceName()),
rm(umpire::ResourceManager::getInstance()),
- d_allocator(rm.isAllocator(name)? rm.getAllocator(name):
+ d_allocator((!std::strcmp(name, "DEVICE") || rm.isAllocator(name)) ?
+ rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("DEVICE"))) { }
void Alloc(Memory &base) { base.d_ptr = d_allocator.allocate(base.bytes); }
@@ -0,0 +1,10 @@
--- mfem/miniapps/performance/makefile 2017-06-07 13:51:29.366596901 -0700
+++ mfem/miniapps/performance/makefile.new 2017-06-07 13:51:57.087104178 -0700
@@ -26,7 +26,6 @@
# Compiler specific optimizations.
# For best performance, GCC 5 (or newer) is recommended.
ifneq (,$(findstring $(MFEM_CXX),g++ mpicxx))
- MFEM_CXXFLAGS += -march=native
# MFEM_CXXFLAGS += -std=c++03
MFEM_CXXFLAGS += -std=c++11
MFEM_CXXFLAGS += -pedantic -Wall
+846
View File
@@ -0,0 +1,846 @@
# Copyright 2013-2020 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)
from spack import *
import socket
import os
import shutil
from os import environ as env
from os.path import join as pjoin
class Mfem(Package):
"""Free, lightweight, scalable C++ library for finite element methods."""
tags = ['FEM', 'finite elements', 'high-order', 'AMR', 'HPC']
homepage = 'http://www.mfem.org'
git = 'https://github.com/mfem/mfem.git'
maintainers = ['v-dobrev', 'tzanio', 'acfisher',
'goxberry', 'markcmiller86']
# 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:
# http://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.2.0',
'4352a225b55948d2e73a5ee88cece0e88bdbe7ba6726a23d68b2736d3221a86d',
url='https://bit.ly/mfem-4-2', extension='tar.gz',
preferred=True)
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')
variant('cuda', default=False, description='Enable CUDA support')
variant('cuda_arch', default='sm_60',
description='CUDA architecture to compile for')
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('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: HIP, SIMD, Ginkgo, AmgX, SLEPc, 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.99.99+openmp')
conflicts('+cuda', when='@:3.99.99')
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.99.99')
conflicts('+gnutls', when='@:3.1')
conflicts('+zlib', when='@:3.2')
conflicts('+mpfr', when='@:3.2')
conflicts('+petsc', when='@:3.2')
conflicts('+sundials', when='@:3.2')
conflicts('+pumi', when='@:3.3.2')
conflicts('+gslib', when='@:4.0.99')
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.99.99')
conflicts('+raja', when='mfem@:3.99.99')
conflicts('+libceed', when='mfem@:4.0.99')
conflicts('+umpire', when='mfem@:4.0.99')
conflicts('+amgx', when='mfem@:4.1.99')
conflicts('+amgx', when='~cuda')
conflicts('+superlu-dist', when='~mpi')
conflicts('+strumpack', when='~mpi')
conflicts('+petsc', when='~mpi')
conflicts('+pumi', when='~mpi')
conflicts('timer=mpi', when='~mpi')
depends_on('mpi', when='+mpi')
depends_on('hypre@2.10.0:2.13.99', when='@:3.3.99+mpi')
depends_on('hypre', when='@3.4:+mpi')
depends_on('metis', when='+metis')
depends_on('blas', when='+lapack')
depends_on('lapack@3.0:', when='+lapack')
depends_on('cuda', when='+cuda')
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')
depends_on('sundials@5.4.0:+cuda', when='@4.2.0:+sundials+cuda')
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')
# 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')
# 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.99 ^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.99 ^hypre@2.16.0:')
conflicts('+strumpack ^strumpack+cuda', when='~cuda')
depends_on('occa@1.0.8:', when='@:4.1.99+occa')
depends_on('occa@1.1.0:', when='@4.2.0:+occa')
depends_on('occa+cuda', when='+occa+cuda')
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')
depends_on('raja+cuda', when='+raja+cuda')
depends_on('libceed@0.6:', when='@:4.1.99+libceed')
depends_on('libceed@0.7:', when='@4.2.0:+libceed')
depends_on('libceed+cuda', when='+libceed+cuda')
depends_on('umpire@2.0.0:', when='+umpire')
depends_on('umpire+cuda', when='+umpire+cuda')
depends_on('amgx', when='+amgx')
# MPI is enabled by default
depends_on('amgx~mpi', when='+amgx~mpi')
for sm_ in CudaPackage.cuda_arch_values:
depends_on('amgx cuda_arch={0}'.format(sm_),
when='+amgx cuda_arch=sm_{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 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')
def _get_sys_type(self, spec):
sys_type = str(spec.architecture)
# if on llnl systems, we can use the SYS_TYPE
if "SYS_TYPE" in env:
sys_type = env["SYS_TYPE"]
return sys_type
def _get_host_config_path(self, spec):
host_config_path = "hc-%s-%s-%s.mk" % (socket.gethostname().rstrip('1234567890'),
self._get_sys_type(spec),
spec.format('{name}-{version}-{compiler}-{hash:8}'))
dest_dir = self.stage.source_path
host_config_path = os.path.abspath(pjoin(dest_dir, host_config_path))
return host_config_path
#
# 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 = 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['SPACK_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_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_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=%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 '+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=%s' % cuda_arch]
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)
# Uberenv: Save the config_mk with a spec dependent name
copy('config/config.mk',self._get_host_config_path(spec))
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'))
@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))
+112
View File
@@ -0,0 +1,112 @@
#!/bin/bash
# Set a compiler to test with, e.g. '%gcc', '%clang', etc.
compiler=''
mfem='mfem'${compiler}
mfem_dev='mfem@develop'${compiler}
backends='+occa+raja+libceed'
backends_specs='^occa~cuda ^raja~openmp'
# Help the concrtizer find suitable hdf5 version (conduit constraint)
full_mpi_specs='^hdf5@1.8.19:1.8.999'
full_ser_specs='^hdf5@1.8.19:1.8.999'
# Restrict strumpack build
full_mpi_specs+=' ^strumpack~cuda'
builds=(
# preferred version:
${mfem}
${mfem}'~mpi~metis~zlib'
${mfem}"$backends"'+superlu-dist+strumpack+suite-sparse+petsc \
+sundials+pumi+gslib+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
^petsc+suite-sparse+mumps'" $backends_specs"" $full_mpi_specs"
${mfem}'~mpi \
'"$backends"'+suite-sparse+sundials+gslib+mpfr+netcdf \
+zlib+gnutls+libunwind+conduit'" $backends_specs"" $full_ser_specs"
# develop version:
${mfem_dev}'+shared~static'
${mfem_dev}'+shared~static~mpi~metis~zlib'
# NOTE: Shared build with +gslib works on mac but not on linux
# FIXME: As of 2020/11/03 the next config fails in PETSc ex5p:
# ${mfem_dev}'+shared~static \
# '"$backends"'+superlu-dist+strumpack+suite-sparse+petsc \
# +sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
# ^petsc+suite-sparse+mumps'" $backends_specs"" $full_mpi_specs"
# Removing just petsc works:
${mfem_dev}'+shared~static \
'"$backends"'+superlu-dist+strumpack+suite-sparse \
+sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
'" $backends_specs"" $full_mpi_specs"
# Removing just strumpack works on linux, fails on mac:
# ${mfem_dev}'+shared~static \
# '"$backends"'+superlu-dist+suite-sparse+petsc \
# +sundials+pumi+mpfr+netcdf+zlib+gnutls+libunwind+conduit \
# ^petsc+suite-sparse+mumps'" $backends_specs"" ^hdf5@1.8.19:1.8.999"
# Petsc and strumpack: fails on linux and mac in PETSc ex5p:
# ${mfem_dev}'+shared~static +strumpack+petsc \
# ^petsc+suite-sparse+mumps ^strumpack~cuda'
${mfem_dev}'+shared~static~mpi \
'"$backends"'+suite-sparse+sundials+mpfr+netcdf \
+zlib+gnutls+libunwind+conduit'" $backends_specs"" $full_ser_specs"
)
builds2=(
# preferred version
${mfem}"$backends $backends_specs"
${mfem}'+superlu-dist'
${mfem}'+strumpack ^strumpack~cuda'
${mfem}'+suite-sparse~mpi'
${mfem}'+suite-sparse'
${mfem}'+sundials~mpi'
${mfem}'+sundials'
${mfem}'+pumi'
${mfem}'+gslib'
${mfem}'+netcdf~mpi'
${mfem}'+netcdf'
${mfem}'+mpfr'
${mfem}'+gnutls'
${mfem}'+conduit~mpi'
${mfem}'+conduit'
${mfem}'+umpire'
${mfem}'+petsc ^petsc+suite-sparse+mumps'
# develop version
${mfem_dev}"$backends $backends_specs"
${mfem_dev}'+superlu-dist'
${mfem_dev}'+strumpack ^strumpack~cuda'
${mfem_dev}'+suite-sparse~mpi'
${mfem_dev}'+suite-sparse'
${mfem_dev}'+sundials~mpi'
${mfem_dev}'+sundials'
${mfem_dev}'+pumi'
${mfem_dev}'+gslib'
${mfem_dev}'+netcdf~mpi'
${mfem_dev}'+netcdf'
${mfem_dev}'+mpfr'
${mfem_dev}'+gnutls'
${mfem_dev}'+conduit~mpi'
${mfem_dev}'+conduit'
${mfem_dev}'+umpire'
${mfem_dev}'+petsc ^petsc+suite-sparse+mumps'
)
trap 'printf "\nScript interrupted.\n"; exit 33' INT
SEP='=========================================================================='
sep='--------------------------------------------------------------------------'
for bld in "${builds[@]}" "${builds2[@]}"; do
printf "\n%s\n" "${SEP}"
printf " %s\n" "${bld}"
printf "%s\n" "${SEP}"
eval bbb="\"${bld}\""
spack spec -I $bbb || exit 1
printf "%s\n" "${sep}"
spack install --test=root $bbb || exit 2
done
# Uninstall all mfem builds:
# spack uninstall --all mfem
+99
View File
@@ -0,0 +1,99 @@
# Copyright 2013-2020 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)
from spack import *
class Pumi(CMakePackage):
"""SCOREC RPI's Parallel Unstructured Mesh Infrastructure (PUMI).
An efficient distributed mesh data structure and methods to support
parallel adaptive analysis including general mesh-based operations,
such as mesh entity creation/deletion, adjacency and geometric
classification, iterators, arbitrary (field) data attachable to mesh
entities, efficient communication involving entities duplicated
across multiple tasks, migration of mesh entities between tasks,
and dynamic load balancing."""
homepage = "https://www.scorec.rpi.edu/pumi"
git = "https://github.com/SCOREC/core.git"
maintainers = ['cwsmith']
# We will use the scorec/core master branch as the 'nightly' version
# of pumi in spack. The master branch is more stable than the
# scorec/core develop branch and we perfer not to expose spack users
# to the added instability.
version('master', submodules=True, branch='master')
version('2.2.4', commit='8439d928afcb95d88652f4812dcb62077ed958f6') # tag 2.2.4
version('2.2.3', commit='d200cb366813695d0f18b514d8d8ecc382cb79fc') # tag 2.2.3
version('2.2.2', commit='bc34e3f7cfd8ab314968510c71486b140223a68f') # tag 2.2.2
version('2.2.1', commit='cd826205db21b8439026db1f6af61a8ed4a18564') # tag 2.2.1
version('2.2.0', commit='8c7e6f13943893b2bc1ece15003e4869a0e9634f') # tag 2.2.0
version('2.1.0', commit='840fbf6ec49a63aeaa3945f11ddb224f6055ac9f')
variant('int64', default=False, description='Enable 64bit mesh entity ids')
variant('shared', default=False, description='Build shared libraries')
variant('zoltan', default=False, description='Enable Zoltan Features')
variant('fortran', default=False, description='Enable FORTRAN interface')
variant('simmodsuite', default='none',
values=('none', 'base', 'kernels', 'full'),
description="Enable Simmetrix SimModSuite Support: 'base' enables "
"the minimum set of functionality, 'kernels' adds CAD kernel "
"support to 'base', and 'full' enables all functionality.")
variant('simmodsuite_version_check', default=True,
description="Enable check of Simmetrix SimModSuite version. "
"Disable the check for testing new versions.")
depends_on('mpi')
depends_on('cmake@3:', type='build')
depends_on('zoltan', when='+zoltan')
depends_on('zoltan+int64', when='+zoltan+int64')
simbase = "+base"
simkernels = simbase + "+parasolid+acis+discrete"
simfull = simkernels + "+abstract+adv+advmodel\
+import+paralleladapt+parallelmesh"
depends_on('simmetrix-simmodsuite' + simbase,
when='simmodsuite=base')
depends_on('simmetrix-simmodsuite' + simkernels,
when='simmodsuite=kernels')
depends_on('simmetrix-simmodsuite' + simfull,
when='simmodsuite=full')
def cmake_args(self):
spec = self.spec
args = [
'-DSCOREC_CXX_WARNINGS=OFF',
'-DENABLE_ZOLTAN=%s' % ('ON' if '+zoltan' in spec else 'OFF'),
'-DCMAKE_C_COMPILER=%s' % spec['mpi'].mpicc,
'-DCMAKE_CXX_COMPILER=%s' % spec['mpi'].mpicxx,
'-DBUILD_SHARED_LIBS=%s' % ('ON' if '+shared' in spec else 'OFF'),
'-DCMAKE_Fortran_COMPILER=%s' % spec['mpi'].mpifc,
'-DPUMI_FORTRAN_INTERFACE=%s' %
('ON' if '+fortran' in spec else 'OFF'),
'-DMDS_ID_TYPE=%s' % ('long' if '+int64' in spec else 'int'),
'-DSKIP_SIMMETRIX_VERSION_CHECK=%s' %
('ON' if '~simmodsuite_version_check' in spec else 'OFF'),
'-DMESHES=%s' % join_path(self.stage.source_path, 'pumi_meshes')
]
if self.spec.satisfies('simmodsuite=base'):
args.append('-DENABLE_SIMMETRIX=ON')
if self.spec.satisfies('simmodsuite=kernels') or \
self.spec.satisfies('simmodsuite=full'):
args.append('-DENABLE_SIMMETRIX=ON')
args.append('-DSIM_PARASOLID=ON')
args.append('-DSIM_ACIS=ON')
args.append('-DSIM_DISCRETE=ON')
mpi_id = spec['mpi'].name + spec['mpi'].version.string
args.append('-DSIM_MPI=' + mpi_id)
return args
@run_after('build')
@on_package_attributes(run_tests=True)
def check(self):
"""Run ctest after building project."""
with working_dir(self.build_directory):
ctest(parallel=False)
+9
View File
@@ -0,0 +1,9 @@
{
"package_name" : "mfem-cmake",
"package_version" : "develop",
"package_final_phase" : "cmake",
"package_source_dir" : "../..",
"spack_url": "https://github.com/spack/spack",
"spack_branch": "mfem-updates",
"spack_activate" : {}
}
+80
View File
@@ -0,0 +1,80 @@
# -------------------------------------------------------------------------
# This is the default spack configuration file.
#
# Settings here are versioned with Spack and are intended to provide
# sensible defaults out of the box. Spack maintainers should edit this
# file to keep it current.
#
# Users can override these settings by editing the following files.
#
# Per-spack-instance settings (overrides defaults):
# $SPACK_ROOT/etc/spack/config.yaml
#
# Per-user settings (overrides default and site settings):
# ~/.spack/config.yaml
# -------------------------------------------------------------------------
config:
# This is the path to the root of the Spack install tree.
# You can use $spack here to refer to the root of the spack instance.
install_tree: $spack/..
# install directory layout
install_path_scheme: "${COMPILERNAME}-${COMPILERVER}/${PACKAGE}-${VERSION}"
# Locations where templates should be found
template_dirs:
- $spack/templates
# Locations where different types of modules should be installed.
module_roots:
tcl: $spack/share/spack/modules
lmod: $spack/share/spack/lmod
# Temporary locations Spack can try to use for builds.
#
# Spack will use the first one it finds that exists and is writable.
# You can use $tempdir to refer to the system default temp directory
# (as returned by tempfile.gettempdir()).
#
# A value of $spack/var/spack/stage indicates that Spack should run
# builds directly inside its install directory without staging them in
# temporary space.
#
# The build stage can be purged with `spack purge --stage`.
build_stage:
# skipping tempdir b/c running mpi tests fails with local fs
# - $tempdir
- $spack/../builds
# Cache directory already downloaded source tarballs and archived
# repositories. This can be purged with `spack purge --downloads`.
source_cache: $spack/var/spack/cache
# Cache directory for miscellaneous files, like the package index.
# This can be purged with `spack purge --misc-cache`
misc_cache: .spack/misccache
# If this is false, tools like curl that use SSL will not verify
# certifiates. (e.g., curl will use use the -k option)
verify_ssl: true
# If set to true, Spack will always check checksums after downloading
# archives. If false, Spack skips the checksum step.
checksum: true
# If set to true, `spack install` and friends will NOT clean
# potentially harmful variables from the build environment. Use wisely.
dirty: false
# The default number of jobs to use when running `make` in parallel.
# If set to 4, for example, `spack install` will run `make -j4`.
# If not set, all available cores are used by default.
# for uberenv, limit build_jobs to 8
build_jobs: 8
@@ -0,0 +1,40 @@
compilers:
- compiler:
spec: apple-clang@10.0.0
paths:
cc: /usr/bin/clang
cxx: /usr/bin/clang++
f77: /usr/local/bin/gfortran
fc: /usr/local/bin/gfortran
flags: {}
operating_system: mojave
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: clang@10.0.0
paths:
cc: /usr/local/opt/llvm/bin/clang
cxx: /usr/local/opt/llvm/bin/clang++
f77: /usr/local/bin/gfortran
fc: /usr/local/bin/gfortran
flags: {}
operating_system: mojave
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: apple-clang@11.0.0
paths:
cc: /usr/bin/clang
cxx: /usr/bin/clang++
f77: /usr/local/bin/gfortran
fc: /usr/local/bin/gfortran
flags: {}
operating_system: catalina
target: x86_64
modules: []
environment: {}
extra_rpaths: []
@@ -0,0 +1,85 @@
# -------------------------------------------------------------------------
# This file controls default concretization preferences for Spack.
#
# Settings here are versioned with Spack and are intended to provide
# sensible defaults out of the box. Spack maintainers should edit this
# file to keep it current.
#
# Users can override these settings by editing the following files.
#
# Per-spack-instance settings (overrides defaults):
# $SPACK_ROOT/etc/spack/packages.yaml
#
# Per-user settings (overrides default and site settings):
# ~/.spack/packages.yaml
# -------------------------------------------------------------------------
packages:
bzip2:
buildable: false
externals:
- spec: bzip2
prefix: /usr/bin/
gettext:
buildable: false
externals:
- spec: gettext
prefix: /usr/local/bin/
m4:
buildable: false
externals:
- spec: m4
prefix: /usr/bin/
pkg-config:
buildable: false
externals:
- spec: pkg-config
prefix: /usr/local/bin/
tar:
buildable: false
externals:
- spec: tar
prefix: /usr/bin/
perl:
buildable: false
externals:
- spec: perl
prefix: /usr/local/bin/
cmake:
buildable: false
externals:
- spec: cmake
prefix: /usr/local/
# - spec: cmake@3.17.2
# prefix: /usr/local/Cellar/cmake/3.17.2/bin/
# openmpi:
# buildable: false
# externals:
# - spec: openmpi
# prefix: /usr/local/
## - spec: openmpi@4.0.3
## prefix: /usr/local/Cellar/open-mpi/4.0.3/bin/
mpich:
buildable: false
externals:
- spec: mpich
prefix: /usr/local/
# - spec: mpich@3.3.2
# prefix: /usr/local/Cellar/mpich/3.3.2_1
openblas:
buildable: false
externals:
- spec: openblas
prefix: /usr/local/opt/openblas/
# - spec: openmpi@4.0.3
# prefix: /usr/local/Cellar/open-mpi/4.0.3/bin/
@@ -0,0 +1,309 @@
compilers:
- compiler:
spec: clang@3.9.1
paths:
cc: /usr/tce/packages/clang/clang-3.9.1/bin/clang
cxx: /usr/tce/packages/clang/clang-3.9.1/bin/clang++
f77: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
flags:
cflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-4.9.3
cxxflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-4.9.3
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: clang@4.0.0
paths:
cc: /usr/tce/packages/clang/clang-4.0.0/bin/clang
cxx: /usr/tce/packages/clang/clang-4.0.0/bin/clang++
f77: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
flags:
cflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-4.9.3
cxxflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-4.9.3
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: clang@6.0.0
paths:
cc: /usr/tce/packages/clang/clang-6.0.0/bin/clang
cxx: /usr/tce/packages/clang/clang-6.0.0/bin/clang++
f77: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
flags:
cflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
cxxflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: clang@9.0.0
paths:
cc: /usr/tce/packages/clang/clang-9.0.0/bin/clang
cxx: /usr/tce/packages/clang/clang-9.0.0/bin/clang++
f77: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
flags:
cflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
cxxflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: clang@10.0.1
paths:
cc: /usr/tce/packages/clang/clang-10.0.1/bin/clang
cxx: /usr/tce/packages/clang/clang-10.0.1/bin/clang++
f77: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
flags:
cflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
cxxflags: --gcc-toolchain=/usr/tce/packages/gcc/gcc-8.3.1
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@16.0.4
paths:
cc: /usr/tce/packages/intel/intel-16.0.4/bin/icc
cxx: /usr/tce/packages/intel/intel-16.0.4/bin/icpc
f77: /usr/tce/packages/intel/intel-16.0.4/bin/ifort
fc: /usr/tce/packages/intel/intel-16.0.4/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-4.9.3/bin/gcc
cxxflags: -gcc-name=/usr/tce/packages/gcc/gcc-4.9.3/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@17.0.2
paths:
cc: /usr/tce/packages/intel/intel-17.0.2/bin/icc
cxx: /usr/tce/packages/intel/intel-17.0.2/bin/icpc
f77: /usr/tce/packages/intel/intel-17.0.2/bin/ifort
fc: /usr/tce/packages/intel/intel-17.0.2/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-4.9.3/bin/gcc
cxxflags: -gxx-name=/usr/tce/packages/gcc/gcc-4.9.3/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@18.0.0
paths:
cc: /usr/tce/packages/intel/intel-18.0.0/bin/icc
cxx: /usr/tce/packages/intel/intel-18.0.0/bin/icpc
f77: /usr/tce/packages/intel/intel-18.0.0/bin/ifort
fc: /usr/tce/packages/intel/intel-18.0.0/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-7.3.0/bin/gcc
cxxflags: -gxx-name=/usr/tce/packages/gcc/gcc-7.3.0/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@18.0.2
paths:
cc: /usr/tce/packages/intel/intel-18.0.2/bin/icc
cxx: /usr/tce/packages/intel/intel-18.0.2/bin/icpc
f77: /usr/tce/packages/intel/intel-18.0.2/bin/ifort
fc: /usr/tce/packages/intel/intel-18.0.2/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-7.3.0/bin/gcc
cxxflags: -gxx-name=/usr/tce/packages/gcc/gcc-7.3.0/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@19.0.4
paths:
cc: /usr/tce/packages/intel/intel-19.0.4/bin/icc
cxx: /usr/tce/packages/intel/intel-19.0.4/bin/icpc
f77: /usr/tce/packages/intel/intel-19.0.4/bin/ifort
fc: /usr/tce/packages/intel/intel-19.0.4/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-8.3.1/bin/gcc
cxxflags: -gxx-name=/usr/tce/packages/gcc/gcc-8.3.1/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: intel@19.1.0
paths:
cc: /usr/tce/packages/intel/intel-19.1.0/bin/icc
cxx: /usr/tce/packages/intel/intel-19.1.0/bin/icpc
f77: /usr/tce/packages/intel/intel-19.1.0/bin/ifort
fc: /usr/tce/packages/intel/intel-19.1.0/bin/ifort
flags:
cflags: -gcc-name=/usr/tce/packages/gcc/gcc-8.3.1/bin/gcc
cxxflags: -gxx-name=/usr/tce/packages/gcc/gcc-8.3.1/bin/g++
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: pgi@17.10
paths:
cc: /usr/tce/packages/pgi/pgi-17.10/bin/pgcc
cxx: /usr/tce/packages/pgi/pgi-17.10/bin/pgc++
f77: /usr/tce/packages/pgi/pgi-17.10/bin/pgf77
fc: /usr/tce/packages/pgi/pgi-17.10/bin/pgf95
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: pgi@18.5
paths:
cc: /usr/tce/packages/pgi/pgi-18.5/bin/pgcc
cxx: /usr/tce/packages/pgi/pgi-18.5/bin/pgc++
f77: /usr/tce/packages/pgi/pgi-18.5/bin/pgf77
fc: /usr/tce/packages/pgi/pgi-18.5/bin/pgf95
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: pgi@19.4
paths:
cc: /usr/tce/packages/pgi/pgi-19.4/bin/pgcc
cxx: /usr/tce/packages/pgi/pgi-19.4/bin/pgc++
f77: /usr/tce/packages/pgi/pgi-19.4/bin/pgfortran
fc: /usr/tce/packages/pgi/pgi-19.4/bin/pgfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: pgi@19.7
paths:
cc: /usr/tce/packages/pgi/pgi-19.7/bin/pgcc
cxx: /usr/tce/packages/pgi/pgi-19.7/bin/pgc++
f77: /usr/tce/packages/pgi/pgi-19.7/bin/pgfortran
fc: /usr/tce/packages/pgi/pgi-19.7/bin/pgf95
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: pgi@20.1
paths:
cc: /usr/tce/packages/pgi/pgi-20.1/bin/pgcc
cxx: /usr/tce/packages/pgi/pgi-20.1/bin/pgc++
f77: /usr/tce/packages/pgi/pgi-20.1/bin/pgfortran
fc: /usr/tce/packages/pgi/pgi-20.1/bin/pgf95
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@4.9.3
paths:
cc: /usr/tce/packages/gcc/gcc-4.9.3/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-4.9.3/bin/g++
f77: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-4.9.3/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@6.1.0
paths:
cc: /usr/tce/packages/gcc/gcc-6.1.0/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-6.1.0/bin/g++
f77: /usr/tce/packages/gcc/gcc-6.1.0/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-6.1.0/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@7.1.0
paths:
cc: /usr/tce/packages/gcc/gcc-7.1.0/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-7.1.0/bin/g++
f77: /usr/tce/packages/gcc/gcc-7.1.0/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-7.1.0/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@7.3.0
paths:
cc: /usr/tce/packages/gcc/gcc-7.3.0/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-7.3.0/bin/g++
f77: /usr/tce/packages/gcc/gcc-7.3.0/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-7.3.0/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@8.1.0
paths:
cc: /usr/tce/packages/gcc/gcc-8.1.0/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-8.1.0/bin/g++
f77: /usr/tce/packages/gcc/gcc-8.1.0/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-8.1.0/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@8.3.1
paths:
cc: /usr/tce/packages/gcc/gcc-8.3.1/bin/gcc
cxx: /usr/tce/packages/gcc/gcc-8.3.1/bin/g++
f77: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
fc: /usr/tce/packages/gcc/gcc-8.3.1/bin/gfortran
flags: {}
operating_system: rhel7
target: x86_64
modules: []
environment: {}
extra_rpaths: []
@@ -0,0 +1,238 @@
packages:
all:
# This defaults us to machine specific flags of ivybridge which allows
# us to run on broadwell as well
target: [ivybridge]
compiler: [gcc, intel, pgi, clang]
providers:
blas: [netlib-lapack]
lapack: [netlib-lapack]
mpi: [mvapich2]
gl: [opengl]
glu: [openglu]
opengl:
buildable: false
externals:
- spec: opengl@1.7.0
prefix: /usr
openglu:
buildable: false
externals:
- spec: openglu@1.3.1
prefix: /usr
# Lock down which MPI we are using
mpi:
buildable: false
mvapich2:
externals:
- spec: mvapich2@2.3%clang@3.9.1 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-clang-3.9.1
- spec: mvapich2@2.3%clang@4.0.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-clang-4.0.0
- spec: mvapich2@2.3%clang@6.0.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-clang-6.0.0
- spec: mvapich2@2.3%clang@9.0.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-clang-9.0.0
- spec: mvapich2@2.3%clang@10.0.1 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-clang-10.0.0
- spec: mvapich2@2.3%gcc@4.9.3 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-4.9.3
- spec: mvapich2@2.3%gcc@6.1.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-6.1.0
- spec: mvapich2@2.3%gcc@7.1.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-7.1.0
- spec: mvapich2@2.3%gcc@7.3.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-7.3.0
- spec: mvapich2@2.3%gcc@8.1.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-8.1.0
- spec: mvapich2@2.3%gcc@8.3.1 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-gcc-8.3.1
- spec: mvapich2@2.3%intel@16.0.4 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-16.0.4
- spec: mvapich2@2.3%intel@17.0.2 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-17.0.2
- spec: mvapich2@2.3%intel@18.0.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-18.0.0
- spec: mvapich2@2.3%intel@18.0.2 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-18.0.2
- spec: mvapich2@2.3%intel@19.0.4 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-19.0.4
- spec: mvapich2@2.3%intel@19.1.0 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-intel-19.1.0
- spec: mvapich2@2.3%pgi@17.10 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-pgi-17.10
- spec: mvapich2@2.3%pgi@18.5 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-pgi-18.5
- spec: mvapich2@2.3%pgi@19.4 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-pgi-19.4
- spec: mvapich2@2.3%pgi@19.7 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-pgi-19.7
- spec: mvapich2@2.3%pgi@20.1 arch=linux-rhel7-ivybridge
prefix: /usr/tce/packages/mvapich2/mvapich2-2.3-pgi-20.1
# blas is a bit more complicated because its a virtual package so fake it with
# the following per spack docs
netlib-lapack:
buildable: false
externals:
- spec: netlib-lapack@3.6.1
prefix: /usr
# System level packages to not build
autoconf:
buildable: false
externals:
- spec: autoconf
prefix: /usr
automake:
buildable: false
externals:
- spec: automake
prefix: /usr
bzip2:
buildable: false
externals:
- spec: bzip2
prefix: /usr
gettext:
buildable: false
externals:
- spec: gettext
prefix: /usr
graphviz:
buildable: false
externals:
- spec: graphviz
prefix: /usr
libtool:
buildable: false
externals:
- spec: libtool
prefix: /usr
libx11:
buildable: false
externals:
- spec: libx11
prefix: /usr
m4:
buildable: false
externals:
- spec: m4
prefix: /usr
perl:
buildable: false
externals:
- spec: perl
prefix: /usr
pkg-config:
buildable: false
externals:
- spec: pkg-config
prefix: /usr
tar:
buildable: false
externals:
- spec: tar
prefix: /usr
readline:
buildable: false
externals:
- spec: readline
prefix: /usr
unzip:
buildable: false
externals:
- spec: unzip
prefix: /usr
zlib:
buildable: false
externals:
- spec: zlib
prefix: /usr
# Dev tools
cmake:
version: [3.14.5]
buildable: false
externals:
- spec: cmake
prefix: /usr/tce/packages/cmake/cmake-3.14.5
python:
buildable: false
externals:
- spec: python@3.8.2
prefix: /usr/tce/packages/python/python-3.8.2
py-sphinx:
version: [2.2.0]
buildable: false
externals:
- spec: py-sphinx@2.2.0
prefix: /usr/tce/packages/python/python-3.8.2/
doxygen:
version: [1.8.5]
buildable: False
externals:
- spec: doxygen@1.8.5
prefix: /usr/bin
# GPU
cuda:
version: [10.1.168]
buildable: False
externals:
- spec: cuda@10.1.168
prefix: /usr/tce/packages/cuda/cuda-10.1.168
hip:
version: [3.7.0]
buildable: False
externals:
- spec: hip@3.7.0
prefix: /opt/rocm-3.7.0/hip
llvm-amdgpu:
version: [3.7.0]
buildable: False
externals:
- spec: llvm-amdgpu@3.7.0
prefix: /opt/rocm-3.7.0/llvm
hsa-rocr-dev:
version: [3.7.0]
buildable: False
externals:
- spec: hsa-rocr-dev@3.7.0
prefix: /opt/rocm-3.7.0/
rocminfo:
version: [3.7.0]
buildable: False
externals:
- spec: rocminfo@3.7.0
prefix: /opt/rocm-3.7.0/
rocm-device-libs:
version: [3.7.0]
buildable: False
externals:
- spec: rocm-device-libs@3.7.0
prefix: /opt/rocm-3.7.0/
+811
View File
@@ -0,0 +1,811 @@
#!/bin/sh
"exec" "python" "-u" "-B" "$0" "$@"
###############################################################################
# Copyright (c) 2014-2020, Lawrence Livermore National Security, LLC.
#
# Produced at the Lawrence Livermore National Laboratory
#
# LLNL-CODE-666778
#
# All rights reserved.
#
# This file is part of Conduit.
#
# For details, see https://lc.llnl.gov/conduit/.
#
# Please also read conduit/LICENSE
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the disclaimer below.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the disclaimer (as noted below) in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of the LLNS/LLNL nor the names of its contributors may
# be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL SECURITY,
# LLC, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
###############################################################################
"""
file: uberenv.py
description: automates using spack to install a project.
"""
import os
import sys
import subprocess
import shutil
import socket
import platform
import json
import datetime
import glob
import re
from optparse import OptionParser
from os import environ as env
from os.path import join as pjoin
def sexe(cmd,ret_output=False,echo=False):
""" Helper for executing shell commands. """
if echo:
print("[exe: {}]".format(cmd))
if ret_output:
p = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
out = p.communicate()[0]
out = out.decode('utf8')
return p.returncode,out
else:
return subprocess.call(cmd,shell=True)
def parse_args():
"Parses args from command line"
parser = OptionParser()
parser.add_option("--install",
action="store_true",
dest="install",
default=False,
help="Install `package_name`, not just its dependencies.")
# where to install
parser.add_option("--prefix",
dest="prefix",
default="uberenv_libs",
help="destination directory")
# what compiler to use
parser.add_option("--spec",
dest="spec",
default=None,
help="spack compiler spec")
# optional location of spack mirror
parser.add_option("--mirror",
dest="mirror",
default=None,
help="spack mirror directory")
# flag to create mirror
parser.add_option("--create-mirror",
action="store_true",
dest="create_mirror",
default=False,
help="Create spack mirror")
# optional location of spack upstream
parser.add_option("--upstream",
dest="upstream",
default=None,
help="add an external spack instance as upstream")
# this option allows a user to explicitly to select a
# group of spack settings files (compilers.yaml , packages.yaml)
parser.add_option("--spack-config-dir",
dest="spack_config_dir",
default=None,
help="dir with spack settings files (compilers.yaml, packages.yaml, etc)")
# overrides package_name
parser.add_option("--package-name",
dest="package_name",
default=None,
help="override the default package name")
# controls after which package phase spack should stop
parser.add_option("--package-final-phase",
dest="package_final_phase",
default=None,
help="override the default phase after which spack should stop")
# controls source_dir spack should use to build the package
parser.add_option("--package-source-dir",
dest="package_source_dir",
default=None,
help="override the default source dir spack should use")
# a file that holds settings for a specific project
# using uberenv.py
parser.add_option("--project-json",
dest="project_json",
default=pjoin(uberenv_script_dir(),"project.json"),
help="uberenv project settings json file")
# flag to use insecure curl + git
parser.add_option("-k",
action="store_true",
dest="ignore_ssl_errors",
default=False,
help="Ignore SSL Errors")
# option to force a spack pull
parser.add_option("--pull",
action="store_true",
dest="spack_pull",
default=False,
help="Pull if spack repo already exists")
# option to force for clean of packages specified to
# be cleaned in the project.json
parser.add_option("--clean",
action="store_true",
dest="spack_clean",
default=False,
help="Force uninstall of packages specified in project.json")
# option to tell spack to run tests
parser.add_option("--run_tests",
action="store_true",
dest="run_tests",
default=False,
help="Invoke build tests during spack install")
# option to init osx sdk env flags
parser.add_option("--macos-sdk-env-setup",
action="store_true",
dest="macos_sdk_env_setup",
default=False,
help="Set several env vars to select OSX SDK settings."
"This was necessary for older versions of macOS "
" but can cause issues with macOS versions >= 10.13. "
" so it is disabled by default.")
# option to stop after spack download and setup
parser.add_option("--setup-only",
action="store_true",
dest="setup_only",
default=False,
help="Only download and setup Spack. No further Spack command will be run.")
###############
# parse args
###############
opts, extras = parser.parse_args()
# we want a dict b/c the values could
# be passed without using optparse
opts = vars(opts)
if not opts["spack_config_dir"] is None:
opts["spack_config_dir"] = os.path.abspath(opts["spack_config_dir"])
if not os.path.isdir(opts["spack_config_dir"]):
print("[ERROR: invalid spack config dir: {} ]".format(opts["spack_config_dir"]))
sys.exit(-1)
# if rel path is given for the mirror, we need to evaluate here -- before any
# chdirs to avoid confusion related to what it is relative to.
# (it should be relative to where uberenv is run from, so it matches what you expect
# from shell completion, etc)
if not opts["mirror"] is None:
if not opts["mirror"].startswith("http") and not os.path.isabs(opts["mirror"]):
opts["mirror"] = os.path.abspath(opts["mirror"])
return opts, extras
def uberenv_script_dir():
# returns the directory of the uberenv.py script
return os.path.dirname(os.path.abspath(__file__))
def load_json_file(json_file):
# reads json file
return json.load(open(json_file))
def is_darwin():
return "darwin" in platform.system().lower()
def is_windows():
return "windows" in platform.system().lower()
class UberEnv():
""" Base class for package manager """
def __init__(self, opts, extra_opts):
self.opts = opts
self.extra_opts = extra_opts
# load project settings
self.project_opts = load_json_file(opts["project_json"])
print("[uberenv project settings: {}]".format(str(self.project_opts)))
print("[uberenv options: {}]".format(str(self.opts)))
def setup_paths_and_dirs(self):
self.uberenv_path = os.path.dirname(os.path.realpath(__file__))
def set_from_args_or_json(self,setting):
try:
setting_value = self.project_opts[setting]
except (KeyError):
print("ERROR: {} must at least be defined in project.json".format(setting))
raise
else:
if self.opts[setting]:
setting_value = self.opts[setting]
return setting_value
def set_from_json(self,setting):
try:
setting_value = self.project_opts[setting]
except (KeyError):
print("ERROR: {} must at least be defined in project.json".format(setting))
raise
return setting_value
def detect_platform(self):
# find supported sets of compilers.yaml, packages,yaml
res = None
if is_darwin():
res = "darwin"
elif "SYS_TYPE" in os.environ.keys():
sys_type = os.environ["SYS_TYPE"].lower()
res = sys_type
return res
class SpackEnv(UberEnv):
""" Helper to clone spack and install libraries on MacOS an Linux """
def __init__(self, opts, extra_opts):
UberEnv.__init__(self,opts,extra_opts)
self.pkg_name = self.set_from_args_or_json("package_name")
self.pkg_version = self.set_from_json("package_version")
self.pkg_final_phase = self.set_from_args_or_json("package_final_phase")
self.pkg_src_dir = self.set_from_args_or_json("package_source_dir")
self.spec_hash = ""
self.use_install = False
# Some additional setup for macos
if is_darwin():
if opts["macos_sdk_env_setup"]:
# setup osx deployment target and sdk settings
setup_osx_sdk_env_vars()
else:
print("[skipping MACOSX env var setup]")
# setup default spec
if opts["spec"] is None:
if is_darwin():
opts["spec"] = "%clang"
else:
opts["spec"] = "%gcc"
self.opts["spec"] = "@{}{}".format(self.pkg_version,opts["spec"])
elif not opts["spec"].startswith("@"):
self.opts["spec"] = "@{}{}".format(self.pkg_version,opts["spec"])
else:
self.opts["spec"] = "{}".format(opts["spec"])
print("[spack spec: {}]".format(self.opts["spec"]))
def setup_paths_and_dirs(self):
# get the current working path, and the glob used to identify the
# package files we want to hot-copy to spack
UberEnv.setup_paths_and_dirs(self)
self.pkgs = pjoin(self.uberenv_path, "packages","*")
# setup destination paths
self.dest_dir = os.path.abspath(self.opts["prefix"])
self.dest_spack = pjoin(self.dest_dir,"spack")
print("[installing to: {0}]".format(self.dest_dir))
# print a warning if the dest path already exists
if not os.path.isdir(self.dest_dir):
os.mkdir(self.dest_dir)
else:
print("[info: destination '{}' already exists]".format(self.dest_dir))
if os.path.isdir(self.dest_spack):
print("[info: destination '{}' already exists]".format(self.dest_spack))
self.pkg_src_dir = os.path.join(self.uberenv_path,self.pkg_src_dir)
if not os.path.isdir(self.pkg_src_dir):
print("[ERROR: package_source_dir '{}' does not exist]".format(self.pkg_src_dir))
sys.exit(-1)
def find_spack_pkg_path_from_hash(self, pkg_name, pkg_hash):
res, out = sexe("spack/bin/spack find -p /{}".format(pkg_hash), ret_output = True)
for l in out.split("\n"):
if l.startswith(pkg_name):
return {"name": pkg_name, "path": l.split()[-1]}
print("[ERROR: failed to find package named '{}']".format(pkg_name))
sys.exit(-1)
def find_spack_pkg_path(self, pkg_name, spec = ""):
res, out = sexe("spack/bin/spack find -p " + pkg_name + spec,ret_output = True)
for l in out.split("\n"):
# TODO: at least print a warning when several choices exist. This will
# pick the first in the list.
if l.startswith(pkg_name):
return {"name": pkg_name, "path": l.split()[-1]}
print("[ERROR: failed to find package named '{}']".format(pkg_name))
sys.exit(-1)
# Extract the first line of the full spec
def read_spack_full_spec(self,pkg_name,spec):
res, out = sexe("spack/bin/spack spec " + pkg_name + " " + spec, ret_output=True)
for l in out.split("\n"):
if l.startswith(pkg_name) and l.count("@") > 0 and l.count("arch=") > 0:
return l.strip()
def clone_repo(self):
if not os.path.isdir(self.dest_spack):
# compose clone command for the dest path, spack url and branch
print("[info: cloning spack develop branch from github]")
os.chdir(self.dest_dir)
clone_opts = ("-c http.sslVerify=false "
if self.opts["ignore_ssl_errors"] else "")
spack_url = self.project_opts.get("spack_url", "https://github.com/spack/spack.git")
spack_branch = self.project_opts.get("spack_branch", "develop")
clone_cmd = "git {0} clone --single-branch --depth=1 -b {1} {2}".format(clone_opts, spack_branch,spack_url)
sexe(clone_cmd, echo=True)
if "spack_commit" in self.project_opts:
# optionally, check out a specific commit
os.chdir(pjoin(self.dest_dir,"spack"))
sha1 = self.project_opts["spack_commit"]
res, current_sha1 = sexe("git log -1 --pretty=%H", ret_output=True)
if sha1 != current_sha1:
print("[info: using spack commit {}]".format(sha1))
sexe("git stash", echo=True)
sexe("git fetch --depth=1 origin {0}".format(sha1),echo=True)
sexe("git checkout {0}".format(sha1),echo=True)
if self.opts["spack_pull"]:
# do a pull to make sure we have the latest
os.chdir(pjoin(self.dest_dir,"spack"))
sexe("git stash", echo=True)
sexe("git pull", echo=True)
def config_dir(self):
""" path to compilers.yaml, which we will use for spack's compiler setup"""
spack_config_dir = self.opts["spack_config_dir"]
if spack_config_dir is None:
uberenv_plat = self.detect_platform()
if not uberenv_plat is None:
spack_config_dir = os.path.abspath(pjoin(self.uberenv_path,"spack_configs",uberenv_plat))
return spack_config_dir
def disable_spack_config_scopes(self,spack_dir):
# disables all config scopes except "defaults", which we will
# force our settings into
spack_lib_config = pjoin(spack_dir,"lib","spack","spack","config.py")
print("[disabling config scope (except defaults) in: {}]".format(spack_lib_config))
cfg_script = open(spack_lib_config).read()
for cfg_scope_stmt in ["('system', os.path.join(spack.paths.system_etc_path, 'spack')),",
"('site', os.path.join(spack.paths.etc_path, 'spack')),",
"('user', spack.paths.user_config_path)"]:
cfg_script = cfg_script.replace(cfg_scope_stmt,
"#DISABLED BY UBERENV: " + cfg_scope_stmt)
open(spack_lib_config,"w").write(cfg_script)
def patch(self):
cfg_dir = self.config_dir()
spack_dir = self.dest_spack
# force spack to use only "defaults" config scope
self.disable_spack_config_scopes(spack_dir)
spack_etc_defaults_dir = pjoin(spack_dir,"etc","spack","defaults")
# copy in "defaults" config.yaml
config_yaml = os.path.abspath(pjoin(self.uberenv_path,"spack_configs","config.yaml"))
sexe("cp {} {}/".format(config_yaml, spack_etc_defaults_dir ), echo=True)
# copy in other settings per platform
if not cfg_dir is None:
print("[copying uberenv compiler and packages settings from {0}]".format(cfg_dir))
config_yaml = pjoin(cfg_dir,"config.yaml")
compilers_yaml = pjoin(cfg_dir,"compilers.yaml")
packages_yaml = pjoin(cfg_dir,"packages.yaml")
if os.path.isfile(config_yaml):
sexe("cp {} {}/".format(config_yaml , spack_etc_defaults_dir ), echo=True)
if os.path.isfile(compilers_yaml):
sexe("cp {} {}/".format(compilers_yaml, spack_etc_defaults_dir ), echo=True)
if os.path.isfile(packages_yaml):
sexe("cp {} {}/".format(packages_yaml, spack_etc_defaults_dir ), echo=True)
else:
# let spack try to auto find compilers
sexe("spack/bin/spack compiler find", echo=True)
# hot-copy our packages into spack
if self.pkgs:
dest_spack_pkgs = pjoin(spack_dir,"var","spack","repos","builtin","packages")
print("[copying patched packages from {0}]".format(self.pkgs))
sexe("cp -Rf {} {}".format(self.pkgs,dest_spack_pkgs))
def clean_build(self):
# clean out any temporary spack build stages
cln_cmd = "spack/bin/spack clean "
res = sexe(cln_cmd, echo=True)
# clean out any spack cached stuff
cln_cmd = "spack/bin/spack clean --all"
res = sexe(cln_cmd, echo=True)
# check if we need to force uninstall of selected packages
if self.opts["spack_clean"]:
if self.project_opts.has_key("spack_clean_packages"):
for cln_pkg in self.project_opts["spack_clean_packages"]:
if not self.find_spack_pkg_path(cln_pkg) is None:
unist_cmd = "spack/bin/spack uninstall -f -y --all --dependents " + cln_pkg
res = sexe(unist_cmd, echo=True)
def show_info(self):
# prints install status and 32 characters hash
options="--install-status --very-long"
spec_cmd = "spack/bin/spack spec {0} {1}{2}".format(options,self.pkg_name,self.opts["spec"])
res, out = sexe(spec_cmd, ret_output=True, echo=True)
print(out)
#Check if spec is already installed
for line in out.split("\n"):
# Example of matching line: ("status" "hash" "package"...)
# [+] hf3cubkgl74ryc3qwen73kl4yfh2ijgd serac@develop%clang@10.0.0-apple~debug~devtools~glvis arch=darwin-mojave-x86_64
if re.match(r"^(\[\+\]| - ) [a-z0-9]{32} " + re.escape(self.pkg_name), line):
self.spec_hash = line.split(" ")[1]
# if spec already installed
if line.startswith("[+]"):
pkg_path = self.find_spack_pkg_path_from_hash(self.pkg_name,self.spec_hash)
install_path = pkg_path["path"]
# testing that the path exists is mandatory until Spack team fixes
# https://github.com/spack/spack/issues/16329
if os.path.isdir(install_path):
print("[Warning: {} {} has already been installed in {}]".format(self.pkg_name, self.opts["spec"],install_path))
print("[Warning: Uberenv will proceed using this directory]".format(self.pkg_name))
self.use_install = True
return res
def install(self):
# use the uberenv package to trigger the right builds
# and build an host-config.cmake file
if not self.use_install:
install_cmd = "spack/bin/spack "
if self.opts["ignore_ssl_errors"]:
install_cmd += "-k "
if not self.opts["install"]:
install_cmd += "dev-build --quiet -d {} -u {} ".format(self.pkg_src_dir,self.pkg_final_phase)
else:
install_cmd += "install "
if self.opts["run_tests"]:
install_cmd += "--test=root "
install_cmd += self.pkg_name + self.opts["spec"]
res = sexe(install_cmd, echo=True)
if res != 0:
print("[ERROR: failure of spack install/dev-build]")
return res
full_spec = self.read_spack_full_spec(self.pkg_name,self.opts["spec"])
if "spack_activate" in self.project_opts:
print("[activating dependent packages]")
# get the full spack spec for our project
pkg_names = self.project_opts["spack_activate"].keys()
for pkg_name in pkg_names:
pkg_spec_requirements = self.project_opts["spack_activate"][pkg_name]
activate=True
for req in pkg_spec_requirements:
if req not in full_spec:
activate=False
break
if activate:
activate_cmd = "spack/bin/spack activate " + pkg_name
sexe(activate_cmd, echo=True)
# note: this assumes package extends python when +python
# this may fail general cases
if self.opts["install"] and "+python" in full_spec:
activate_cmd = "spack/bin/spack activate /" + self.spec_hash
sexe(activate_cmd, echo=True)
# if user opt'd for an install, we want to symlink the final
# install to an easy place:
if self.opts["install"] or self.use_install:
pkg_path = self.find_spack_pkg_path_from_hash(self.pkg_name, self.spec_hash)
if self.pkg_name != pkg_path["name"]:
print("[ERROR: Could not find install of {}]".format(self.pkg_name))
return -1
else:
# Symlink host-config file
hc_glob = glob.glob(pjoin(pkg_path["path"],"*.cmake"))
if len(hc_glob) > 0:
hc_path = hc_glob[0]
hc_fname = os.path.split(hc_path)[1]
if os.path.islink(hc_fname):
os.unlink(hc_fname)
elif os.path.isfile(hc_fname):
sexe("rm -f {}".format(hc_fname))
print("[symlinking host config file to {}]".format(pjoin(self.dest_dir,hc_fname)))
os.symlink(hc_path,hc_fname)
# Symlink install directory
if self.opts["install"]:
pkg_lnk_dir = "{}-install".format(self.pkg_name)
if os.path.islink(pkg_lnk_dir):
os.unlink(pkg_lnk_dir)
print("")
print("[symlinking install to {}]".format(pjoin(self.dest_dir,pkg_lnk_dir)))
os.symlink(pkg_path["path"],os.path.abspath(pkg_lnk_dir))
print("")
print("[install complete!]")
# otherwise we are in the "only dependencies" case and the host-config
# file has to be copied from the do-be-deleted spack-build dir.
else:
pattern = "*{}.cmake".format(self.pkg_name)
build_dir = pjoin(self.pkg_src_dir,"spack-build")
hc_glob = glob.glob(pjoin(build_dir,pattern))
if len(hc_glob) > 0:
hc_path = hc_glob[0]
hc_fname = os.path.split(hc_path)[1]
if os.path.islink(hc_fname):
os.unlink(hc_fname)
print("[copying host config file to {}]".format(pjoin(self.dest_dir,hc_fname)))
sexe("cp {} {}".format(hc_path,hc_fname))
print("[removing project build directory {}]".format(pjoin(build_dir)))
sexe("rm -rf {}".format(build_dir))
def get_mirror_path(self):
mirror_path = self.opts["mirror"]
if not mirror_path:
print("[--create-mirror requires a mirror directory]")
sys.exit(-1)
return mirror_path
def create_mirror(self):
"""
Creates a spack mirror for pkg_name at mirror_path.
"""
mirror_path = self.get_mirror_path()
mirror_cmd = "spack/bin/spack "
if self.opts["ignore_ssl_errors"]:
mirror_cmd += "-k "
mirror_cmd += "mirror create -d {} --dependencies {}{}".format(mirror_path,
self.pkg_name,
self.opts["spec"])
return sexe(mirror_cmd, echo=True)
def find_spack_mirror(self, mirror_name):
"""
Returns the path of a defaults scoped spack mirror with the
given name, or None if no mirror exists.
"""
res, out = sexe("spack/bin/spack mirror list", ret_output=True)
mirror_path = None
for mirror in out.split('\n'):
if mirror:
parts = mirror.split()
if parts[0] == mirror_name:
mirror_path = parts[1]
return mirror_path
def use_mirror(self):
"""
Configures spack to use mirror at a given path.
"""
mirror_name = self.pkg_name
mirror_path = self.get_mirror_path()
existing_mirror_path = self.find_spack_mirror(mirror_name)
if existing_mirror_path and mirror_path != existing_mirror_path:
# Existing mirror has different URL, error out
print("[removing existing spack mirror `{}` @ {}]".format(mirror_name,
existing_mirror_path))
#
# Note: In this case, spack says it removes the mirror, but we still
# get errors when we try to add a new one, sounds like a bug
#
sexe("spack/bin/spack mirror remove --scope=defaults {} ".format(mirror_name),
echo=True)
existing_mirror_path = None
if not existing_mirror_path:
# Add if not already there
sexe("spack/bin/spack mirror add --scope=defaults {} {}".format(
mirror_name, mirror_path), echo=True)
print("[using mirror {}]".format(mirror_path))
def find_spack_upstream(self, upstream_name):
"""
Returns the path of a defaults scoped spack upstream with the
given name, or None if no upstream exists.
"""
upstream_path = None
res, out = sexe('spack/bin/spack config get upstreams', ret_output=True)
if (not out) and ("upstreams:" in out):
out = out.replace(' ', '')
out = out.replace('install_tree:', '')
out = out.replace(':', '')
out = out.splitlines()
out = out[1:]
upstreams = dict(zip(out[::2], out[1::2]))
for name in upstreams.keys():
if name == upstream_name:
upstream_path = upstreams[name]
return upstream_path
def use_spack_upstream(self):
"""
Configures spack to use upstream at a given path.
"""
upstream_path = self.opts["upstream"]
if not upstream_path:
print("[--create-upstream requires a upstream directory]")
sys.exit(-1)
upstream_path = os.path.abspath(upstream_path)
upstream_name = self.pkg_name
existing_upstream_path = self.find_spack_upstream(upstream_name)
if (not existing_upstream_path) or (upstream_path != os.path.abspath(existing_upstream_path)):
# Existing upstream has different URL, error out
print("[removing existing spack upstream configuration file]")
sexe("rm spack/etc/spack/defaults/upstreams.yaml")
with open('spack/etc/spack/defaults/upstreams.yaml','w+') as upstreams_cfg_file:
upstreams_cfg_file.write("upstreams:\n")
upstreams_cfg_file.write(" {}:\n".format(upstream_name))
upstreams_cfg_file.write(" install_tree: {}\n".format(upstream_path))
def find_osx_sdks():
"""
Finds installed osx sdks, returns dict mapping version to file system path
"""
res = {}
sdks = glob.glob("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk")
for sdk in sdks:
sdk_base = os.path.split(sdk)[1]
ver = sdk_base[len("MacOSX"):sdk_base.rfind(".")]
res[ver] = sdk
return res
def setup_osx_sdk_env_vars():
"""
Finds installed osx sdks, returns dict mapping version to file system path
"""
# find current osx version (10.11.6)
dep_tgt = platform.mac_ver()[0]
# sdk file names use short version (ex: 10.11)
dep_tgt_short = dep_tgt[:dep_tgt.rfind(".")]
# find installed sdks, ideally we want the sdk that matches the current os
sdk_root = None
sdks = find_osx_sdks()
if dep_tgt_short in sdks.keys():
# matches our osx, use this one
sdk_root = sdks[dep_tgt_short]
elif len(sdks) > 0:
# for now, choose first one:
dep_tgt = sdks.keys()[0]
sdk_root = sdks[dep_tgt]
else:
# no valid sdks, error out
print("[ERROR: Could not find OSX SDK @ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/]")
sys.exit(-1)
env["MACOSX_DEPLOYMENT_TARGET"] = dep_tgt
env["SDKROOT"] = sdk_root
print("[setting MACOSX_DEPLOYMENT_TARGET to {}]".format(env["MACOSX_DEPLOYMENT_TARGET"]))
print("[setting SDKROOT to {}]".format(env[ "SDKROOT"]))
def main():
"""
Clones and runs a package manager to setup third_party libs.
Also creates a host-config.cmake file that can be used by our project.
"""
# parse args from command line
opts, extra_opts = parse_args()
# Initialize the environment
env = SpackEnv(opts, extra_opts)
# Setup the necessary paths and directories
env.setup_paths_and_dirs()
# Clone the package manager
env.clone_repo()
os.chdir(env.dest_dir)
# Patch the package manager, as necessary
env.patch()
# Clean the build
env.clean_build()
# Allow to end uberenv after spack is ready
if opts["setup_only"]:
return 0
# Show the spec for what will be built
env.show_info()
##########################################################
# we now have an instance of spack configured how we
# need it to build our tpls at this point there are two
# possible next steps:
#
# *) create a mirror of the packages
# OR
# *) build
#
##########################################################
if opts["create_mirror"]:
return env.create_mirror()
else:
if not opts["mirror"] is None:
env.use_mirror()
if not opts["upstream"] is None:
env.use_spack_upstream()
res = env.install()
return res
if __name__ == "__main__":
sys.exit(main())