Skip to content

Commit 601fe2c

Browse files
authored
Merge pull request #3456 from easybuilders/4.9.x
release EasyBuild v4.9.4
2 parents 360bd58 + 15e8d51 commit 601fe2c

File tree

10 files changed

+88
-22
lines changed

10 files changed

+88
-22
lines changed

RELEASE_NOTES

+15
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,25 @@ These release notes can also be consulted at http://easybuild.readthedocs.org/en
66
The latest version of easybuild-easyblocks provides 259 software-specific easyblocks and 43 generic easyblocks.
77

88

9+
v4.9.4 (22 september 2024)
10+
--------------------------
11+
12+
update/bugfix release
13+
14+
- various enhancements, including:
15+
- allow Python bundles and packages to specify a maximum Python version for the system toolchain (#3431)
16+
- copy EasyConfig instance in constructor of Bundle and Cargo easyblocks before making changes to it (#3448)
17+
- fix crash in GCC easyblock when cuda-compute-capabilities EasyBuild configuration option is not set (#3449)
18+
- various bug fixes, including:
19+
- ignore Python from virtualenvs in GROMACS configure via -DPython3_FIND_VIRTUALENV=STANDARD (#3283)
20+
- enhance custom easyblock for NCCL: add licence to NCCL installation (#3451)
21+
22+
923
v4.9.3 (14 September 2024)
1024
--------------------------
1125

1226
update/bugfix release
27+
1328
- minor updates, including:
1429
- update custom easyblock for Tensorflow for versions 2.14 + 2.15 (#3303)
1530
- add support for versions >= 2024a to MCR easyblock (#3369)

easybuild/easyblocks/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
# recent setuptools versions will *TRANSFORM* something like 'X.Y.Zdev' into 'X.Y.Z.dev0', with a warning like
4444
# UserWarning: Normalizing '2.4.0dev' to '2.4.0.dev0'
4545
# This causes problems further up the dependency chain...
46-
VERSION = LooseVersion('4.9.3')
46+
VERSION = LooseVersion('4.9.4')
4747
UNKNOWN = 'UNKNOWN'
4848

4949

easybuild/easyblocks/g/gcc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ def map_nvptx_capability(self):
383383
architecture_mappings_replacement = "misa=,"
384384

385385
# Determine which compute capabilities are configured. If there are none, return immediately.
386-
if cuda_cc_list is None:
386+
if not cuda_cc_list:
387387
return None
388388
cuda_sm_list = [f"sm_{cc.replace('.', '')}" for cc in cuda_cc_list]
389389

easybuild/easyblocks/g/gromacs.py

+21-14
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ def prepare_step(self, *args, **kwargs):
167167
def configure_step(self):
168168
"""Custom configuration procedure for GROMACS: set configure options for configure or cmake."""
169169

170-
if LooseVersion(self.version) >= LooseVersion('4.6'):
170+
gromacs_version = LooseVersion(self.version)
171+
172+
if gromacs_version >= '4.6':
171173
cuda = get_software_root('CUDA')
172174
if cuda:
173175
# CUDA with double precision is currently not supported in GROMACS yet
@@ -188,10 +190,11 @@ def configure_step(self):
188190
self.log.info("skipping configure step")
189191
return
190192

191-
if LooseVersion(self.version) >= LooseVersion('2021'):
192-
self.cfg.update('configopts', "-DGMX_GPU=CUDA -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda)
193+
if gromacs_version >= '2021':
194+
self.cfg.update('configopts', "-DGMX_GPU=CUDA")
193195
else:
194-
self.cfg.update('configopts', "-DGMX_GPU=ON -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda)
196+
self.cfg.update('configopts', "-DGMX_GPU=ON")
197+
self.cfg.update('configopts', "-DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda)
195198

196199
# Set CUDA capabilities based on template value.
197200
if '-DGMX_CUDA_TARGET_SM' not in self.cfg['configopts']:
@@ -236,14 +239,14 @@ def configure_step(self):
236239
# Ensure that the GROMACS log files report how the code was patched
237240
# during the build, so that any problems are easier to diagnose.
238241
# The GMX_VERSION_STRING_OF_FORK feature is available since 2020.
239-
if (LooseVersion(self.version) >= LooseVersion('2020') and
242+
if (gromacs_version >= '2020' and
240243
'-DGMX_VERSION_STRING_OF_FORK=' not in self.cfg['configopts']):
241244
gromacs_version_string_suffix = 'EasyBuild-%s' % EASYBUILD_VERSION
242245
if plumed_root:
243246
gromacs_version_string_suffix += '-PLUMED-%s' % get_software_version('PLUMED')
244247
self.cfg.update('configopts', '-DGMX_VERSION_STRING_OF_FORK=%s' % gromacs_version_string_suffix)
245248

246-
if LooseVersion(self.version) < LooseVersion('4.6'):
249+
if gromacs_version < '4.6':
247250
self.log.info("Using configure script for configuring GROMACS build.")
248251

249252
if self.cfg['build_shared_libs']:
@@ -259,7 +262,7 @@ def configure_step(self):
259262
self.cfg.update('configopts', "--without-x")
260263

261264
# OpenMP is not supported for versions older than 4.5.
262-
if LooseVersion(self.version) >= LooseVersion('4.5'):
265+
if gromacs_version >= '4.5':
263266
# enable OpenMP support if desired
264267
if self.toolchain.options.get('openmp', None):
265268
self.cfg.update('configopts', "--enable-threads")
@@ -310,22 +313,26 @@ def configure_step(self):
310313
mpiexec_path, self.cfg.get('mpiexec_numproc_flag'),
311314
mpi_numprocs)
312315

313-
if LooseVersion(self.version) >= LooseVersion('2019'):
316+
if gromacs_version >= '2019':
314317
# Building the gmxapi interface requires shared libraries,
315318
# this is handled in the class initialisation so --module-only works
316319
self.cfg.update('configopts', "-DGMXAPI=ON")
317320

318-
if LooseVersion(self.version) >= LooseVersion('2020'):
321+
if gromacs_version >= '2020':
319322
# build Python bindings if Python is loaded as a dependency
320323
python_root = get_software_root('Python')
321324
if python_root:
325+
self.cfg.update('configopts', "-DGMX_PYTHON_PACKAGE=ON")
322326
bin_python = os.path.join(python_root, 'bin', 'python')
327+
# For find_package(PythonInterp)
323328
self.cfg.update('configopts', "-DPYTHON_EXECUTABLE=%s" % bin_python)
324-
self.cfg.update('configopts', "-DGMX_PYTHON_PACKAGE=ON")
329+
if gromacs_version >= '2021':
330+
# For find_package(Python3) - Ignore virtual envs
331+
self.cfg.update('configopts', "-DPython3_FIND_VIRTUALENV=STANDARD")
325332

326333
# Now patch GROMACS for PLUMED before cmake
327334
if plumed_root:
328-
if LooseVersion(self.version) >= LooseVersion('5.1'):
335+
if gromacs_version >= '5.1':
329336
# Use shared or static patch depending on
330337
# setting of self.cfg['build_shared_libs']
331338
# and adapt cmake flags accordingly as per instructions
@@ -355,7 +362,7 @@ def configure_step(self):
355362
if self.toolchain.toolchain_family() != toolchain.CRAYPE:
356363
gmx_simd = self.get_gromacs_arch()
357364
if gmx_simd:
358-
if LooseVersion(self.version) < LooseVersion('5.0'):
365+
if gromacs_version < '5.0':
359366
self.cfg.update('configopts', "-DGMX_CPU_ACCELERATION=%s" % gmx_simd)
360367
else:
361368
self.cfg.update('configopts', "-DGMX_SIMD=%s" % gmx_simd)
@@ -404,7 +411,7 @@ def configure_step(self):
404411
env.setvar('LDFLAGS', "%s -lgfortran -lm" % os.environ.get('LDFLAGS', ''))
405412

406413
# no more GSL support in GROMACS 5.x, see http://redmine.gromacs.org/issues/1472
407-
if LooseVersion(self.version) < LooseVersion('5.0'):
414+
if gromacs_version < '5.0':
408415
# enable GSL when it's provided
409416
if get_software_root('GSL'):
410417
self.cfg.update('configopts', "-DGMX_GSL=ON")
@@ -424,7 +431,7 @@ def configure_step(self):
424431
out = super(EB_GROMACS, self).configure_step()
425432

426433
# for recent GROMACS versions, make very sure that a decent BLAS, LAPACK and FFT is found and used
427-
if LooseVersion(self.version) >= LooseVersion('4.6.5'):
434+
if gromacs_version >= '4.6.5':
428435
patterns = [
429436
r"Using external FFT library - \S*",
430437
r"Looking for dgemm_ - found",

easybuild/easyblocks/generic/bundle.py

+4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ def __init__(self, *args, **kwargs):
8585
if self.cfg['patches']:
8686
raise EasyBuildError("List of patches for bundle itself must be empty, found %s", self.cfg['patches'])
8787

88+
# copy EasyConfig instance before we make changes to it
89+
# (like adding component sources to top-level sources easyconfig parameter)
90+
self.cfg = self.cfg.copy()
91+
8892
# disable templating to avoid premature resolving of template values
8993
self.cfg.enable_templating = False
9094

easybuild/easyblocks/generic/cargo.py

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ def __init__(self, *args, **kwargs):
151151
'filename': self.crate_src_filename(crate, version),
152152
})
153153

154+
# copy EasyConfig instance before we make changes to it
155+
self.cfg = self.cfg.copy()
156+
154157
self.cfg.update('sources', sources)
155158

156159
@property

easybuild/easyblocks/generic/pythonbundle.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,21 @@ def prepare_step(self, *args, **kwargs):
107107
if req_py_minver is None:
108108
req_py_minver = sys.version_info[1]
109109

110-
python_cmd = pick_python_cmd(req_maj_ver=req_py_majver, req_min_ver=req_py_minver)
110+
# Get the max_py_majver and max_py_minver from the config
111+
max_py_majver = self.cfg['max_py_majver']
112+
max_py_minver = self.cfg['max_py_minver']
113+
114+
python_cmd = pick_python_cmd(req_maj_ver=req_py_majver, req_min_ver=req_py_minver,
115+
max_py_majver=max_py_majver, max_py_minver=max_py_minver)
111116

112117
# If pick_python_cmd didn't find a (system) Python command, we should raise an error
113118
if python_cmd:
114119
self.log.info("Python command being used: %s", python_cmd)
115120
else:
116121
raise EasyBuildError(
117122
"Failed to pick Python command that satisfies requirements in the easyconfig "
118-
"(req_py_majver = %s, req_py_minver = %s)", req_py_majver, req_py_minver
123+
"(req_py_majver = %s, req_py_minver = %s, max_py_majver = %s, max_py_minver = %s)",
124+
req_py_majver, req_py_minver, max_py_majver, max_py_minver
119125
)
120126

121127
self.all_pylibdirs = get_pylibdirs(python_cmd=python_cmd)

easybuild/easyblocks/generic/pythonpackage.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def det_python_version(python_cmd):
8383
return out.strip()
8484

8585

86-
def pick_python_cmd(req_maj_ver=None, req_min_ver=None):
86+
def pick_python_cmd(req_maj_ver=None, req_min_ver=None, max_py_majver=None, max_py_minver=None):
8787
"""
8888
Pick 'python' command to use, based on specified version requirements.
8989
If the major version is specified, it must be an exact match (==).
@@ -130,6 +130,20 @@ def check_python_cmd(python_cmd):
130130
log.debug("Minimal requirement for minor Python version not satisfied: %s vs %s", pyver, req_majmin_ver)
131131
return False
132132

133+
if max_py_majver is not None:
134+
if max_py_minver is None:
135+
max_majmin_ver = '%s.0' % max_py_majver
136+
else:
137+
max_majmin_ver = '%s.%s' % (max_py_majver, max_py_minver)
138+
139+
pyver = det_python_version(python_cmd)
140+
141+
if LooseVersion(pyver) > LooseVersion(max_majmin_ver):
142+
log.debug("Python version (%s) on the system is newer than the maximum supported "
143+
"Python version specified in the easyconfig (%s)",
144+
pyver, max_majmin_ver)
145+
return False
146+
133147
# all check passed
134148
log.debug("All check passed for Python command '%s'!", python_cmd)
135149
return True
@@ -348,6 +362,8 @@ def extra_options(extra_vars=None):
348362
"Enabled by default if the EB option --debug is used.", CUSTOM],
349363
'req_py_majver': [None, "Required major Python version (only relevant when using system Python)", CUSTOM],
350364
'req_py_minver': [None, "Required minor Python version (only relevant when using system Python)", CUSTOM],
365+
'max_py_majver': [None, "Maximum major Python version (only relevant when using system Python)", CUSTOM],
366+
'max_py_minver': [None, "Maximum minor Python version (only relevant when using system Python)", CUSTOM],
351367
'sanity_pip_check': [False, "Run 'python -m pip check' to ensure all required Python packages are "
352368
"installed and check for any package with an invalid (0.0.0) version.", CUSTOM],
353369
'runtest': [True, "Run unit tests.", CUSTOM], # overrides default
@@ -508,18 +524,25 @@ def prepare_python(self):
508524
if req_py_minver is None:
509525
req_py_minver = sys.version_info[1]
510526

527+
# Get the max_py_majver and max_py_minver from the config
528+
max_py_majver = self.cfg['max_py_majver']
529+
max_py_minver = self.cfg['max_py_minver']
530+
511531
# if using system Python, go hunting for a 'python' command that satisfies the requirements
512-
python = pick_python_cmd(req_maj_ver=req_py_majver, req_min_ver=req_py_minver)
532+
python = pick_python_cmd(req_maj_ver=req_py_majver, req_min_ver=req_py_minver,
533+
max_py_majver=max_py_majver, max_py_minver=max_py_minver)
513534

514535
# Check if we have Python by now. If not, and if self.require_python, raise a sensible error
515536
if python:
516537
self.python_cmd = python
517538
self.log.info("Python command being used: %s", self.python_cmd)
518539
elif self.require_python:
519-
if req_py_majver is not None or req_py_minver is not None:
540+
if (req_py_majver is not None or req_py_minver is not None
541+
or max_py_majver is not None or max_py_minver is not None):
520542
raise EasyBuildError(
521543
"Failed to pick Python command that satisfies requirements in the easyconfig "
522-
"(req_py_majver = %s, req_py_minver = %s)", req_py_majver, req_py_minver
544+
"(req_py_majver = %s, req_py_minver = %s, max_py_majver = %s, max_py_minver = %s)",
545+
req_py_majver, req_py_minver, max_py_majver, max_py_minver
523546
)
524547
else:
525548
raise EasyBuildError("Failed to pick Python command to use")

easybuild/easyblocks/n/nccl.py

+6
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@
2626
EasyBuild support for building NCCL, implemented as an easyblock
2727
2828
@author: Simon Branford (University of Birmingham)
29+
@author: Lara Peeters (Gent University)
2930
"""
31+
import os
32+
3033
from easybuild.easyblocks.generic.configuremake import ConfigureMake
3134
from easybuild.tools.config import build_option
3235
from easybuild.tools.systemtools import get_shared_lib_ext
36+
from easybuild.tools.filetools import copy_file
3337

3438

3539
class EB_NCCL(ConfigureMake):
@@ -67,6 +71,8 @@ def install_step(self):
6771
"""Install NCCL"""
6872
self.cfg.update('installopts', "PREFIX=%s" % self.installdir)
6973

74+
copy_file(os.path.join(self.cfg['start_dir'], 'LICENSE.txt'), os.path.join(self.installdir, 'LICENSE.txt'))
75+
7076
super(EB_NCCL, self).install_step()
7177

7278
def sanity_check_step(self):

test/easyblocks/module.py

+2
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ def test_pythonpackage_pick_python_cmd(self):
231231
self.assertTrue(pick_python_cmd(2) is not None)
232232
self.assertTrue(pick_python_cmd(2, 6) is not None)
233233
self.assertTrue(pick_python_cmd(123, 456) is None)
234+
self.assertTrue(pick_python_cmd(2, 6, 123, 456) is not None)
235+
self.assertTrue(pick_python_cmd(2, 6, 1, 1) is None)
234236

235237

236238
def template_module_only_test(self, easyblock, name, version='1.3.2', extra_txt='', tmpdir=None):

0 commit comments

Comments
 (0)