summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/eckit/package.py
blob: 2c5ca7326786d7e9bf65b4ca4ffedacda8105f1a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# 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")