Newer
Older
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
# #
# Copyright 2021-2021 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
# #
"""
EasyBuild support for installing Intel compilers, implemented as an easyblock
@author: Kenneth Hoste (Ghent University)
"""
import os
from distutils.version import LooseVersion
from easybuild.easyblocks.generic.intelbase import IntelBase
from easybuild.easyblocks.t.tbb import get_tbb_gccprefix
from easybuild.tools.build_log import EasyBuildError, print_msg
from easybuild.tools.run import run_cmd
class EB_intel_minus_compilers(IntelBase):
"""
Support for installing Intel compilers, starting with verion 2021.x (oneAPI)
"""
def __init__(self, *args, **kwargs):
"""
Easyblock constructor: check version
"""
super(EB_intel_minus_compilers, self).__init__(*args, **kwargs)
# this easyblock is only valid for recent versions of the Intel compilers (2021.x, oneAPI)
if LooseVersion(self.version) < LooseVersion('2021'):
raise EasyBuildError("Invalid version %s, should be >= 2021.x" % self.version)
self.compilers_subdir = os.path.join('compiler', self.version, 'linux')
# note that tbb may have a lower version number than the compiler, so use 'latest' symlink
# for example compiler 2021.1.2 has tbb 2021.1.1.
self.tbb_subdir = os.path.join('tbb', 'latest')
def prepare_step(self, *args, **kwargs):
"""
Prepare environment for installing.
Specify that oneAPI versions of Intel compilers don't require a runtime license.
"""
# avoid that IntelBase trips over not having license info specified
kwargs['requires_runtime_license'] = False
super(EB_intel_minus_compilers, self).prepare_step(*args, **kwargs)
def configure_step(self):
"""Configure installation."""
# redefine $HOME for install step, to avoid that anything is stored in $HOME/intel
# (like the 'installercache' database)
self.cfg['preinstallopts'] += " HOME=%s " % self.builddir
def install_step(self):
"""
Install step: install each 'source file' one by one.
Installing the Intel compilers could be done via a single installation file (HPC Toolkit),
or with separate installation files (patch releases of the C++ and Fortran compilers).
"""
srcs = self.src[:]
cnt = len(srcs)
for idx, src in enumerate(srcs):
print_msg("installing part %d/%s (%s)..." % (idx + 1, cnt, src['name']))
self.src = [src]
super(EB_intel_minus_compilers, self).install_step()
def sanity_check_step(self):
"""
Custom sanity check for Intel compilers.
"""
classic_compiler_cmds = ['icc', 'icpc', 'ifort']
oneapi_compiler_cmds = [
'dpcpp', # Intel oneAPI Data Parallel C++ compiler
'icx', # oneAPI Intel C compiler
'icpx', # oneAPI Intel C++ compiler
'ifx', # oneAPI Intel Fortran compiler
]
bindir = os.path.join(self.compilers_subdir, 'bin')
classic_compiler_paths = [os.path.join(bindir, x) for x in oneapi_compiler_cmds]
oneapi_compiler_paths = [os.path.join(bindir, 'intel64', x) for x in classic_compiler_cmds]
custom_paths = {
'files': classic_compiler_paths + oneapi_compiler_paths,
'dirs': [self.compilers_subdir],
}
all_compiler_cmds = classic_compiler_cmds + oneapi_compiler_cmds
custom_commands = ["which %s" % c for c in all_compiler_cmds]
# only for 2021.x versions do all compiler commands have the expected version;
# for example: for 2022.0.1, icc has version 2021.5.0, icpx has 2022.0.0
if LooseVersion(self.version) >= LooseVersion('2022.0'):
custom_commands.extend("%s --version" % c for c in all_compiler_cmds)
else:
custom_commands.extend("%s --version | grep %s" % (c, self.version) for c in all_compiler_cmds)
super(EB_intel_minus_compilers, self).sanity_check_step(custom_paths=custom_paths,
custom_commands=custom_commands)
def make_module_req_guess(self):
"""
Paths to consider for prepend-paths statements in module file
"""
libdirs = [
'lib',
os.path.join('lib', 'x64'),
os.path.join('compiler', 'lib', 'intel64_lin'),
]
libdirs = [os.path.join(self.compilers_subdir, x) for x in libdirs]
# resolve 'latest' symlink for tbb (if module guess is run with install in place)
if os.path.islink(os.path.join(self.installdir, self.tbb_subdir)):
tbb_version = os.readlink(os.path.join(self.installdir, self.tbb_subdir))
else:
tbb_version = 'latest'
tbb_subdir = os.path.join('tbb', tbb_version)
tbb_libsubdir = os.path.join(tbb_subdir, 'lib', 'intel64')
libdirs.append(os.path.join(tbb_libsubdir,
get_tbb_gccprefix(os.path.join(self.installdir, tbb_libsubdir))))
guesses = {
'PATH': [
os.path.join(self.compilers_subdir, 'bin'),
os.path.join(self.compilers_subdir, 'bin', 'intel64'),
],
'LD_LIBRARY_PATH': libdirs,
'LIBRARY_PATH': libdirs,
'OCL_ICD_FILENAMES': [
os.path.join(self.compilers_subdir, 'lib', 'x64', 'libintelocl.so'),
],
'CPATH': [
os.path.join(tbb_subdir, 'include'),
],
'TBBROOT': [tbb_subdir],
}
return guesses
def make_module_extra(self):
"""Additional custom variables for intel-compiler"""
txt = super(EB_intel_minus_compilers, self).make_module_extra()
# On Debian/Ubuntu, /usr/include/x86_64-linux-gnu, or whatever dir gcc uses, needs to be included
# in $CPATH for Intel C compiler
multiarch_out, ec = run_cmd("gcc -print-multiarch", simple=False)
multiarch_out = multiarch_out.strip()
if ec == 0 and multiarch_out:
multiarch_inc_dir, ec = run_cmd("gcc -E -Wp,-v -xc /dev/null 2>&1 | grep %s$" % multiarch_out)
if ec == 0 and multiarch_inc_dir:
multiarch_inc_dir = multiarch_inc_dir.strip()
self.log.info("Adding multiarch include path %s to $CPATH in generated module file", multiarch_inc_dir)
# system location must be appended at the end, so use append_paths
txt += self.module_generator.append_paths('CPATH', [multiarch_inc_dir], allow_abs=True)
return txt