# Copyright 2013-2024 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)
import os
from spack.package import *
class Eckit(CMakePackage):
"""ecKit is a cross-platform c++ toolkit that supports development of tools
and applications at ECMWF."""
homepage = "https://github.com/ecmwf/eckit"
git = "https://github.com/ecmwf/eckit.git"
url = "https://github.com/ecmwf/eckit/archive/refs/tags/1.16.0.tar.gz"
maintainers("skosukhin", "climbfuji", "victoria-cherkas", "dominichofer")
license("Apache-2.0")
version("1.24.5", sha256="2fd74e04c20a59f9e13635828d9da880e18f8a2cb7fd3bfd0201e07071d6ec41")
version("1.24.4", sha256="b6129eb4f7b8532aa6905033e4cf7d09aadc8547c225780fea3db196e34e4671")
version("1.23.1", sha256="cd3c4b7a3a2de0f4a59f00f7bab3178dd59c0e27900d48eaeb357975e8ce2f15")
version("1.23.0", sha256="3cac55ddf7036ecd32cb0974a1ec3a2d347de574ab3a2c0bb6c6f8982e5a7a09")
version("1.22.1", sha256="a3463d07e47e3bd3e5efa13fdc03d7d3a30ada919ccec3259c6c9c7da4cfdfd9")
version("1.20.2", sha256="9c11ddaaf346e40d11312b81ca7f1b510017f26618f4c0f5c5c59c37623fbac8")
version("1.19.0", sha256="a5fef36b4058f2f0aac8daf5bcc9740565f68da7357ddd242de3a5eed4765cc7")
version("1.16.3", sha256="d2aae7d8030e2ce39e5d04e36dd6aa739f3c8dfffe32c61c2a3127c36b573485")
version("1.16.0", sha256="9e09161ea6955df693d3c9ac70131985eaf7cf24a9fa4d6263661c6814ebbaf1")
variant(
"build_type",
default="RelWithDebInfo",
description="CMake build type",
values=("Debug", "Release", "RelWithDebInfo"),
)
variant("tools", default=True, description="Build the command line tools")
variant("mpi", default=True, description="Enable MPI support")
variant("openmp", default=True, description="Enable OpenMP support")
variant("admin", default=True, description="Build utilities for administration tools")
variant("sql", default=True, description="Build SQL engine")
variant(
"linalg",
values=any_combination_of("eigen", "armadillo", "mkl", "lapack"),
description="List of supported linear algebra backends",
)
variant(
"compression",
values=any_combination_of("bzip2", "snappy", "lz4", "aec"),
description="List of supported compression backends",
)
variant("xxhash", default=True, description="Enable xxHash support for hashing")
variant("ssl", default=False, description="Enable MD4 and SHA1 support with OpenSSL")
variant("curl", default=False, description="Enable URL data transferring with cURL")
variant("jemalloc", default=False, description="Link against jemalloc memory allocator")
variant(
"unicode",
default=True,
description="Enable support for Unicode characters in Yaml/JSON" "parsers",
)
variant("aio", default=True, description="Enable asynchronous IO")
variant("fismahigh", default=False, description="Apply patching for FISMA-high compliance")
# Build issues with cmake 3.20, not sure about 3.21
depends_on("cmake@3.12:3.19,3.22:", type="build")
depends_on("ecbuild@3.5:", when="@:1.20.99", type="build")
depends_on("ecbuild@3.7:", when="@1.21:", type="build")
depends_on("mpi", when="+mpi")
depends_on("llvm-openmp", when="+openmp %apple-clang", type=("build", "run"))
depends_on("yacc", type="build", when="+admin")
depends_on("flex", type="build", when="+admin")
depends_on("ncurses", when="+admin")
depends_on("yacc", type="build", when="+sql")
depends_on("flex", type="build", when="+sql")
depends_on("eigen", when="linalg=eigen")
depends_on("armadillo", when="linalg=armadillo")
depends_on("mkl", when="linalg=mkl")
depends_on("lapack", when="linalg=lapack")
depends_on("bzip2", when="compression=bzip2")
depends_on("snappy", when="compression=snappy")
depends_on("lz4", when="compression=lz4")
depends_on("libaec", when="compression=aec")
depends_on("openssl", when="+ssl")
depends_on("curl", when="+curl")
depends_on("jemalloc", when="+jemalloc")
# The package enables LAPACK backend (together with MKL backend)
# when='linalg=mkl'. This leads to two identical installations when:
# eckit linalg=mkl
# eckit linalg=mkl,lapack
# We prevent that by introducing the following conflict:
conflicts(
"linalg=lapack",
when="linalg=mkl",
msg='"linalg=lapack" is implied when "linalg=mkl" and '
"must not be specified additionally",
)
def cmake_args(self):
args = [
# Some features that we want to build are experimental:
self.define("ENABLE_EXPERIMENTAL", self._enable_experimental),
self.define_from_variant("ENABLE_BUILD_TOOLS", "tools"),
# We let ecBuild find the MPI library. We could help it by setting
# CMAKE_C_COMPILER to mpicc but that might give CMake a wrong
# impression that no additional flags are needed to link to
# libpthread, which will lead to problems with libraries that are
# linked with the C++ compiler. We could additionally set
# CMAKE_CXX_COMPILER to mpicxx. That would solve the problem with
# libpthread but lead to overlinking to MPI libraries, which we
# currently prefer to avoid since ecBuild does the job in all known
# cases.
self.define_from_variant("ENABLE_MPI", "mpi"),
self.define_from_variant("ENABLE_OMP", "openmp"),
self.define_from_variant("ENABLE_ECKIT_CMD", "admin"),
self.define_from_variant("ENABLE_ECKIT_SQL", "sql"),
self.define("ENABLE_EIGEN", "linalg=eigen" in self.spec),
self.define("ENABLE_ARMADILLO", "linalg=armadillo" in self.spec),
self.define("ENABLE_MKL", "linalg=mkl" in self.spec),
self.define("ENABLE_BZIP2", "compression=bzip2" in self.spec),
self.define("ENABLE_SNAPPY", "compression=snappy" in self.spec),
self.define("ENABLE_LZ4", "compression=lz4" in self.spec),
self.define("ENABLE_AEC", "compression=aec" in self.spec),
self.define_from_variant("ENABLE_XXHASH", "xxhash"),
self.define_from_variant("ENABLE_SSL", "ssl"),
self.define_from_variant("ENABLE_CURL", "curl"),
self.define_from_variant("ENABLE_JEMALLOC", "jemalloc"),
self.define_from_variant("ENABLE_UNICODE", "unicode"),
self.define_from_variant("ENABLE_AIO", "aio"),
self.define("ENABLE_TESTS", self.run_tests),
# Unconditionally disable additional unit/performance tests, since
# they download additional data (~1.6GB):
self.define("ENABLE_EXTRA_TESTS", False),
# No reason to check for doxygen and generate the documentation
# since it is not installed:
self.define("ENABLE_DOCS", False),
# Disable features that are currently not needed:
self.define("ENABLE_CUDA", False),
self.define("ENABLE_VIENNACL", False),
# Ceph/Rados storage support requires https://github.com/ceph/ceph
# and will be added later:
self.define("ENABLE_RADOS", False),
# rsync support requires https://github.com/librsync/librsync and
# will be added later:
self.define("ENABLE_RSYNC", False),
# Disable "prototyping code that may never see the light of day":
self.define("ENABLE_SANDBOX", False),
]
# Static build of eckit not working, many places in eckit's build
# system have SHARED hardcoded (in several CMakeLists.txt files).
args.append("-DBUILD_SHARED_LIBS=ON")
if "linalg=mkl" not in self.spec:
# ENABLE_LAPACK is ignored if MKL backend is enabled
# (the LAPACK backend is still built though):
args.append(self.define("ENABLE_LAPACK", "linalg=lapack" in self.spec))
if "+admin" in self.spec and "+termlib" in self.spec["ncurses"]:
# Make sure that libeckit_cmd is linked to a library that resolves 'setupterm',
# 'tputs', etc. That is either libncurses (when 'ncurses~termlib') or libtinfo (when
# 'ncurses+termlib'). CMake considers the latter only if CURSES_NEED_NCURSES is set to
# TRUE. Note that the installation of eckit does not fail without this but the building
# of a dependent package (e.g. fdb) might fail due to the undefined references.
args.append(self.define("CURSES_NEED_NCURSES", True))
return args
def setup_build_environment(self, env):
# Bug fix for macOS - cmake's find_package doesn't add "libtinfo.dylib" to the
# ncurses libraries, but the ncurses pkgconfig explicitly sets it. We need to
# add the correct spec['ncurses'].libs.ld_flags to LDFLAGS to compile eckit
# when the admin variant is enabled.
if self.spec.satisfies("platform=darwin") and self.spec.satisfies("+admin"):
env.append_flags("LDFLAGS", self.spec["ncurses"].libs.ld_flags)
def check(self):
ctest_args = ["-j", str(make_jobs)]
broken_tests = []
if self._enable_experimental:
# The following test quasi-randomly fails not because it reveals a bug in the library
# but because its implementation has a bug (static initialization order fiasco):
broken_tests.append("eckit_test_experimental_singleton_singleton")
if broken_tests:
ctest_args.extend(["-E", "|".join(broken_tests)])
with working_dir(self.build_directory):
ctest(*ctest_args)
@property
def _enable_experimental(self):
return "linalg=armadillo" in self.spec
@when("+fismahigh")
def patch(self):
if os.path.exists(".travis.yml"):
os.remove(".travis.yml")