forked from EESSI/software-layer-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEESSI-extend-easybuild.eb
More file actions
260 lines (235 loc) · 12.5 KB
/
EESSI-extend-easybuild.eb
File metadata and controls
260 lines (235 loc) · 12.5 KB
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
easyblock = 'Bundle'
name = 'EESSI-extend'
import os
version = os.getenv('EESSI_VERSION', '2023.06')
# May have different ways to extend EESSI in future (manually, other tools,...)
versionsuffix = '-easybuild'
homepage = 'https://eessi.io/docs/'
description = """
The goal of the European Environment for Scientific Software Installations
(EESSI, pronounced as "easy") is to build a common stack of scientific
software installations for HPC systems and beyond, including laptops,
personal workstations and cloud infrastructure.
This module allows you to extend EESSI using the same configuration for
EasyBuild as EESSI itself uses. A number of environment variables control the
behaviour of the module:
- EESSI_USER_INSTALL can be set to a location to install modules for use by
the user only. The location must already exist on the filesystem.
- EESSI_PROJECT_INSTALL can be set to a location to install modules for use by
a project. The location must already exist on the filesystem and you should
ensure that the location has the correct Linux group and the SGID permission
is set on that directory (`chmod g+s $EESSI_PROJECT_INSTALL`) so that all
members of the group have permission to read and write installations.
- EESSI_SITE_INSTALL is either defined or not and cannot be used with another
environment variable. A site installation is done in a defined location and
any installations there are (by default) world readable.
- EESSI_CVMFS_INSTALL is either defined or not and cannot be used with another
environment variable. A CVMFS installation targets a defined location which
will be ingested into CVMFS and is only useful for CVMFS administrators.
- If none of the environment variables above are defined, an EESSI_USER_INSTALL
is assumed with a value of $HOME/EESSI
If both EESSI_USER_INSTALL and EESSI_PROJECT_INSTALL are defined, both sets of
installations are exposed, but new installations are created as user
installations.
Strict installation path checking is enforced by EESSI for EESSI and site
installations involving accelerators. In these cases, if you wish to create an
accelerator installation you must set the environment variable
EESSI_ACCELERATOR_INSTALL (and load/reload this module).
"""
toolchain = SYSTEM
# All the dependencies we filter in EESSI
local_deps_to_filter = "binutils,bzip2,DBus,flex,gettext,gperf,help2man,intltool,libreadline,makeinfo,ncurses,NVPL,ParMETIS,util-linux,XZ,zlib"
# Filter extra dependencies based on CPU family
local_arch_specific_deps_to_filter = {'aarch64': ',Yasm', 'riscv64': ',Yasm', 'x86_64': ''}
local_deps_to_filter += local_arch_specific_deps_to_filter[ARCH]
# Only filter Autotools & co for EESSI 2023.06
if version == '2023.06':
local_deps_to_filter += ",Autoconf,Automake,Autotools,libtool,M4"
# Set the universal EasyBuild variables
modextravars = {
'EASYBUILD_FILTER_DEPS': local_deps_to_filter,
'EASYBUILD_IGNORE_OSDEPS': '1',
'EASYBUILD_DEBUG': '1',
'EASYBUILD_TRACE': '1',
'EASYBUILD_ZIP_LOGS': 'bzip2',
'EASYBUILD_RPATH': '1',
'EASYBUILD_FILTER_ENV_VARS': 'LD_LIBRARY_PATH',
'EASYBUILD_READ_ONLY_INSTALLDIR': '1',
'EASYBUILD_MODULE_EXTENSIONS': '1',
'EASYBUILD_EXPERIMENTAL': '1',
}
# Need a few other variables, but they are more dynamic
# EASYBUILD_SYSROOT=${EPREFIX}
# EASYBUILD_PREFIX=${WORKDIR}/easybuild
# EASYBUILD_HOOKS=${EESSI_PREFIX}/init/easybuild/eb_hooks.py
# EASYBUILD_INSTALLPATH=${EESSI_PREFIX}/software/${EESSI_OS_TYPE}/${EESSI_SOFTWARE_SUBDIR}
# EASYBUILD_SOURCEPATH=${WORKDIR}/easybuild/sources:${EESSI_SOURCEPATH}
#
# And also some optional ones based on the installation mode
# EASYBUILD_SET_GID_BIT
# EASYBUILD_GROUP_WRITABLE_INSTALLDIR
# EASYBUILD_UMASK
# EASYBUILD_STICKY_BIT
modluafooter = """
if (mode() == "load") then
-- Use a working directory for temporary build files
if (os.getenv("WORKING_DIR") == nil) then
LmodMessage("-- Using /tmp/$USER as a temporary working directory for installations, you can override this by setting the environment variable WORKING_DIR and reloading the module (e.g., /dev/shm is a common option)")
end
end
working_dir = os.getenv("WORKING_DIR") or pathJoin("/tmp", os.getenv("USER"))
-- Gather the EPREFIX to use as a sysroot
sysroot = os.getenv("EESSI_EPREFIX")
-- Check if we have GPU capabilities and configure CUDA compute capabilities
eessi_accelerator_target = os.getenv("EESSI_ACCELERATOR_TARGET")
if (eessi_accelerator_target ~= nil) then
cuda_compute_capability = string.match(eessi_accelerator_target, "^accel/nvidia/cc([0-9]+)$")
if (cuda_compute_capability ~= nil) then
-- The last digit should be the minor version, insert a dot in the one-but-last position
major_version = cuda_compute_capability:sub(1, #cuda_compute_capability - 1)
minor_version = cuda_compute_capability:sub(#cuda_compute_capability)
easybuild_cuda_compute_capabilities = string.format("%s.%s", major_version, minor_version)
else
LmodError("Incorrect value for $EESSI_ACCELERATOR_TARGET: " .. eessi_accelerator_target)
end
-- If architectures are 9.0, 10.0 or 12.0, enable architecture or family-specific optimizations
if easybuild_cuda_compute_capabilities == '9.0' then
easybuild_cuda_compute_capabilities = '9.0a'
elseif easybuild_cuda_compute_capabilities == '10.0' then
easybuild_cuda_compute_capabilities = '10.0f'
elseif easybuild_cuda_compute_capabilities == '12.0' then
easybuild_cuda_compute_capabilities = '12.0f'
end
end
-- Some environment variables affect behaviour, let's gather them once
local eessi_cvmfs_install = os.getenv("EESSI_CVMFS_INSTALL") ~= nil
local eessi_site_install = os.getenv("EESSI_SITE_INSTALL") ~= nil
local eessi_project_install = os.getenv("EESSI_PROJECT_INSTALL") ~= nil
local eessi_user_install = os.getenv("EESSI_USER_INSTALL") ~= nil
-- Use an installation prefix that we _should_ have write access to
if eessi_cvmfs_install then
-- Make sure no other EESSI install environment variables are set
if (eessi_site_install or eessi_project_install or eessi_user_install) then
LmodError("You cannot use EESSI_CVMFS_INSTALL in combination with any other EESSI_*_INSTALL environment variables")
end
easybuild_installpath = os.getenv("EESSI_SOFTWARE_PATH")
-- enforce accelerator subdirectory usage for CVMFS installs (only if an accelerator install is requested)
if (eessi_accelerator_target ~= nil) and (cuda_compute_capability ~= nil) and (os.getenv("EESSI_ACCELERATOR_INSTALL") ~= nil) then
easybuild_installpath = pathJoin(easybuild_installpath, eessi_accelerator_target)
end
elseif eessi_site_install then
-- Make sure no other EESSI install environment variables are set
if (eessi_project_install or eessi_user_install) then
LmodError("You cannot use EESSI_SITE_INSTALL in combination with any other EESSI_*_INSTALL environment variables")
end
easybuild_installpath = os.getenv("EESSI_SITE_SOFTWARE_PATH")
-- enforce accelerator subdirectory usage for site installs (only if an accelerator install is requested)
if (eessi_accelerator_target ~= nil) and (cuda_compute_capability ~= nil) and (os.getenv("EESSI_ACCELERATOR_INSTALL") ~= nil) then
easybuild_installpath = pathJoin(easybuild_installpath, eessi_accelerator_target)
end
else
-- Deal with user and project installs
project_install_dir = os.getenv("EESSI_PROJECT_INSTALL")
project_modulepath = nil
if eessi_project_install then
-- Check the folder exists
if not isDir(project_install_dir) then
LmodError("The location of EESSI_PROJECT_INSTALL (" .. project_install_dir .. ") does not exist or is not a folder")
end
if (mode() == "load") then
LmodMessage("Configuring for use of EESSI_PROJECT_INSTALL under " .. project_install_dir)
end
easybuild_installpath = string.gsub(os.getenv("EESSI_SOFTWARE_PATH"), os.getenv("EESSI_CVMFS_REPO"), project_install_dir)
project_modulepath = pathJoin(easybuild_installpath, 'modules', 'all')
end
user_install_dir = os.getenv("EESSI_USER_INSTALL")
user_modulepath = nil
if eessi_user_install then
-- Check the folder exists
if not isDir(user_install_dir) then
LmodError("The location of EESSI_USER_INSTALL (" .. user_install_dir .. ") does not exist or is not a folder")
end
elseif (user_install_dir == nil) and (project_install_dir == nil) then
-- No need to check for existence when we use a HOME subdir
user_install_dir = pathJoin(os.getenv("HOME"), "eessi")
end
if (user_install_dir ~= nil) then
if (mode() == "load") then
LmodMessage("Configuring for use of EESSI_USER_INSTALL under " .. user_install_dir)
end
easybuild_installpath = string.gsub(os.getenv("EESSI_SOFTWARE_PATH"), os.getenv("EESSI_CVMFS_REPO"), user_install_dir)
user_modulepath = pathJoin(easybuild_installpath, 'modules', 'all')
end
end
if (mode() == "load") then
LmodMessage("-- To create installations for EESSI, you _must_ have write permissions to " .. easybuild_installpath)
-- Advise them to reuse sources
if (os.getenv("EASYBUILD_SOURCEPATH") == nil) then
LmodMessage("-- You may wish to configure a sources directory for EasyBuild (for example, via setting the environment variable EASYBUILD_SOURCEPATH) to allow you to reuse existing sources for packages.")
end
end
-- Set the relevant universal environment variables for EasyBuild
setenv ("EASYBUILD_SYSROOT", sysroot)
setenv ("EASYBUILD_PREFIX", pathJoin(working_dir, "easybuild"))
setenv ("EASYBUILD_INSTALLPATH", easybuild_installpath)
eessi_init_prefix = os.getenv("EESSI_INIT_PREFIX") or pathJoin(os.getenv("EESSI_PREFIX"), "init")
setenv ("EASYBUILD_HOOKS", pathJoin(eessi_init_prefix, "easybuild", "eb_hooks.py"))
-- Make sure to use the general umask that allows a global read
setenv ("EASYBUILD_UMASK", "022")
-- Allow this module to be loaded when running EasyBuild
setenv ("EASYBUILD_ALLOW_LOADED_MODULES", "EasyBuild,EESSI-extend")
-- Set environment variables if building for CUDA compute capabilities
if (easybuild_cuda_compute_capabilities ~= nil) then
setenv ("EASYBUILD_CUDA_COMPUTE_CAPABILITIES", easybuild_cuda_compute_capabilities)
end
-- Set all related environment variables if we have project or user installations (including extending MODULEPATH)
if (user_modulepath ~= nil) then
-- Use a more restrictive umask for this case
setenv ("EASYBUILD_UMASK", "077")
setenv ("EASYBUILD_STICKY_BIT", "1")
-- configure MODULEPATH
if (project_modulepath ~= nil) then
prepend_path("MODULEPATH", project_modulepath)
end
prepend_path("MODULEPATH", user_modulepath)
elseif (project_modulepath ~= nil) then
setenv ("EASYBUILD_SET_GID_BIT", "1")
setenv ("EASYBUILD_GROUP_WRITABLE_INSTALLDIR", "1")
setenv ("EASYBUILD_STICKY_BIT", "0")
setenv ("EASYBUILD_UMASK", "002")
-- configure MODULEPATH
prepend_path("MODULEPATH", project_modulepath)
end
-- Make sure EasyBuild itself is loaded
-- need to also handle the unload behaviour where the version is defined only before we unload
easybuild_version = os.getenv("EBVERSIONEASYBUILD")
if not ( isloaded("EasyBuild") ) then
load(latest("EasyBuild"))
end
easybuild_version = os.getenv("EBVERSIONEASYBUILD") or easybuild_version
eessi_version = os.getenv("EESSI_VERSION") or "2023.06"
-- Set environment variables that are EasyBuild version specific
-- Do unload unconditionally, so that even if EB versions were switched in the meantime, this gets unset
-- This avoids issues where EESSI-extend is first loaded with EB => 5.1 (which set these vars)
-- but then EB is swapped for a version < 5.1 and then EESSI-extend is unloaded (which would not unset
-- these vars if we did it conditional on the EB version)
if mode() == "unload" or mode() == "dependencyCk" or convertToCanonical(easybuild_version) >= convertToCanonical("5.1") then
setenv ("EASYBUILD_STRICT_RPATH_SANITY_CHECK", "1")
setenv ("EASYBUILD_CUDA_SANITY_CHECK_ERROR_ON_FAILED_CHECKS", "1")
setenv ("EASYBUILD_FAIL_ON_MOD_FILES_GCCCORE", "1")
setenv ("EASYBUILD_LOCAL_VAR_NAMING_CHECK", "error")
setenv ("EASYBUILD_PARALLEL_EXTENSIONS_INSTALL", "1")
-- Set environment variables that are EESSI version specific
if convertToCanonical(eessi_version) > convertToCanonical("2023.06") then
setenv ("EASYBUILD_PREFER_PYTHON_SEARCH_PATH", "EBPYTHONPREFIXES")
setenv ("EASYBUILD_MODULE_SEARCH_PATH_HEADERS", "include_paths")
setenv ("EASYBUILD_SEARCH_PATH_CPP_HEADERS", "include_paths")
end
end
-- Avoid locale related problems by (temporarily) overwriting the locale with one we know exists ('locale -a')
pushenv ("LANG", "C.utf8")
pushenv ("LC_ALL", "C.utf8")
pushenv ("LC_CTYPE", "C.utf8")
pushenv ("LC_MESSAGES", "C.utf8")
"""
moduleclass = 'devel'