summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/spectrum-mpi/package.py
blob: 8b4efee5ff14169e8a32295354faa98093cef308 (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
# Copyright 2013-2023 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
import re

from spack.package import *


class SpectrumMpi(BundlePackage):
    """IBM MPI implementation from Spectrum MPI."""

    has_code = False

    homepage = "https://www-03.ibm.com/systems/spectrum-computing/products/mpi"

    # https://www.ibm.com/docs/en/smpi/10.4
    version("10.4")

    provides("mpi")

    executables = ["^ompi_info$"]

    @classmethod
    def determine_version(cls, exe):
        output = Executable(exe)(output=str, error=str)
        match = re.search(r"Spectrum MPI: (\S+)", output)
        if not match:
            return None
        version = match.group(1)
        return version

    @classmethod
    def determine_variants(cls, exes, version):
        compiler_suites = {
            "xl": {"cc": "mpixlc", "cxx": "mpixlC", "f77": "mpixlf", "fc": "mpixlf"},
            "pgi": {"cc": "mpipgicc", "cxx": "mpipgic++", "f77": "mpipgifort", "fc": "mpipgifort"},
            "default": {"cc": "mpicc", "cxx": "mpicxx", "f77": "mpif77", "fc": "mpif90"},
        }

        def get_host_compiler(exe):
            output = Executable(exe)("--showme", output=str, error=str)
            match = re.search(r"^(\S+)", output)
            return match.group(1) if match else None

        def get_spack_compiler_spec(compilers_found):
            # check using cc for now, as everyone should have that defined.
            path = os.path.dirname(compilers_found["cc"])
            spack_compilers = spack.compilers.find_compilers([path])
            actual_compiler = None
            # check if the compiler actually matches the one we want
            for spack_compiler in spack_compilers:
                if os.path.dirname(spack_compiler.cc) == path:
                    actual_compiler = spack_compiler
                    break
            return actual_compiler.spec if actual_compiler else None

        def get_opal_prefix(exe):
            output = Executable(exe)(output=str, error=str)
            match = re.search(r"Prefix: (\S+)", output)
            if not match:
                return None
            opal_prefix = match.group(1)
            return opal_prefix

        results = []
        for exe in exes:
            dirname = os.path.dirname(exe)
            siblings = os.listdir(dirname)
            compilers_found = {}
            for compiler_suite in compiler_suites.values():
                for compiler_class, compiler_name in compiler_suite.items():
                    if compiler_name in siblings:
                        # Get the real name of the compiler
                        full_exe = os.path.join(dirname, compiler_name)
                        host_exe = get_host_compiler(full_exe)
                        if host_exe:
                            compilers_found[compiler_class] = host_exe
                if compilers_found:
                    break
            if compilers_found:
                compiler_spec = get_spack_compiler_spec(compilers_found)
                if compiler_spec:
                    variant = "%" + str(compiler_spec)
                else:
                    variant = ""
                # Use this variant when you need to define the
                # compilers explicitly
                #
                # results.append((variant, {'compilers': compilers_found}))
                #
                # Otherwise, use this simpler attribute
            else:
                variant = ""
            opal_prefix = get_opal_prefix(exe)
            if opal_prefix:
                extra_attributes = {"opal_prefix": opal_prefix}
                results.append((variant, extra_attributes))
            else:
                results.append(variant)
        return results

    def setup_dependent_package(self, module, dependent_spec):
        # get the compiler names
        if "%xl" in dependent_spec or "%xl_r" in dependent_spec:
            self.spec.mpicc = os.path.join(self.prefix.bin, "mpixlc")
            self.spec.mpicxx = os.path.join(self.prefix.bin, "mpixlC")
            self.spec.mpif77 = os.path.join(self.prefix.bin, "mpixlf")
            self.spec.mpifc = os.path.join(self.prefix.bin, "mpixlf")
        elif "%pgi" in dependent_spec:
            self.spec.mpicc = os.path.join(self.prefix.bin, "mpipgicc")
            self.spec.mpicxx = os.path.join(self.prefix.bin, "mpipgic++")
            self.spec.mpif77 = os.path.join(self.prefix.bin, "mpipgifort")
            self.spec.mpifc = os.path.join(self.prefix.bin, "mpipgifort")
        else:
            self.spec.mpicc = os.path.join(self.prefix.bin, "mpicc")
            self.spec.mpicxx = os.path.join(self.prefix.bin, "mpicxx")
            self.spec.mpif77 = os.path.join(self.prefix.bin, "mpif77")
            self.spec.mpifc = os.path.join(self.prefix.bin, "mpif90")

    def setup_dependent_build_environment(self, env, dependent_spec):
        if "%xl" in dependent_spec or "%xl_r" in dependent_spec:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpixlc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpixlC"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpixlf"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpixlf"))
        elif "%pgi" in dependent_spec:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpipgicc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpipgic++"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpipgifort"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpipgifort"))
        else:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpicc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpic++"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpif77"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpif90"))

        env.set("OMPI_CC", spack_cc)
        env.set("OMPI_CXX", spack_cxx)
        env.set("OMPI_FC", spack_fc)
        env.set("OMPI_F77", spack_f77)

        env.prepend_path("LD_LIBRARY_PATH", self.prefix.lib)

    def setup_run_environment(self, env):
        # Because MPI functions as a compiler we need to setup the compilers
        # in the run environment, like any compiler
        if "%xl" in self.spec or "%xl_r" in self.spec:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpixlc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpixlC"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpixlf"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpixlf"))
        elif "%pgi" in self.spec:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpipgicc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpipgic++"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpipgifort"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpipgifort"))
        else:
            env.set("MPICC", os.path.join(self.prefix.bin, "mpicc"))
            env.set("MPICXX", os.path.join(self.prefix.bin, "mpic++"))
            env.set("MPIF77", os.path.join(self.prefix.bin, "mpif77"))
            env.set("MPIF90", os.path.join(self.prefix.bin, "mpif90"))

        env.set("OPAL_PREFIX", self.spec.extra_attributes.get("opal_prefix", self.prefix))
        env.set("MPI_ROOT", self.spec.extra_attributes.get("opal_prefix", self.prefix))