237 lines
7.2 KiB
Python
237 lines
7.2 KiB
Python
# Copyright Spack Project Developers. See COPYRIGHT file for details.
|
|
#
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
import os
|
|
|
|
from spack.package import *
|
|
from spack.pkg.builtin.boost import Boost
|
|
|
|
|
|
class Xios(Package):
|
|
"""XML-IO-SERVER library for IO management of climate models."""
|
|
|
|
homepage = "https://forge.ipsl.jussieu.fr/ioserver/wiki"
|
|
|
|
version("develop", svn="http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/trunk")
|
|
version(
|
|
"2.5", revision=1860, svn="http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/branchs/xios-2.5"
|
|
)
|
|
version(
|
|
"2.0", revision=1627, svn="http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/branchs/xios-2.0"
|
|
)
|
|
version(
|
|
"1.0", revision=910, svn="http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/branchs/xios-1.0"
|
|
)
|
|
|
|
variant(
|
|
"mode",
|
|
values=("debug", "dev", "prod"),
|
|
default="dev",
|
|
description="Build for debugging, development or production",
|
|
)
|
|
# NOTE: oasis coupler could be supported with a variant
|
|
|
|
# Use spack versions of blitz and netcdf-c for compatibility
|
|
# with recent compilers and optimised platform libraries:
|
|
patch("bld_extern_1.0.patch", when="@:1.0")
|
|
|
|
# Workaround bug #17782 in llvm, where reading a double
|
|
# followed by a character is broken (e.g. duration '1d'):
|
|
patch("llvm_bug_17782.patch", when="@1.1: %apple-clang")
|
|
patch("llvm_bug_17782.patch", when="@1.1: %clang")
|
|
|
|
depends_on("netcdf-c+mpi")
|
|
depends_on("netcdf-fortran")
|
|
depends_on("hdf5+mpi")
|
|
depends_on("mpi")
|
|
|
|
# TODO: replace this with an explicit list of components of Boost,
|
|
# for instance depends_on('boost +filesystem')
|
|
# See https://github.com/spack/spack/pull/22303 for reference
|
|
depends_on(Boost.with_default_variants)
|
|
depends_on("blitz")
|
|
depends_on("perl", type="build")
|
|
depends_on("perl-uri", type="build")
|
|
depends_on("gmake", type="build")
|
|
|
|
@when("%clang")
|
|
def patch(self):
|
|
self.patch_llvm()
|
|
|
|
@when("%apple-clang")
|
|
def patch(self):
|
|
self.patch_llvm()
|
|
|
|
def patch_llvm(self):
|
|
"""Fix type references that are ambiguous for clang."""
|
|
for dirpath, dirnames, filenames in os.walk("src"):
|
|
for filename in filenames:
|
|
filepath = os.path.join(dirpath, filename)
|
|
# Use boost definition of type shared_ptr:
|
|
filter_file(r"([^:/])shared_ptr<", r"\1boost::shared_ptr<", filepath)
|
|
# Use type long for position in output stream:
|
|
filter_file(
|
|
r"oss.tellp\(\) *- *startPos", r"(long)oss.tellp() - startPos", filepath
|
|
)
|
|
|
|
def xios_env(self):
|
|
file = join_path("arch", "arch-SPACK.env")
|
|
touch(file)
|
|
|
|
def xios_path(self):
|
|
file = join_path("arch", "arch-SPACK.path")
|
|
spec = self.spec
|
|
paths = {
|
|
"NETCDF_INC_DIR": spec["netcdf-c"].prefix.include,
|
|
"NETCDF_LIB_DIR": spec["netcdf-c"].prefix.lib,
|
|
"HDF5_INC_DIR": spec["hdf5"].prefix.include,
|
|
"HDF5_LIB_DIR": spec["hdf5"].prefix.lib,
|
|
}
|
|
text = r"""
|
|
NETCDF_INCDIR="-I {NETCDF_INC_DIR}"
|
|
NETCDF_LIBDIR="-L {NETCDF_LIB_DIR}"
|
|
NETCDF_LIB="-lnetcdff -lnetcdf"
|
|
|
|
MPI_INCDIR=""
|
|
MPI_LIBDIR=""
|
|
MPI_LIB=""
|
|
|
|
HDF5_INCDIR="-I {HDF5_INC_DIR}"
|
|
HDF5_LIBDIR="-L {HDF5_LIB_DIR}"
|
|
HDF5_LIB="-lhdf5_hl -lhdf5"
|
|
|
|
OASIS_INCDIR=""
|
|
OASIS_LIBDIR=""
|
|
OASIS_LIB=""
|
|
"""
|
|
with open(file, "w") as f:
|
|
f.write(text.format(**paths))
|
|
|
|
def xios_fcm(self):
|
|
file = join_path("arch", "arch-SPACK.fcm")
|
|
spec = self.spec
|
|
param = dict()
|
|
param["MPICXX"] = spec["mpi"].mpicxx
|
|
param["MPIFC"] = spec["mpi"].mpifc
|
|
param["CC"] = self.compiler.cc
|
|
param["FC"] = self.compiler.fc
|
|
param["BOOST_INC_DIR"] = spec["boost"].prefix.include
|
|
param["BOOST_LIB_DIR"] = spec["boost"].prefix.lib
|
|
param["BLITZ_INC_DIR"] = spec["blitz"].prefix.include
|
|
param["BLITZ_LIB_DIR"] = spec["blitz"].prefix.lib
|
|
if spec.satisfies("%apple-clang"):
|
|
param["LIBCXX"] = "-lc++"
|
|
else:
|
|
param["LIBCXX"] = "-lstdc++"
|
|
|
|
if any(map(spec.satisfies, ("%gcc", "%intel", "%apple-clang", "%clang", "%fj"))):
|
|
text = r"""
|
|
%CCOMPILER {MPICXX}
|
|
%FCOMPILER {MPIFC}
|
|
%LINKER {MPIFC}
|
|
|
|
%BASE_CFLAGS -ansi -w -D_GLIBCXX_USE_CXX11_ABI=0 \
|
|
-I{BOOST_INC_DIR} -I{BLITZ_INC_DIR}
|
|
%PROD_CFLAGS -O3 -DBOOST_DISABLE_ASSERTS
|
|
%DEV_CFLAGS -g -O2
|
|
%DEBUG_CFLAGS -g
|
|
|
|
%BASE_FFLAGS -D__NONE__
|
|
%PROD_FFLAGS -O3
|
|
%DEV_FFLAGS -g -O2
|
|
%DEBUG_FFLAGS -g
|
|
|
|
%BASE_INC -D__NONE__
|
|
%BASE_LD -L{BOOST_LIB_DIR} -L{BLITZ_LIB_DIR} -lblitz {LIBCXX}
|
|
|
|
%CPP {CC} -E
|
|
%FPP {CC} -E -P -x c
|
|
%MAKE make
|
|
""".format(
|
|
**param
|
|
)
|
|
elif spec.satisfies("%cce"):
|
|
# In the CC compiler prior to cce/8.3.7,
|
|
# optimisation must be reduced to avoid a bug,
|
|
# as reported by Mike Rezny at the UK Met Office:
|
|
if spec.satisfies("%cce@8.3.7:"):
|
|
param.update({"CC_OPT_DEV": "-O2", "CC_OPT_PROD": "-O3"})
|
|
else:
|
|
param.update({"CC_OPT_DEV": "-O1", "CC_OPT_PROD": "-O1"})
|
|
|
|
text = r"""
|
|
%CCOMPILER {MPICXX}
|
|
%FCOMPILER {MPIFC}
|
|
%LINKER {MPIFC}
|
|
|
|
%BASE_CFLAGS -DMPICH_SKIP_MPICXX -h msglevel_4 -h zero -h gnu \
|
|
-I{BOOST_INC_DIR} -I{BLITZ_INC_DIR}
|
|
%PROD_CFLAGS {CC_OPT_PROD} -DBOOST_DISABLE_ASSERTS
|
|
%DEV_CFLAGS {CC_OPT_DEV}
|
|
%DEBUG_CFLAGS -g
|
|
|
|
%BASE_FFLAGS -em -m 4 -e0 -eZ
|
|
%PROD_FFLAGS -O3
|
|
%DEV_FFLAGS -G2
|
|
%DEBUG_FFLAGS -g
|
|
|
|
%BASE_INC -D__NONE__
|
|
%BASE_LD -D__NONE__ -L{BOOST_LIB_DIR} -L{BLITZ_LIB_DIR} -lblitz
|
|
|
|
%CPP cpp
|
|
%FPP cpp -P -CC
|
|
%MAKE gmake
|
|
""".format(
|
|
**param
|
|
)
|
|
else:
|
|
raise InstallError("Unsupported compiler.")
|
|
|
|
with open(file, "w") as f:
|
|
f.write(text)
|
|
|
|
def install(self, spec, prefix):
|
|
env["CC"] = spec["mpi"].mpicc
|
|
env["CXX"] = spec["mpi"].mpicxx
|
|
env["F77"] = spec["mpi"].mpif77
|
|
env["FC"] = spec["mpi"].mpifc
|
|
|
|
options = [
|
|
"--full",
|
|
"--%s" % spec.variants["mode"].value,
|
|
"--arch",
|
|
"SPACK",
|
|
"--netcdf_lib",
|
|
"netcdf4_par",
|
|
"--job",
|
|
str(make_jobs),
|
|
]
|
|
|
|
self.xios_env()
|
|
self.xios_path()
|
|
self.xios_fcm()
|
|
|
|
make_xios = Executable("./make_xios")
|
|
make_xios(*options)
|
|
|
|
mkdirp(spec.prefix)
|
|
install_tree("bin", spec.prefix.bin)
|
|
install_tree("lib", spec.prefix.lib)
|
|
install_tree("inc", spec.prefix.include)
|
|
install_tree("etc", spec.prefix.etc)
|
|
install_tree("cfg", spec.prefix.cfg)
|
|
|
|
@run_after("install")
|
|
@on_package_attributes(run_tests=True)
|
|
def check_build(self):
|
|
mpirun = os.getenv("MPIRUN")
|
|
if mpirun is None:
|
|
mpirun = "mpiexec"
|
|
mpiexec = Executable(mpirun)
|
|
with working_dir("inputs"):
|
|
try:
|
|
mpiexec("-n", "2", join_path("..", "bin", "test_client.exe"))
|
|
except Exception:
|
|
raise InstallError("Test failed; defining MPIRUN variable may help.")
|