From b520b2e84bdfd88bc8c4b1f2d23e66227f3a29f2 Mon Sep 17 00:00:00 2001 From: sassy Date: Thu, 22 Sep 2022 14:23:35 +0100 Subject: [PATCH 001/134] Working EasyBlock for newer versions of GAMESS-US, based on PR #1925 --- easybuild/easyblocks/g/gamess_us.py | 237 ++++++++++++++++++++++------ 1 file changed, 185 insertions(+), 52 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4d658a7c0e..35a92812b4 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2022 Ghent University +# Copyright 2009-2020 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -37,17 +37,20 @@ import fileinput import glob import os +import random import re import shutil import sys import tempfile +import fnmatch from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import read_file, write_file +from easybuild.tools.filetools import change_dir, read_file, write_file from easybuild.tools.modules import get_software_root, get_software_version +from easybuild.tools.py2vs3 import ascii_letters from easybuild.tools.run import run_cmd, run_cmd_qa from easybuild.tools.systemtools import get_platform_name from easybuild.tools import toolchain @@ -64,6 +67,7 @@ def extra_options(): 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], + 'omp': [False, "Enabling OpenMP", CUSTOM], 'scratch_dir': ['$TMPDIR', "Scratch dir to be used in rungms script", CUSTOM], } return EasyBlock.extra_options(extra_vars) @@ -77,8 +81,10 @@ def __init__(self, *args, **kwargs): self.testdir = tempfile.mkdtemp() # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): - error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" - raise EasyBuildError(error_msg, self.testdir) + raise EasyBuildError("Temporary dir for tests '%s' will cause problems with rungms csh script", + self.testdir) + + self.scratch_dir = self.cfg['scratch_dir'] def extract_step(self): """Extract sources.""" @@ -88,12 +94,17 @@ def extract_step(self): def configure_step(self): """Configure GAMESS-US build via provided interactive 'config' script.""" - + """Opening install.info file as append""" + f = open(self.builddir + "/install.info", "a") + f.writelines(["setenv GMS_PATH " + self.builddir + "\n" + "setenv GMS_BUILD_DIR " + self.installdir + "\n"]) # machine type platform_name = get_platform_name() x86_64_linux_re = re.compile('^x86_64-.*$') if x86_64_linux_re.match(platform_name): machinetype = "linux64" + f.writelines(["setenv GMS_TARGET " + machinetype + "\n" + + "setenv GMS_HPC_SYSTEM_TARGET generic" + "\n"]) else: raise EasyBuildError("Build target %s currently unsupported", platform_name) @@ -114,6 +125,9 @@ def configure_step(self): else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) + f.writelines(["setenv GMS_FORTRAN " + fortran_comp + "\n" + + "setenv GMS_GFORTRAN_VERNO " + fortran_ver + "\n"]) + # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] mathlib, mathlib_root = None, None @@ -125,15 +139,38 @@ def configure_step(self): raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) if mathlib == 'imkl': mathlib = 'mkl' - mathlib_root = os.path.join(mathlib_root, 'mkl') + mathlib_vers_res = '.'.join(get_software_version('imkl').split('.')[:1]) + if int(mathlib_vers_res) == 2020: + mathlib_root = os.path.join(mathlib_root, 'mkl/lib/intel64') + elif int(mathlib_vers_res) == 2021: + mathlib_root = os.path.join(mathlib_root, 'mkl/latest/lib/intel64') + + if int(mathlib_vers_res) >= 2020: + # For some GAMESS-US versions oneapi is not in lked, so we use 12-so instead + if self.version == "20200630-R1" or self.version == "20200930-R2": + mathlib_vers = "12-so" + elif self.version == "20210620-R1": + mathlib_vers = "12-so" + else: + mathlib_vers = "oneapi-so" + else: + mathlib_vers = "12" + else: mathlib = mathlib.lower() + f.writelines(["setenv GMS_MATHLIB " + mathlib + "\n" + + "setenv GMS_MATHLIB_PATH " + mathlib_root + "\n" + + "setenv GMS_MKL_VERNO " + mathlib_vers + "\n" + + "setenv GMS_LAPACK_LINK_LINE" + "" + "\n"]) + # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] if not self.cfg['ddi_comm'] in known_ddi_comms: raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm']) + + f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n" ]) # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None @@ -154,38 +191,32 @@ def configure_step(self): else: mpilib, mpilib_root = '', '' - # run interactive 'config' script to generate install.info file - cmd = "%(preconfigopts)s ./config %(configopts)s" % { - 'preconfigopts': self.cfg['preconfigopts'], - 'configopts': self.cfg['configopts'], - } - qa = { - "After the new window is open, please hit to go on.": '', - "please enter your target machine name: ": machinetype, - "Version? [00] ": self.version, - "Please enter your choice of FORTRAN: ": fortran_comp, - "hit to continue to the math library setup.": '', - "MKL pathname? ": mathlib_root, - "MKL version (or 'skip')? ": 'skip', - "MKL version (or 'proceed')? ": 'proceed', # changed in gamess-20170420R1 - "please hit to compile the GAMESS source code activator": '', - "please hit to set up your network for Linux clusters.": '', - "communication library ('sockets' or 'mpi')? ": self.cfg['ddi_comm'], - "Enter MPI library (impi, mvapich2, mpt, sockets):": mpilib, - "Enter MPI library (impi, mpich, mpich2, mvapich2, mpt, sockets):": mpilib, # changed in gamess-20170420R1 - "Please enter your %s's location: " % mpilib: mpilib_root, - "Do you want to try LIBCCHEM? (yes/no): ": 'no', - "Enter full path to OpenBLAS libraries (without 'lib' subdirectory):": mathlib_root, - "Optional: Build Michigan State University CCT3 & CCSD3A methods? (yes/no): ": 'no', - } - stdqa = { - r"GAMESS directory\? \[.*\] ": self.builddir, - r"GAMESS build directory\? \[.*\] ": self.installdir, # building in install directory - r"Enter only the main version number, such as .*\nVersion\? ": fortran_ver, - r".+gfortran version.\n( \n)?Please enter only the first decimal place, such as .*:": fortran_ver, - "Enter your choice of 'mkl' or .* 'none': ": mathlib, - } - run_cmd_qa(cmd, qa=qa, std_qa=stdqa, log_all=True, simple=True) + f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + + "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + + # These are extra programs which for now we simply set all to FALSE + f. writelines(["setenv GMS_MSUCC false " + "\n"]) + f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) + f. writelines(["setenv GMS_PHI none " + "\n"]) + f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) + + if self.cfg['omp'] == 'True': + f. writelines(["setenv GMS_OPENMP true" + "\n"]) + else: + f. writelines(["setenv GMS_OPENMP false" + "\n"]) + + f. writelines(["setenv GMS_LIBXC false " + "\n"]) + f. writelines(["setenv GMS_MDI false " + "\n"]) + f. writelines(["setenv GMS_VM2 false " + "\n"]) + f. writelines(["setenv TINKER false " + "\n"]) + f. writelines(["setenv VB2000 false " + "\n"]) + f. writelines(["setenv XMVB false " + "\n"]) + f. writelines(["setenv NEO false " + "\n"]) + f. writelines(["setenv NBO false " + "\n"]) + f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) + #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging + + f.close() self.log.debug("Contents of install.info:\n%s" % read_file(os.path.join(self.builddir, 'install.info'))) @@ -209,6 +240,107 @@ def configure_step(self): except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) + # Replacing the MAXCPUS and MAXNODES in compddi to a value from the EasyConfig file + compddi = os.path.join(self.builddir, 'ddi/compddi') + try: + for line in fileinput.input(compddi, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set MAXCPUS)=.*", r"\1=%s" % self.cfg['maxcpus'], line, 1) + line = re.sub(r"^(\s*set MAXNODES)=.*", r"\1=%s" % self.cfg['maxnodes'], line, 1) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch compddi", compddi, err) + + # for GAMESS-US 20200630-R1 we need to build the actvte.x program + if self.version == "20200630-R1": + actvte = os.path.join(self.builddir, 'tools/actvte.code') + try: + for line in fileinput.input(actvte, inplace=1, backup='.orig'): + line = re.sub("\*UNX", " ", line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch actvte.code", actvte, err) + # compiling + run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) + run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) + + def build_step(self): + """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" + compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') + run_cmd(compddi, log_all=True, simple=True) + + # make sure the libddi.a library is present + libddi = os.path.join(self.cfg['start_dir'], 'ddi', 'libddi.a') + if not os.path.isfile(libddi): + raise EasyBuildError("The libddi.a library (%s) was never built", libddi) + else: + self.log.info("The libddi.a library (%s) was successfully built." % libddi) + + ddikick = os.path.join(self.cfg['start_dir'], 'ddi', 'ddikick.x') + if os.path.isfile(ddikick): + self.log.info("The ddikick.x executable (%s) was successfully built." % ddikick) + + if self.cfg['ddi_comm'] == 'sockets': + src = ddikick + dst = os.path.join(self.cfg['start_dir'], 'ddikick.x') + self.log.info("Moving ddikick.x executable from %s to %s." % (src, dst)) + os.rename(src, dst) + + compall_cmd = os.path.join(self.cfg['start_dir'], 'compall') + compall = "%s %s %s" % (self.cfg['prebuildopts'], compall_cmd, self.cfg['buildopts']) + run_cmd(compall, log_all=True, simple=True) + + cmd = "%s gamess %s" % (os.path.join(self.cfg['start_dir'], 'lked'), self.version) + run_cmd(cmd, log_all=True, simple=True) + + # Done up to here + quit() + + if self.scratch_dir: + # FIXME: resolve environment variables used in scratch_dir values + + # use unique subdirectory in specified scratch dir; + # we should use a shell command to create this directory, + # since scratch_dir may include names of environment variables + salt = ''.join(random.choice(ascii_letters) for i in range(10)) + self.scratch_dir = os.path.join(self.scratch_dir, self.name + '-' + salt) + + # make sure that specified directory is accessible via 'ssh', since rungms relies on that; + # touch a file, and then use "ssh localhost ls" to see if it's accessible; + # we must use shell commands for this, since scratch_dir may contain names of environment variables + test_file = os.path.join(self.scratch_dir, 'test.txt') + run_cmd("mkdir -p %s" % self.scratch_dir) + run_cmd("touch %s" % test_file) + test_cmd = 'ssh localhost "ls %s"' % test_file + (out, ec) = run_cmd(test_cmd, simple=False, log_ok=False, log_all=False) + if ec: + error_msg = "Scratch directory %s is not accessible via 'ssh'!\n" % self.scratch_dir + error_msg += "Specify a different path using the 'scratch_dir' easyconfig parameter.\n" + error_msg += "Output of test command '%s': %s" % (test_cmd, out) + raise EasyBuildError(error_msg) + else: + self.log.info("Using %s as scratch directory", self.scratch_dir) + + # patch hardcoded settings in rungms to use values specified in easyconfig file + rungms = os.path.join(self.builddir, 'rungms') + extra_gmspath_lines = "set ERICFMT=$GMSPATH/auxdata/ericfmt.dat\nset MCPPATH=$GMSPATH/auxdata/MCP\n" + try: + for line in fileinput.input(rungms, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set\s*TARGET)=.*", r"\1=%s" % self.cfg['ddi_comm'], line) + line = re.sub(r"^(\s*set\s*GMSPATH)=.*", r"\1=%s\n%s" % (self.installdir, extra_gmspath_lines), line) + line = re.sub(r"^(\s*set\s*GMS_OPENMP)=.*", r"\1=%s" % "true", line) # changed in gamess-20190930-R2 for OpenBLAS support + line = re.sub(r"(null\) set VERNO)=.*", r"\1=%s" % self.version, line) + line = re.sub(r"^(\s*set DDI_MPI_CHOICE)=.*", r"\1=%s" % mpilib, line) + line = re.sub(r"^(\s*set DDI_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) + line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) + # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths + line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) + if self.scratch_dir: + line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.scratch_dir, line) + line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.scratch_dir, line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch %s: %s", rungms, err) + def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') @@ -247,11 +379,7 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") return - try: - cwd = os.getcwd() - os.chdir(self.testdir) - except OSError as err: - raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) + cwd = change_dir(self.testdir) # copy input files for exam standard tests for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): @@ -261,7 +389,7 @@ def test_step(self): raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['TMPDIR=%s' % self.testdir] + test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir ] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) @@ -269,8 +397,10 @@ def test_step(self): ]) # run all exam tests, dump output to exam.log - n_tests = 47 - for i in range(1, n_tests + 1): + # we let Python count the number of *.inp files as that changes + tests_path = os.path.join(self.installdir, 'tests', 'standard') + n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + for i in range(1, n_tests+1): test_cmd = ' '.join(test_env_vars + [rungms, 'exam%02d' % i, self.version, '1', '2']) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) @@ -284,12 +414,7 @@ def test_step(self): else: raise EasyBuildError("Not all tests ran successfully...") - # cleanup - os.chdir(cwd) - try: - shutil.rmtree(self.testdir) - except OSError as err: - raise EasyBuildError("Failed to remove test directory %s: %s", self.testdir, err) + change_dir(cwd) def install_step(self): """Skip install step, since we're building in the install directory.""" @@ -309,3 +434,11 @@ def make_module_extra(self): txt += self.module_generator.set_environment('GAMESSUSROOT', self.installdir) txt += self.module_generator.prepend_paths("PATH", ['']) return txt + + def cleanup_step(self): + """Cleanup set.""" + # remove dedicated scratch directory (if any); + # we must use a shell command for this, since the path may contain environment variables + super(EB_GAMESS_minus_US, self).cleanup_step() + + # FIXME From e1691ad3f71594a7b454ea23f0e07853a73780a9 Mon Sep 17 00:00:00 2001 From: sassy Date: Thu, 22 Sep 2022 16:34:10 +0100 Subject: [PATCH 002/134] Whitespace deleted --- easybuild/easyblocks/g/gamess_us.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 35a92812b4..04b9abae28 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -389,7 +389,7 @@ def test_step(self): raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir ] + test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) From 1b03f22c81a2414af083c476d661d4a246db78b2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:20:07 +0100 Subject: [PATCH 003/134] revert error message format change in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 04b9abae28..2ffe4414a2 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -81,8 +81,8 @@ def __init__(self, *args, **kwargs): self.testdir = tempfile.mkdtemp() # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): - raise EasyBuildError("Temporary dir for tests '%s' will cause problems with rungms csh script", - self.testdir) + error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" + raise EasyBuildError(error_msg, self.testdir) self.scratch_dir = self.cfg['scratch_dir'] From 1fe8e0aba57c7e1287955352f652e5670bbdfdaa Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:27:47 +0100 Subject: [PATCH 004/134] remove duplicate build step in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 78 ----------------------------- 1 file changed, 78 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 2ffe4414a2..a450ab9387 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -263,84 +263,6 @@ def configure_step(self): run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) - def build_step(self): - """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" - compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') - run_cmd(compddi, log_all=True, simple=True) - - # make sure the libddi.a library is present - libddi = os.path.join(self.cfg['start_dir'], 'ddi', 'libddi.a') - if not os.path.isfile(libddi): - raise EasyBuildError("The libddi.a library (%s) was never built", libddi) - else: - self.log.info("The libddi.a library (%s) was successfully built." % libddi) - - ddikick = os.path.join(self.cfg['start_dir'], 'ddi', 'ddikick.x') - if os.path.isfile(ddikick): - self.log.info("The ddikick.x executable (%s) was successfully built." % ddikick) - - if self.cfg['ddi_comm'] == 'sockets': - src = ddikick - dst = os.path.join(self.cfg['start_dir'], 'ddikick.x') - self.log.info("Moving ddikick.x executable from %s to %s." % (src, dst)) - os.rename(src, dst) - - compall_cmd = os.path.join(self.cfg['start_dir'], 'compall') - compall = "%s %s %s" % (self.cfg['prebuildopts'], compall_cmd, self.cfg['buildopts']) - run_cmd(compall, log_all=True, simple=True) - - cmd = "%s gamess %s" % (os.path.join(self.cfg['start_dir'], 'lked'), self.version) - run_cmd(cmd, log_all=True, simple=True) - - # Done up to here - quit() - - if self.scratch_dir: - # FIXME: resolve environment variables used in scratch_dir values - - # use unique subdirectory in specified scratch dir; - # we should use a shell command to create this directory, - # since scratch_dir may include names of environment variables - salt = ''.join(random.choice(ascii_letters) for i in range(10)) - self.scratch_dir = os.path.join(self.scratch_dir, self.name + '-' + salt) - - # make sure that specified directory is accessible via 'ssh', since rungms relies on that; - # touch a file, and then use "ssh localhost ls" to see if it's accessible; - # we must use shell commands for this, since scratch_dir may contain names of environment variables - test_file = os.path.join(self.scratch_dir, 'test.txt') - run_cmd("mkdir -p %s" % self.scratch_dir) - run_cmd("touch %s" % test_file) - test_cmd = 'ssh localhost "ls %s"' % test_file - (out, ec) = run_cmd(test_cmd, simple=False, log_ok=False, log_all=False) - if ec: - error_msg = "Scratch directory %s is not accessible via 'ssh'!\n" % self.scratch_dir - error_msg += "Specify a different path using the 'scratch_dir' easyconfig parameter.\n" - error_msg += "Output of test command '%s': %s" % (test_cmd, out) - raise EasyBuildError(error_msg) - else: - self.log.info("Using %s as scratch directory", self.scratch_dir) - - # patch hardcoded settings in rungms to use values specified in easyconfig file - rungms = os.path.join(self.builddir, 'rungms') - extra_gmspath_lines = "set ERICFMT=$GMSPATH/auxdata/ericfmt.dat\nset MCPPATH=$GMSPATH/auxdata/MCP\n" - try: - for line in fileinput.input(rungms, inplace=1, backup='.orig'): - line = re.sub(r"^(\s*set\s*TARGET)=.*", r"\1=%s" % self.cfg['ddi_comm'], line) - line = re.sub(r"^(\s*set\s*GMSPATH)=.*", r"\1=%s\n%s" % (self.installdir, extra_gmspath_lines), line) - line = re.sub(r"^(\s*set\s*GMS_OPENMP)=.*", r"\1=%s" % "true", line) # changed in gamess-20190930-R2 for OpenBLAS support - line = re.sub(r"(null\) set VERNO)=.*", r"\1=%s" % self.version, line) - line = re.sub(r"^(\s*set DDI_MPI_CHOICE)=.*", r"\1=%s" % mpilib, line) - line = re.sub(r"^(\s*set DDI_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) - line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) - # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths - line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) - if self.scratch_dir: - line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.scratch_dir, line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.scratch_dir, line) - sys.stdout.write(line) - except IOError as err: - raise EasyBuildError("Failed to patch %s: %s", rungms, err) - def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" compddi = os.path.join(self.cfg['start_dir'], 'ddi', 'compddi') From bcb9f0fbcca6da8459a35b74833cfd4bc9f4757a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 Mar 2023 11:32:52 +0100 Subject: [PATCH 005/134] add user_scratch_dir extra option to gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a450ab9387..612b987951 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -68,7 +68,8 @@ def extra_options(): 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], 'omp': [False, "Enabling OpenMP", CUSTOM], - 'scratch_dir': ['$TMPDIR', "Scratch dir to be used in rungms script", CUSTOM], + 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], + 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], } return EasyBlock.extra_options(extra_vars) @@ -84,8 +85,6 @@ def __init__(self, *args, **kwargs): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" raise EasyBuildError(error_msg, self.testdir) - self.scratch_dir = self.cfg['scratch_dir'] - def extract_step(self): """Extract sources.""" # strip off 'gamess' part to avoid having everything in a 'gamess' subdirectory @@ -233,9 +232,10 @@ def configure_step(self): line = re.sub(r"^(\s*set GA_MPI_ROOT)=.*%s.*" % mpilib.lower(), r"\1=%s" % mpilib_path, line) # comment out all adjustments to $LD_LIBRARY_PATH that involves hardcoded paths line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) - if self.cfg['scratch_dir']: - line = re.sub(r"^(\s*set\s*SCR)=.*", r"\1=%s" % self.cfg['scratch_dir'], line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"\1=%s" % self.cfg['scratch_dir'], line) + # scratch directory paths + line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) + line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) + line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) From bf674ad87f23ae303cd710afbf8a0de6c7d500ad Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:26:55 +0100 Subject: [PATCH 006/134] streamline IMKL and fix support for OpenBLAS in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 62 +++++++++++++++-------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 612b987951..4ac5684faf 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -44,6 +44,8 @@ import tempfile import fnmatch +from distutils.version import LooseVersion + from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError @@ -129,39 +131,41 @@ def configure_step(self): # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] - mathlib, mathlib_root = None, None - for mathlib in known_mathlibs: - mathlib_root = get_software_root(mathlib) - if mathlib_root is not None: - break - if mathlib_root is None: + loaded_mathlib = [mathlib for mathlib in known_mathlibs if get_software_root(mathlib)] + + # math library: default settings + try: + mathlib = loaded_mathlib[0].lower() + mathlib_root = get_software_root(loaded_mathlib[0]) + mathlib_subfolder = '' + mathlib_flags = '' + except IndexError: raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) + if mathlib == 'imkl': mathlib = 'mkl' - mathlib_vers_res = '.'.join(get_software_version('imkl').split('.')[:1]) - if int(mathlib_vers_res) == 2020: - mathlib_root = os.path.join(mathlib_root, 'mkl/lib/intel64') - elif int(mathlib_vers_res) == 2021: - mathlib_root = os.path.join(mathlib_root, 'mkl/latest/lib/intel64') - - if int(mathlib_vers_res) >= 2020: - # For some GAMESS-US versions oneapi is not in lked, so we use 12-so instead - if self.version == "20200630-R1" or self.version == "20200930-R2": - mathlib_vers = "12-so" - elif self.version == "20210620-R1": - mathlib_vers = "12-so" - else: - mathlib_vers = "oneapi-so" - else: - mathlib_vers = "12" - + mathlib_subfolder = 'mkl' + mathlib_flags = '-lmkl_intel_lp64' + imkl_ver = get_software_version('imkl') + if LooseVersion(imkl_ver) >= LooseVersion("2021"): + mathlib_subfolder = 'mkl/latest/lib/intel64' + elif LooseVersion(imkl_ver) >= LooseVersion("2020"): + mathlib_subfolder = 'mkl/lib/intel64' + elif mathlib == 'openblas': + mathlib_flags="-lopenblas -lgfortran" + if LooseVersion(self.version) >= LooseVersion('20210101'): + mathlib_subfolder = 'lib' + + if mathlib_root is not None: + mathlib_path = os.path.join(mathlib_root, mathlib_subfolder) + self.log.debug("Software root of math libraries set to: %s", mathlib_path) else: - mathlib = mathlib.lower() + raise EasyBuildError("Software root of math libraries (%s) not found", mathlib) - f.writelines(["setenv GMS_MATHLIB " + mathlib + "\n" + - "setenv GMS_MATHLIB_PATH " + mathlib_root + "\n" + - "setenv GMS_MKL_VERNO " + mathlib_vers + "\n" + - "setenv GMS_LAPACK_LINK_LINE" + "" + "\n"]) + f.writelines([ + "setenv GMS_MATHLIB " + mathlib + "\n" + + "setenv GMS_MATHLIB_PATH " + mathlib_path + "\n" + + "setenv GMS_LAPACK_LINK_LINE " + '"%s"' % mathlib_flags + "\n"]) # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] @@ -169,7 +173,7 @@ def configure_step(self): raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm']) - f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n" ]) + f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n"]) # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None From 04ef3a9922c3456d5b35114d5a087184b5cd194a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:27:27 +0100 Subject: [PATCH 007/134] replace extra omp option with toolchain.options.openmp --- easybuild/easyblocks/g/gamess_us.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4ac5684faf..d7b741e6eb 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -69,7 +69,6 @@ def extra_options(): 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], - 'omp': [False, "Enabling OpenMP", CUSTOM], 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], } @@ -203,7 +202,7 @@ def configure_step(self): f. writelines(["setenv GMS_PHI none " + "\n"]) f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) - if self.cfg['omp'] == 'True': + if self.toolchain.options.get('openmp', None): f. writelines(["setenv GMS_OPENMP true" + "\n"]) else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) From 18db2c552d83c7a6e073b24ee2536f9e0cd7124b Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 8 Mar 2023 15:41:29 +0100 Subject: [PATCH 008/134] check dependency on libxc to enable GMS_LIBXC --- easybuild/easyblocks/g/gamess_us.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d7b741e6eb..11d641ae34 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -206,8 +206,16 @@ def configure_step(self): f. writelines(["setenv GMS_OPENMP true" + "\n"]) else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) - - f. writelines(["setenv GMS_LIBXC false " + "\n"]) + + external_plugs = dict() + if LooseVersion(self.version) >= LooseVersion('2021'): + external_plugs['GMS_LIBXC'] = "false" + if get_software_root('libxc'): + external_plugs['GMS_LIBXC'] = "true" + + for opt in external_plugs.items(): + f. writelines(["setenv %s %s \n" % opt]) + f. writelines(["setenv GMS_MDI false " + "\n"]) f. writelines(["setenv GMS_VM2 false " + "\n"]) f. writelines(["setenv TINKER false " + "\n"]) From 3b91897d652791eff2ab0c3c924efaaa4e4126f8 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 9 Mar 2023 14:10:09 +0100 Subject: [PATCH 009/134] set interfaces and plugins through plugs_opts in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 39 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 11d641ae34..e369987dc5 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -207,22 +207,35 @@ def configure_step(self): else: f. writelines(["setenv GMS_OPENMP false" + "\n"]) - external_plugs = dict() - if LooseVersion(self.version) >= LooseVersion('2021'): - external_plugs['GMS_LIBXC'] = "false" + # Optional plug-ins and interfaces + # libXC + plugs_opt = dict() + if LooseVersion(self.version) >= LooseVersion('20210101'): + plugs_opt['GMS_LIBXC'] = "false" if get_software_root('libxc'): - external_plugs['GMS_LIBXC'] = "true" - - for opt in external_plugs.items(): + plugs_opt['GMS_LIBXC'] = "true" + # MDI + # needs https://github.com/MolSSI-MDI/MDI_Library + plugs_opt['GMS_MDI'] = "false" + # VM2 + plugs_opt['GMS_VM2'] = "false" + # NBO + plugs_opt['NBO'] = "false" + if get_software_root('NBO'): + plugs_opt['NBO'] = "true" + # NEO + plugs_opt['NEO'] = "false" + # TINKER + plugs_opt['TINKER'] = "false" + if get_software_root('TINKER'): + plugs_opt['TINKER'] = "true" + # VB2000 + plugs_opt['VB2000'] = "false" + # XMVB + plugs_opt['XMVB'] = "false" + for opt in plugs_opt.items(): f. writelines(["setenv %s %s \n" % opt]) - f. writelines(["setenv GMS_MDI false " + "\n"]) - f. writelines(["setenv GMS_VM2 false " + "\n"]) - f. writelines(["setenv TINKER false " + "\n"]) - f. writelines(["setenv VB2000 false " + "\n"]) - f. writelines(["setenv XMVB false " + "\n"]) - f. writelines(["setenv NEO false " + "\n"]) - f. writelines(["setenv NBO false " + "\n"]) f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging From b85076a7d94afae428a4a02920a65cb0aa6f2c4e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 9 Mar 2023 21:09:41 +0100 Subject: [PATCH 010/134] fix linking to libxc in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index e369987dc5..a2d7670c5c 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -214,6 +214,16 @@ def configure_step(self): plugs_opt['GMS_LIBXC'] = "false" if get_software_root('libxc'): plugs_opt['GMS_LIBXC'] = "true" + # the linker needs to be patched to use external libXC + lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] + libxc_linker_flags = ' '.join(lixc_libs) + try: + lked = os.path.join(self.builddir, 'lked') + for line in fileinput.input(lked, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*set\sLIBXC_FLAGS)=.*GMS_PATH.*", r'\1="%s"' % libxc_linker_flags, line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library plugs_opt['GMS_MDI'] = "false" @@ -236,7 +246,8 @@ def configure_step(self): for opt in plugs_opt.items(): f. writelines(["setenv %s %s \n" % opt]) - f. writelines(["setenv GMS_FPE_FLAGS " + "\n"]) + # add include paths from dependencies + f. writelines(['setenv GMS_FPE_FLAGS "%s" \n' % os.environ['CPPFLAGS']]) #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging f.close() From 133861ca1c939c041f35160aa45e3ca1cc01c7fb Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 10 Mar 2023 08:55:21 +0100 Subject: [PATCH 011/134] move openmp settings to original position in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a2d7670c5c..125397d64a 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -196,17 +196,18 @@ def configure_step(self): f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + # OpenMP config + if self.toolchain.options.get('openmp', None): + f. writelines(["setenv GMS_OPENMP true" + "\n"]) + else: + f. writelines(["setenv GMS_OPENMP false" + "\n"]) + # These are extra programs which for now we simply set all to FALSE f. writelines(["setenv GMS_MSUCC false " + "\n"]) f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) f. writelines(["setenv GMS_PHI none " + "\n"]) f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) - if self.toolchain.options.get('openmp', None): - f. writelines(["setenv GMS_OPENMP true" + "\n"]) - else: - f. writelines(["setenv GMS_OPENMP false" + "\n"]) - # Optional plug-ins and interfaces # libXC plugs_opt = dict() From b7834736ae54caf448b6b2630cec4a676f2c9a40 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 11 Mar 2023 23:47:42 +0100 Subject: [PATCH 012/134] skip tests in gamess-us with less than 2 cores --- easybuild/easyblocks/g/gamess_us.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 125397d64a..9254726298 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -337,6 +337,10 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") return + if int(self.cfg['parallel']) < 2: + self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") + return + cwd = change_dir(self.testdir) # copy input files for exam standard tests From d4a6a38f2c81ab82d5a6befbba2791ad556a8152 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 11 Mar 2023 23:58:59 +0100 Subject: [PATCH 013/134] remove unused modules from gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9254726298..b344f96d76 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -52,8 +52,7 @@ from easybuild.tools.config import build_option from easybuild.tools.filetools import change_dir, read_file, write_file from easybuild.tools.modules import get_software_root, get_software_version -from easybuild.tools.py2vs3 import ascii_letters -from easybuild.tools.run import run_cmd, run_cmd_qa +from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_platform_name from easybuild.tools import toolchain From 29e42e3aca40c93f3ce37c04c65d5d335c31b815 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 00:09:53 +0100 Subject: [PATCH 014/134] cleanup scratch generated by tests of gamess-us --- easybuild/easyblocks/g/gamess_us.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index b344f96d76..baad03e504 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -50,7 +50,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, read_file, write_file +from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import get_platform_name @@ -398,8 +398,12 @@ def make_module_extra(self): def cleanup_step(self): """Cleanup set.""" + super(EB_GAMESS_minus_US, self).cleanup_step() + # remove dedicated scratch directory (if any); # we must use a shell command for this, since the path may contain environment variables - super(EB_GAMESS_minus_US, self).cleanup_step() + (scratch_path, _) = run_cmd('echo "%s"' % self.cfg['scratch_dir'], simple=False) + if os.path.isdir(scratch_path): + remove_dir(scratch_path) + self.log.info("Removed test scratch: %s", scratch_path) - # FIXME From e5bc041287c707214ee1597b4f7fbc9158d2f00e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 00:44:38 +0100 Subject: [PATCH 015/134] use write_file from easybuild to create install.info file in gamess-us --- easybuild/easyblocks/g/gamess_us.py | 108 +++++++++++++++------------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index baad03e504..9fc3c64390 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -53,8 +53,10 @@ from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import get_platform_name +from easybuild.tools.systemtools import POWER, X86_64 +from easybuild.tools.systemtools import get_cpu_architecture from easybuild.tools import toolchain +INSTALL_INFO = 'install.info' class EB_GAMESS_minus_US(EasyBlock): @@ -92,20 +94,24 @@ def extract_step(self): super(EB_GAMESS_minus_US, self).extract_step() def configure_step(self): - """Configure GAMESS-US build via provided interactive 'config' script.""" - """Opening install.info file as append""" - f = open(self.builddir + "/install.info", "a") - f.writelines(["setenv GMS_PATH " + self.builddir + "\n" - "setenv GMS_BUILD_DIR " + self.installdir + "\n"]) + """Configure GAMESS-US via install.info file""" + installinfo_opts = {} + + # installation paths + installinfo_opts["GMS_PATH"] = self.installdir + installinfo_opts["GMS_BUILD_DIR"] = self.builddir + # machine type - platform_name = get_platform_name() - x86_64_linux_re = re.compile('^x86_64-.*$') - if x86_64_linux_re.match(platform_name): + cpu_arch = get_cpu_architecture() + if cpu_arch == X86_64: machinetype = "linux64" - f.writelines(["setenv GMS_TARGET " + machinetype + "\n" + - "setenv GMS_HPC_SYSTEM_TARGET generic" + "\n"]) + elif cpu_arch == POWER: + machinetype = "ibm64" else: - raise EasyBuildError("Build target %s currently unsupported", platform_name) + raise EasyBuildError("Build target %s currently unsupported", cpu_arch) + + installinfo_opts["GMS_TARGET"] = machinetype + installinfo_opts["GMS_HPC_SYSTEM_TARGET"] = "generic" # compiler config comp_fam = self.toolchain.comp_family() @@ -124,8 +130,8 @@ def configure_step(self): else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) - f.writelines(["setenv GMS_FORTRAN " + fortran_comp + "\n" + - "setenv GMS_GFORTRAN_VERNO " + fortran_ver + "\n"]) + installinfo_opts["GMS_FORTRAN"] = fortran_comp + installinfo_opts["GMS_GFORTRAN_VERNO"] = fortran_ver # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] @@ -140,6 +146,7 @@ def configure_step(self): except IndexError: raise EasyBuildError("None of the known math libraries (%s) available, giving up.", known_mathlibs) + # math library: special cases if mathlib == 'imkl': mathlib = 'mkl' mathlib_subfolder = 'mkl' @@ -160,18 +167,18 @@ def configure_step(self): else: raise EasyBuildError("Software root of math libraries (%s) not found", mathlib) - f.writelines([ - "setenv GMS_MATHLIB " + mathlib + "\n" + - "setenv GMS_MATHLIB_PATH " + mathlib_path + "\n" + - "setenv GMS_LAPACK_LINK_LINE " + '"%s"' % mathlib_flags + "\n"]) + installinfo_opts["GMS_MATHLIB"] = mathlib + installinfo_opts["GMS_MATHLIB_PATH"] = mathlib_path + installinfo_opts["GMS_LAPACK_LINK_LINE"] = '"%s"' % mathlib_flags # verify selected DDI communication layer known_ddi_comms = ['mpi', 'mixed', 'shmem', 'sockets'] if not self.cfg['ddi_comm'] in known_ddi_comms: - raise EasyBuildError("Unsupported DDI communication layer specified (known: %s): %s", - known_ddi_comms, self.cfg['ddi_comm']) + raise EasyBuildError( + "Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm'] + ) - f.writelines(["setenv GMS_DDI_COMM " + self.cfg['ddi_comm'] + "\n"]) + installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config mpilib, mpilib_root, mpilib_path = None, None, None @@ -192,28 +199,29 @@ def configure_step(self): else: mpilib, mpilib_root = '', '' - f.writelines(["setenv GMS_MPI_LIB " + mpilib + "\n" + - "setenv GMS_MPI_PATH " + mpilib_root + "\n"]) + installinfo_opts["GMS_MPI_LIB"] = mpilib + installinfo_opts["GMS_MPI_PATH"] = mpilib_root # OpenMP config if self.toolchain.options.get('openmp', None): - f. writelines(["setenv GMS_OPENMP true" + "\n"]) + omp_enabled = "true" else: - f. writelines(["setenv GMS_OPENMP false" + "\n"]) + omp_enabled = "false" + + installinfo_opts["GMS_OPENMP"] = omp_enabled # These are extra programs which for now we simply set all to FALSE - f. writelines(["setenv GMS_MSUCC false " + "\n"]) - f. writelines(["setenv GMS_LIBCCHEM false" + "\n"]) - f. writelines(["setenv GMS_PHI none " + "\n"]) - f. writelines(["setenv GMS_SHMTYPE sysv " + "\n"]) + installinfo_opts["GMS_MSUCC"] = "false" + installinfo_opts["GMS_LIBCCHEM"] = "false" + installinfo_opts["GMS_PHI"] = "none" + installinfo_opts["GMS_SHMTYPE"] = "sysv" # Optional plug-ins and interfaces # libXC - plugs_opt = dict() if LooseVersion(self.version) >= LooseVersion('20210101'): - plugs_opt['GMS_LIBXC'] = "false" + installinfo_opts['GMS_LIBXC'] = "false" if get_software_root('libxc'): - plugs_opt['GMS_LIBXC'] = "true" + installinfo_opts['GMS_LIBXC'] = "true" # the linker needs to be patched to use external libXC lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) @@ -226,33 +234,35 @@ def configure_step(self): raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library - plugs_opt['GMS_MDI'] = "false" + installinfo_opts['GMS_MDI'] = "false" # VM2 - plugs_opt['GMS_VM2'] = "false" + installinfo_opts['GMS_VM2'] = "false" # NBO - plugs_opt['NBO'] = "false" + installinfo_opts['NBO'] = "false" if get_software_root('NBO'): - plugs_opt['NBO'] = "true" + installinfo_opts['NBO'] = "true" # NEO - plugs_opt['NEO'] = "false" + installinfo_opts['NEO'] = "false" # TINKER - plugs_opt['TINKER'] = "false" + installinfo_opts['TINKER'] = "false" if get_software_root('TINKER'): - plugs_opt['TINKER'] = "true" + installinfo_opts['TINKER'] = "true" # VB2000 - plugs_opt['VB2000'] = "false" + installinfo_opts['VB2000'] = "false" # XMVB - plugs_opt['XMVB'] = "false" - for opt in plugs_opt.items(): - f. writelines(["setenv %s %s \n" % opt]) + installinfo_opts['XMVB'] = "false" # add include paths from dependencies - f. writelines(['setenv GMS_FPE_FLAGS "%s" \n' % os.environ['CPPFLAGS']]) - #f. writelines(["setenv GMS_FPE_FLAGS '-ffpe-trap=invalid,zero,overflow' " + "\n"]) # This seems to be useful for debugging - - f.close() + installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + # might be useful for debugging + # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" - self.log.debug("Contents of install.info:\n%s" % read_file(os.path.join(self.builddir, 'install.info'))) + # write install.info file with configuration settings + # format: setenv KEY VALUE + installinfo_file = os.path.join(self.builddir, INSTALL_INFO) + txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) + write_file(installinfo_file, txt) + self.log.debug("Contents of install.info:\n%s" % read_file(installinfo_file)) # patch hardcoded settings in rungms to use values specified in easyconfig file rungms = os.path.join(self.builddir, 'rungms') @@ -402,7 +412,7 @@ def cleanup_step(self): # remove dedicated scratch directory (if any); # we must use a shell command for this, since the path may contain environment variables - (scratch_path, _) = run_cmd('echo "%s"' % self.cfg['scratch_dir'], simple=False) + (scratch_path, _) = run_cmd('printf "%%s" "%s"' % self.cfg['scratch_dir'], simple=False) if os.path.isdir(scratch_path): remove_dir(scratch_path) self.log.info("Removed test scratch: %s", scratch_path) From 6dc3248b4136121736014455e82164351ace7325 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 02:18:22 +0100 Subject: [PATCH 016/134] use specific version setting for each fortran compiler in gamess-us --- easybuild/easyblocks/g/gamess_us.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9fc3c64390..a069f271f5 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -120,18 +120,20 @@ def configure_step(self): fortran_comp = 'ifort' (out, _) = run_cmd("ifort -v", simple=False) res = re.search(r"^ifort version ([0-9]+)\.[0-9.]+$", out) - if res: - fortran_ver = res.group(1) - else: + try: + version_num = res.group(1) + except (AttributeError, IndexError): raise EasyBuildError("Failed to determine ifort major version number") + fortran_version = {"GMS_IFORT_VERNO": version_num} elif comp_fam == toolchain.GCC: fortran_comp = 'gfortran' - fortran_ver = '.'.join(get_software_version('GCC').split('.')[:2]) + version_num = '.'.join(get_software_version('GCC').split('.')[:2]) + fortran_version = {"GMS_GFORTRAN_VERNO": version_num} else: raise EasyBuildError("Compiler family '%s' currently unsupported.", comp_fam) installinfo_opts["GMS_FORTRAN"] = fortran_comp - installinfo_opts["GMS_GFORTRAN_VERNO"] = fortran_ver + installinfo_opts.update(fortran_version) # math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] From fa047dcd7cd0f26ab5728b11661ec623ef411d15 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 02:43:13 +0100 Subject: [PATCH 017/134] add support for impi v2021+ to gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a069f271f5..221ba1ff0d 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -183,9 +183,8 @@ def configure_step(self): installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config - mpilib, mpilib_root, mpilib_path = None, None, None + mpilib, mpilib_path = '', '' if self.cfg['ddi_comm'] == 'mpi': - known_mpilibs = ['impi', 'OpenMPI', 'MVAPICH2', 'MPICH2'] for mpilib in known_mpilibs: mpilib_root = get_software_root(mpilib) @@ -195,14 +194,16 @@ def configure_step(self): raise EasyBuildError("None of the known MPI libraries (%s) available, giving up.", known_mpilibs) mpilib_path = mpilib_root if mpilib == 'impi': - mpilib_path = os.path.join(mpilib_root, 'intel64') + impi_ver = get_software_version('impi') + if LooseVersion(impi_ver) >= LooseVersion("2021.0.0"): + mpilib_path = os.path.join(mpilib_root, 'mpi', 'latest') + else: + mpilib_path = os.path.join(mpilib_root, 'intel64') else: mpilib = mpilib.lower() - else: - mpilib, mpilib_root = '', '' installinfo_opts["GMS_MPI_LIB"] = mpilib - installinfo_opts["GMS_MPI_PATH"] = mpilib_root + installinfo_opts["GMS_MPI_PATH"] = mpilib_path # OpenMP config if self.toolchain.options.get('openmp', None): From c04d19d794b49a24db668649e142755e003605d0 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sun, 12 Mar 2023 01:52:13 +0100 Subject: [PATCH 018/134] add extra option to gamess-us easyblock to disable hyperthreading --- easybuild/easyblocks/g/gamess_us.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 221ba1ff0d..0d254ebfbb 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -69,6 +69,7 @@ def extra_options(): 'ddi_comm': ['mpi', "DDI communication layer to use", CUSTOM], 'maxcpus': [None, "Maximum number of cores per node", MANDATORY], 'maxnodes': [None, "Maximum number of nodes", MANDATORY], + 'hyperthreading': [True, "Enable support for hyperthreading (2 threads per core)", CUSTOM], 'runtest': [True, "Run GAMESS-US tests", CUSTOM], 'scratch_dir': ['$TMPDIR', "dir for temporary binary files", CUSTOM], 'user_scratch_dir': ['$TMPDIR', "dir for supplementary output files", CUSTOM], @@ -284,6 +285,10 @@ def configure_step(self): line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) + if self.cfg['hyperthreading'] is False: + # disable hyperthreading (1 thread per core) + line = re.sub(r"\$PPN \+ \$PPN", r"$PPN", line) + line = re.sub(r"\$NCPUS \+ \$NCPUS", r"$NCPUS", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch %s: %s", rungms, err) From 440f9600fdab92d9aa41e33195a58dc5c56a8528 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 00:32:41 +0100 Subject: [PATCH 019/134] set version of MKL in gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 0d254ebfbb..dc56010716 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -152,13 +152,15 @@ def configure_step(self): # math library: special cases if mathlib == 'imkl': mathlib = 'mkl' - mathlib_subfolder = 'mkl' - mathlib_flags = '-lmkl_intel_lp64' + mathlib_subfolder = 'mkl/lib/intel64' + mkl_version = '12' imkl_ver = get_software_version('imkl') if LooseVersion(imkl_ver) >= LooseVersion("2021"): + # OneAPI version mathlib_subfolder = 'mkl/latest/lib/intel64' - elif LooseVersion(imkl_ver) >= LooseVersion("2020"): - mathlib_subfolder = 'mkl/lib/intel64' + mkl_version = 'oneapi' + installinfo_opts["GMS_MKL_VERNO"] = mkl_version + elif mathlib == 'openblas': mathlib_flags="-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): From 45e9a3e48310e6fb4509453de48fbce4ebb6d4c0 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 11:59:29 +0100 Subject: [PATCH 020/134] set parallelization of tests in gamess-us to 2 processes --- easybuild/easyblocks/g/gamess_us.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index dc56010716..567a6c98ca 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -56,7 +56,9 @@ from easybuild.tools.systemtools import POWER, X86_64 from easybuild.tools.systemtools import get_cpu_architecture from easybuild.tools import toolchain -INSTALL_INFO = 'install.info' + +GAMESS_INSTALL_INFO = 'install.info' +GAMESS_TEST_TASKS = 2 class EB_GAMESS_minus_US(EasyBlock): @@ -265,10 +267,10 @@ def configure_step(self): # write install.info file with configuration settings # format: setenv KEY VALUE - installinfo_file = os.path.join(self.builddir, INSTALL_INFO) + installinfo_file = os.path.join(self.builddir, GAMESS_INSTALL_INFO) txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) write_file(installinfo_file, txt) - self.log.debug("Contents of install.info:\n%s" % read_file(installinfo_file)) + self.log.debug("Contents of %s:\n%s" % (installinfo_file, read_file(installinfo_file))) # patch hardcoded settings in rungms to use values specified in easyconfig file rungms = os.path.join(self.builddir, 'rungms') @@ -382,7 +384,8 @@ def test_step(self): tests_path = os.path.join(self.installdir, 'tests', 'standard') n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) for i in range(1, n_tests+1): - test_cmd = ' '.join(test_env_vars + [rungms, 'exam%02d' % i, self.version, '1', '2']) + rungms_cmd = [rungms, 'exam%02d' % i, self.version, str(GAMESS_TEST_TASKS), str(GAMESS_TEST_TASKS)] + test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) From a9de2fdf0a316ca70db760b8ad8154fd4d95a199 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 13 Mar 2023 15:19:16 +0100 Subject: [PATCH 021/134] fix gamess-us configuration for Intel MPI v2019+ --- easybuild/easyblocks/g/gamess_us.py | 39 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 567a6c98ca..7bbf77d906 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -191,21 +191,40 @@ def configure_step(self): mpilib, mpilib_path = '', '' if self.cfg['ddi_comm'] == 'mpi': known_mpilibs = ['impi', 'OpenMPI', 'MVAPICH2', 'MPICH2'] - for mpilib in known_mpilibs: - mpilib_root = get_software_root(mpilib) - if mpilib_root is not None: - break - if mpilib_root is None: + loaded_mpilib = [mpilib for mpilib in known_mpilibs if get_software_root(mpilib)] + + # mpi library: default settings + try: + mpilib = loaded_mpilib[0].lower() + mpilib_root = get_software_root(loaded_mpilib[0]) + mpilib_subfolder = '' + except IndexError: raise EasyBuildError("None of the known MPI libraries (%s) available, giving up.", known_mpilibs) - mpilib_path = mpilib_root + if mpilib == 'impi': impi_ver = get_software_version('impi') - if LooseVersion(impi_ver) >= LooseVersion("2021.0.0"): - mpilib_path = os.path.join(mpilib_root, 'mpi', 'latest') + if LooseVersion(impi_ver) >= LooseVersion("2021"): + mpilib_subfolder = "mpi/latest" else: - mpilib_path = os.path.join(mpilib_root, 'intel64') + mpilib_subfolder = "intel64" + + if LooseVersion(impi_ver) >= LooseVersion("2019"): + # fix rungms settings for newer versions of Intel MPI + print("PATCH IMPI") + rungms = os.path.join(self.builddir, 'rungms') + try: + for line in fileinput.input(rungms, inplace=1, backup='.orig'): + line = re.sub(r"^(\s*setenv\s*I_MPI_STATS).*", r"# \1", line) + line = re.sub(r"^(\s*setenv\s*I_MPI_WAIT_MODE)\s*enable.*", r"\1 1", line) + sys.stdout.write(line) + except IOError as err: + raise EasyBuildError("Failed to patch Intel MPI settings in %s: %s", rungms, err) + + if mpilib_root is not None: + mpilib_path = os.path.join(mpilib_root, mpilib_subfolder) + self.log.debug("Software root of MPI libraries set to: %s", mpilib_path) else: - mpilib = mpilib.lower() + raise EasyBuildError("Software root of MPI libraries (%s) not found", mpilib) installinfo_opts["GMS_MPI_LIB"] = mpilib installinfo_opts["GMS_MPI_PATH"] = mpilib_path From b009762a6e9a40c2660da772cfc26b9762108dfc Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 20 Mar 2023 16:06:57 +0100 Subject: [PATCH 022/134] reduce minimum version for libxc support in gamess-us to 20200101 --- easybuild/easyblocks/g/gamess_us.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 7bbf77d906..9b9149cb74 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -245,7 +245,7 @@ def configure_step(self): # Optional plug-ins and interfaces # libXC - if LooseVersion(self.version) >= LooseVersion('20210101'): + if LooseVersion(self.version) >= LooseVersion('20200101'): installinfo_opts['GMS_LIBXC'] = "false" if get_software_root('libxc'): installinfo_opts['GMS_LIBXC'] = "true" From c4f0baec11cbb45831d83b0f21197204be817954 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 20 Mar 2023 16:07:36 +0100 Subject: [PATCH 023/134] add Alex Domingo as author of gamess-us easyblock --- easybuild/easyblocks/g/gamess_us.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 9b9149cb74..aff9753f4e 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -33,6 +33,7 @@ @author: Toon Willems (Ghent University) @author: Pablo Escobar (sciCORE, SIB, University of Basel) @author: Benjamin Roberts (The University of Auckland) +@author: Alex Domingo (Vrije Universiteit Brussel) """ import fileinput import glob From 1505dc54499e85e45af4db1938aea55f8d145e8c Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 6 Dec 2023 18:18:06 +0100 Subject: [PATCH 024/134] fix code formatting in gamess_us easyblock --- easybuild/easyblocks/g/gamess_us.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index ea8f10da33..cf8bdd00d9 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -38,7 +38,6 @@ import fileinput import glob import os -import random import re import shutil import sys @@ -165,7 +164,7 @@ def configure_step(self): installinfo_opts["GMS_MKL_VERNO"] = mkl_version elif mathlib == 'openblas': - mathlib_flags="-lopenblas -lgfortran" + mathlib_flags = "-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): mathlib_subfolder = 'lib' @@ -185,7 +184,7 @@ def configure_step(self): raise EasyBuildError( "Unsupported DDI communication layer specified (known: %s): %s", known_ddi_comms, self.cfg['ddi_comm'] ) - + installinfo_opts["GMS_DDI_COMM"] = self.cfg['ddi_comm'] # MPI library config @@ -282,7 +281,7 @@ def configure_step(self): # add include paths from dependencies installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] - # might be useful for debugging + # might be useful for debugging # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" # write install.info file with configuration settings @@ -307,7 +306,9 @@ def configure_step(self): line = re.sub(r"^(\s*)(setenv\s*LD_LIBRARY_PATH\s*/.*)", r"\1#\2", line) # scratch directory paths line = re.sub(r"^(\s*set\s*SCR)=.*", r"if ( ! $?SCR ) \1=%s" % self.cfg['scratch_dir'], line) - line = re.sub(r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line) + line = re.sub( + r"^(\s*set\s*USERSCR)=.*", r"if ( ! $?USERSCR ) \1=%s" % self.cfg['user_scratch_dir'], line + ) line = re.sub(r"^(df -k \$SCR)$", r"mkdir -p $SCR && mkdir -p $USERSCR && \1", line) if self.cfg['hyperthreading'] is False: # disable hyperthreading (1 thread per core) @@ -325,20 +326,22 @@ def configure_step(self): line = re.sub(r"^(\s*set MAXNODES)=.*", r"\1=%s" % self.cfg['maxnodes'], line, 1) sys.stdout.write(line) except IOError as err: - raise EasyBuildError("Failed to patch compddi", compddi, err) + raise EasyBuildError("Failed to patch compddi", compddi, err) # for GAMESS-US 20200630-R1 we need to build the actvte.x program if self.version == "20200630-R1": actvte = os.path.join(self.builddir, 'tools/actvte.code') try: for line in fileinput.input(actvte, inplace=1, backup='.orig'): - line = re.sub("\*UNX", " ", line) + line = re.sub("[*]UNX", " ", line) sys.stdout.write(line) except IOError as err: raise EasyBuildError("Failed to patch actvte.code", actvte, err) # compiling run_cmd("mv %s/tools/actvte.code" % self.builddir + " %s/tools/actvte.f" % self.builddir) - run_cmd("%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir) + run_cmd( + "%s -o " % fortran_comp + " %s/tools/actvte.x" % self.builddir + " %s/tools/actvte.f" % self.builddir + ) def build_step(self): """Custom build procedure for GAMESS-US: using compddi, compall and lked scripts.""" @@ -449,4 +452,3 @@ def cleanup_step(self): if os.path.isdir(scratch_path): remove_dir(scratch_path) self.log.info("Removed test scratch: %s", scratch_path) - From 9fd5be5e4a6b5d67084c87829fd25a439a1038d6 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 6 Dec 2023 18:20:39 +0100 Subject: [PATCH 025/134] fix variable names in gamess_us easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index cf8bdd00d9..02a073fc4c 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -118,7 +118,7 @@ def configure_step(self): # compiler config comp_fam = self.toolchain.comp_family() - fortran_comp, fortran_ver = None, None + fortran_comp, fortran_version = None, None if comp_fam == toolchain.INTELCOMP: fortran_comp = 'ifort' (out, _) = run_cmd("ifort -v", simple=False) @@ -250,7 +250,7 @@ def configure_step(self): if get_software_root('libxc'): installinfo_opts['GMS_LIBXC'] = "true" # the linker needs to be patched to use external libXC - lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', l) for l in ['libxcf03.a', 'libxc.a']] + lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', lib) for lib in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) try: lked = os.path.join(self.builddir, 'lked') From 2bd1871e9fc3bfac327036740f0ba0a897cf1088 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 11 Dec 2023 15:29:20 +0100 Subject: [PATCH 026/134] disable libcchem2 support in GAMESS-US v20230601+ --- easybuild/easyblocks/g/gamess_us.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 02a073fc4c..d9c98da3c2 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -239,9 +239,13 @@ def configure_step(self): # These are extra programs which for now we simply set all to FALSE installinfo_opts["GMS_MSUCC"] = "false" - installinfo_opts["GMS_LIBCCHEM"] = "false" installinfo_opts["GMS_PHI"] = "none" installinfo_opts["GMS_SHMTYPE"] = "sysv" + installinfo_opts["GMS_LIBCCHEM"] = "false" # libcchem + if LooseVersion(self.version) >= LooseVersion('20230601'): + # install options for libcchem2 + installinfo_opts["GMS_HPCCHEM"] = "false" + installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" # Optional plug-ins and interfaces # libXC From d46d5a12ed74810772e35399ec2508080f287a80 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 09:22:01 +0100 Subject: [PATCH 027/134] disable OpenMP offloading on Intel GPUs in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d9c98da3c2..318a84594d 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -237,6 +237,12 @@ def configure_step(self): installinfo_opts["GMS_OPENMP"] = omp_enabled + # Accelerators (disabled) + # TODO: add support for GPUs + if LooseVersion(self.version) >= LooseVersion('20230601'): + # offloading onto Intel GPUs + installinfo_opts["GMS_OPENMP_OFFLOAD"] = "false" + # These are extra programs which for now we simply set all to FALSE installinfo_opts["GMS_MSUCC"] = "false" installinfo_opts["GMS_PHI"] = "none" From c0c0e5e7a85489a1b73baa9bb598633176fdbcb1 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 09:22:20 +0100 Subject: [PATCH 028/134] disable Michigan State University code in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 318a84594d..f3f0d1da17 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -252,6 +252,8 @@ def configure_step(self): # install options for libcchem2 installinfo_opts["GMS_HPCCHEM"] = "false" installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" + # build Michigan State University code + installinfo_opts["GMS_MSUAUTO"] = "false" # Optional plug-ins and interfaces # libXC From df5cfd1c04c29fe927c1aa1bec53b542f49ee137 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 12 Dec 2023 14:02:11 +0100 Subject: [PATCH 029/134] disable RISM plugin in GAMESS-US v20230601+ --- easybuild/easyblocks/g/gamess_us.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index f3f0d1da17..5a45ddc9ba 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -274,20 +274,23 @@ def configure_step(self): # MDI # needs https://github.com/MolSSI-MDI/MDI_Library installinfo_opts['GMS_MDI'] = "false" - # VM2 - installinfo_opts['GMS_VM2'] = "false" # NBO installinfo_opts['NBO'] = "false" if get_software_root('NBO'): installinfo_opts['NBO'] = "true" # NEO installinfo_opts['NEO'] = "false" + # RISM + if LooseVersion(self.version) >= LooseVersion('20230601'): + installinfo_opts['RISM'] = "false" # TINKER installinfo_opts['TINKER'] = "false" if get_software_root('TINKER'): installinfo_opts['TINKER'] = "true" # VB2000 installinfo_opts['VB2000'] = "false" + # VM2 + installinfo_opts['GMS_VM2'] = "false" # XMVB installinfo_opts['XMVB'] = "false" From b4b7479553c5e89bc3b7fff2f99cb939659bab19 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 15 Dec 2023 11:40:05 +0100 Subject: [PATCH 030/134] run GAMESS-US tests following the parallelism set in parallel setting --- easybuild/easyblocks/g/gamess_us.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 5a45ddc9ba..28614e4b0f 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -58,7 +58,6 @@ from easybuild.tools import toolchain GAMESS_INSTALL_INFO = 'install.info' -GAMESS_TEST_TASKS = 2 class EB_GAMESS_minus_US(EasyBlock): @@ -420,9 +419,10 @@ def test_step(self): # run all exam tests, dump output to exam.log # we let Python count the number of *.inp files as that changes tests_path = os.path.join(self.installdir, 'tests', 'standard') - n_tests = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) - for i in range(1, n_tests+1): - rungms_cmd = [rungms, 'exam%02d' % i, self.version, str(GAMESS_TEST_TASKS), str(GAMESS_TEST_TASKS)] + tests_num = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + tests_procs = str(self.cfg['parallel']) + for i in range(1, tests_num+1): + rungms_cmd = [rungms, 'exam%02d' % i, self.version, tests_procs, tests_procs] test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) write_file('exam%02d.log' % i, out) @@ -430,7 +430,7 @@ def test_step(self): # verify output of tests check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) - success_regex = re.compile("^All %d test results are correct" % n_tests, re.M) + success_regex = re.compile("^All %d test results are correct" % tests_num, re.M) if success_regex.search(out): self.log.info("All tests ran successfully!") else: From a017f26b9391cdf4494a112a2893b31cb0018262 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 16 Dec 2023 00:39:31 +0100 Subject: [PATCH 031/134] blacklist GAMESS-US tests not compatible with parallel execution --- easybuild/easyblocks/g/gamess_us.py | 47 ++++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 28614e4b0f..4eb717c836 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -42,7 +42,6 @@ import shutil import sys import tempfile -import fnmatch from distutils.version import LooseVersion @@ -58,7 +57,14 @@ from easybuild.tools import toolchain GAMESS_INSTALL_INFO = 'install.info' - +GAMESS_MPI_TEST_BLACKLIST = [ + 'exam05', # only the gradients for CITYP=CIS run in parallel + 'exam32', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel + 'exam42', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution + 'exam45', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel + 'exam46', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution + 'exam47', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution +] class EB_GAMESS_minus_US(EasyBlock): """Support for building/installing GAMESS-US.""" @@ -402,11 +408,16 @@ def test_step(self): cwd = change_dir(self.testdir) # copy input files for exam standard tests + target_tests = [] for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): - try: - shutil.copy2(test_input, os.getcwd()) - except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + test_name = os.path.splitext(os.path.basename(test_input))[0] + if test_name not in GAMESS_MPI_TEST_BLACKLIST: + try: + shutil.copy2(test_input, os.getcwd()) + except OSError as err: + raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + else: + target_tests.append(test_name) rungms = os.path.join(self.installdir, 'rungms') test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] @@ -416,25 +427,25 @@ def test_step(self): 'I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required ]) - # run all exam tests, dump output to exam.log - # we let Python count the number of *.inp files as that changes - tests_path = os.path.join(self.installdir, 'tests', 'standard') - tests_num = len(fnmatch.filter(os.listdir(tests_path), '*.inp')) + # run target exam tests, dump output to exam.log tests_procs = str(self.cfg['parallel']) - for i in range(1, tests_num+1): - rungms_cmd = [rungms, 'exam%02d' % i, self.version, tests_procs, tests_procs] + for test_exam in target_tests: + rungms_cmd = [rungms, test_exam, self.version, tests_procs, tests_procs] test_cmd = ' '.join(test_env_vars + rungms_cmd) (out, _) = run_cmd(test_cmd, log_all=True, simple=False) - write_file('exam%02d.log' % i, out) + write_file('%s.log' % test_exam, out) - # verify output of tests check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) - success_regex = re.compile("^All %d test results are correct" % tests_num, re.M) - if success_regex.search(out): - self.log.info("All tests ran successfully!") + + # verify output of tests + failed_regex = re.compile(r"^.*!!FAILED\.$", re.M) + failed_tests = [exam[0:6] for exam in failed_regex.findall(out)] + if set(failed_tests) == set(GAMESS_MPI_TEST_BLACKLIST): + blacklisted_msg = "(blacklisted: %s)" % ", ".join(GAMESS_MPI_TEST_BLACKLIST) + self.log.info("All target tests ran successfully! %s", blacklisted_msg) else: - raise EasyBuildError("Not all tests ran successfully...") + raise EasyBuildError("ERROR: Not all target tests ran successfully") change_dir(cwd) From a9d1ef0f43c247e3e1e6041061935f0317a3729e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 10:32:19 +0100 Subject: [PATCH 032/134] run GAMESS-US tests in the scratch directory --- easybuild/easyblocks/g/gamess_us.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 4eb717c836..dcdc5728d9 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -49,7 +49,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, read_file, write_file, remove_dir +from easybuild.tools.filetools import change_dir, mkdir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 @@ -87,9 +87,20 @@ def __init__(self, *args, **kwargs): """Easyblock constructor, enable building in installation directory.""" super(EB_GAMESS_minus_US, self).__init__(*args, **kwargs) self.build_in_installdir = True + + # resolve path to scratch dir and make it + scratch_dir_resolved = os.path.expandvars(self.cfg['scratch_dir']) + if "$" in scratch_dir_resolved: + error_msg = "Provided scratch directory '%s' does not resolve into a path." + raise EasyBuildError(error_msg, self.cfg['scratch_dir']) + + mkdir(scratch_dir_resolved, parents=True) + self.testdir = None if self.cfg['runtest']: - self.testdir = tempfile.mkdtemp() + # run tests in scratch dir + self.testdir = tempfile.mkdtemp(dir=scratch_dir_resolved) + # make sure test dir doesn't contain [ or ], rungms csh script doesn't handle that well ("set: No match") if re.search(r'[\[\]]', self.testdir): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" @@ -420,7 +431,7 @@ def test_step(self): target_tests.append(test_name) rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; TMPDIR=%s' % self.testdir] + test_env_vars = ['export OMP_NUM_THREADS=1; SCR=%s' % self.testdir] if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) @@ -472,9 +483,7 @@ def cleanup_step(self): """Cleanup set.""" super(EB_GAMESS_minus_US, self).cleanup_step() - # remove dedicated scratch directory (if any); - # we must use a shell command for this, since the path may contain environment variables - (scratch_path, _) = run_cmd('printf "%%s" "%s"' % self.cfg['scratch_dir'], simple=False) - if os.path.isdir(scratch_path): - remove_dir(scratch_path) - self.log.info("Removed test scratch: %s", scratch_path) + # remove test directory + if os.path.isdir(self.testdir): + remove_dir(self.testdir) + self.log.info("Removed test scratch: %s", self.testdir) From da4b7770252ffa37cfe29c6c589440b84b48cab2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 11:12:46 +0100 Subject: [PATCH 033/134] fix code formatting in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index dcdc5728d9..f1f941ca98 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -66,6 +66,7 @@ 'exam47', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution ] + class EB_GAMESS_minus_US(EasyBlock): """Support for building/installing GAMESS-US.""" From b839b5dd1e09c7191304046fe79c9434a068b2c1 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:05:55 +0100 Subject: [PATCH 034/134] move cleanup of test dir back to test step of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index f1f941ca98..22e2d711c4 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -459,7 +459,12 @@ def test_step(self): else: raise EasyBuildError("ERROR: Not all target tests ran successfully") + # cleanup change_dir(cwd) + try: + remove_dir(self.testdir) + except OSError as err: + raise EasyBuildError("Failed to remove test directory %s: %s", self.testdir, err) def install_step(self): """Skip install step, since we're building in the install directory.""" @@ -479,12 +484,3 @@ def make_module_extra(self): txt += self.module_generator.set_environment('GAMESSUSROOT', self.installdir) txt += self.module_generator.prepend_paths("PATH", ['']) return txt - - def cleanup_step(self): - """Cleanup set.""" - super(EB_GAMESS_minus_US, self).cleanup_step() - - # remove test directory - if os.path.isdir(self.testdir): - remove_dir(self.testdir) - self.log.info("Removed test scratch: %s", self.testdir) From cf206fb485fdcda4344f45c677811ee57550cca3 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:07:03 +0100 Subject: [PATCH 035/134] replace shutil.copy2 with filetools.copy_files method in GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 22e2d711c4..b6e6655e75 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -39,7 +39,6 @@ import glob import os import re -import shutil import sys import tempfile @@ -49,7 +48,7 @@ from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.filetools import change_dir, mkdir, read_file, write_file, remove_dir +from easybuild.tools.filetools import change_dir, copy_file, mkdir, read_file, write_file, remove_dir from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 @@ -417,7 +416,11 @@ def test_step(self): self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") return - cwd = change_dir(self.testdir) + try: + cwd = os.getcwd() + change_dir(self.testdir) + except OSError as err: + raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) # copy input files for exam standard tests target_tests = [] @@ -425,9 +428,9 @@ def test_step(self): test_name = os.path.splitext(os.path.basename(test_input))[0] if test_name not in GAMESS_MPI_TEST_BLACKLIST: try: - shutil.copy2(test_input, os.getcwd()) + copy_file(test_input, self.testdir) except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, os.getcwd(), err) + raise EasyBuildError("Failed to copy %s to %s: %s", test_input, self.testdir, err) else: target_tests.append(test_name) From 2d513f25aa9d6d1c7ef005678d1dbcffc3898f1a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 18 Dec 2023 14:09:46 +0100 Subject: [PATCH 036/134] replace distutils.LooseVersion with easybuild.tools.LooseVersion in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index b6e6655e75..e8fd7d8512 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -42,8 +42,6 @@ import sys import tempfile -from distutils.version import LooseVersion - from easybuild.framework.easyblock import EasyBlock from easybuild.framework.easyconfig import CUSTOM, MANDATORY from easybuild.tools.build_log import EasyBuildError @@ -53,7 +51,7 @@ from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import POWER, X86_64 from easybuild.tools.systemtools import get_cpu_architecture -from easybuild.tools import toolchain +from easybuild.tools import LooseVersion, toolchain GAMESS_INSTALL_INFO = 'install.info' GAMESS_MPI_TEST_BLACKLIST = [ From 9af8f84c87e8d57a5a52f59def57c99f2538ab34 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Thu, 21 Dec 2023 09:46:41 +0100 Subject: [PATCH 037/134] add support for GMS_THREADED_BLAS in 2023+ versions of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index e8fd7d8512..0c73fc6063 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -130,7 +130,7 @@ def configure_step(self): installinfo_opts["GMS_TARGET"] = machinetype installinfo_opts["GMS_HPC_SYSTEM_TARGET"] = "generic" - # compiler config + # Compiler config comp_fam = self.toolchain.comp_family() fortran_comp, fortran_version = None, None if comp_fam == toolchain.INTELCOMP: @@ -152,7 +152,15 @@ def configure_step(self): installinfo_opts["GMS_FORTRAN"] = fortran_comp installinfo_opts.update(fortran_version) - # math library config + # OpenMP config + if self.toolchain.options.get('openmp', None): + omp_enabled = "true" + else: + omp_enabled = "false" + + installinfo_opts["GMS_OPENMP"] = omp_enabled + + # Math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] loaded_mathlib = [mathlib for mathlib in known_mathlibs if get_software_root(mathlib)] @@ -177,6 +185,9 @@ def configure_step(self): mkl_version = 'oneapi' installinfo_opts["GMS_MKL_VERNO"] = mkl_version + if LooseVersion(self.version) >= LooseVersion('20230601'): + installinfo_opts["GMS_THREADED_BLAS"] = omp_enabled + elif mathlib == 'openblas': mathlib_flags = "-lopenblas -lgfortran" if LooseVersion(self.version) >= LooseVersion('20210101'): @@ -243,14 +254,6 @@ def configure_step(self): installinfo_opts["GMS_MPI_LIB"] = mpilib installinfo_opts["GMS_MPI_PATH"] = mpilib_path - # OpenMP config - if self.toolchain.options.get('openmp', None): - omp_enabled = "true" - else: - omp_enabled = "false" - - installinfo_opts["GMS_OPENMP"] = omp_enabled - # Accelerators (disabled) # TODO: add support for GPUs if LooseVersion(self.version) >= LooseVersion('20230601'): From c79e6e250d03ef6013b7d63677bfd25dd8f65b83 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 3 Feb 2024 10:58:24 +0100 Subject: [PATCH 038/134] execute all tests in serial for non-mpi builds of GAMESS-US --- easybuild/easyblocks/g/gamess_us.py | 90 ++++++++++++++++------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 0c73fc6063..d68e96c2db 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -54,7 +54,7 @@ from easybuild.tools import LooseVersion, toolchain GAMESS_INSTALL_INFO = 'install.info' -GAMESS_MPI_TEST_BLACKLIST = [ +GAMESS_SERIAL_TESTS = [ 'exam05', # only the gradients for CITYP=CIS run in parallel 'exam32', # only CCTYP=CCSD or CCTYP=CCSD(T) can run in parallel 'exam42', # ROHF'S CCTYP must be CCSD or CR-CCL, with serial execution @@ -406,60 +406,72 @@ def build_step(self): def test_step(self): """Run GAMESS-US tests (if 'runtest' easyconfig parameter is set to True).""" - # don't use provided 'runall' script for tests, since that only runs the tests single-core if self.cfg['runtest']: - - if not build_option('mpi_tests'): - self.log.info("Skipping testing of GAMESS-US since MPI testing is disabled") - return - - if int(self.cfg['parallel']) < 2: - self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") - return - + # Avoid provided 'runall' script for tests, since that only runs the tests in serial + # Tests must be run in parallel for MPI builds and can be run serial for other build types + + target_tests = [ + # (test name, path to test input) + (os.path.splitext(os.path.basename(exam_file))[0], exam_file) + for exam_file in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')) + ] + test_procs = "1" + test_env_vars = ['export OMP_NUM_THREADS=1'] + + if self.cfg['ddi_comm'] == 'mpi': + if not build_option('mpi_tests'): + self.log.info("Skipping tests of MPI build of GAMESS-US by user request ('mpi_tests' is disabled)") + retur + + # MPI builds can only run tests that support parallel execution + if int(self.cfg['parallel']) < 2: + self.log.info("Skipping testing of GAMESS-US as MPI tests need at least 2 CPU cores to run") + return + + test_procs = str(self.cfg['parallel']) + target_tests = [exam for exam in target_tests if exam[0] not in GAMESS_SERIAL_TESTS] + + if self.toolchain.mpi_family() == toolchain.INTELMPI: + test_env_vars.extend([ + 'export I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) + 'export I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required + ]) + + # Prepare test directory to run tests try: cwd = os.getcwd() change_dir(self.testdir) except OSError as err: raise EasyBuildError("Failed to move to temporary directory for running tests: %s", err) - # copy input files for exam standard tests - target_tests = [] - for test_input in glob.glob(os.path.join(self.installdir, 'tests', 'standard', 'exam*.inp')): - test_name = os.path.splitext(os.path.basename(test_input))[0] - if test_name not in GAMESS_MPI_TEST_BLACKLIST: - try: - copy_file(test_input, self.testdir) - except OSError as err: - raise EasyBuildError("Failed to copy %s to %s: %s", test_input, self.testdir, err) - else: - target_tests.append(test_name) + for exam, exam_file in target_tests: + try: + copy_file(exam_file, self.testdir) + except OSError as err: + raise EasyBuildError("Failed to copy test '%s' to %s: %s", exam, self.testdir, err) - rungms = os.path.join(self.installdir, 'rungms') - test_env_vars = ['export OMP_NUM_THREADS=1; SCR=%s' % self.testdir] - if self.toolchain.mpi_family() == toolchain.INTELMPI: - test_env_vars.extend([ - 'I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) - 'I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required - ]) + test_env_vars.append('SCR=%s' % self.testdir) # run target exam tests, dump output to exam.log - tests_procs = str(self.cfg['parallel']) - for test_exam in target_tests: - rungms_cmd = [rungms, test_exam, self.version, tests_procs, tests_procs] - test_cmd = ' '.join(test_env_vars + rungms_cmd) - (out, _) = run_cmd(test_cmd, log_all=True, simple=False) - write_file('%s.log' % test_exam, out) + rungms = os.path.join(self.installdir, 'rungms') + for exam, exam_file in target_tests: + rungms_prefix = ' && '.join(test_env_vars) + test_cmd = [rungms_prefix, rungms, exam_file, self.version, test_procs, test_procs] + (out, _) = run_cmd(' '.join(test_cmd), log_all=True, simple=False) + write_file('%s.log' % exam, out) check_cmd = os.path.join(self.installdir, 'tests', 'standard', 'checktst') (out, _) = run_cmd(check_cmd, log_all=True, simple=False) # verify output of tests failed_regex = re.compile(r"^.*!!FAILED\.$", re.M) - failed_tests = [exam[0:6] for exam in failed_regex.findall(out)] - if set(failed_tests) == set(GAMESS_MPI_TEST_BLACKLIST): - blacklisted_msg = "(blacklisted: %s)" % ", ".join(GAMESS_MPI_TEST_BLACKLIST) - self.log.info("All target tests ran successfully! %s", blacklisted_msg) + failed_tests = set([exam[0:6] for exam in failed_regex.findall(out)]) + done_tests = set([exam[0] for exam in target_tests]) + if done_tests - failed_tests == done_tests: + info_msg = "All target tests ran successfully!" + if self.cfg['ddi_comm'] == 'mpi': + info_msg += " (serial tests ignored: %s)" % ", ".join(GAMESS_SERIAL_TESTS) + self.log.info(info_msg) else: raise EasyBuildError("ERROR: Not all target tests ran successfully") From 253ef5b522dd3b266278ef25c3220174adf06cdd Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Sat, 3 Feb 2024 11:02:26 +0100 Subject: [PATCH 039/134] fix code formatting in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index d68e96c2db..60b2b32397 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -421,7 +421,7 @@ def test_step(self): if self.cfg['ddi_comm'] == 'mpi': if not build_option('mpi_tests'): self.log.info("Skipping tests of MPI build of GAMESS-US by user request ('mpi_tests' is disabled)") - retur + return # MPI builds can only run tests that support parallel execution if int(self.cfg['parallel']) < 2: @@ -433,8 +433,10 @@ def test_step(self): if self.toolchain.mpi_family() == toolchain.INTELMPI: test_env_vars.extend([ - 'export I_MPI_FALLBACK=enable', # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) - 'export I_MPI_HYDRA_BOOTSTRAP=fork', # tests are only run locally (2 processes), so no SSH required + # enable fallback in case first fabric fails (see $I_MPI_FABRICS_LIST) + 'export I_MPI_FALLBACK=enable', + # tests are only run locally (single node), so no SSH required + 'export I_MPI_HYDRA_BOOTSTRAP=fork', ]) # Prepare test directory to run tests From bf2392926fe6e2f3d3dd86533bbb76a690c1131c Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 14 Mar 2024 15:45:12 +0100 Subject: [PATCH 040/134] Added easyblock for QE with cmake --- .../easyblocks/q/quantumespressocmake.py | 354 ++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 easybuild/easyblocks/q/quantumespressocmake.py diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py new file mode 100644 index 0000000000..2209afed49 --- /dev/null +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -0,0 +1,354 @@ +## +# Copyright 2009-2023 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 . +## +""" +EasyBuild support for Quantum ESPRESSO, implemented as an easyblock + +@author: Davide Grassano (CECAM, EPFL) +""" +import os +import re + +from easybuild.framework.easyconfig import CUSTOM +from easybuild.tools import LooseVersion +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.modules import get_software_root +from easybuild.tools.run import run_cmd + +from easybuild.easyblocks.generic.cmakemake import CMakeMake + + +class EB_QuantumESPRESSOcmake(CMakeMake): + """Support for building and installing Quantum ESPRESSO.""" + + TEST_SUITE_DIR = "test-suite" + + @staticmethod + def extra_options(): + """Custom easyconfig parameters for Quantum ESPRESSO.""" + extra_vars = { + 'with_cuda': [False, "Enable CUDA support", CUSTOM], + 'with_scalapack': [True, "Enable ScaLAPACK support", CUSTOM], + 'with_fox': [False, "Enable FoX support", CUSTOM], + 'with_gipaw': [True, "Enable GIPAW support", CUSTOM], + 'with_d3q': [False, "Enable D3Q support", CUSTOM], + 'with_qmcpack': [False, "Enable QMCPACK support", CUSTOM], + 'test_suite_nprocs': [1, "Number of processors to use for the test suite", CUSTOM], + 'test_suite_allow_failures': [[ + 'test_qe_xclib_', # 7.3.1: https://gitlab.com/QEF/q-e/-/issues/640 + '--hp_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) + '--ph_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) + '--epw_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) + '--tddfpt_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) + ], "List of test suite targets that are allowed to fail (name can partially match)", CUSTOM], + 'test_suite_threshold': [ + 0.97, + "Threshold for test suite success rate (does count also allowed failures)", + CUSTOM + ], + 'test_suite_max_failed': [0, "Maximum number of failing tests (does not count allowed failures)", CUSTOM], + } + return CMakeMake.extra_options(extra_vars) + + def __init__(self, *args, **kwargs): + """Add extra config options specific to Quantum ESPRESSO.""" + super(EB_QuantumESPRESSOcmake, self).__init__(*args, **kwargs) + + self.install_subdir = "qe-%s" % self.version + + self.check_bins = [] + + def _add_toolchains_opts(self): + """Enable toolchain options for Quantum ESPRESSO.""" + self._add_mpi() + self._add_openmp() + self._add_cuda() + + def _add_libraries(self): + """Enable external libraries for Quantum ESPRESSO.""" + self._add_scalapack() + self._add_fox() + self._add_libxc() + self._add_elpa() + self._add_hdf5() + + def _add_plugins(self): + """Enable plugins for Quantum ESPRESSO.""" + plugins = [] + plugins += self._add_gipaw() + plugins += self._add_d3q() + plugins += self._add_qmcpack() + if plugins: + self.cfg.update('configopts', '-DQE_ENABLE_PLUGINS="%s"' % ';'.join(plugins)) + + def _add_mpi(self): + """Enable MPI for Quantum ESPRESSO.""" + if self.toolchain.options.get('usempi', False): + self.cfg.update('configopts', '-DENABLE_MPI=ON') + + def _add_openmp(self): + """Enable OpenMP for Quantum ESPRESSO.""" + if self.toolchain.options.get('openmp', False): + self.cfg.update('configopts', '-DENABLE_OPENMP=ON') + + def _add_cuda(self): + """Enable CUDA for Quantum ESPRESSO.""" + if self.cfg.get('with_cuda', False): + self.cfg.update('configopts', '-DQE_ENABLE_CUDA=ON') + self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=ON') + + def _add_scalapack(self): + """Enable ScaLAPACK for Quantum ESPRESSO.""" + if self.cfg.get('with_scalapack', False): + if not self.toolchain.options.get('usempi', False): + raise EasyBuildError("ScaLAPACK support requires MPI") + self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') + + def _add_fox(self): + """Enable FoX for Quantum ESPRESSO.""" + if self.cfg.get('with_fox', False): + self.cfg.update('configopts', '-DQE_ENABLE_FOX=ON') + + def _add_hdf5(self): + """Enable HDF5 for Quantum ESPRESSO.""" + if get_software_root("HDF5"): + self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') + + def _add_libxc(self): + """Enable LibXC for Quantum ESPRESSO.""" + if get_software_root("libxc"): + self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') + + def _add_elpa(self): + """Enable ELPA for Quantum ESPRESSO.""" + if get_software_root("ELPA"): + if not self.cfg.get('with_scalapack', False): + raise EasyBuildError("ELPA support requires ScaLAPACK") + if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): + raise EasyBuildError("QE 7.3 with cmake does not support ELPA with OpenMP") + self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') + + def _add_gipaw(self): + """Enable GIPAW for Quantum ESPRESSO.""" + res = [] + if self.cfg.get('with_gipaw', False): + if LooseVersion(self.version) == LooseVersion('7.3.1'): + # See issue: https://github.com/dceresoli/qe-gipaw/issues/19 + raise EasyBuildError("GIPAW will fail to compile in QE 7.3.1") + res = ['gipaw'] + self.check_bins += ['gipaw.x'] + return res + + def _add_d3q(self): + """Enable D3Q for Quantum ESPRESSO.""" + res = [] + if self.cfg.get('with_d3q', False): + if LooseVersion(self.version) > LooseVersion('7.0'): + # See issues: + # https://gitlab.com/QEF/q-e/-/issues/666 + # https://github.com/anharmonic/d3q/issues/13 + raise EasyBuildError("D3Q is not supported in QE 7.0+") + res = ['d3q'] + self.check_bins += [ + 'd3_asr3.x', 'd3_lw.x', 'd3_q2r.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', + 'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x' + ] + return res + + def _add_qmcpack(self): + """Enable QMCPACK for Quantum ESPRESSO.""" + res = [] + if self.cfg.get('with_qmcpack', False): + res = ['pw2qmcpack'] + self.check_bins += ['pw2qmcpack.x'] + return res + + def configure_step(self): + """Custom configuration procedure for Quantum ESPRESSO.""" + + if LooseVersion(self.version) < LooseVersion('7.3'): + raise EasyBuildError("EB QuantumEspresso cmake is implemented for versions >= 7.3") + + self._add_toolchains_opts() + self._add_libraries() + self._add_plugins() + + # Enable/configure test suite + nprocs = self.cfg.get('test_suite_nprocs', 1) + self.cfg.update('configopts', '-DQE_ENABLE_TEST=ON') + self.cfg.update('configopts', '-DTESTCODE_NPROCS=%d' % nprocs) + + # Change format of timings to seconds only (from d/h/m/s) + self.cfg.update('configopts', '-DQE_CLOCK_SECONDS=ON') + + super(EB_QuantumESPRESSOcmake, self).configure_step() + + def test_step(self): + """ + Test the compilation using Quantum ESPRESSO's test suite. + ctest -j NCONCURRENT (NCONCURRENT = max (1, PARALLEL / NPROCS)) + """ + + thr = self.cfg.get('test_suite_threshold', 0.97) + nprocs = self.cfg.get('test_suite_nprocs', 1) + concurrent = max(1, self.cfg.get('parallel', 1) // nprocs) + allow_fail = self.cfg.get('test_suite_allow_failures', []) + + cmd = ' '.join([ + 'ctest', + '-j%d' % concurrent, + '--output-on-failure', + ]) + + (out, _) = run_cmd(cmd, log_all=False, log_ok=False, simple=False, regexp=False) + + # Example output: + # 74% tests passed, 124 tests failed out of 481 + rgx = r'^ *(?P\d+)% tests passed, +(?P\d+) +tests failed out of +(?P\d+)' + mch = re.search(rgx, out, re.MULTILINE) + if not mch: + raise EasyBuildError("Failed to parse test suite output") + + perc = int(mch.group('perc')) / 100 + num_fail = int(mch.group('failed')) + total = int(mch.group('total')) + passed = total - num_fail + failures = [] # list of tests that failed, to be logged at the end + + + # Example output for reported failures: + # 635/635 Test #570: system--epw_wfpt-correctness ......................................***Failed 3.52 sec + self.log.debug("Test suite output:") + self.log.debug(out) + for line in out.splitlines(): + if '***Failed' in line: + for allowed in allow_fail: + if allowed in line: + self.log.info('Ignoring failure: %s' % line) + break + else: + failures.append(line) + self.log.warning(line) + + # Allow for flaky tests (eg too strict thresholds on results for structure relaxation) + num_fail = len(failures) + num_fail_thr = self.cfg.get('test_suite_max_failed', 0) + # perc = spass / max(stot, 1) + self.log.info("Total tests passed %d out of %d (%.2f%%)" % (passed, total, perc * 100)) + if perc < thr: + raise EasyBuildError( + "Test suite failed with less than %.2f %% (%.2f) success rate" % (thr * 100, perc * 100) + ) + if num_fail > num_fail_thr: + raise EasyBuildError( + "Test suite failed with more than %d failures %d" % (num_fail_thr, num_fail) + ) + + return out + + def sanity_check_step(self): + """Custom sanity check for Quantum ESPRESSO.""" + + targets = self.cfg['buildopts'].split() + + # Condition for all targets being build 'make' or 'make all_currents' + all_cond = len(targets) == 0 or 'all_currents' in targets + pwall_cond = 'pwall' in targets + + + # Standard binaries + if all_cond or 'cp' in targets : + self.check_bins += ["cp.x", "cppp.x", "manycp.x", "wfdd.x"] + + if all_cond or 'epw' in targets: + self.check_bins += ["epw.x"] + + if all_cond or 'gwl' in targets: + self.check_bins += [ + "abcoeff_to_eps.x", "bse_main.x", "graph.x", "gww_fit.x", "gww.x", "head.x", "memory_pw4gww.x", + "pw4gww.x", "simple_bse.x", "simple_ip.x", "simple.x" + ] + + if all_cond or 'hp' in targets: + self.check_bins += ["hp.x"] + + if all_cond or 'ld1' in targets: + self.check_bins += ["ld1.x"] + + if all_cond or pwall_cond or 'neb' in targets: + self.check_bins += ["neb.x", "path_interpolation.x"] + + if all_cond or pwall_cond or 'ph' in targets: + self.check_bins += [ + "alpha2f.x", "dynmat.x", "fd_ef.x", "fd.x", "lambda.x", "phcg.x", "postahc.x", "q2r.x", "dvscf_q2r.x", + "epa.x", "fd_ifc.x", "fqha.x", "matdyn.x", "ph.x", "q2qstar.x" + ] + + if all_cond or pwall_cond or 'pp' in targets: + self.check_bins += [ + "average.x", "dos_sp.x", "ef.x", "fermi_int_0.x", "fermi_proj.x", "fs.x", "molecularpdos.x", + "pawplot.x", "plotband.x", "plotrho.x", "ppacf.x", "pp.x", "pw2bgw.x", "pw2gt.x", "pw2wannier90.x", + "wannier_ham.x", "wfck2r.x", "bands.x", "dos.x", "epsilon.x", "fermi_int_1.x", "fermi_velocity.x", + "initial_state.x", "open_grid.x", "plan_avg.x", "plotproj.x", "pmw.x", "pprism.x", "projwfc.x", + "pw2critic.x", "pw2gw.x", "sumpdos.x", "wannier_plot.x" + ] + + if all_cond or pwall_cond or 'pw' in targets: + self.check_bins += [ + "cell2ibrav.x", "ev.x", "ibrav2cell.x", "kpoints.x", "pwi2xsf.x", "pw.x", "scan_ibrav.x" + ] + + if all_cond or pwall_cond or 'pwcond' in targets: + self.check_bins += ["pwcond.x"] + + if all_cond or 'tddfpt' in targets: + self.check_bins += ["turbo_davidson.x", "turbo_eels.x", "turbo_lanczos.x", "turbo_magnon.x", "turbo_spectrum.x"] + + if all_cond or 'upf' in targets: + self.check_bins += ["upfconv.x", "virtual_v2.x"] + + if all_cond or 'xspectra' in targets: + self.check_bins += ["molecularnexafs.x", "spectra_correction.x", "xspectra.x"] + + # Plugins binaries + if (all_cond and self.cfg.get('with_gipaw', False)) or 'gipaw' in targets: + self.check_bins += ["gipaw.x"] + + if (all_cond and self.cfg.get('d3q', False)) or 'd3q' in targets: + self.check_bins += [ + 'd3_asr3.x', 'd3_lw.x', 'd3_q2r.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', + 'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x' + ] + + if (all_cond and self.cfg.get('with_qmcpack', False)) or 'pw2qmcpack' in targets: + self.check_bins += ['pw2qmcpack.x'] + + self.log.debug("Checking for binaries: %s" % ', '.join(self.check_bins)) + + custom_paths = { + 'files': [os.path.join('bin', x) for x in self.check_bins], + 'dirs': [] + } + + super(EB_QuantumESPRESSOcmake, self).sanity_check_step(custom_paths=custom_paths) From 28bbe87685e94782bd3eb8e62e16b72263e34c95 Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 14 Mar 2024 15:46:13 +0100 Subject: [PATCH 041/134] Plugin binaries already added in the _add_XXX methods --- easybuild/easyblocks/q/quantumespressocmake.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 2209afed49..d78180be83 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -331,21 +331,6 @@ def sanity_check_step(self): if all_cond or 'xspectra' in targets: self.check_bins += ["molecularnexafs.x", "spectra_correction.x", "xspectra.x"] - # Plugins binaries - if (all_cond and self.cfg.get('with_gipaw', False)) or 'gipaw' in targets: - self.check_bins += ["gipaw.x"] - - if (all_cond and self.cfg.get('d3q', False)) or 'd3q' in targets: - self.check_bins += [ - 'd3_asr3.x', 'd3_lw.x', 'd3_q2r.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', - 'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x' - ] - - if (all_cond and self.cfg.get('with_qmcpack', False)) or 'pw2qmcpack' in targets: - self.check_bins += ['pw2qmcpack.x'] - - self.log.debug("Checking for binaries: %s" % ', '.join(self.check_bins)) - custom_paths = { 'files': [os.path.join('bin', x) for x in self.check_bins], 'dirs': [] From 2a814076b3be4ecc8a157c1ab4193c60ea5b331c Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 15 Mar 2024 14:13:22 +0100 Subject: [PATCH 042/134] Added fix for intel toolchain --- easybuild/easyblocks/q/quantumespressocmake.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index d78180be83..265bce17ac 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -30,6 +30,7 @@ import os import re +import easybuild.tools.toolchain as toolchain from easybuild.framework.easyconfig import CUSTOM from easybuild.tools import LooseVersion from easybuild.tools.build_log import EasyBuildError @@ -189,6 +190,8 @@ def configure_step(self): if LooseVersion(self.version) < LooseVersion('7.3'): raise EasyBuildError("EB QuantumEspresso cmake is implemented for versions >= 7.3") + + comp_fam = self.toolchain.comp_family() self._add_toolchains_opts() self._add_libraries() @@ -202,6 +205,13 @@ def configure_step(self): # Change format of timings to seconds only (from d/h/m/s) self.cfg.update('configopts', '-DQE_CLOCK_SECONDS=ON') + # Needed to avoid a DSO missing from command line linking error with the Intel toolchain + # https://gitlab.com/QEF/q-e/-/issues/667 + if self.cfg.get('build_shared_libs', False) and comp_fam == toolchain.INTELCOMP: + ldflags = os.environ.get('LDFLAGS', '') + ldflags += ' -Wl,--copy-dt-needed-entries ' + os.environ['LDFLAGS'] = ldflags + super(EB_QuantumESPRESSOcmake, self).configure_step() def test_step(self): @@ -323,7 +333,9 @@ def sanity_check_step(self): self.check_bins += ["pwcond.x"] if all_cond or 'tddfpt' in targets: - self.check_bins += ["turbo_davidson.x", "turbo_eels.x", "turbo_lanczos.x", "turbo_magnon.x", "turbo_spectrum.x"] + self.check_bins += [ + "turbo_davidson.x", "turbo_eels.x", "turbo_lanczos.x", "turbo_magnon.x", "turbo_spectrum.x" + ] if all_cond or 'upf' in targets: self.check_bins += ["upfconv.x", "virtual_v2.x"] From 1337fcc368326d9cfa4adc4505aa8330ca7e41eb Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 15 Mar 2024 15:39:40 +0100 Subject: [PATCH 043/134] pre-commit hooks --- .../easyblocks/q/quantumespressocmake.py | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 265bce17ac..4e027b63a6 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -43,32 +43,32 @@ class EB_QuantumESPRESSOcmake(CMakeMake): """Support for building and installing Quantum ESPRESSO.""" - TEST_SUITE_DIR = "test-suite" + TEST_SUITE_DIR = 'test-suite' @staticmethod def extra_options(): """Custom easyconfig parameters for Quantum ESPRESSO.""" extra_vars = { - 'with_cuda': [False, "Enable CUDA support", CUSTOM], - 'with_scalapack': [True, "Enable ScaLAPACK support", CUSTOM], - 'with_fox': [False, "Enable FoX support", CUSTOM], - 'with_gipaw': [True, "Enable GIPAW support", CUSTOM], - 'with_d3q': [False, "Enable D3Q support", CUSTOM], - 'with_qmcpack': [False, "Enable QMCPACK support", CUSTOM], - 'test_suite_nprocs': [1, "Number of processors to use for the test suite", CUSTOM], + 'with_cuda': [False, 'Enable CUDA support', CUSTOM], + 'with_scalapack': [True, 'Enable ScaLAPACK support', CUSTOM], + 'with_fox': [False, 'Enable FoX support', CUSTOM], + 'with_gipaw': [True, 'Enable GIPAW support', CUSTOM], + 'with_d3q': [False, 'Enable D3Q support', CUSTOM], + 'with_qmcpack': [False, 'Enable QMCPACK support', CUSTOM], + 'test_suite_nprocs': [1, 'Number of processors to use for the test suite', CUSTOM], 'test_suite_allow_failures': [[ 'test_qe_xclib_', # 7.3.1: https://gitlab.com/QEF/q-e/-/issues/640 '--hp_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) '--ph_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) '--epw_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) '--tddfpt_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) - ], "List of test suite targets that are allowed to fail (name can partially match)", CUSTOM], + ], 'List of test suite targets that are allowed to fail (name can partially match)', CUSTOM], 'test_suite_threshold': [ 0.97, - "Threshold for test suite success rate (does count also allowed failures)", + 'Threshold for test suite success rate (does count also allowed failures)', CUSTOM ], - 'test_suite_max_failed': [0, "Maximum number of failing tests (does not count allowed failures)", CUSTOM], + 'test_suite_max_failed': [0, 'Maximum number of failing tests (does not count allowed failures)', CUSTOM], } return CMakeMake.extra_options(extra_vars) @@ -76,7 +76,7 @@ def __init__(self, *args, **kwargs): """Add extra config options specific to Quantum ESPRESSO.""" super(EB_QuantumESPRESSOcmake, self).__init__(*args, **kwargs) - self.install_subdir = "qe-%s" % self.version + self.install_subdir = 'qe-%s' % self.version self.check_bins = [] @@ -123,7 +123,7 @@ def _add_scalapack(self): """Enable ScaLAPACK for Quantum ESPRESSO.""" if self.cfg.get('with_scalapack', False): if not self.toolchain.options.get('usempi', False): - raise EasyBuildError("ScaLAPACK support requires MPI") + raise EasyBuildError('ScaLAPACK support requires MPI') self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') def _add_fox(self): @@ -133,21 +133,21 @@ def _add_fox(self): def _add_hdf5(self): """Enable HDF5 for Quantum ESPRESSO.""" - if get_software_root("HDF5"): + if get_software_root('HDF5'): self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') def _add_libxc(self): """Enable LibXC for Quantum ESPRESSO.""" - if get_software_root("libxc"): + if get_software_root('libxc'): self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') def _add_elpa(self): """Enable ELPA for Quantum ESPRESSO.""" - if get_software_root("ELPA"): + if get_software_root('ELPA'): if not self.cfg.get('with_scalapack', False): - raise EasyBuildError("ELPA support requires ScaLAPACK") + raise EasyBuildError('ELPA support requires ScaLAPACK') if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): - raise EasyBuildError("QE 7.3 with cmake does not support ELPA with OpenMP") + raise EasyBuildError('QE 7.3 with cmake does not support ELPA with OpenMP') self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') def _add_gipaw(self): @@ -156,7 +156,7 @@ def _add_gipaw(self): if self.cfg.get('with_gipaw', False): if LooseVersion(self.version) == LooseVersion('7.3.1'): # See issue: https://github.com/dceresoli/qe-gipaw/issues/19 - raise EasyBuildError("GIPAW will fail to compile in QE 7.3.1") + raise EasyBuildError('GIPAW will fail to compile in QE 7.3.1') res = ['gipaw'] self.check_bins += ['gipaw.x'] return res @@ -169,7 +169,7 @@ def _add_d3q(self): # See issues: # https://gitlab.com/QEF/q-e/-/issues/666 # https://github.com/anharmonic/d3q/issues/13 - raise EasyBuildError("D3Q is not supported in QE 7.0+") + raise EasyBuildError('D3Q is not supported in QE 7.0+') res = ['d3q'] self.check_bins += [ 'd3_asr3.x', 'd3_lw.x', 'd3_q2r.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', @@ -189,8 +189,8 @@ def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" if LooseVersion(self.version) < LooseVersion('7.3'): - raise EasyBuildError("EB QuantumEspresso cmake is implemented for versions >= 7.3") - + raise EasyBuildError('EB QuantumEspresso cmake is implemented for versions >= 7.3') + comp_fam = self.toolchain.comp_family() self._add_toolchains_opts() @@ -211,7 +211,7 @@ def configure_step(self): ldflags = os.environ.get('LDFLAGS', '') ldflags += ' -Wl,--copy-dt-needed-entries ' os.environ['LDFLAGS'] = ldflags - + super(EB_QuantumESPRESSOcmake, self).configure_step() def test_step(self): @@ -238,8 +238,8 @@ def test_step(self): rgx = r'^ *(?P\d+)% tests passed, +(?P\d+) +tests failed out of +(?P\d+)' mch = re.search(rgx, out, re.MULTILINE) if not mch: - raise EasyBuildError("Failed to parse test suite output") - + raise EasyBuildError('Failed to parse test suite output') + perc = int(mch.group('perc')) / 100 num_fail = int(mch.group('failed')) total = int(mch.group('total')) @@ -249,7 +249,7 @@ def test_step(self): # Example output for reported failures: # 635/635 Test #570: system--epw_wfpt-correctness ......................................***Failed 3.52 sec - self.log.debug("Test suite output:") + self.log.debug('Test suite output:') self.log.debug(out) for line in out.splitlines(): if '***Failed' in line: @@ -265,14 +265,14 @@ def test_step(self): num_fail = len(failures) num_fail_thr = self.cfg.get('test_suite_max_failed', 0) # perc = spass / max(stot, 1) - self.log.info("Total tests passed %d out of %d (%.2f%%)" % (passed, total, perc * 100)) + self.log.info('Total tests passed %d out of %d (%.2f%%)' % (passed, total, perc * 100)) if perc < thr: raise EasyBuildError( - "Test suite failed with less than %.2f %% (%.2f) success rate" % (thr * 100, perc * 100) + 'Test suite failed with less than %.2f %% (%.2f) success rate' % (thr * 100, perc * 100) ) if num_fail > num_fail_thr: raise EasyBuildError( - "Test suite failed with more than %d failures %d" % (num_fail_thr, num_fail) + 'Test suite failed with more than %d failures %d' % (num_fail_thr, num_fail) ) return out @@ -289,59 +289,59 @@ def sanity_check_step(self): # Standard binaries if all_cond or 'cp' in targets : - self.check_bins += ["cp.x", "cppp.x", "manycp.x", "wfdd.x"] + self.check_bins += ['cp.x', 'cppp.x', 'manycp.x', 'wfdd.x'] if all_cond or 'epw' in targets: - self.check_bins += ["epw.x"] + self.check_bins += ['epw.x'] if all_cond or 'gwl' in targets: self.check_bins += [ - "abcoeff_to_eps.x", "bse_main.x", "graph.x", "gww_fit.x", "gww.x", "head.x", "memory_pw4gww.x", - "pw4gww.x", "simple_bse.x", "simple_ip.x", "simple.x" + 'abcoeff_to_eps.x', 'bse_main.x', 'graph.x', 'gww_fit.x', 'gww.x', 'head.x', 'memory_pw4gww.x', + 'pw4gww.x', 'simple_bse.x', 'simple_ip.x', 'simple.x' ] if all_cond or 'hp' in targets: - self.check_bins += ["hp.x"] + self.check_bins += ['hp.x'] if all_cond or 'ld1' in targets: - self.check_bins += ["ld1.x"] + self.check_bins += ['ld1.x'] if all_cond or pwall_cond or 'neb' in targets: - self.check_bins += ["neb.x", "path_interpolation.x"] + self.check_bins += ['neb.x', 'path_interpolation.x'] if all_cond or pwall_cond or 'ph' in targets: self.check_bins += [ - "alpha2f.x", "dynmat.x", "fd_ef.x", "fd.x", "lambda.x", "phcg.x", "postahc.x", "q2r.x", "dvscf_q2r.x", - "epa.x", "fd_ifc.x", "fqha.x", "matdyn.x", "ph.x", "q2qstar.x" + 'alpha2f.x', 'dynmat.x', 'fd_ef.x', 'fd.x', 'lambda.x', 'phcg.x', 'postahc.x', 'q2r.x', 'dvscf_q2r.x', + 'epa.x', 'fd_ifc.x', 'fqha.x', 'matdyn.x', 'ph.x', 'q2qstar.x' ] if all_cond or pwall_cond or 'pp' in targets: self.check_bins += [ - "average.x", "dos_sp.x", "ef.x", "fermi_int_0.x", "fermi_proj.x", "fs.x", "molecularpdos.x", - "pawplot.x", "plotband.x", "plotrho.x", "ppacf.x", "pp.x", "pw2bgw.x", "pw2gt.x", "pw2wannier90.x", - "wannier_ham.x", "wfck2r.x", "bands.x", "dos.x", "epsilon.x", "fermi_int_1.x", "fermi_velocity.x", - "initial_state.x", "open_grid.x", "plan_avg.x", "plotproj.x", "pmw.x", "pprism.x", "projwfc.x", - "pw2critic.x", "pw2gw.x", "sumpdos.x", "wannier_plot.x" + 'average.x', 'dos_sp.x', 'ef.x', 'fermi_int_0.x', 'fermi_proj.x', 'fs.x', 'molecularpdos.x', + 'pawplot.x', 'plotband.x', 'plotrho.x', 'ppacf.x', 'pp.x', 'pw2bgw.x', 'pw2gt.x', 'pw2wannier90.x', + 'wannier_ham.x', 'wfck2r.x', 'bands.x', 'dos.x', 'epsilon.x', 'fermi_int_1.x', 'fermi_velocity.x', + 'initial_state.x', 'open_grid.x', 'plan_avg.x', 'plotproj.x', 'pmw.x', 'pprism.x', 'projwfc.x', + 'pw2critic.x', 'pw2gw.x', 'sumpdos.x', 'wannier_plot.x' ] if all_cond or pwall_cond or 'pw' in targets: self.check_bins += [ - "cell2ibrav.x", "ev.x", "ibrav2cell.x", "kpoints.x", "pwi2xsf.x", "pw.x", "scan_ibrav.x" + 'cell2ibrav.x', 'ev.x', 'ibrav2cell.x', 'kpoints.x', 'pwi2xsf.x', 'pw.x', 'scan_ibrav.x' ] if all_cond or pwall_cond or 'pwcond' in targets: - self.check_bins += ["pwcond.x"] + self.check_bins += ['pwcond.x'] if all_cond or 'tddfpt' in targets: self.check_bins += [ - "turbo_davidson.x", "turbo_eels.x", "turbo_lanczos.x", "turbo_magnon.x", "turbo_spectrum.x" + 'turbo_davidson.x', 'turbo_eels.x', 'turbo_lanczos.x', 'turbo_magnon.x', 'turbo_spectrum.x' ] if all_cond or 'upf' in targets: - self.check_bins += ["upfconv.x", "virtual_v2.x"] + self.check_bins += ['upfconv.x', 'virtual_v2.x'] if all_cond or 'xspectra' in targets: - self.check_bins += ["molecularnexafs.x", "spectra_correction.x", "xspectra.x"] + self.check_bins += ['molecularnexafs.x', 'spectra_correction.x', 'xspectra.x'] custom_paths = { 'files': [os.path.join('bin', x) for x in self.check_bins], From 4621fb738570e90db26d768fb95429376b9e3c85 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 18 Mar 2024 15:38:06 +0100 Subject: [PATCH 044/134] Linting + moved ignored tests to config files --- .../easyblocks/q/quantumespressocmake.py | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 4e027b63a6..dce75d3b50 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -30,7 +30,6 @@ import os import re -import easybuild.tools.toolchain as toolchain from easybuild.framework.easyconfig import CUSTOM from easybuild.tools import LooseVersion from easybuild.tools.build_log import EasyBuildError @@ -56,13 +55,11 @@ def extra_options(): 'with_d3q': [False, 'Enable D3Q support', CUSTOM], 'with_qmcpack': [False, 'Enable QMCPACK support', CUSTOM], 'test_suite_nprocs': [1, 'Number of processors to use for the test suite', CUSTOM], - 'test_suite_allow_failures': [[ - 'test_qe_xclib_', # 7.3.1: https://gitlab.com/QEF/q-e/-/issues/640 - '--hp_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) - '--ph_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) - '--epw_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) - '--tddfpt_', # 7.3.1: Broken testsuite (https://gitlab.com/QEF/q-e/-/issues/665) - ], 'List of test suite targets that are allowed to fail (name can partially match)', CUSTOM], + 'test_suite_allow_failures': [ + [], + 'List of test suite targets that are allowed to fail (name can partially match)', + CUSTOM + ], 'test_suite_threshold': [ 0.97, 'Threshold for test suite success rate (does count also allowed failures)', @@ -165,15 +162,16 @@ def _add_d3q(self): """Enable D3Q for Quantum ESPRESSO.""" res = [] if self.cfg.get('with_d3q', False): - if LooseVersion(self.version) > LooseVersion('7.0'): + if LooseVersion(self.version) <= LooseVersion('7.3.1'): # See issues: # https://gitlab.com/QEF/q-e/-/issues/666 # https://github.com/anharmonic/d3q/issues/13 - raise EasyBuildError('D3Q is not supported in QE 7.0+') + raise EasyBuildError('D3Q compilation will fail for QE 7.3 and 7.3.1') res = ['d3q'] self.check_bins += [ - 'd3_asr3.x', 'd3_lw.x', 'd3_q2r.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', - 'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x' + 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', + 'd3_qha.x','d3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', 'd3_rmzeu.x', 'd3_sparse.x', + 'd3_sqom.x', 'd3_tk.x', ] return res @@ -191,8 +189,6 @@ def configure_step(self): if LooseVersion(self.version) < LooseVersion('7.3'): raise EasyBuildError('EB QuantumEspresso cmake is implemented for versions >= 7.3') - comp_fam = self.toolchain.comp_family() - self._add_toolchains_opts() self._add_libraries() self._add_plugins() @@ -205,9 +201,9 @@ def configure_step(self): # Change format of timings to seconds only (from d/h/m/s) self.cfg.update('configopts', '-DQE_CLOCK_SECONDS=ON') - # Needed to avoid a DSO missing from command line linking error with the Intel toolchain + # Needed to avoid a DSO missing from command line linking error # https://gitlab.com/QEF/q-e/-/issues/667 - if self.cfg.get('build_shared_libs', False) and comp_fam == toolchain.INTELCOMP: + if self.cfg.get('build_shared_libs', False) : ldflags = os.environ.get('LDFLAGS', '') ldflags += ' -Wl,--copy-dt-needed-entries ' os.environ['LDFLAGS'] = ldflags From ee3695fafd3273327d43a535afb8ab04f6da5918 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 18 Mar 2024 15:45:30 +0100 Subject: [PATCH 045/134] Reuse message --- .../easyblocks/q/quantumespressocmake.py | 117 +++++++++--------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index dce75d3b50..b9f003b37a 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -79,115 +79,112 @@ def __init__(self, *args, **kwargs): def _add_toolchains_opts(self): """Enable toolchain options for Quantum ESPRESSO.""" - self._add_mpi() - self._add_openmp() - self._add_cuda() + if self.toolchain.options.get('usempi', False): + self._add_mpi() + if self.toolchain.options.get('openmp', False): + self._add_openmp() + if self.cfg.get('with_cuda', False): + self._add_cuda() def _add_libraries(self): """Enable external libraries for Quantum ESPRESSO.""" - self._add_scalapack() - self._add_fox() - self._add_libxc() - self._add_elpa() - self._add_hdf5() + if self.cfg.get('with_scalapack', False): + self._add_scalapack() + if self.cfg.get('with_fox', False): + self._add_fox() + if get_software_root('libxc'): + self._add_libxc() + if get_software_root('ELPA'): + self._add_elpa() + if get_software_root('HDF5'): + self._add_hdf5() def _add_plugins(self): """Enable plugins for Quantum ESPRESSO.""" plugins = [] - plugins += self._add_gipaw() - plugins += self._add_d3q() - plugins += self._add_qmcpack() + if self.cfg.get('with_gipaw', False): + plugins += self._add_gipaw() + if self.cfg.get('with_d3q', False): + plugins += self._add_d3q() + if self.cfg.get('with_qmcpack', False): + plugins += self._add_qmcpack() if plugins: self.cfg.update('configopts', '-DQE_ENABLE_PLUGINS="%s"' % ';'.join(plugins)) def _add_mpi(self): """Enable MPI for Quantum ESPRESSO.""" - if self.toolchain.options.get('usempi', False): - self.cfg.update('configopts', '-DENABLE_MPI=ON') + self.cfg.update('configopts', '-DENABLE_MPI=ON') def _add_openmp(self): """Enable OpenMP for Quantum ESPRESSO.""" - if self.toolchain.options.get('openmp', False): - self.cfg.update('configopts', '-DENABLE_OPENMP=ON') + self.cfg.update('configopts', '-DENABLE_OPENMP=ON') def _add_cuda(self): """Enable CUDA for Quantum ESPRESSO.""" - if self.cfg.get('with_cuda', False): - self.cfg.update('configopts', '-DQE_ENABLE_CUDA=ON') - self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=ON') + self.cfg.update('configopts', '-DQE_ENABLE_CUDA=ON') + self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=ON') def _add_scalapack(self): """Enable ScaLAPACK for Quantum ESPRESSO.""" - if self.cfg.get('with_scalapack', False): - if not self.toolchain.options.get('usempi', False): - raise EasyBuildError('ScaLAPACK support requires MPI') - self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') + if not self.toolchain.options.get('usempi', False): + raise EasyBuildError('ScaLAPACK support requires MPI') + self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') def _add_fox(self): """Enable FoX for Quantum ESPRESSO.""" - if self.cfg.get('with_fox', False): - self.cfg.update('configopts', '-DQE_ENABLE_FOX=ON') + self.cfg.update('configopts', '-DQE_ENABLE_FOX=ON') def _add_hdf5(self): """Enable HDF5 for Quantum ESPRESSO.""" - if get_software_root('HDF5'): - self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') + self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') def _add_libxc(self): """Enable LibXC for Quantum ESPRESSO.""" - if get_software_root('libxc'): - self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') + self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') def _add_elpa(self): """Enable ELPA for Quantum ESPRESSO.""" - if get_software_root('ELPA'): - if not self.cfg.get('with_scalapack', False): - raise EasyBuildError('ELPA support requires ScaLAPACK') - if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): - raise EasyBuildError('QE 7.3 with cmake does not support ELPA with OpenMP') - self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') + if not self.cfg.get('with_scalapack', False): + raise EasyBuildError('ELPA support requires ScaLAPACK') + if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): + raise EasyBuildError('QE 7.3 with cmake does not support ELPA with OpenMP') + self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') def _add_gipaw(self): """Enable GIPAW for Quantum ESPRESSO.""" - res = [] - if self.cfg.get('with_gipaw', False): - if LooseVersion(self.version) == LooseVersion('7.3.1'): - # See issue: https://github.com/dceresoli/qe-gipaw/issues/19 - raise EasyBuildError('GIPAW will fail to compile in QE 7.3.1') - res = ['gipaw'] - self.check_bins += ['gipaw.x'] + if LooseVersion(self.version) == LooseVersion('7.3.1'): + # See issue: https://github.com/dceresoli/qe-gipaw/issues/19 + raise EasyBuildError('GIPAW will fail to compile in QE 7.3.1') + res = ['gipaw'] + self.check_bins += ['gipaw.x'] return res def _add_d3q(self): """Enable D3Q for Quantum ESPRESSO.""" - res = [] - if self.cfg.get('with_d3q', False): - if LooseVersion(self.version) <= LooseVersion('7.3.1'): - # See issues: - # https://gitlab.com/QEF/q-e/-/issues/666 - # https://github.com/anharmonic/d3q/issues/13 - raise EasyBuildError('D3Q compilation will fail for QE 7.3 and 7.3.1') - res = ['d3q'] - self.check_bins += [ - 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', - 'd3_qha.x','d3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', 'd3_rmzeu.x', 'd3_sparse.x', - 'd3_sqom.x', 'd3_tk.x', - ] + if LooseVersion(self.version) <= LooseVersion('7.3.1'): + # See issues: + # https://gitlab.com/QEF/q-e/-/issues/666 + # https://github.com/anharmonic/d3q/issues/13 + raise EasyBuildError('D3Q compilation will fail for QE 7.3 and 7.3.1') + res = ['d3q'] + self.check_bins += [ + 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', + 'd3_qha.x','d3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', 'd3_rmzeu.x', 'd3_sparse.x', + 'd3_sqom.x', 'd3_tk.x', + ] return res def _add_qmcpack(self): """Enable QMCPACK for Quantum ESPRESSO.""" - res = [] - if self.cfg.get('with_qmcpack', False): - res = ['pw2qmcpack'] - self.check_bins += ['pw2qmcpack.x'] + res = ['pw2qmcpack'] + self.check_bins += ['pw2qmcpack.x'] return res def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" if LooseVersion(self.version) < LooseVersion('7.3'): - raise EasyBuildError('EB QuantumEspresso cmake is implemented for versions >= 7.3') + raise EasyBuildError('EB QuantumEspresso with cmake is implemented for versions >= 7.3') self._add_toolchains_opts() self._add_libraries() @@ -268,7 +265,7 @@ def test_step(self): ) if num_fail > num_fail_thr: raise EasyBuildError( - 'Test suite failed with more than %d failures %d' % (num_fail_thr, num_fail) + 'Test suite failed with %d failures (%d failures permitted)' % (num_fail, num_fail_thr) ) return out From f4b87a696f038dbaf4ad596a149b10d9be906381 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 18 Mar 2024 15:56:59 +0100 Subject: [PATCH 046/134] Linting --- easybuild/easyblocks/q/quantumespressocmake.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index b9f003b37a..bb4fd95949 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -169,7 +169,7 @@ def _add_d3q(self): res = ['d3q'] self.check_bins += [ 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', - 'd3_qha.x','d3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', 'd3_rmzeu.x', 'd3_sparse.x', + 'd3_qha.x', 'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x', 'd3_rmzeu.x', 'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x', ] return res @@ -200,7 +200,7 @@ def configure_step(self): # Needed to avoid a DSO missing from command line linking error # https://gitlab.com/QEF/q-e/-/issues/667 - if self.cfg.get('build_shared_libs', False) : + if self.cfg.get('build_shared_libs', False): ldflags = os.environ.get('LDFLAGS', '') ldflags += ' -Wl,--copy-dt-needed-entries ' os.environ['LDFLAGS'] = ldflags @@ -239,7 +239,6 @@ def test_step(self): passed = total - num_fail failures = [] # list of tests that failed, to be logged at the end - # Example output for reported failures: # 635/635 Test #570: system--epw_wfpt-correctness ......................................***Failed 3.52 sec self.log.debug('Test suite output:') @@ -279,9 +278,8 @@ def sanity_check_step(self): all_cond = len(targets) == 0 or 'all_currents' in targets pwall_cond = 'pwall' in targets - # Standard binaries - if all_cond or 'cp' in targets : + if all_cond or 'cp' in targets: self.check_bins += ['cp.x', 'cppp.x', 'manycp.x', 'wfdd.x'] if all_cond or 'epw' in targets: From ac204f4f1cd4f080ccca811666b717bfa0bbc989 Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 21 Mar 2024 12:49:38 +0100 Subject: [PATCH 047/134] Using `env.setvar` instead of `os.environ` --- easybuild/easyblocks/q/quantumespressocmake.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index bb4fd95949..fa6977141e 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -30,6 +30,7 @@ import os import re +import easybuild.tools.environment as env from easybuild.framework.easyconfig import CUSTOM from easybuild.tools import LooseVersion from easybuild.tools.build_log import EasyBuildError @@ -201,9 +202,9 @@ def configure_step(self): # Needed to avoid a DSO missing from command line linking error # https://gitlab.com/QEF/q-e/-/issues/667 if self.cfg.get('build_shared_libs', False): - ldflags = os.environ.get('LDFLAGS', '') + ldflags = os.getenv('LDFLAGS', '') ldflags += ' -Wl,--copy-dt-needed-entries ' - os.environ['LDFLAGS'] = ldflags + env.setvar('LDFLAGS', ldflags) super(EB_QuantumESPRESSOcmake, self).configure_step() From b3759f5458f20959afb0d6d48bc4995462c52589 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 22 Mar 2024 15:50:33 +0100 Subject: [PATCH 048/134] Added possibility to install with pre-downloaded submodules --- .../easyblocks/q/quantumespressocmake.py | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index fa6977141e..2e845ded3d 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -29,6 +29,7 @@ """ import os import re +import shutil import easybuild.tools.environment as env from easybuild.framework.easyconfig import CUSTOM @@ -44,6 +45,16 @@ class EB_QuantumESPRESSOcmake(CMakeMake): """Support for building and installing Quantum ESPRESSO.""" TEST_SUITE_DIR = 'test-suite' + SUBMODULES = [ + 'lapack', + 'mbd', + 'devxlib', + 'fox', + 'd3q', + 'qe-gipaw', + 'pw2qmcpack', + 'wannier90' + ] @staticmethod def extra_options(): @@ -166,7 +177,10 @@ def _add_d3q(self): # See issues: # https://gitlab.com/QEF/q-e/-/issues/666 # https://github.com/anharmonic/d3q/issues/13 - raise EasyBuildError('D3Q compilation will fail for QE 7.3 and 7.3.1') + if not os.path.exists(os.path.join(self.builddir, self.install_subdir, 'external', 'd3q', '.git')): + raise EasyBuildError( + 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded from easyconfig.' + ) res = ['d3q'] self.check_bins += [ 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', @@ -181,12 +195,36 @@ def _add_qmcpack(self): self.check_bins += ['pw2qmcpack.x'] return res + def _copy_submodule_dirs(self): + """Copy submodule dirs downloaded by EB into XXX/external""" + for submod in self.SUBMODULES: + src = os.path.join(self.builddir, submod) + dst = os.path.join(self.builddir, self.install_subdir, 'external', submod) + if os.path.exists(src): + self.log.info('Copying submodule %s into %s' % (submod, dst)) + # Remove empty directories and replace them with the downloaded submodule + if os.path.exists(dst): + shutil.rmtree(dst) + shutil.move(src, dst) + else: + self.log.warning('Submodule %s not found at %s' % (submod, src)) + + # Trick QE to think that the submodule is already installed in case `keep_git_dir` is not used in + # the easyconfig file + gitf = os.path.join(dst, '.git') + if not os.path.exists(gitf): + os.mkdir(gitf) + def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" if LooseVersion(self.version) < LooseVersion('7.3'): raise EasyBuildError('EB QuantumEspresso with cmake is implemented for versions >= 7.3') + # Needs to be before other functions that could check existance of .git for submodules to + # make compatibility checks + self._copy_submodule_dirs() + self._add_toolchains_opts() self._add_libraries() self._add_plugins() @@ -257,15 +295,18 @@ def test_step(self): # Allow for flaky tests (eg too strict thresholds on results for structure relaxation) num_fail = len(failures) num_fail_thr = self.cfg.get('test_suite_max_failed', 0) - # perc = spass / max(stot, 1) self.log.info('Total tests passed %d out of %d (%.2f%%)' % (passed, total, perc * 100)) + if failures: + self.log.warning('The following tests failed (and are not ignored):') + for failure in failures: + self.log.warning('| ' + failure) if perc < thr: raise EasyBuildError( 'Test suite failed with less than %.2f %% (%.2f) success rate' % (thr * 100, perc * 100) ) if num_fail > num_fail_thr: raise EasyBuildError( - 'Test suite failed with %d failures (%d failures permitted)' % (num_fail, num_fail_thr) + 'Test suite failed with %d non-ignored failures (%d failures permitted)' % (num_fail, num_fail_thr) ) return out From a91fabe30b722eb705d820ee3442bc2cfa3cfffb Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 22 Mar 2024 18:35:23 +0100 Subject: [PATCH 049/134] Fixed flags --- easybuild/easyblocks/q/quantumespressocmake.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 2e845ded3d..c3899aaaf8 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -125,11 +125,11 @@ def _add_plugins(self): def _add_mpi(self): """Enable MPI for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DENABLE_MPI=ON') + self.cfg.update('configopts', '-DQE_ENABLE_MPI=ON') def _add_openmp(self): """Enable OpenMP for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DENABLE_OPENMP=ON') + self.cfg.update('configopts', '-DQE_ENABLE_OPENMP=ON') def _add_cuda(self): """Enable CUDA for Quantum ESPRESSO.""" From 7433a5e0abd5edacea855f577a8c4a3948d15971 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 25 Mar 2024 11:24:05 +0100 Subject: [PATCH 050/134] Ensure that options can also be disabled (plus error in compilation of d3q without mpi) --- .../easyblocks/q/quantumespressocmake.py | 81 ++++++++++++------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index c3899aaaf8..14c606572d 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -91,25 +91,17 @@ def __init__(self, *args, **kwargs): def _add_toolchains_opts(self): """Enable toolchain options for Quantum ESPRESSO.""" - if self.toolchain.options.get('usempi', False): - self._add_mpi() - if self.toolchain.options.get('openmp', False): - self._add_openmp() - if self.cfg.get('with_cuda', False): - self._add_cuda() + self._add_mpi() + self._add_openmp() + self._add_cuda() def _add_libraries(self): """Enable external libraries for Quantum ESPRESSO.""" - if self.cfg.get('with_scalapack', False): - self._add_scalapack() - if self.cfg.get('with_fox', False): - self._add_fox() - if get_software_root('libxc'): - self._add_libxc() - if get_software_root('ELPA'): - self._add_elpa() - if get_software_root('HDF5'): - self._add_hdf5() + self._add_scalapack() + self._add_fox() + self._add_hdf5() + self._add_libxc() + self._add_elpa() def _add_plugins(self): """Enable plugins for Quantum ESPRESSO.""" @@ -125,42 +117,67 @@ def _add_plugins(self): def _add_mpi(self): """Enable MPI for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_MPI=ON') + if self.toolchain.options.get('usempi', False): + self.cfg.update('configopts', '-DQE_ENABLE_MPI=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_MPI=OFF') def _add_openmp(self): """Enable OpenMP for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_OPENMP=ON') + if self.toolchain.options.get('openmp', False): + self.cfg.update('configopts', '-DQE_ENABLE_OPENMP=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_OPENMP=OFF') def _add_cuda(self): """Enable CUDA for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_CUDA=ON') - self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=ON') + if self.cfg.get('with_cuda', False): + self.cfg.update('configopts', '-DQE_ENABLE_CUDA=ON') + self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_CUDA=OFF') + self.cfg.update('configopts', '-DQE_ENABLE_OPENACC=OFF') def _add_scalapack(self): """Enable ScaLAPACK for Quantum ESPRESSO.""" - if not self.toolchain.options.get('usempi', False): - raise EasyBuildError('ScaLAPACK support requires MPI') - self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') + if self.cfg.get('with_scalapack', False): + if not self.toolchain.options.get('usempi', False): + raise EasyBuildError('ScaLAPACK support requires MPI') + self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_SCALAPACK=OFF') def _add_fox(self): """Enable FoX for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_FOX=ON') + if self.cfg.get('with_fox', False): + self.cfg.update('configopts', '-DQE_ENABLE_FOX=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_FOX=OFF') def _add_hdf5(self): """Enable HDF5 for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') + if get_software_root('HDF5'): + self.cfg.update('configopts', '-DQE_ENABLE_HDF5=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_HDF5=OFF') def _add_libxc(self): """Enable LibXC for Quantum ESPRESSO.""" - self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') + if get_software_root('libxc'): + self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_LIBXC=OFF') def _add_elpa(self): """Enable ELPA for Quantum ESPRESSO.""" - if not self.cfg.get('with_scalapack', False): - raise EasyBuildError('ELPA support requires ScaLAPACK') - if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): - raise EasyBuildError('QE 7.3 with cmake does not support ELPA with OpenMP') - self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') + if get_software_root('ELPA'): + if not self.cfg.get('with_scalapack', False): + raise EasyBuildError('ELPA support requires ScaLAPACK') + if LooseVersion(self.version) == LooseVersion('7.3') and self.toolchain.options.get('openmp', False): + raise EasyBuildError('QE 7.3 with cmake does not support ELPA with OpenMP') + self.cfg.update('configopts', '-DQE_ENABLE_ELPA=ON') + else: + self.cfg.update('configopts', '-DQE_ENABLE_ELPA=OFF') def _add_gipaw(self): """Enable GIPAW for Quantum ESPRESSO.""" @@ -181,6 +198,8 @@ def _add_d3q(self): raise EasyBuildError( 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded from easyconfig.' ) + if not self.toolchain.options.get('usempi', False): + raise EasyBuildError('D3Q support requires MPI enabled') res = ['d3q'] self.check_bins += [ 'd3_asr3.x', 'd3_db.x', 'd3_import_shengbte.x', 'd3_interpolate2.x', 'd3_lw.x', 'd3_q2r.x', From 2bb7f0bf882b44e665d82ba150a6633469e8f7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20=C3=96hman?= Date: Thu, 4 Apr 2024 15:30:14 +0000 Subject: [PATCH 051/134] Add ABAQUS license server to generated module --- easybuild/easyblocks/a/abaqus.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/easybuild/easyblocks/a/abaqus.py b/easybuild/easyblocks/a/abaqus.py index fc614ab7e8..000b2f9de3 100644 --- a/easybuild/easyblocks/a/abaqus.py +++ b/easybuild/easyblocks/a/abaqus.py @@ -366,3 +366,12 @@ def make_module_req_guess(self): }) return guesses + + def make_module_extra(self): + """Add LM_LICENSE_FILE path if specified""" + txt = super(EB_ABAQUS, self).make_module_extra() + license_file = os.getenv('EB_ABAQUS_LICENSE_FILE', None) + if license_file is not None: + txt += self.module_generator.prepend_paths('LM_LICENSE_FILE', [license_file], allow_abs=True) + + return txt From 556445be88a078149e60ca7004ed0f24887c718b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20=C3=96hman?= Date: Thu, 4 Apr 2024 16:33:41 +0000 Subject: [PATCH 052/134] Fix style --- easybuild/easyblocks/a/abaqus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/a/abaqus.py b/easybuild/easyblocks/a/abaqus.py index 000b2f9de3..868a2e52a2 100644 --- a/easybuild/easyblocks/a/abaqus.py +++ b/easybuild/easyblocks/a/abaqus.py @@ -369,7 +369,7 @@ def make_module_req_guess(self): def make_module_extra(self): """Add LM_LICENSE_FILE path if specified""" - txt = super(EB_ABAQUS, self).make_module_extra() + txt = super(EB_ABAQUS, self).make_module_extra() license_file = os.getenv('EB_ABAQUS_LICENSE_FILE', None) if license_file is not None: txt += self.module_generator.prepend_paths('LM_LICENSE_FILE', [license_file], allow_abs=True) From e14ec142323960619c2d5ef245a5284a8f35fa50 Mon Sep 17 00:00:00 2001 From: Davide Grassano <34096612+Crivella@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:32:30 +0200 Subject: [PATCH 053/134] Update easybuild/easyblocks/q/quantumespressocmake.py Co-authored-by: ocaisa --- easybuild/easyblocks/q/quantumespressocmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 14c606572d..5b0cffc36c 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -196,7 +196,7 @@ def _add_d3q(self): # https://github.com/anharmonic/d3q/issues/13 if not os.path.exists(os.path.join(self.builddir, self.install_subdir, 'external', 'd3q', '.git')): raise EasyBuildError( - 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded from easyconfig.' + 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded via sources in easyconfig.' ) if not self.toolchain.options.get('usempi', False): raise EasyBuildError('D3Q support requires MPI enabled') From 311a819eb2f34fbd472060a4df4a73b34c0abb97 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 5 Apr 2024 10:47:45 +0200 Subject: [PATCH 054/134] Linting and version check --- easybuild/easyblocks/q/quantumespressocmake.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 5b0cffc36c..d4bb979682 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -196,7 +196,8 @@ def _add_d3q(self): # https://github.com/anharmonic/d3q/issues/13 if not os.path.exists(os.path.join(self.builddir, self.install_subdir, 'external', 'd3q', '.git')): raise EasyBuildError( - 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded via sources in easyconfig.' + 'D3Q compilation will fail for QE 7.3 and 7.3.1 without submodule downloaded via' + + 'sources in easyconfig.' ) if not self.toolchain.options.get('usempi', False): raise EasyBuildError('D3Q support requires MPI enabled') @@ -256,12 +257,13 @@ def configure_step(self): # Change format of timings to seconds only (from d/h/m/s) self.cfg.update('configopts', '-DQE_CLOCK_SECONDS=ON') - # Needed to avoid a DSO missing from command line linking error - # https://gitlab.com/QEF/q-e/-/issues/667 - if self.cfg.get('build_shared_libs', False): - ldflags = os.getenv('LDFLAGS', '') - ldflags += ' -Wl,--copy-dt-needed-entries ' - env.setvar('LDFLAGS', ldflags) + if LooseVersion(self.version) <= LooseVersion('7.3.1'): + # Needed to avoid a `DSO missing from command line` linking error + # https://gitlab.com/QEF/q-e/-/issues/667 + if self.cfg.get('build_shared_libs', False): + ldflags = os.getenv('LDFLAGS', '') + ldflags += ' -Wl,--copy-dt-needed-entries ' + env.setvar('LDFLAGS', ldflags) super(EB_QuantumESPRESSOcmake, self).configure_step() From c9c8bc23943bab590d21e5ec3bdfbb88d3139841 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 5 Apr 2024 11:45:32 +0200 Subject: [PATCH 055/134] Fixed logic --- easybuild/easyblocks/q/quantumespressocmake.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index d4bb979682..48914d36f4 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -220,20 +220,22 @@ def _copy_submodule_dirs(self): for submod in self.SUBMODULES: src = os.path.join(self.builddir, submod) dst = os.path.join(self.builddir, self.install_subdir, 'external', submod) + if os.path.exists(src): self.log.info('Copying submodule %s into %s' % (submod, dst)) # Remove empty directories and replace them with the downloaded submodule if os.path.exists(dst): shutil.rmtree(dst) shutil.move(src, dst) + + # Trick QE to think that the submodule is already installed in case `keep_git_dir` is not used in + # the easyconfig file + gitf = os.path.join(dst, '.git') + if not os.path.exists(gitf): + os.mkdir(gitf) else: self.log.warning('Submodule %s not found at %s' % (submod, src)) - # Trick QE to think that the submodule is already installed in case `keep_git_dir` is not used in - # the easyconfig file - gitf = os.path.join(dst, '.git') - if not os.path.exists(gitf): - os.mkdir(gitf) def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" From 0e0f27cd5b5f68f44b775fe94dc9aec3e03a6c58 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 5 Apr 2024 11:46:42 +0200 Subject: [PATCH 056/134] Lint --- easybuild/easyblocks/q/quantumespressocmake.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 48914d36f4..74554223ff 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -236,7 +236,6 @@ def _copy_submodule_dirs(self): else: self.log.warning('Submodule %s not found at %s' % (submod, src)) - def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" From 59a981f67897ed1e0a5fbcec08ecfbe346b7630d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20=C3=96hman?= Date: Fri, 5 Apr 2024 12:19:51 +0000 Subject: [PATCH 057/134] Add ABAQUSLM_LICENSE_FILE as well --- easybuild/easyblocks/a/abaqus.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/easybuild/easyblocks/a/abaqus.py b/easybuild/easyblocks/a/abaqus.py index 868a2e52a2..7f6eb0820a 100644 --- a/easybuild/easyblocks/a/abaqus.py +++ b/easybuild/easyblocks/a/abaqus.py @@ -373,5 +373,7 @@ def make_module_extra(self): license_file = os.getenv('EB_ABAQUS_LICENSE_FILE', None) if license_file is not None: txt += self.module_generator.prepend_paths('LM_LICENSE_FILE', [license_file], allow_abs=True) + # also needed for some versions: + txt += self.module_generator.prepend_paths('ABAQUSLM_LICENSE_FILE', [license_file], allow_abs=True) return txt From 018142a4b01a99877f4e62554dff3cfe1a580785 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Fri, 5 Apr 2024 13:02:42 +0000 Subject: [PATCH 058/134] adding easyblocks: ansysem.py --- easybuild/easyblocks/a/ansysem.py | 98 +++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 easybuild/easyblocks/a/ansysem.py diff --git a/easybuild/easyblocks/a/ansysem.py b/easybuild/easyblocks/a/ansysem.py new file mode 100644 index 0000000000..6cb596e2ba --- /dev/null +++ b/easybuild/easyblocks/a/ansysem.py @@ -0,0 +1,98 @@ +## +# Copyright 2009-2020 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 . +## +""" +EasyBuild support for installing ANSYS Eletromagnetics + +@author: Alexi Rivera (Chalmers University of Technology) +@author: Mikael OEhman (Chalmers University of Technology) +@author: Chia-Jung Hsu (Chalmers University of Technology) +""" +import os +import glob +import tempfile + +from easybuild.easyblocks.generic.packedbinary import PackedBinary +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.run import run_cmd + + +class EB_ANSYSEM(PackedBinary): + """Support for installing Ansys Electromagnetics.""" + + def __init__(self, *args, **kwargs): + """Initialize Ansys Electromagnetics specific variables.""" + super(EB_ANSYSEM, self).__init__(*args, **kwargs) + + def install_step(self): + """Install Ansys Electromagnetics using its setup tool.""" + licserv = os.getenv('EB_ANSYS_EM_LICENSE_SERVER') + licport = os.getenv('EB_ANSYS_EM_LICENSE_SERVER_PORT') + licservs = licserv.split(',') + licservopt = ["-DLICENSE_SERVER%d=%s" % (i, serv) for i, serv in enumerate(licservs, 1)] + redundant = len(licservs) > 1 + options = " ".join([ + "-i silent", + "-DUSER_INSTALL_DIR=%s" % self.installdir, + "-DTMP_DIR=%s" % tempfile.TemporaryDirectory().name, + "-DLIBRARY_COMMON_INSTALL=1", + "-DSPECIFY_LIC_CFG=1", + "-DREDUNDANT_SERVERS=%d" % redundant, + *licservopt, + "-DSPECIFY_PORT=1", + "-DLICENSE_PORT=%s" % licport, + ]) + cmd = "./Linux/AnsysEM/Disk1/InstData/setup.exe %s" % options + run_cmd(cmd, log_all=True, simple=True) + + def make_module_extra(self): + """Extra module entries for Ansys Electromagnetics.""" + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + + txt = super(EB_ANSYSEM, self).make_module_extra() + txt += self.module_generator.prepend_paths('PATH', subdir) + txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', subdir) + txt += self.module_generator.prepend_paths('LIBRARY_PATH', subdir) + return txt + + def sanity_check_step(self): + """Custom sanity check for Ansys Electromagnetics.""" + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + + custom_paths = { + 'files': [os.path.join(subdir, 'ansysedt')], + 'dirs': [subdir], + } + + custom_commands = ['%s -ng' % os.path.join(subdir, 'ansysedt')] + + super(EB_ANSYSEM, self).sanity_check_step(custom_paths=custom_paths) From 53b54bfb08f896058a87b0cc54f1f924c5916593 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 5 Apr 2024 15:21:39 +0200 Subject: [PATCH 059/134] Getting `nprocs` for test only in one place --- easybuild/easyblocks/q/quantumespressocmake.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/q/quantumespressocmake.py b/easybuild/easyblocks/q/quantumespressocmake.py index 74554223ff..70a5df031b 100644 --- a/easybuild/easyblocks/q/quantumespressocmake.py +++ b/easybuild/easyblocks/q/quantumespressocmake.py @@ -251,9 +251,9 @@ def configure_step(self): self._add_plugins() # Enable/configure test suite - nprocs = self.cfg.get('test_suite_nprocs', 1) + self._test_nprocs = self.cfg.get('test_suite_nprocs', 1) self.cfg.update('configopts', '-DQE_ENABLE_TEST=ON') - self.cfg.update('configopts', '-DTESTCODE_NPROCS=%d' % nprocs) + self.cfg.update('configopts', '-DTESTCODE_NPROCS=%d' % self._test_nprocs) # Change format of timings to seconds only (from d/h/m/s) self.cfg.update('configopts', '-DQE_CLOCK_SECONDS=ON') @@ -275,8 +275,7 @@ def test_step(self): """ thr = self.cfg.get('test_suite_threshold', 0.97) - nprocs = self.cfg.get('test_suite_nprocs', 1) - concurrent = max(1, self.cfg.get('parallel', 1) // nprocs) + concurrent = max(1, self.cfg.get('parallel', 1) // self._test_nprocs) allow_fail = self.cfg.get('test_suite_allow_failures', []) cmd = ' '.join([ From edcfec4334f7029112213a05784e75f9b644c3f8 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 5 Apr 2024 15:22:35 +0200 Subject: [PATCH 060/134] Check for QE < 7.3.1 on configmake easyblock --- easybuild/easyblocks/q/quantumespresso.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/easybuild/easyblocks/q/quantumespresso.py b/easybuild/easyblocks/q/quantumespresso.py index 563890072a..dad09fb4ea 100644 --- a/easybuild/easyblocks/q/quantumespresso.py +++ b/easybuild/easyblocks/q/quantumespresso.py @@ -367,6 +367,12 @@ def _adjust_compiler_flags(self, comp_fam): def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" + if LooseVersion(self.version) < LooseVersion("7.3.1"): + raise EasyBuildError( + "QuantumESPRESSO 7.3.1 and later are not supported with the this easyblock (ConfigureMake), " + + "use the EB_QuantumESPRESSOcmake (CMakeMake) easyblock instead." + ) + # compose list of DFLAGS (flag, value, keep_stuff) # for guidelines, see include/defs.h.README in sources self.dflags = [] From a1cbcad0fdd0d0868ba80e77e904d637e29e6d05 Mon Sep 17 00:00:00 2001 From: Davide Grassano <34096612+Crivella@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:28:09 +0200 Subject: [PATCH 061/134] Update easybuild/easyblocks/q/quantumespresso.py Co-authored-by: ocaisa --- easybuild/easyblocks/q/quantumespresso.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/q/quantumespresso.py b/easybuild/easyblocks/q/quantumespresso.py index dad09fb4ea..7d86dfabeb 100644 --- a/easybuild/easyblocks/q/quantumespresso.py +++ b/easybuild/easyblocks/q/quantumespresso.py @@ -367,7 +367,7 @@ def _adjust_compiler_flags(self, comp_fam): def configure_step(self): """Custom configuration procedure for Quantum ESPRESSO.""" - if LooseVersion(self.version) < LooseVersion("7.3.1"): + if LooseVersion(self.version) >= LooseVersion("7.3.1"): raise EasyBuildError( "QuantumESPRESSO 7.3.1 and later are not supported with the this easyblock (ConfigureMake), " + "use the EB_QuantumESPRESSOcmake (CMakeMake) easyblock instead." From 47b7975d5b0115d50acddbbac9ce721d30b2aca0 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Fri, 5 Apr 2024 14:28:43 +0000 Subject: [PATCH 062/134] Fix sanity check command --- easybuild/easyblocks/a/ansysem.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/a/ansysem.py b/easybuild/easyblocks/a/ansysem.py index 6cb596e2ba..8dd9c1feb8 100644 --- a/easybuild/easyblocks/a/ansysem.py +++ b/easybuild/easyblocks/a/ansysem.py @@ -93,6 +93,8 @@ def sanity_check_step(self): 'dirs': [subdir], } - custom_commands = ['%s -ng' % os.path.join(subdir, 'ansysedt')] + executable = os.path.join(subdir, 'ansysedt') + inpfile = os.path.join(subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') + custom_commands = ['./%s -ng -BatchSolve -Distributed %s' % (executable, inpfile)] - super(EB_ANSYSEM, self).sanity_check_step(custom_paths=custom_paths) + super(EB_ANSYSEM, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 3c6b47b0c57ce79594029442cda561f944b717e6 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Fri, 5 Apr 2024 20:55:53 +0200 Subject: [PATCH 063/134] bump version to 4.9.2dev --- easybuild/easyblocks/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/__init__.py b/easybuild/easyblocks/__init__.py index a1f69a95f6..56d224f3be 100644 --- a/easybuild/easyblocks/__init__.py +++ b/easybuild/easyblocks/__init__.py @@ -43,7 +43,7 @@ # recent setuptools versions will *TRANSFORM* something like 'X.Y.Zdev' into 'X.Y.Z.dev0', with a warning like # UserWarning: Normalizing '2.4.0dev' to '2.4.0.dev0' # This causes problems further up the dependency chain... -VERSION = LooseVersion('4.9.1') +VERSION = LooseVersion('4.9.2.dev0') UNKNOWN = 'UNKNOWN' From 28101a024f5147a4f6c2c8c4b26df3abbb866e93 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Tue, 9 Apr 2024 09:29:32 +0000 Subject: [PATCH 064/134] adding easyblocks: optislang.py --- easybuild/easyblocks/o/optislang.py | 108 ++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 easybuild/easyblocks/o/optislang.py diff --git a/easybuild/easyblocks/o/optislang.py b/easybuild/easyblocks/o/optislang.py new file mode 100644 index 0000000000..0436fc6c42 --- /dev/null +++ b/easybuild/easyblocks/o/optislang.py @@ -0,0 +1,108 @@ +## +# Copyright 2009-2024 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 . +## +""" +EasyBuild support for installing ANSYS optiSLang, implemented as an easyblock + +@author: Chia-Jung Hsu (Chalmers University for Technology) +""" +import os +import re +import stat +import tempfile +from easybuild.tools import LooseVersion + +from easybuild.easyblocks.generic.packedbinary import PackedBinary +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.filetools import adjust_permissions +from easybuild.tools.run import run_cmd + + +class EB_optiSLang(PackedBinary): + """Support for installing ANSYS optiSLang.""" + + def __init__(self, *args, **kwargs): + """Initialize optiSLang-specific variables.""" + super(EB_optiSLang, self).__init__(*args, **kwargs) + self.ansysver = None + + def install_step(self): + """Custom install procedure for ANSYS optiSLang.""" + licservs = self.cfg['license_server'] + if licservs is None: + licservs = os.getenv('EB_ANSYS_LICENSE_SERVER', 'license.example.com') + licservs = licservs.split(',') + licport = self.cfg['license_server_port'] + if licport is None: + licport = os.getenv('EB_ANSYS_LICENSE_SERVER_PORT', '2325:1055') + licopts = ['-licserverinfo %s:%s' % (licport, serv) for serv in licservs] + licoptsstr = ' '.join(licopts) + + tmpdir = tempfile.mkdtemp() + + # Sources (e.g. iso files) may drop the execute permissions + adjust_permissions('INSTALL', stat.S_IXUSR) + cmd = "./INSTALL -silent -install_dir %s -usetempdir %s %s" % (self.installdir, tmpdir, licoptsstr) + run_cmd(cmd, log_all=True, simple=True) + + adjust_permissions(self.installdir, stat.S_IWOTH, add=False) + + def set_ansysver(self): + """Determine name of version subdirectory in installation directory.""" + entries = os.listdir(self.installdir) + version_dir_regex = re.compile('^v[0-9]+') + version_dirs = [e for e in entries if version_dir_regex.match(e)] + if len(version_dirs) == 1: + self.ansysver = version_dirs[0] + else: + raise EasyBuildError("Failed to isolate version subdirectory in %s: %s", self.installdir, entries) + + def make_module_req_guess(self): + """Custom extra module file entries for ANSYS optiSLang.""" + + if self.ansysver is None: + self.set_ansysver() + + guesses = super(EB_optiSLang, self).make_module_req_guess() + dirs = [ + 'aisol/bin/linx64', + 'dpf/bin/linux64', + 'optiSLang', + ] + + guesses['PATH'] = [os.path.join(self.ansysver, d) for d in dirs] + + return guesses + + def sanity_check_step(self): + """Custom sanity check for ANSYS optiSLang.""" + + if self.ansysver is None: + self.set_ansysver() + + custom_paths = { + 'files': [os.path.join(self.ansysver, 'optiSLang', x) for x in ['optislang', 'optislang-python']], + 'dirs': [os.path.join(self.ansysver, x) for x in ['aisol', 'dpf']] + } + super(EB_optiSLang, self).sanity_check_step(custom_paths=custom_paths) From 46186d6f68569e389102e54234e879a82c21cb71 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Tue, 9 Apr 2024 15:50:16 +0000 Subject: [PATCH 065/134] Rename to AEDT --- easybuild/easyblocks/a/aedt.py | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 easybuild/easyblocks/a/aedt.py diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py new file mode 100644 index 0000000000..a7af3e3333 --- /dev/null +++ b/easybuild/easyblocks/a/aedt.py @@ -0,0 +1,100 @@ +## +# Copyright 2009-2020 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 . +## +""" +EasyBuild support for installing Ansys Electronics Desktop + +@author: Alexi Rivera (Chalmers University of Technology) +@author: Mikael OEhman (Chalmers University of Technology) +@author: Chia-Jung Hsu (Chalmers University of Technology) +""" +import os +import glob +import tempfile + +from easybuild.easyblocks.generic.packedbinary import PackedBinary +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.run import run_cmd + + +class EB_AEDT(PackedBinary): + """Support for installing Ansys Electronics Desktop.""" + + def __init__(self, *args, **kwargs): + """Initialize Ansys Electronics Desktop specific variables.""" + super(EB_AEDT, self).__init__(*args, **kwargs) + + def install_step(self): + """Install Ansys Electronics Desktop using its setup tool.""" + licserv = os.getenv('EB_AEDT_LICENSE_SERVER') + licport = os.getenv('EB_AEDT_LICENSE_SERVER_PORT') + licservs = licserv.split(',') + licservopt = ["-DLICENSE_SERVER%d=%s" % (i, serv) for i, serv in enumerate(licservs, 1)] + redundant = len(licservs) > 1 + options = " ".join([ + "-i silent", + "-DUSER_INSTALL_DIR=%s" % self.installdir, + "-DTMP_DIR=%s" % tempfile.TemporaryDirectory().name, + "-DLIBRARY_COMMON_INSTALL=1", + "-DSPECIFY_LIC_CFG=1", + "-DREDUNDANT_SERVERS=%d" % redundant, + *licservopt, + "-DSPECIFY_PORT=1", + "-DLICENSE_PORT=%s" % licport, + ]) + cmd = "./Linux/AnsysEM/Disk1/InstData/setup.exe %s" % options + run_cmd(cmd, log_all=True, simple=True) + + def make_module_extra(self): + """Extra module entries for Ansys Electronics Desktop.""" + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + + txt = super(EB_AEDT, self).make_module_extra() + txt += self.module_generator.prepend_paths('PATH', subdir) + txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', subdir) + txt += self.module_generator.prepend_paths('LIBRARY_PATH', subdir) + return txt + + def sanity_check_step(self): + """Custom sanity check for Ansys Electronics Desktop.""" + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + + custom_paths = { + 'files': [os.path.join(subdir, 'ansysedt')], + 'dirs': [subdir], + } + + executable = os.path.join(subdir, 'ansysedt') + inpfile = os.path.join(subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') + custom_commands = ['./%s -ng -BatchSolve -Distributed %s' % (executable, inpfile)] + + super(EB_AEDT, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 8a48908b34f53a22357434fa3a8b441a2f881619 Mon Sep 17 00:00:00 2001 From: Chia-Jung Hsu Date: Tue, 9 Apr 2024 17:53:53 +0200 Subject: [PATCH 066/134] Remove old ansysem.py --- easybuild/easyblocks/a/ansysem.py | 100 ------------------------------ 1 file changed, 100 deletions(-) delete mode 100644 easybuild/easyblocks/a/ansysem.py diff --git a/easybuild/easyblocks/a/ansysem.py b/easybuild/easyblocks/a/ansysem.py deleted file mode 100644 index 8dd9c1feb8..0000000000 --- a/easybuild/easyblocks/a/ansysem.py +++ /dev/null @@ -1,100 +0,0 @@ -## -# Copyright 2009-2020 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 . -## -""" -EasyBuild support for installing ANSYS Eletromagnetics - -@author: Alexi Rivera (Chalmers University of Technology) -@author: Mikael OEhman (Chalmers University of Technology) -@author: Chia-Jung Hsu (Chalmers University of Technology) -""" -import os -import glob -import tempfile - -from easybuild.easyblocks.generic.packedbinary import PackedBinary -from easybuild.tools.build_log import EasyBuildError -from easybuild.tools.run import run_cmd - - -class EB_ANSYSEM(PackedBinary): - """Support for installing Ansys Electromagnetics.""" - - def __init__(self, *args, **kwargs): - """Initialize Ansys Electromagnetics specific variables.""" - super(EB_ANSYSEM, self).__init__(*args, **kwargs) - - def install_step(self): - """Install Ansys Electromagnetics using its setup tool.""" - licserv = os.getenv('EB_ANSYS_EM_LICENSE_SERVER') - licport = os.getenv('EB_ANSYS_EM_LICENSE_SERVER_PORT') - licservs = licserv.split(',') - licservopt = ["-DLICENSE_SERVER%d=%s" % (i, serv) for i, serv in enumerate(licservs, 1)] - redundant = len(licservs) > 1 - options = " ".join([ - "-i silent", - "-DUSER_INSTALL_DIR=%s" % self.installdir, - "-DTMP_DIR=%s" % tempfile.TemporaryDirectory().name, - "-DLIBRARY_COMMON_INSTALL=1", - "-DSPECIFY_LIC_CFG=1", - "-DREDUNDANT_SERVERS=%d" % redundant, - *licservopt, - "-DSPECIFY_PORT=1", - "-DLICENSE_PORT=%s" % licport, - ]) - cmd = "./Linux/AnsysEM/Disk1/InstData/setup.exe %s" % options - run_cmd(cmd, log_all=True, simple=True) - - def make_module_extra(self): - """Extra module entries for Ansys Electromagnetics.""" - idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) - if len(idirs) == 1: - subdir = os.path.relpath(idirs[0], self.installdir) - else: - raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") - - txt = super(EB_ANSYSEM, self).make_module_extra() - txt += self.module_generator.prepend_paths('PATH', subdir) - txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', subdir) - txt += self.module_generator.prepend_paths('LIBRARY_PATH', subdir) - return txt - - def sanity_check_step(self): - """Custom sanity check for Ansys Electromagnetics.""" - idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) - if len(idirs) == 1: - subdir = os.path.relpath(idirs[0], self.installdir) - else: - raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") - - custom_paths = { - 'files': [os.path.join(subdir, 'ansysedt')], - 'dirs': [subdir], - } - - executable = os.path.join(subdir, 'ansysedt') - inpfile = os.path.join(subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') - custom_commands = ['./%s -ng -BatchSolve -Distributed %s' % (executable, inpfile)] - - super(EB_ANSYSEM, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 87005fbac923565cc0f8f9af1d25fb97bac74703 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Tue, 9 Apr 2024 16:04:25 +0000 Subject: [PATCH 067/134] Remove unused imports --- easybuild/easyblocks/o/optislang.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easybuild/easyblocks/o/optislang.py b/easybuild/easyblocks/o/optislang.py index 0436fc6c42..0e345c1310 100644 --- a/easybuild/easyblocks/o/optislang.py +++ b/easybuild/easyblocks/o/optislang.py @@ -31,7 +31,6 @@ import re import stat import tempfile -from easybuild.tools import LooseVersion from easybuild.easyblocks.generic.packedbinary import PackedBinary from easybuild.tools.build_log import EasyBuildError From 4d264a4d1f295cee3b8bc246b66300ca33d9adf1 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Thu, 11 Apr 2024 09:29:43 +0000 Subject: [PATCH 068/134] Add post install step --- easybuild/easyblocks/a/aedt.py | 54 +++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index a7af3e3333..4aa435a8e6 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -44,6 +44,14 @@ class EB_AEDT(PackedBinary): def __init__(self, *args, **kwargs): """Initialize Ansys Electronics Desktop specific variables.""" super(EB_AEDT, self).__init__(*args, **kwargs) + self.subdir = None + + def _set_subdir(self): + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + self.subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") def install_step(self): """Install Ansys Electronics Desktop using its setup tool.""" @@ -66,35 +74,47 @@ def install_step(self): cmd = "./Linux/AnsysEM/Disk1/InstData/setup.exe %s" % options run_cmd(cmd, log_all=True, simple=True) + def post_install_step(self): + """Disable OS check and set LC_ALL/LANG for runtime""" + if not self.subdir: + self._set_subdir() + + # Clean script file to disable over restrict OS checking + with open(os.path.join(self.installdir, self.subdir, "VerifyOS.bash"), "w") as f: + f.write("") + + # Set LC_ALL and LANG for runtime + for fname in [".setup_runtime", ".setup_runtime_mpi"]: + with open(os.path.join(self.installdir, self.subdir, fname), "r") as f: + orig = f.read() + with open(os.path.join(self.installdir, self.subdir, fname), "w") as f: + f.write("export LC_ALL=C\n") + f.write("export LANG=C\n") + f.write(orig) + def make_module_extra(self): """Extra module entries for Ansys Electronics Desktop.""" - idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) - if len(idirs) == 1: - subdir = os.path.relpath(idirs[0], self.installdir) - else: - raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + if not self.subdir: + self._set_subdir() txt = super(EB_AEDT, self).make_module_extra() - txt += self.module_generator.prepend_paths('PATH', subdir) - txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', subdir) - txt += self.module_generator.prepend_paths('LIBRARY_PATH', subdir) + txt += self.module_generator.prepend_paths('PATH', self.subdir) + txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', self.subdir) + txt += self.module_generator.prepend_paths('LIBRARY_PATH', self.subdir) return txt def sanity_check_step(self): """Custom sanity check for Ansys Electronics Desktop.""" - idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) - if len(idirs) == 1: - subdir = os.path.relpath(idirs[0], self.installdir) - else: - raise EasyBuildError("Failed to locate single install subdirectory v*/Linux*/") + if not self.subdir: + self._set_subdir() custom_paths = { - 'files': [os.path.join(subdir, 'ansysedt')], - 'dirs': [subdir], + 'files': [os.path.join(self.subdir, 'ansysedt')], + 'dirs': [self.subdir], } - executable = os.path.join(subdir, 'ansysedt') - inpfile = os.path.join(subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') + executable = os.path.join(self.subdir, 'ansysedt') + inpfile = os.path.join(self.subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') custom_commands = ['./%s -ng -BatchSolve -Distributed %s' % (executable, inpfile)] super(EB_AEDT, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 8a6033105f66e1a26e3f1abee1f274d8949155e5 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Thu, 11 Apr 2024 11:06:03 +0000 Subject: [PATCH 069/134] Skip adding path if empty dir, add more sanity check --- easybuild/easyblocks/o/optislang.py | 47 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/easybuild/easyblocks/o/optislang.py b/easybuild/easyblocks/o/optislang.py index 0e345c1310..acdf16ea81 100644 --- a/easybuild/easyblocks/o/optislang.py +++ b/easybuild/easyblocks/o/optislang.py @@ -27,6 +27,7 @@ @author: Chia-Jung Hsu (Chalmers University for Technology) """ +import glob import os import re import stat @@ -44,7 +45,6 @@ class EB_optiSLang(PackedBinary): def __init__(self, *args, **kwargs): """Initialize optiSLang-specific variables.""" super(EB_optiSLang, self).__init__(*args, **kwargs) - self.ansysver = None def install_step(self): """Custom install procedure for ANSYS optiSLang.""" @@ -67,41 +67,40 @@ def install_step(self): adjust_permissions(self.installdir, stat.S_IWOTH, add=False) - def set_ansysver(self): - """Determine name of version subdirectory in installation directory.""" - entries = os.listdir(self.installdir) - version_dir_regex = re.compile('^v[0-9]+') - version_dirs = [e for e in entries if version_dir_regex.match(e)] - if len(version_dirs) == 1: - self.ansysver = version_dirs[0] - else: - raise EasyBuildError("Failed to isolate version subdirectory in %s: %s", self.installdir, entries) - def make_module_req_guess(self): """Custom extra module file entries for ANSYS optiSLang.""" - if self.ansysver is None: - self.set_ansysver() - guesses = super(EB_optiSLang, self).make_module_req_guess() - dirs = [ - 'aisol/bin/linx64', - 'dpf/bin/linux64', - 'optiSLang', - ] - guesses['PATH'] = [os.path.join(self.ansysver, d) for d in dirs] + idirs = glob.glob(os.path.join(self.installdir, 'v*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + bindirs = [ + 'aisol/bin/linx64', + 'dpf/bin/linux64', + 'optiSLang', + ] + guesses['PATH'] = [os.path.join(subdir, d) for d in bindirs] return guesses def sanity_check_step(self): """Custom sanity check for ANSYS optiSLang.""" - if self.ansysver is None: - self.set_ansysver() + idirs = glob.glob(os.path.join(self.installdir, 'v*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + else: + raise EasyBuildError("Failed to locate single install subdirectory v*/") + + errorlogfile = os.path.join(self.installdir, "install.err") + if os.path.isfile(errorlogfile): + raise EasyBuildError("Found error log from optiSLang installer %s" % errorlogfile) custom_paths = { - 'files': [os.path.join(self.ansysver, 'optiSLang', x) for x in ['optislang', 'optislang-python']], - 'dirs': [os.path.join(self.ansysver, x) for x in ['aisol', 'dpf']] + 'files': [os.path.join(subdir, 'optiSLang', x) for x in ['optislang', 'optislang-python']], + 'dirs': [os.path.join(subdir, x) for x in ['aisol', 'dpf']] } + custom_commands = ['./optislang --help'] + super(EB_optiSLang, self).sanity_check_step(custom_paths=custom_paths) From 7d4c1051db841e95fcc58b677ce0b72b74d08801 Mon Sep 17 00:00:00 2001 From: c3-builder Date: Thu, 11 Apr 2024 12:56:34 +0000 Subject: [PATCH 070/134] Fix sanity check command --- easybuild/easyblocks/o/optislang.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/o/optislang.py b/easybuild/easyblocks/o/optislang.py index acdf16ea81..b92190b1f8 100644 --- a/easybuild/easyblocks/o/optislang.py +++ b/easybuild/easyblocks/o/optislang.py @@ -29,7 +29,6 @@ """ import glob import os -import re import stat import tempfile @@ -101,6 +100,6 @@ def sanity_check_step(self): 'files': [os.path.join(subdir, 'optiSLang', x) for x in ['optislang', 'optislang-python']], 'dirs': [os.path.join(subdir, x) for x in ['aisol', 'dpf']] } - custom_commands = ['./optislang --help'] + custom_commands = ['optislang --help'] - super(EB_optiSLang, self).sanity_check_step(custom_paths=custom_paths) + super(EB_optiSLang, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 230e0da2ea032db3e4f0108e578173e756eb3080 Mon Sep 17 00:00:00 2001 From: Chia-Jung Hsu Date: Thu, 11 Apr 2024 14:58:12 +0200 Subject: [PATCH 071/134] Fix style --- easybuild/easyblocks/o/optislang.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/o/optislang.py b/easybuild/easyblocks/o/optislang.py index b92190b1f8..84b335e5fd 100644 --- a/easybuild/easyblocks/o/optislang.py +++ b/easybuild/easyblocks/o/optislang.py @@ -100,6 +100,6 @@ def sanity_check_step(self): 'files': [os.path.join(subdir, 'optiSLang', x) for x in ['optislang', 'optislang-python']], 'dirs': [os.path.join(subdir, x) for x in ['aisol', 'dpf']] } - custom_commands = ['optislang --help'] + custom_commands = ['optislang --help'] super(EB_optiSLang, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From b7508dffa434069b92657a3f309501903481f4fe Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 12 Apr 2024 17:07:40 +0200 Subject: [PATCH 072/134] Allow 'nosource: True' in PythonPackage extensions' --- easybuild/easyblocks/generic/pythonpackage.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/easybuild/easyblocks/generic/pythonpackage.py b/easybuild/easyblocks/generic/pythonpackage.py index da6ca8c2a8..de4bd0b7bc 100644 --- a/easybuild/easyblocks/generic/pythonpackage.py +++ b/easybuild/easyblocks/generic/pythonpackage.py @@ -623,7 +623,7 @@ def compose_install_command(self, prefix, extrapath=None, installopts=None): loc = self.cfg.get('install_src') if not loc: - if self._should_unpack_source(): + if self._should_unpack_source() or not self.src: # specify current directory loc = '.' elif isinstance(self.src, string_type): @@ -904,9 +904,6 @@ def install_step(self): def run(self, *args, **kwargs): """Perform the actual Python package build/installation procedure""" - if not self.src: - raise EasyBuildError("No source found for Python package %s, required for installation. (src: %s)", - self.name, self.src) # we unpack unless explicitly told otherwise kwargs.setdefault('unpack_src', self._should_unpack_source()) super(PythonPackage, self).run(*args, **kwargs) From 7855ee7045e45788dc285b9ffc60af2da4303dfe Mon Sep 17 00:00:00 2001 From: c3-builder Date: Fri, 12 Apr 2024 17:38:43 +0000 Subject: [PATCH 073/134] Skip adding path if dir is empty --- easybuild/easyblocks/a/aedt.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index 4aa435a8e6..24314b7e44 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -94,13 +94,21 @@ def post_install_step(self): def make_module_extra(self): """Extra module entries for Ansys Electronics Desktop.""" - if not self.subdir: - self._set_subdir() txt = super(EB_AEDT, self).make_module_extra() - txt += self.module_generator.prepend_paths('PATH', self.subdir) - txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', self.subdir) - txt += self.module_generator.prepend_paths('LIBRARY_PATH', self.subdir) + version = self.version[2:].replace('R', '') + + idirs = glob.glob(os.path.join(self.installdir, 'v*/Linux*/')) + if len(idirs) == 1: + subdir = os.path.relpath(idirs[0], self.installdir) + # PyAEDT and other tools use the variable to find available AEDT versions + txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, + os.path.join(self.installdir, self.subdir)) + + txt += self.module_generator.prepend_paths('PATH', subdir) + txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', subdir) + txt += self.module_generator.prepend_paths('LIBRARY_PATH', subdir) + return txt def sanity_check_step(self): @@ -113,8 +121,7 @@ def sanity_check_step(self): 'dirs': [self.subdir], } - executable = os.path.join(self.subdir, 'ansysedt') inpfile = os.path.join(self.subdir, 'Examples', 'RMxprt', 'lssm', 'sm-1.aedt') - custom_commands = ['./%s -ng -BatchSolve -Distributed %s' % (executable, inpfile)] + custom_commands = ['ansysedt -ng -BatchSolve -Distributed %s' % inpfile] super(EB_AEDT, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From 31eefba17334f1248c104bec043fbc1ccaaf00b3 Mon Sep 17 00:00:00 2001 From: Chia-Jung Hsu Date: Fri, 12 Apr 2024 21:18:16 +0200 Subject: [PATCH 074/134] Fix style --- easybuild/easyblocks/a/aedt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index 24314b7e44..a08fcca2bf 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -102,7 +102,7 @@ def make_module_extra(self): if len(idirs) == 1: subdir = os.path.relpath(idirs[0], self.installdir) # PyAEDT and other tools use the variable to find available AEDT versions - txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, + txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, os.path.join(self.installdir, self.subdir)) txt += self.module_generator.prepend_paths('PATH', subdir) From d6755a237aa89aff32fb43bb7a6080d52107bdf8 Mon Sep 17 00:00:00 2001 From: Simon Branford <4967+branfosj@users.noreply.github.com> Date: Mon, 15 Apr 2024 08:52:55 +0100 Subject: [PATCH 075/134] Binary easyblock already adds top level directory, so no need to do it in the Stata easyblock --- easybuild/easyblocks/s/stata.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/easybuild/easyblocks/s/stata.py b/easybuild/easyblocks/s/stata.py index cfa31fc951..25e9e6c0da 100644 --- a/easybuild/easyblocks/s/stata.py +++ b/easybuild/easyblocks/s/stata.py @@ -75,9 +75,3 @@ def sanity_check_step(self): regex = re.compile('libpng.*not found', re.M) if regex.search(out): raise EasyBuildError("Required libpng library for 'stata' is not available") - - def make_module_req_guess(self): - """Add top install directory to $PATH for Stata""" - guesses = super(EB_Stata, self).make_module_req_guess() - guesses['PATH'] = [''] - return guesses From 9ae80a01f9ba6b79d617a9b9422b9c360935533b Mon Sep 17 00:00:00 2001 From: c3-builder Date: Thu, 18 Apr 2024 09:39:15 +0000 Subject: [PATCH 076/134] Remove authors left from old file --- easybuild/easyblocks/a/aedt.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index a08fcca2bf..8fec82412c 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -25,8 +25,6 @@ """ EasyBuild support for installing Ansys Electronics Desktop -@author: Alexi Rivera (Chalmers University of Technology) -@author: Mikael OEhman (Chalmers University of Technology) @author: Chia-Jung Hsu (Chalmers University of Technology) """ import os @@ -102,7 +100,7 @@ def make_module_extra(self): if len(idirs) == 1: subdir = os.path.relpath(idirs[0], self.installdir) # PyAEDT and other tools use the variable to find available AEDT versions - txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, + txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, os.path.join(self.installdir, self.subdir)) txt += self.module_generator.prepend_paths('PATH', subdir) From c5d4ce9dc01ea0d0e8d6ff3934a21050ebead9ad Mon Sep 17 00:00:00 2001 From: c3-builder Date: Thu, 18 Apr 2024 09:41:30 +0000 Subject: [PATCH 077/134] Clean whitespace --- easybuild/easyblocks/a/aedt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index 8fec82412c..ff14a7379f 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -100,7 +100,7 @@ def make_module_extra(self): if len(idirs) == 1: subdir = os.path.relpath(idirs[0], self.installdir) # PyAEDT and other tools use the variable to find available AEDT versions - txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, + txt += self.module_generator.set_environment('ANSYSEM_ROOT%s' % version, os.path.join(self.installdir, self.subdir)) txt += self.module_generator.prepend_paths('PATH', subdir) From 08cfe0373c6eff1e1874f983d71f1802cfc1f9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20=C3=96hman?= Date: Thu, 18 Apr 2024 11:44:06 +0200 Subject: [PATCH 078/134] Update easybuild/easyblocks/a/aedt.py --- easybuild/easyblocks/a/aedt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index ff14a7379f..6b88946414 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2020 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), From 8e52a4bda611d13365701db1a6011e18967e1b4e Mon Sep 17 00:00:00 2001 From: Chia-Jung Hsu Date: Thu, 18 Apr 2024 13:48:54 +0000 Subject: [PATCH 079/134] Improve comments --- easybuild/easyblocks/a/aedt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/a/aedt.py b/easybuild/easyblocks/a/aedt.py index 6b88946414..53d04d506e 100644 --- a/easybuild/easyblocks/a/aedt.py +++ b/easybuild/easyblocks/a/aedt.py @@ -81,7 +81,9 @@ def post_install_step(self): with open(os.path.join(self.installdir, self.subdir, "VerifyOS.bash"), "w") as f: f.write("") - # Set LC_ALL and LANG for runtime + # Follow the settings in .setup_runtime and .setup_runtime_mpi to set LC_ALL and LANG + # If LC_ALL is not set properly, AEDT throws the following runtime error: + # what(): locale::facet::_S_create_c_locale name not valid for fname in [".setup_runtime", ".setup_runtime_mpi"]: with open(os.path.join(self.installdir, self.subdir, fname), "r") as f: orig = f.read() From 4a9bbf88fffe4d816eb478f51943500a1fe55625 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 19 Apr 2024 16:50:42 +0200 Subject: [PATCH 080/134] Added easyblock for MetalWalls --- easybuild/easyblocks/m/metalwalls.py | 148 +++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 easybuild/easyblocks/m/metalwalls.py diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py new file mode 100644 index 0000000000..a6bbf41216 --- /dev/null +++ b/easybuild/easyblocks/m/metalwalls.py @@ -0,0 +1,148 @@ +## +# Copyright 2009-2023 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 . +## +""" +EasyBuild support for `metalwalls`, implemented as an easyblock + +@author: Davide Grassano (CECAM, EPFL) +""" +import os + +import easybuild.tools.environment as env +import easybuild.tools.toolchain as toolchain +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.modules import get_software_root +from easybuild.tools.run import run_cmd + +from easybuild.easyblocks.generic.makecp import MakeCp + + +class EB_MetalWalls(MakeCp): + """Support for building and installing `metalwalls`.""" + + def __init__(self, *args, **kwargs): + """Add extra config options specific to `metalwalls`.""" + super(EB_MetalWalls, self).__init__(*args, **kwargs) + + self._build_python_interface = False + + + def configure_step(self): + """Custom configuration procedure for `metalwalls`.""" + comp_fam = self.toolchain.comp_family() + + f90flags = os.getenv('F90FLAGS', '').split(' ') + fppflags = os.getenv('FPPFLAGS', '').split(' ') + ldflags = os.getenv('LDFLAGS', '').split(' ') + f90wrap = '' + f2py = '' + fcompiler = '' + + if comp_fam == toolchain.INTELCOMP: + jflag = '-module' + fppflags = ['-fpp'] + elif comp_fam == toolchain.GCC: + jflag = '-J' + fppflags = ['-cpp'] + else: + raise EasyBuildError('Unsupported compiler family: %s' % comp_fam) + + # https://gitlab.com/ampere2/metalwalls/-/wikis/install#plumed + plumed = get_software_root('PLUMED') + f90wrap = get_software_root('f90wrap') + + tpl_rgx = 'alltests\.append(suite_%s)' + if plumed: + f90flags += ['-fallow-argument-mismatch'] # Code inside ifdef causes mismatch errors + fppflags += ['-DMW_USE_PLUMED'] + cmd = ['plumed', 'patch', '--new', 'mw2'] + run_cmd(' '.join(cmd), log_all=False, log_ok=False, simple=False, regexp=False) + cmd = ['plumed', 'patch', '--patch', '--shared', '--engine', 'mw2'] + run_cmd(' '.join(cmd), log_all=True, simple=False) + else: + self.log.info('PLUMED not found, excluding from test-suite') + rgx = tpl_rgx % 'plumed' + cmd = ['sed', '-i', "'s/^\( \+\)%s$/\\1pass # %s/'" % (rgx, rgx), 'tests/regression_tests.py'] + cmd = ['sed', '-i', "'s/%s/pass/'" % rgx, 'tests/regression_tests.py'] + run_cmd(' '.join(cmd), log_all=True, simple=False) + + if f90wrap: + if not get_software_root('mpi4py'): + raise EasyBuildError('Building the Python interface requires mpi4py') + self._build_python_interface = True + f90wrap = 'f90wrap' + f2py = 'f2py' + fcompiler = os.getenv('F90_SEQ') + f90flags += ['-fPIC'] + self.cfg.update('build_cmd_targets', 'python') + else: + self.log.info('f90wrap not found, excluding python interface from test-suite') + rgx = tpl_rgx % 'python_interface' + cmd = ['sed', '-i', "'s/%s/pass/'" % rgx, 'tests/regression_tests.py'] + run_cmd(' '.join(cmd), log_all=True, simple=False) + + # Add libraries with LAPACK support + lapack_shared_libs = os.getenv('LAPACK_SHARED_LIBS', None) + if not lapack_shared_libs: + raise EasyBuildError('Must use a toolchain with LAPACK support') + extra_libs = lapack_shared_libs.replace('.so', '').split(',') + extra_libs = [_[3:] for _ in extra_libs if _.startswith('lib')] + ldflags += ['-l%s' % lib for lib in extra_libs] + + # Write the `config.mk` file + configmk = os.path.join(self.cfg['start_dir'], 'config.mk') + with open(configmk, 'w') as f: + f.write('F90FLAGS := %s\n' % ' '.join(f90flags)) + f.write('FPPFLAGS := %s\n' % ' '.join(fppflags)) + f.write('LDFLAGS := %s\n' % ' '.join(ldflags)) + f.write('F90WRAP := %s\n' % f90wrap) + f.write('F2PY := %s\n' % f2py) + f.write('FCOMPILER := %s\n' % fcompiler) + f.write('J := %s\n' % jflag) + + with open(configmk, 'r') as f: + self.log.info('Contents of generated `config.mk`:\n%s' % f.read()) + + def test_step(self): + """ + Test the compilation using `metalwalls`'s test suite. + """ + + if self._build_python_interface: + ppath = os.getenv('PYTHONPATH', '') + ppath = os.path.join(self.cfg['start_dir'], 'build', 'python') + ':' + ppath + self.log.info('Setting PYTHONPATH for testing to %s' % ppath) + env.setvar('PYTHONPATH', ppath) + + super(EB_MetalWalls, self).test_step() + + def make_module_extra(self, extra=None): + """Add custom entries to module.""" + + txt = super(EB_MetalWalls, self).make_module_extra() + + if self._build_python_interface: + txt += self.module_generator.prepend_paths('PYTHONPATH', 'python') + + return txt From 720b7851729d9d1eceab3bcd21f958748b7713fa Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 19 Apr 2024 17:21:38 +0200 Subject: [PATCH 081/134] Linting and sanity checks --- easybuild/easyblocks/m/metalwalls.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py index a6bbf41216..31157007f9 100644 --- a/easybuild/easyblocks/m/metalwalls.py +++ b/easybuild/easyblocks/m/metalwalls.py @@ -46,7 +46,7 @@ def __init__(self, *args, **kwargs): super(EB_MetalWalls, self).__init__(*args, **kwargs) self._build_python_interface = False - + self._extra_schecks = [] def configure_step(self): """Custom configuration procedure for `metalwalls`.""" @@ -72,7 +72,7 @@ def configure_step(self): plumed = get_software_root('PLUMED') f90wrap = get_software_root('f90wrap') - tpl_rgx = 'alltests\.append(suite_%s)' + tpl_rgx = 'alltests\\.append(suite_%s)' if plumed: f90flags += ['-fallow-argument-mismatch'] # Code inside ifdef causes mismatch errors fppflags += ['-DMW_USE_PLUMED'] @@ -83,7 +83,7 @@ def configure_step(self): else: self.log.info('PLUMED not found, excluding from test-suite') rgx = tpl_rgx % 'plumed' - cmd = ['sed', '-i', "'s/^\( \+\)%s$/\\1pass # %s/'" % (rgx, rgx), 'tests/regression_tests.py'] + cmd = ['sed', '-i', "'s/^\\( \\+\\)%s$/\\1pass # %s/'" % (rgx, rgx), 'tests/regression_tests.py'] cmd = ['sed', '-i', "'s/%s/pass/'" % rgx, 'tests/regression_tests.py'] run_cmd(' '.join(cmd), log_all=True, simple=False) @@ -96,6 +96,9 @@ def configure_step(self): fcompiler = os.getenv('F90_SEQ') f90flags += ['-fPIC'] self.cfg.update('build_cmd_targets', 'python') + self.cfg.update('files_to_copy', 'build/python') + self._extra_schecks += ['python/mw.py', 'python/metalwalls.py'] + else: self.log.info('f90wrap not found, excluding python interface from test-suite') rgx = tpl_rgx % 'python_interface' @@ -146,3 +149,15 @@ def make_module_extra(self, extra=None): txt += self.module_generator.prepend_paths('PYTHONPATH', 'python') return txt + + def sanity_check_step(self): + """Custom sanity check for Quantum ESPRESSO.""" + + bins = ['mw'] + + custom_paths = { + 'files': [os.path.join('bin', x) for x in bins] + self._extra_schecks, + 'dirs': [] + } + + super(EB_MetalWalls, self).sanity_check_step(custom_paths=custom_paths) From 3c3765df606e7e98aa8c6dbcce44adcf75a7413a Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 19 Apr 2024 17:35:51 +0200 Subject: [PATCH 082/134] linting --- easybuild/easyblocks/m/metalwalls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py index 31157007f9..2288092b00 100644 --- a/easybuild/easyblocks/m/metalwalls.py +++ b/easybuild/easyblocks/m/metalwalls.py @@ -74,7 +74,7 @@ def configure_step(self): tpl_rgx = 'alltests\\.append(suite_%s)' if plumed: - f90flags += ['-fallow-argument-mismatch'] # Code inside ifdef causes mismatch errors + f90flags += ['-fallow-argument-mismatch'] # Code inside ifdef causes mismatch errors fppflags += ['-DMW_USE_PLUMED'] cmd = ['plumed', 'patch', '--new', 'mw2'] run_cmd(' '.join(cmd), log_all=False, log_ok=False, simple=False, regexp=False) From a2be222ed064fafb8ca01bcc6786d50c11fca5b8 Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Mon, 22 Apr 2024 18:23:18 +0000 Subject: [PATCH 083/134] Don't manipulate setup.py for Python 3.12+ It's gone in Python 3.12, see https://docs.python.org/3/whatsnew/3.12.html#build-changes --- easybuild/easyblocks/p/python.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/p/python.py b/easybuild/easyblocks/p/python.py index 0f42c6e41f..f2fe976cb7 100644 --- a/easybuild/easyblocks/p/python.py +++ b/easybuild/easyblocks/p/python.py @@ -195,8 +195,9 @@ def patch_step(self, *args, **kwargs): # if we're installing Python with an alternate sysroot, # we need to patch setup.py which includes hardcoded paths like /usr/include and /lib64; # this fixes problems like not being able to build the _ssl module ("Could not build the ssl module") + # Python 3.12 doesn't have setup.py any more sysroot = build_option('sysroot') - if sysroot: + if sysroot and LooseVersion(self.version) < LooseVersion('3.12'): sysroot_inc_dirs, sysroot_lib_dirs = [], [] for pattern in ['include*', os.path.join('usr', 'include*')]: From 7c4996a89e9c11b02df7938df5024937e4ee0af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Wed, 24 Apr 2024 10:04:20 +0200 Subject: [PATCH 084/134] also auto-disable quad-precision on RISC-V --- easybuild/easyblocks/f/fftw.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/f/fftw.py b/easybuild/easyblocks/f/fftw.py index ff3788a4e2..baa287e2d5 100644 --- a/easybuild/easyblocks/f/fftw.py +++ b/easybuild/easyblocks/f/fftw.py @@ -37,7 +37,7 @@ from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option from easybuild.tools.modules import get_software_version -from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, X86_64 +from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, RISCV32, RISCV64, X86_64 from easybuild.tools.systemtools import get_cpu_architecture, get_cpu_features, get_shared_lib_ext from easybuild.tools.toolchain.compiler import OPTARCH_GENERIC from easybuild.tools.utilities import nub @@ -141,7 +141,7 @@ def __init__(self, *args, **kwargs): setattr(self, flag, True) # Auto-disable quad-precision on ARM and POWER, as it is unsupported - if self.cfg['with_quad_prec'] and cpu_arch in [AARCH32, AARCH64, POWER]: + if self.cfg['with_quad_prec'] and cpu_arch in [AARCH32, AARCH64, POWER, RISCV32, RISCV64]: self.cfg['with_quad_prec'] = False self.log.debug("Quad-precision automatically disabled; not supported on %s.", cpu_arch) From 7be0c26032aeeb88a7137e48030fde1532e06886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20=C3=96hman?= Date: Sat, 27 Apr 2024 15:29:50 +0000 Subject: [PATCH 085/134] remove alternative flex license manager environment variable --- easybuild/easyblocks/a/abaqus.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/easybuild/easyblocks/a/abaqus.py b/easybuild/easyblocks/a/abaqus.py index 7f6eb0820a..8bb0ec7280 100644 --- a/easybuild/easyblocks/a/abaqus.py +++ b/easybuild/easyblocks/a/abaqus.py @@ -372,8 +372,6 @@ def make_module_extra(self): txt = super(EB_ABAQUS, self).make_module_extra() license_file = os.getenv('EB_ABAQUS_LICENSE_FILE', None) if license_file is not None: - txt += self.module_generator.prepend_paths('LM_LICENSE_FILE', [license_file], allow_abs=True) - # also needed for some versions: txt += self.module_generator.prepend_paths('ABAQUSLM_LICENSE_FILE', [license_file], allow_abs=True) return txt From 5e1010b980214807b6e75f1f4eb53f3801f5b996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Sun, 28 Apr 2024 14:21:46 +0200 Subject: [PATCH 086/134] don't set configure_cmd, stick to regular configure script --- easybuild/easyblocks/u/ucx_plugins.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easybuild/easyblocks/u/ucx_plugins.py b/easybuild/easyblocks/u/ucx_plugins.py index d6a8227202..77e799d581 100644 --- a/easybuild/easyblocks/u/ucx_plugins.py +++ b/easybuild/easyblocks/u/ucx_plugins.py @@ -77,7 +77,6 @@ def configure_step(self): if not get_software_root('UCX'): raise EasyBuildError("UCX is a required dependency") - self.cfg['configure_cmd'] = 'contrib/configure-release' self.cfg.update('preconfigopts', 'autoreconf -i &&') configopts = '--enable-optimizations --without-java --disable-doxygen-doc ' From b0035e8d7fc8d646101529bd601876d802f701ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Sun, 28 Apr 2024 14:23:06 +0200 Subject: [PATCH 087/134] add the configure flags from contrib/configure-release to configopts --- easybuild/easyblocks/u/ucx_plugins.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/easybuild/easyblocks/u/ucx_plugins.py b/easybuild/easyblocks/u/ucx_plugins.py index 77e799d581..3cba0e277c 100644 --- a/easybuild/easyblocks/u/ucx_plugins.py +++ b/easybuild/easyblocks/u/ucx_plugins.py @@ -82,6 +82,8 @@ def configure_step(self): configopts = '--enable-optimizations --without-java --disable-doxygen-doc ' # omit the lib subdirectory since we are just installing plugins configopts += '--libdir=%(installdir)s ' + # include the configure options from contrib/configure-release + configopts += '--disable-logging --disable-debug --disable-assertions --disable-params-check ' cudaroot = get_software_root('CUDAcore') or get_software_root('CUDA') if cudaroot: From 1bfd25373dca72660f725b65e87833420d8dd936 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 May 2024 15:34:47 +0200 Subject: [PATCH 088/134] swicth OpenMP in GAMESS-US through GMS_OPENMP and disable toolchain option --- easybuild/easyblocks/g/gamess_us.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index 60b2b32397..a3d0625cae 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -104,6 +104,13 @@ def __init__(self, *args, **kwargs): error_msg = "Temporary dir for tests '%s' will cause problems with rungms csh script" raise EasyBuildError(error_msg, self.testdir) + # OpenMP cannot be enabled across the board, activate it only through + # GMS_OPENMP so that it gets enabled by the build where needed + self.omp_enabled = False + if self.toolchain.options.get('openmp', None): + self.omp_enabled = True + self.toolchain.options['openmp'] = False + def extract_step(self): """Extract sources.""" # strip off 'gamess' part to avoid having everything in a 'gamess' subdirectory @@ -153,12 +160,7 @@ def configure_step(self): installinfo_opts.update(fortran_version) # OpenMP config - if self.toolchain.options.get('openmp', None): - omp_enabled = "true" - else: - omp_enabled = "false" - - installinfo_opts["GMS_OPENMP"] = omp_enabled + installinfo_opts["GMS_OPENMP"] = self.omp_enabled # Math library config known_mathlibs = ['imkl', 'OpenBLAS', 'ATLAS', 'ACML'] @@ -186,7 +188,7 @@ def configure_step(self): installinfo_opts["GMS_MKL_VERNO"] = mkl_version if LooseVersion(self.version) >= LooseVersion('20230601'): - installinfo_opts["GMS_THREADED_BLAS"] = omp_enabled + installinfo_opts["GMS_THREADED_BLAS"] = self.omp_enabled elif mathlib == 'openblas': mathlib_flags = "-lopenblas -lgfortran" From 49e0c87a146f9b9acc02244c9a3b35e7ce196cea Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 7 May 2024 15:36:06 +0200 Subject: [PATCH 089/134] use real booleans for true/false install.info options in GAMESS-US easyblock --- easybuild/easyblocks/g/gamess_us.py | 45 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/easybuild/easyblocks/g/gamess_us.py b/easybuild/easyblocks/g/gamess_us.py index a3d0625cae..ca03c51714 100644 --- a/easybuild/easyblocks/g/gamess_us.py +++ b/easybuild/easyblocks/g/gamess_us.py @@ -260,26 +260,26 @@ def configure_step(self): # TODO: add support for GPUs if LooseVersion(self.version) >= LooseVersion('20230601'): # offloading onto Intel GPUs - installinfo_opts["GMS_OPENMP_OFFLOAD"] = "false" + installinfo_opts["GMS_OPENMP_OFFLOAD"] = False # These are extra programs which for now we simply set all to FALSE - installinfo_opts["GMS_MSUCC"] = "false" + installinfo_opts["GMS_MSUCC"] = False installinfo_opts["GMS_PHI"] = "none" installinfo_opts["GMS_SHMTYPE"] = "sysv" - installinfo_opts["GMS_LIBCCHEM"] = "false" # libcchem + installinfo_opts["GMS_LIBCCHEM"] = False # libcchem if LooseVersion(self.version) >= LooseVersion('20230601'): # install options for libcchem2 - installinfo_opts["GMS_HPCCHEM"] = "false" - installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = "false" + installinfo_opts["GMS_HPCCHEM"] = False + installinfo_opts["GMS_HPCCHEM_USE_DATA_SERVERS"] = False # build Michigan State University code - installinfo_opts["GMS_MSUAUTO"] = "false" + installinfo_opts["GMS_MSUAUTO"] = False # Optional plug-ins and interfaces # libXC if LooseVersion(self.version) >= LooseVersion('20200101'): - installinfo_opts['GMS_LIBXC'] = "false" + installinfo_opts['GMS_LIBXC'] = False if get_software_root('libxc'): - installinfo_opts['GMS_LIBXC'] = "true" + installinfo_opts['GMS_LIBXC'] = True # the linker needs to be patched to use external libXC lixc_libs = [os.path.join(os.environ['EBROOTLIBXC'], 'lib', lib) for lib in ['libxcf03.a', 'libxc.a']] libxc_linker_flags = ' '.join(lixc_libs) @@ -292,26 +292,26 @@ def configure_step(self): raise EasyBuildError("Failed to patch %s: %s", lked, err) # MDI # needs https://github.com/MolSSI-MDI/MDI_Library - installinfo_opts['GMS_MDI'] = "false" + installinfo_opts['GMS_MDI'] = False # NBO - installinfo_opts['NBO'] = "false" + installinfo_opts['NBO'] = False if get_software_root('NBO'): - installinfo_opts['NBO'] = "true" + installinfo_opts['NBO'] = True # NEO - installinfo_opts['NEO'] = "false" + installinfo_opts['NEO'] = False # RISM if LooseVersion(self.version) >= LooseVersion('20230601'): - installinfo_opts['RISM'] = "false" + installinfo_opts['RISM'] = False # TINKER - installinfo_opts['TINKER'] = "false" + installinfo_opts['TINKER'] = False if get_software_root('TINKER'): - installinfo_opts['TINKER'] = "true" + installinfo_opts['TINKER'] = True # VB2000 - installinfo_opts['VB2000'] = "false" + installinfo_opts['VB2000'] = False # VM2 - installinfo_opts['GMS_VM2'] = "false" + installinfo_opts['GMS_VM2'] = False # XMVB - installinfo_opts['XMVB'] = "false" + installinfo_opts['XMVB'] = False # add include paths from dependencies installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] @@ -319,10 +319,13 @@ def configure_step(self): # installinfo_opts["GMS_FPE_FLAGS"] = '"%s"' % os.environ['CPPFLAGS'] + "-ffpe-trap=invalid,zero,overflow" # write install.info file with configuration settings - # format: setenv KEY VALUE installinfo_file = os.path.join(self.builddir, GAMESS_INSTALL_INFO) - txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) - write_file(installinfo_file, txt) + # replace boolean options with their string representation + boolean_opts = {opt: str(val).lower() for opt, val in installinfo_opts.items() if val in [True, False]} + installinfo_opts.update(boolean_opts) + # format: setenv KEY VALUE + installinfo_txt = '\n'.join(["setenv %s %s" % (k, installinfo_opts[k]) for k in installinfo_opts]) + write_file(installinfo_file, installinfo_txt) self.log.debug("Contents of %s:\n%s" % (installinfo_file, read_file(installinfo_file))) # patch hardcoded settings in rungms to use values specified in easyconfig file From a6bb74410f7033c5da564ef02b5cbb34d144b2e0 Mon Sep 17 00:00:00 2001 From: crivella Date: Tue, 7 May 2024 17:16:31 +0200 Subject: [PATCH 090/134] Added GPU compilation --- easybuild/easyblocks/m/metalwalls.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py index 2288092b00..2bbdef5f10 100644 --- a/easybuild/easyblocks/m/metalwalls.py +++ b/easybuild/easyblocks/m/metalwalls.py @@ -65,6 +65,12 @@ def configure_step(self): elif comp_fam == toolchain.GCC: jflag = '-J' fppflags = ['-cpp'] + elif comp_fam == toolchain.NVHPC: + if self.toolchain.options.get('usempi', False): + raise EasyBuildError('NVHPC compilation does not support MPI') + jflag = '-module ' # Space is needed + fppflags = ['-DMW_SERIAL', '-Mpreprocess'] + f90flags += ['-Minline', '-acc', '-gpu=managed'] else: raise EasyBuildError('Unsupported compiler family: %s' % comp_fam) From b72bfdc077b8f9e1588fb8ae4aaf144e03ef6ad4 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Tue, 7 May 2024 22:20:11 +0200 Subject: [PATCH 091/134] add libjpeg-turbo to include dir for torchvision easyblock --- easybuild/easyblocks/t/torchvision.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index 928574e50a..64577506c4 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -31,7 +31,7 @@ from easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option -from easybuild.tools.modules import get_software_version +from easybuild.tools.modules import get_software_version, get_software_root import easybuild.tools.environment as env @@ -78,6 +78,11 @@ def configure_step(self): if cuda_cc: env.setvar('TORCH_CUDA_ARCH_LIST', ';'.join(cuda_cc)) + libjpeg = get_software_root('libjpeg-turbo') + if libjpeg and 'TORCHVISION_INCLUDE' not in self.cfg['preinstallopts']: + vision_include = 'TORCHVISION_INCLUDE="$EBROOTLIBJPEGMINTURBO/include:$TORCHVISION_INCLUDE"' + self.cfg.update('preinstallopts', vision_include) + super(EB_torchvision, self).configure_step() def sanity_check_step(self): From 88b5dc4be87bf92da249e12cf3e04f79ab2c7ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Tue, 7 May 2024 23:14:39 +0200 Subject: [PATCH 092/134] add riscv64 support --- easybuild/easyblocks/j/java.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/j/java.py b/easybuild/easyblocks/j/java.py index bca89cc6b2..5731a193bb 100644 --- a/easybuild/easyblocks/j/java.py +++ b/easybuild/easyblocks/j/java.py @@ -38,7 +38,7 @@ from easybuild.tools.config import build_option from easybuild.tools.filetools import adjust_permissions, change_dir, copy_dir, copy_file, remove_dir, which from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import AARCH64, POWER, X86_64, get_cpu_architecture, get_shared_lib_ext +from easybuild.tools.systemtools import AARCH64, POWER, RISCV64, X86_64, get_cpu_architecture, get_shared_lib_ext from easybuild.tools.utilities import nub @@ -54,6 +54,8 @@ def __init__(self, *args, **kwargs): jdkarch = 'aarch64' elif myarch == POWER: jdkarch = 'ppc64le' + elif myarch == RISCV64: + jdkarch = 'riscv64' elif myarch == X86_64: jdkarch = 'x64' else: From 7fdc69564c538d2fe9134895be504c9a94763d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Tue, 7 May 2024 23:29:41 +0200 Subject: [PATCH 093/134] add RISC-V support --- easybuild/easyblocks/m/mesa.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/m/mesa.py b/easybuild/easyblocks/m/mesa.py index 4a73625185..e482ac9c13 100644 --- a/easybuild/easyblocks/m/mesa.py +++ b/easybuild/easyblocks/m/mesa.py @@ -35,7 +35,7 @@ from easybuild.easyblocks.generic.mesonninja import MesonNinja from easybuild.tools.filetools import copy_dir -from easybuild.tools.systemtools import POWER, X86_64, AARCH64 +from easybuild.tools.systemtools import POWER, X86_64, AARCH64, RISCV64 from easybuild.tools.systemtools import get_cpu_architecture, get_cpu_features, get_shared_lib_ext @@ -69,6 +69,7 @@ def __init__(self, *args, **kwargs): X86_64: ['swrast'], POWER: ['swrast'], AARCH64: ['swrast'], + RISCV64: ['swrast'], } if LooseVersion(self.version) < LooseVersion('22'): # swr driver support removed in Mesa 22.0 From 3e29db25ff6c8fb93804fb4eeb6cc1ce81790ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Tue, 7 May 2024 23:34:43 +0200 Subject: [PATCH 094/134] add RISC-V support --- easybuild/easyblocks/c/clang.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/c/clang.py b/easybuild/easyblocks/c/clang.py index b945553969..af9c105910 100644 --- a/easybuild/easyblocks/c/clang.py +++ b/easybuild/easyblocks/c/clang.py @@ -49,13 +49,13 @@ from easybuild.tools.filetools import apply_regex_substitutions, change_dir, mkdir, symlink, which from easybuild.tools.modules import get_software_root from easybuild.tools.run import run_cmd -from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, X86_64 +from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, RISCV64, X86_64 from easybuild.tools.systemtools import get_cpu_architecture, get_os_name, get_os_version, get_shared_lib_ext from easybuild.tools.environment import setvar # List of all possible build targets for Clang CLANG_TARGETS = ["all", "AArch64", "AMDGPU", "ARM", "CppBackend", "Hexagon", "Mips", - "MBlaze", "MSP430", "NVPTX", "PowerPC", "R600", "Sparc", + "MBlaze", "MSP430", "NVPTX", "PowerPC", "R600", "RISCV", "Sparc", "SystemZ", "X86", "XCore"] # Mapping of EasyBuild CPU architecture names to list of default LLVM target names @@ -63,6 +63,7 @@ AARCH32: ['ARM'], AARCH64: ['AArch64'], POWER: ['PowerPC'], + RISCV64: ['RISCV'], X86_64: ['X86'], } From 671331c1c787f041c6284d8bd9dcb33f6f54d03b Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Wed, 8 May 2024 11:45:31 +0200 Subject: [PATCH 095/134] use envvar and add sanity check --- easybuild/easyblocks/t/torchvision.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index 64577506c4..3106d3b8d9 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -28,6 +28,8 @@ @author: Alexander Grund (TU Dresden) @author: Kenneth Hoste (HPC-UGent) """ +import os + from easybuild.easyblocks.generic.pythonpackage import PythonPackage, det_pylibdir from easybuild.tools.build_log import EasyBuildError from easybuild.tools.config import build_option @@ -80,21 +82,21 @@ def configure_step(self): libjpeg = get_software_root('libjpeg-turbo') if libjpeg and 'TORCHVISION_INCLUDE' not in self.cfg['preinstallopts']: - vision_include = 'TORCHVISION_INCLUDE="$EBROOTLIBJPEGMINTURBO/include:$TORCHVISION_INCLUDE"' - self.cfg.update('preinstallopts', vision_include) + # vision_include = 'TORCHVISION_INCLUDE="$EBROOTLIBJPEGMINTURBO/include:$TORCHVISION_INCLUDE"' + # self.cfg.update('preinstallopts', vision_include) + env.setvar('TORCHVISION_INCLUDE', os.path.join(os.getenv('EBROOTLIBJPEGMINTURBO'), 'include')) super(EB_torchvision, self).configure_step() def sanity_check_step(self): """Custom sanity check for torchvision.""" - custom_commands = None + custom_commands = [] custom_paths = None # check whether torchvision was indeed built with CUDA support, # cfr. https://discuss.pytorch.org/t/notimplementederror-could-not-run-torchvision-nms-with-arguments-from-\ # the-cuda-backend-this-could-be-because-the-operator-doesnt-exist-for-this-backend/132352/4 if self.with_cuda: - custom_commands = [] python_code = '\n'.join([ "import torch, torchvision", "if torch.cuda.device_count():", @@ -108,4 +110,14 @@ def sanity_check_step(self): 'dirs': [det_pylibdir()], } + if get_software_root('libjpeg-turbo'): + # check wither torchvision was built with libjpeg support + # if not, will show error "RuntimeError: encode_jpeg: torchvision not compiled with libjpeg support" + python_code = '\n'.join([ + "import torch, torchvision", + "image_tensor = torch.zeros(1, 1, 1, dtype=torch.uint8)", + "print(torchvision.io.image.encode_jpeg(image_tensor))", + ]) + custom_commands.append('python -c "%s"' % python_code) + return super(EB_torchvision, self).sanity_check_step(custom_commands=custom_commands, custom_paths=custom_paths) From 89331871d68656c5dfc52fb8a1493a1890640200 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Wed, 8 May 2024 11:47:24 +0200 Subject: [PATCH 096/134] remove comments --- easybuild/easyblocks/t/torchvision.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index 3106d3b8d9..4c5b2f961d 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -82,8 +82,6 @@ def configure_step(self): libjpeg = get_software_root('libjpeg-turbo') if libjpeg and 'TORCHVISION_INCLUDE' not in self.cfg['preinstallopts']: - # vision_include = 'TORCHVISION_INCLUDE="$EBROOTLIBJPEGMINTURBO/include:$TORCHVISION_INCLUDE"' - # self.cfg.update('preinstallopts', vision_include) env.setvar('TORCHVISION_INCLUDE', os.path.join(os.getenv('EBROOTLIBJPEGMINTURBO'), 'include')) super(EB_torchvision, self).configure_step() From 903e59c128d7b5071783f6f520d0d0be32c57931 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Wed, 8 May 2024 17:36:11 +0200 Subject: [PATCH 097/134] use libjpeg_root --- easybuild/easyblocks/t/torchvision.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index 4c5b2f961d..18b08d25dc 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -80,9 +80,9 @@ def configure_step(self): if cuda_cc: env.setvar('TORCH_CUDA_ARCH_LIST', ';'.join(cuda_cc)) - libjpeg = get_software_root('libjpeg-turbo') - if libjpeg and 'TORCHVISION_INCLUDE' not in self.cfg['preinstallopts']: - env.setvar('TORCHVISION_INCLUDE', os.path.join(os.getenv('EBROOTLIBJPEGMINTURBO'), 'include')) + libjpeg_root = get_software_root('libjpeg-turbo') + if libjpeg_root and 'TORCHVISION_INCLUDE' not in self.cfg['preinstallopts']: + env.setvar('TORCHVISION_INCLUDE', os.path.join(libjpeg_root, 'include')) super(EB_torchvision, self).configure_step() @@ -109,7 +109,7 @@ def sanity_check_step(self): } if get_software_root('libjpeg-turbo'): - # check wither torchvision was built with libjpeg support + # check if torchvision was built with libjpeg support # if not, will show error "RuntimeError: encode_jpeg: torchvision not compiled with libjpeg support" python_code = '\n'.join([ "import torch, torchvision", From 0445cde9c6b72238e204045acd3eb81d8adcbb50 Mon Sep 17 00:00:00 2001 From: Simon Branford <4967+branfosj@users.noreply.github.com> Date: Fri, 10 May 2024 18:26:24 +0100 Subject: [PATCH 098/134] do not run unit tests on Python 3.5 --- .github/workflows/unit_tests.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index b1cf6dc64a..69165889aa 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - python: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11'] + python: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11'] modules_tool: [Lmod-6.6.3, Lmod-7.8.22, Lmod-8.1.14, modules-tcl-1.147, modules-3.2.10, modules-4.1.4] module_syntax: [Lua, Tcl] # exclude some configuration for non-Lmod modules tool: # - don't test with Lua module syntax (only supported in Lmod) - # - don't test with Python 3.5 and 3.7+ (only with 3.6), to limit test configurations + # - don't test with Python 3.7+ (only with 3.6), to limit test configurations exclude: - modules_tool: modules-tcl-1.147 module_syntax: Lua @@ -26,8 +26,6 @@ jobs: module_syntax: Lua - modules_tool: modules-4.1.4 module_syntax: Lua - - modules_tool: modules-tcl-1.147 - python: 3.5 - modules_tool: modules-tcl-1.147 python: 3.7 - modules_tool: modules-tcl-1.147 @@ -37,9 +35,6 @@ jobs: - modules_tool: modules-tcl-1.147 python: '3.10' - modules_tool: modules-tcl-1.147 - python: '3.11' - - modules_tool: modules-3.2.10 - python: 3.5 - modules_tool: modules-3.2.10 python: 3.7 - modules_tool: modules-3.2.10 @@ -50,8 +45,6 @@ jobs: python: '3.10' - modules_tool: modules-3.2.10 python: '3.11' - - modules_tool: modules-4.1.4 - python: 3.5 - modules_tool: modules-4.1.4 python: 3.7 - modules_tool: modules-4.1.4 From 7f3bc6f933dad3896ac348fdc2fdc54211f37b3c Mon Sep 17 00:00:00 2001 From: Simon Branford <4967+branfosj@users.noreply.github.com> Date: Fri, 10 May 2024 18:44:22 +0100 Subject: [PATCH 099/134] restore accidentally deleted line --- .github/workflows/unit_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 69165889aa..3cd95ff88d 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -35,6 +35,7 @@ jobs: - modules_tool: modules-tcl-1.147 python: '3.10' - modules_tool: modules-tcl-1.147 + python: '3.11' - modules_tool: modules-3.2.10 python: 3.7 - modules_tool: modules-3.2.10 From eae3bdd861de7491490d3d3c01145111c65c9a0d Mon Sep 17 00:00:00 2001 From: Alan O'Cais Date: Mon, 13 May 2024 15:24:15 +0200 Subject: [PATCH 100/134] Add a sanity check for OpenFOAM's to make sure it finds the compiler commands --- easybuild/easyblocks/o/openfoam.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/easybuild/easyblocks/o/openfoam.py b/easybuild/easyblocks/o/openfoam.py index db69ddc569..2cd60f364c 100644 --- a/easybuild/easyblocks/o/openfoam.py +++ b/easybuild/easyblocks/o/openfoam.py @@ -486,6 +486,11 @@ def sanity_check_step(self): test_foammonitor = "! foamMonitor -h 2>&1 | grep 'not installed'" custom_commands.append(' && '.join([load_openfoam_env, test_foammonitor])) + if self.is_dot_com and self.looseversion >= LooseVersion("2012"): + # Make sure that wmake can see the compilers + test_wmake_compilers = ["command -V $(wmake -show-cxx)", "command -V $(wmake -show-c)"] + custom_commands.append(' && '.join([load_openfoam_env] + test_wmake_compilers)) + custom_paths = { 'files': [os.path.join(self.openfoamdir, 'etc', x) for x in ["bashrc", "cshrc"]] + bins + libs, 'dirs': dirs, From 3cbe88540cff4ecd8b21995ee9952d56a771eb5a Mon Sep 17 00:00:00 2001 From: Alan O'Cais Date: Tue, 14 May 2024 14:59:28 +0200 Subject: [PATCH 101/134] Always override the compiler version check for CUDA installations --- easybuild/easyblocks/c/cuda.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/easybuild/easyblocks/c/cuda.py b/easybuild/easyblocks/c/cuda.py index 46b3c58854..e024bf2c32 100644 --- a/easybuild/easyblocks/c/cuda.py +++ b/easybuild/easyblocks/c/cuda.py @@ -156,6 +156,15 @@ def install_step(self): # Use C locale to avoid localized questions and crash on CUDA 10.1 self.cfg.update('preinstallopts', "export LANG=C && ") + # As a CUDA recipe gets older and the OS gets updated, it is + # likely that the system GCC becomes too new for the CUDA version. + # Since in EasyBuild we know/expect that CUDA will only ever get used + # as a dependency within the context of a toolchain, we can override + # the compiler version check that would cause the installation to + # fail. + self.cfg.update('installopts', "--override") + + cmd = "%(preinstallopts)s %(interpreter)s %(script)s %(installopts)s" % { 'preinstallopts': self.cfg['preinstallopts'], 'interpreter': install_interpreter, From cd416f0453b063897f7f17359997073903d6c8a6 Mon Sep 17 00:00:00 2001 From: Alan O'Cais Date: Tue, 14 May 2024 15:03:44 +0200 Subject: [PATCH 102/134] Lint --- easybuild/easyblocks/c/cuda.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easybuild/easyblocks/c/cuda.py b/easybuild/easyblocks/c/cuda.py index e024bf2c32..10d6bc3083 100644 --- a/easybuild/easyblocks/c/cuda.py +++ b/easybuild/easyblocks/c/cuda.py @@ -164,7 +164,6 @@ def install_step(self): # fail. self.cfg.update('installopts', "--override") - cmd = "%(preinstallopts)s %(interpreter)s %(script)s %(installopts)s" % { 'preinstallopts': self.cfg['preinstallopts'], 'interpreter': install_interpreter, From b131ada63c3affd7b7dc4015d8eac255dba01602 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 15 May 2024 15:33:38 +0200 Subject: [PATCH 103/134] Fix for plumed genereting patch file inside module location --- easybuild/easyblocks/m/metalwalls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py index 2bbdef5f10..ce22c36187 100644 --- a/easybuild/easyblocks/m/metalwalls.py +++ b/easybuild/easyblocks/m/metalwalls.py @@ -82,9 +82,9 @@ def configure_step(self): if plumed: f90flags += ['-fallow-argument-mismatch'] # Code inside ifdef causes mismatch errors fppflags += ['-DMW_USE_PLUMED'] - cmd = ['plumed', 'patch', '--new', 'mw2'] + cmd = ['touch', 'mw2.diff'] run_cmd(' '.join(cmd), log_all=False, log_ok=False, simple=False, regexp=False) - cmd = ['plumed', 'patch', '--patch', '--shared', '--engine', 'mw2'] + cmd = ['plumed', 'patch', '-d mw2.diff', '--patch', '--shared', '--engine', 'mw2'] run_cmd(' '.join(cmd), log_all=True, simple=False) else: self.log.info('PLUMED not found, excluding from test-suite') From 39195f93c94731cf07959945c5d97c895062fffb Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 15 May 2024 15:44:22 +0200 Subject: [PATCH 104/134] Added compatibility check with f90wraps --- easybuild/easyblocks/m/metalwalls.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/m/metalwalls.py b/easybuild/easyblocks/m/metalwalls.py index ce22c36187..1241249a7a 100644 --- a/easybuild/easyblocks/m/metalwalls.py +++ b/easybuild/easyblocks/m/metalwalls.py @@ -31,8 +31,9 @@ import easybuild.tools.environment as env import easybuild.tools.toolchain as toolchain +from easybuild.tools import LooseVersion from easybuild.tools.build_log import EasyBuildError -from easybuild.tools.modules import get_software_root +from easybuild.tools.modules import get_software_root, get_software_version from easybuild.tools.run import run_cmd from easybuild.easyblocks.generic.makecp import MakeCp @@ -77,6 +78,11 @@ def configure_step(self): # https://gitlab.com/ampere2/metalwalls/-/wikis/install#plumed plumed = get_software_root('PLUMED') f90wrap = get_software_root('f90wrap') + f90wrap_version = get_software_version('f90wrap') + + if LooseVersion(self.version) <= LooseVersion('21.06.1'): + if LooseVersion(f90wrap_version) > LooseVersion('0.2.13'): + raise EasyBuildError('MetalWalls version %s requires f90wrap <= 0.2.13' % self.version) tpl_rgx = 'alltests\\.append(suite_%s)' if plumed: From e07ac51615c39cf70aead1053fd9de9680ff390f Mon Sep 17 00:00:00 2001 From: Sebastian Achilles Date: Fri, 24 May 2024 17:12:36 +0200 Subject: [PATCH 105/134] adjust OpenSSL version regex and OpenSSL header version check in OpenSSL wrapper easyblock --- easybuild/easyblocks/o/openssl_wrapper.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 247a018d62..53cb27aa2c 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -101,7 +101,7 @@ def __init__(self, *args, **kwargs): # Regex pattern to find version strings in OpenSSL libraries and headers full_version_regex = re.compile(r'[0-9]+\.[0-9]+\.[0-9]+[a-z]?') - openssl_version_regex = re.compile(r'OpenSSL\s+([0-9]+\.[0-9]+(\.[0-9]+[a-z]?)*)', re.M) + openssl_version_regex = re.compile(r'(?i)OpenSSL[\s_]+([0-9]+\.[0-9]+(\.[0-9]+[a-z]?)*)', re.M) # Libraries packaged in OpenSSL openssl_libs = ['libssl', 'libcrypto'] @@ -259,13 +259,23 @@ def __init__(self, *args, **kwargs): err_msg = "System OpenSSL header '%s' does not contain any recognizable version string" raise EasyBuildError(err_msg, opensslv_path) - if header_version == self.system_ssl['version']: + header_version_major = header_version.split('.')[0] + system_ssl_version_major = self.system_ssl['version'].split('.')[0] + + # Compare only major version of header for OpenSSL 3+ + # This is needed on Debian-based distros + if LooseVersion(self.version) >= LooseVersion('3'): + header_found = (header_version_major == system_ssl_version_major) + else: + header_found = (header_version == self.system_ssl['version']) + + if header_found: self.system_ssl['include'] = include_dir info_msg = "Found OpenSSL headers v%s in host system: %s" self.log.info(info_msg, header_version, self.system_ssl['include']) break else: - dbg_msg = "System OpenSSL header version '%s' doesn not match library version '%s'" + dbg_msg = "System OpenSSL header version '%s' does not match library version '%s'" self.log.debug(dbg_msg, header_version, self.system_ssl['version']) else: self.log.info("System OpenSSL header file %s not found", opensslv_path) From 67bb99069cb26f128c939076df7a3125a9deed71 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Fri, 24 May 2024 20:05:17 +0200 Subject: [PATCH 106/134] avoid sanity check on the software itself for CargoPythonBundle easyblock --- easybuild/easyblocks/generic/cargopythonbundle.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/easybuild/easyblocks/generic/cargopythonbundle.py b/easybuild/easyblocks/generic/cargopythonbundle.py index 090a38dff4..117004dc2b 100644 --- a/easybuild/easyblocks/generic/cargopythonbundle.py +++ b/easybuild/easyblocks/generic/cargopythonbundle.py @@ -53,6 +53,14 @@ def __init__(self, *args, **kwargs): self.check_for_sources = False # make Bundle allow sources (as crates are treated as sources) super(CargoPythonBundle, self).__init__(*args, **kwargs) + # Cargo inherits from ExtensionEasyBlock, thus EB treats the software itself as an extension + # Setting modulename to False to ensure that sanity checks are performed on the extensions only + self.options = {'modulename': False} + def extract_step(self): """Specifically use the overloaded variant from Cargo as is populates vendored sources with checksums.""" return Cargo.extract_step(self) + + # def sanity_check_step(self, *args, **kwargs): + # self.cfg['sources'] = None + # super(CargoPythonBundle, self).sanity_check_step(*args, **kwargs) From fa440b18992685e1e9fa9e9f333273c05f4d7065 Mon Sep 17 00:00:00 2001 From: Samuel Moors Date: Fri, 24 May 2024 20:15:35 +0200 Subject: [PATCH 107/134] remove old comments --- easybuild/easyblocks/generic/cargopythonbundle.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/easybuild/easyblocks/generic/cargopythonbundle.py b/easybuild/easyblocks/generic/cargopythonbundle.py index 117004dc2b..d76ccde612 100644 --- a/easybuild/easyblocks/generic/cargopythonbundle.py +++ b/easybuild/easyblocks/generic/cargopythonbundle.py @@ -60,7 +60,3 @@ def __init__(self, *args, **kwargs): def extract_step(self): """Specifically use the overloaded variant from Cargo as is populates vendored sources with checksums.""" return Cargo.extract_step(self) - - # def sanity_check_step(self, *args, **kwargs): - # self.cfg['sources'] = None - # super(CargoPythonBundle, self).sanity_check_step(*args, **kwargs) From e67ce87b8b13dd74fcaa423832bbf98450753976 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 00:08:37 +0200 Subject: [PATCH 108/134] add non-standard include path used by RHEL-based systems to install OpenSSL v3 headers alongside OpenSSL v1.1 --- easybuild/easyblocks/o/openssl_wrapper.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 53cb27aa2c..85f3a343b3 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -242,6 +242,10 @@ def __init__(self, *args, **kwargs): # but version 1.1 can be installed in 'include/openssl11/openssl' as well, for example in CentOS 7 # prefer 'include/openssl' as long as the version of headers matches ssl_include_subdirs.append(os.path.join('openssl11', self.name.lower())) + elif LooseVersion(self.version) >= LooseVersion('3'): + # but version 3.x can be installed in 'include/openssl3/openssl' as well, for example in RHEL 8 derivatives + # prefer 'include/openssl' as long as the version of headers matches + ssl_include_subdirs.append(os.path.join('openssl3', self.name.lower())) ssl_include_dirs = [os.path.join(incd, subd) for incd in sys_include_dirs for subd in ssl_include_subdirs] ssl_include_dirs = [include for include in ssl_include_dirs if os.path.isdir(include)] From a8fffcb6bf02220252248ee36f2e5e04d8ead544 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 02:23:01 +0200 Subject: [PATCH 109/134] add non-standard binary name used by RHEL-based systems that install OpenSSL v3 alongside OpenSSL v1.1 --- easybuild/easyblocks/o/openssl_wrapper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 85f3a343b3..eed4ec76cf 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -294,6 +294,9 @@ def __init__(self, *args, **kwargs): if self.majmin_version == '1.1': # prefer 'openssl11' over 'openssl' with v1.1 self.system_ssl['bin'] = which('openssl11') + elif LooseVersion(self.version) >= LooseVersion('3'): + # prefer 'openssl3' over 'openssl' with v3.x + self.system_ssl['bin'] = which('openssl3') if not self.system_ssl['bin']: self.system_ssl['bin'] = which('openssl') From bf408fad7736fc349739501496011f5bff193005 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 01:38:39 +0200 Subject: [PATCH 110/134] consider all versions found from strings in OpenSSL libraries and pick the highest one --- easybuild/easyblocks/o/openssl_wrapper.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index eed4ec76cf..8416f16ca4 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -180,8 +180,14 @@ def __init__(self, *args, **kwargs): # filename lacks the full version, fallback to version strings within the library solib_strings = read_file(system_solib, mode="rb").decode('utf-8', 'replace') try: - openssl_version = openssl_version_regex.search(solib_strings).group(1) - except AttributeError: + openssl_support_versions = openssl_version_regex.findall(solib_strings) + openssl_support_versions.sort() + dbg_msg = "System OpenSSL library '%s' supports versions: %s" + dbg_msg_support_versions = ', '.join([''.join(v) for v in openssl_support_versions]) + self.log.debug(dbg_msg, system_solib, dbg_msg_support_versions) + # pick highest supported version + openssl_version = openssl_support_versions[-1][0] + except IndexError: dbg_msg = "Could not detect the full version of system OpenSSL library: %s" self.log.debug(dbg_msg, system_solib) # check that system version fulfills requirements From a0d42f342d89e7d697e60927b4fb990816b463db Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 02:00:10 +0200 Subject: [PATCH 111/134] simplify code checking OpenSSL system libraries --- easybuild/easyblocks/o/openssl_wrapper.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 8416f16ca4..2438a79e04 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -168,11 +168,13 @@ def __init__(self, *args, **kwargs): # Check the system libraries of OpenSSL # Find library file and compare its version string + target_system_ssl = {} for idx, solibs in enumerate(system_versioned_libs): + target_system_ssl['version'] = '0' + target_system_ssl['libs'] = [] for solib in solibs: system_solib = find_library_path(solib) if system_solib: - openssl_version = '0' # get version of system library filename try: openssl_version = full_version_regex.search(os.path.realpath(system_solib)).group(0) @@ -194,22 +196,21 @@ def __init__(self, *args, **kwargs): if LooseVersion(openssl_version) >= LooseVersion(min_openssl_version): dbg_msg = "System OpenSSL library '%s' with version %s fulfills requested version %s" self.log.debug(dbg_msg, system_solib, openssl_version, min_openssl_version) - self.system_ssl['libs'].append(system_solib) + target_system_ssl['version'] = openssl_version + target_system_ssl['libs'].append(system_solib) else: dbg_msg = "System OpenSSL library '%s' with version %s is older than requested version %s" self.log.debug(dbg_msg, system_solib, openssl_version, min_openssl_version) else: # one of the OpenSSL libraries is missing, switch to next group of versioned libs - self.system_ssl['libs'] = [] break - if len(self.system_ssl['libs']) == len(openssl_libs): - # keep these libraries as possible targets for this installation - target_system_ssl_libs = system_versioned_libs[idx] + if len(target_system_ssl['libs']) == len(openssl_libs): + # target libraries found, ignore further options break - if len(self.system_ssl['libs']) == len(openssl_libs): - self.system_ssl['version'] = openssl_version + if len(target_system_ssl['libs']) == len(openssl_libs): + self.system_ssl.update(target_system_ssl) info_msg = "Found OpenSSL library version %s in host system: %s" self.log.info(info_msg, self.system_ssl['version'], os.path.dirname(self.system_ssl['libs'][0])) else: @@ -314,7 +315,7 @@ def __init__(self, *args, **kwargs): return # system OpenSSL is fine, change target libraries to the ones found in it - self.target_ssl_libs = target_system_ssl_libs + self.target_ssl_libs = [os.path.basename(solib) for solib in target_system_ssl["libs"]] self.log.info("Target system OpenSSL libraries: %s", self.target_ssl_libs) def fetch_step(self, *args, **kwargs): From c24b4f704ccaf3a16cce0788f89c1dc40383da8d Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 02:21:14 +0200 Subject: [PATCH 112/134] replace case insensitive pattern with corresponding flag in re.compile --- easybuild/easyblocks/o/openssl_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 2438a79e04..80d6bb6cd6 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -101,7 +101,7 @@ def __init__(self, *args, **kwargs): # Regex pattern to find version strings in OpenSSL libraries and headers full_version_regex = re.compile(r'[0-9]+\.[0-9]+\.[0-9]+[a-z]?') - openssl_version_regex = re.compile(r'(?i)OpenSSL[\s_]+([0-9]+\.[0-9]+(\.[0-9]+[a-z]?)*)', re.M) + openssl_version_regex = re.compile(r'OpenSSL[\s_]+([0-9]+\.[0-9]+(\.[0-9]+[a-z]?)*)', re.M | re.I) # Libraries packaged in OpenSSL openssl_libs = ['libssl', 'libcrypto'] From 40120e6c230bec7ed609cd9485b5486126b528ae Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 28 May 2024 02:28:06 +0200 Subject: [PATCH 113/134] system OpenSSL header version only needs to be higher than required minimum version in wrapper easyconfig --- easybuild/easyblocks/o/openssl_wrapper.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 80d6bb6cd6..ceddbfe430 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -270,17 +270,7 @@ def __init__(self, *args, **kwargs): err_msg = "System OpenSSL header '%s' does not contain any recognizable version string" raise EasyBuildError(err_msg, opensslv_path) - header_version_major = header_version.split('.')[0] - system_ssl_version_major = self.system_ssl['version'].split('.')[0] - - # Compare only major version of header for OpenSSL 3+ - # This is needed on Debian-based distros - if LooseVersion(self.version) >= LooseVersion('3'): - header_found = (header_version_major == system_ssl_version_major) - else: - header_found = (header_version == self.system_ssl['version']) - - if header_found: + if LooseVersion(header_version) >= LooseVersion(min_openssl_version): self.system_ssl['include'] = include_dir info_msg = "Found OpenSSL headers v%s in host system: %s" self.log.info(info_msg, header_version, self.system_ssl['include']) From c5b86271aff049e5336be2d0046d234ef781dfd3 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 10:16:01 +0200 Subject: [PATCH 114/134] remove unused idx variable from OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index ceddbfe430..c213bea616 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -169,7 +169,7 @@ def __init__(self, *args, **kwargs): # Check the system libraries of OpenSSL # Find library file and compare its version string target_system_ssl = {} - for idx, solibs in enumerate(system_versioned_libs): + for solibs in system_versioned_libs: target_system_ssl['version'] = '0' target_system_ssl['libs'] = [] for solib in solibs: From b8c29bd13161d37bf7c032785a59c2dcfe75e8fa Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 10:17:54 +0200 Subject: [PATCH 115/134] hide pkg-config commands from trace output in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index c213bea616..67ad2dede6 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -464,7 +464,7 @@ def install_pc_files(self): # check suffixed names with v1.1 pc_name_suffix = pc_name + '11' pc_exists_cmd = "pkg-config --exists %s" % pc_name_suffix - if run_cmd(pc_exists_cmd, simple=True, log_ok=False, log_all=False): + if run_cmd(pc_exists_cmd, simple=True, log_ok=False, log_all=False, trace=False): self.log.info("%s exists", pc_name_suffix) pc_name = pc_name_suffix @@ -473,7 +473,7 @@ def install_pc_files(self): for require_type in ['Requires', 'Requires.private']: require_print = require_type.lower().replace('.', '-') pc_print_cmd = "pkg-config --print-%s %s" % (require_print, pc_name) - out, _ = run_cmd(pc_print_cmd, simple=False, log_ok=False) + out, _ = run_cmd(pc_print_cmd, simple=False, log_ok=False, trace=False) self.log.info("Output of '%s': %s", pc_print_cmd, out) if out: @@ -494,12 +494,12 @@ def install_pc_files(self): pc_file['cflags'] = "Cflags: -I${includedir}" # infer private libs through pkg-config pc_libs_cmd = "pkg-config --libs %s" % pc_name - out, _ = run_cmd(pc_libs_cmd, simple=False, log_ok=False) + out, _ = run_cmd(pc_libs_cmd, simple=False, log_ok=False, trace=False) self.log.info("Output of '%s': %s", pc_libs_cmd, out) linker_libs = out pc_libs_static_cmd = "pkg-config --libs --static %s" % pc_name - out, _ = run_cmd(pc_libs_static_cmd, simple=False, log_ok=False) + out, _ = run_cmd(pc_libs_static_cmd, simple=False, log_ok=False, trace=False) self.log.info("Output of '%s': %s", pc_libs_static_cmd, out) libs_priv = "%s " % out.rstrip() From 4073a3145b66fcf91c5f65f880798ef8f33343d2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 10:55:23 +0200 Subject: [PATCH 116/134] replace majmin_version with generation attribute in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 34 ++++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 67ad2dede6..8a15528f2a 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -73,16 +73,15 @@ def __init__(self, *args, **kwargs): """Locate the installation files of OpenSSL in the host system""" super(EB_OpenSSL_wrapper, self).__init__(*args, **kwargs) - # Wrapper should have at least a major minor version numbers for OpenSSL before version 3+ - if LooseVersion(self.version) >= LooseVersion('3') and self.version.count('.') == 0: - self.majmin_version = self.version - else: + if LooseVersion(self.version) < LooseVersion('2'): try: subversions = self.version.split('.') - self.majmin_version = '%s.%s' % (subversions[0], subversions[1]) + self.generation = '%s.%s' % (subversions[0], subversions[1]) except (AttributeError, IndexError): - err_msg = "Wrapper OpenSSL version does not have any subversion: %s" + err_msg = "Wrapper for OpenSSL v1 version is missing a minor version: %s" raise EasyBuildError(err_msg, self.version) + elif LooseVersion(self.version) < LooseVersion('4'): + self.generation = "3" # Set minimum OpenSSL version min_openssl_version = self.cfg.get('minimum_openssl_version') @@ -117,10 +116,6 @@ def __init__(self, *args, **kwargs): LINUX: ('so.1.1', ), DARWIN: ('1.1.dylib', ), }, - '3.0': { - LINUX: ('so.3', ), - DARWIN: ('3.dylib', ), - }, '3': { LINUX: ('so.3', ), DARWIN: ('3.dylib', ), @@ -128,16 +123,16 @@ def __init__(self, *args, **kwargs): } os_type = get_os_type() - if self.majmin_version in openssl_libext and os_type in openssl_libext[self.majmin_version]: + if self.generation in openssl_libext and os_type in openssl_libext[self.generation]: # generate matrix of versioned .so filenames system_versioned_libs = [ ['%s.%s' % (lib, ext) for lib in openssl_libs] - for ext in openssl_libext[self.majmin_version][os_type] + for ext in openssl_libext[self.generation][os_type] ] self.log.info("Matrix of version library names: %s", system_versioned_libs) else: - err_msg = "Don't know name of OpenSSL system library for version %s and OS type %s" - raise EasyBuildError(err_msg, self.majmin_version, os_type) + err_msg = "OpenSSL system library for version %s and OS type %s is unsupported" + raise EasyBuildError(err_msg, self.generation, os_type) # by default target the first option of each OpenSSL library, # which corresponds to installation from source @@ -148,10 +143,9 @@ def __init__(self, *args, **kwargs): openssl_engines = { '1.0': 'engines', '1.1': 'engines-1.1', - '3.0': 'engines-3', '3': 'engines-3', } - self.target_ssl_engine = openssl_engines[self.majmin_version] + self.target_ssl_engine = openssl_engines[self.generation] # Paths to system libraries and headers of OpenSSL self.system_ssl = { @@ -245,11 +239,11 @@ def __init__(self, *args, **kwargs): # headers are located in 'include/openssl' by default ssl_include_subdirs = ['openssl'] - if self.majmin_version == '1.1': + if self.generation == '1.1': # but version 1.1 can be installed in 'include/openssl11/openssl' as well, for example in CentOS 7 # prefer 'include/openssl' as long as the version of headers matches ssl_include_subdirs.append(os.path.join('openssl11', self.name.lower())) - elif LooseVersion(self.version) >= LooseVersion('3'): + elif self.generation == '3': # but version 3.x can be installed in 'include/openssl3/openssl' as well, for example in RHEL 8 derivatives # prefer 'include/openssl' as long as the version of headers matches ssl_include_subdirs.append(os.path.join('openssl3', self.name.lower())) @@ -408,7 +402,7 @@ def sanity_check_step(self): custom_commands = [ # make sure that version mentioned in output of 'openssl version' matches version we are using - "ssl_ver=$(openssl version); [ ${ssl_ver:8:%s} == '%s' ]" % (ssl_ver_comp_chars, self.majmin_version), + "ssl_ver=$(openssl version); [ ${ssl_ver:8:%s} == '%s' ]" % (ssl_ver_comp_chars, self.generation), ("echo | openssl s_client%s -connect github.com:443 -verify 9 " "| grep 'Verify return code: 0 (ok)'" % proxy_arg), ] @@ -460,7 +454,7 @@ def install_pc_files(self): # component name in system pkg-config pc_name = pc_comp - if self.majmin_version == '1.1': + if self.generation == '1.1': # check suffixed names with v1.1 pc_name_suffix = pc_name + '11' pc_exists_cmd = "pkg-config --exists %s" % pc_name_suffix From 2d73932cc0117afb7613541d6ba88959b248736c Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 10:59:14 +0200 Subject: [PATCH 117/134] fix error message on failed header version check in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 8a15528f2a..ee97a3040b 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -270,8 +270,8 @@ def __init__(self, *args, **kwargs): self.log.info(info_msg, header_version, self.system_ssl['include']) break else: - dbg_msg = "System OpenSSL header version '%s' does not match library version '%s'" - self.log.debug(dbg_msg, header_version, self.system_ssl['version']) + dbg_msg = "System OpenSSL header version '%s' does not fulfill minimum version requirement '%s'" + self.log.debug(dbg_msg, header_version, min_openssl_version) else: self.log.info("System OpenSSL header file %s not found", opensslv_path) From 476a7da99e5ef44433e4ce738fa46a288027722b Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 11:40:48 +0200 Subject: [PATCH 118/134] check openssl executable version at detection time in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 41 +++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index ee97a3040b..26a1fdaa74 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -282,20 +282,22 @@ def __init__(self, *args, **kwargs): raise EasyBuildError(err_msg, self.version, self.system_ssl['version']) # Check system OpenSSL binary - if self.majmin_version == '1.1': - # prefer 'openssl11' over 'openssl' with v1.1 - self.system_ssl['bin'] = which('openssl11') - elif LooseVersion(self.version) >= LooseVersion('3'): - # prefer 'openssl3' over 'openssl' with v3.x - self.system_ssl['bin'] = which('openssl3') + target_ssl_bins = ['openssl'] + if self.generation == '1.1': + target_ssl_bins.insert(0, 'openssl11') # prefer 'openssl11' over 'openssl' with v1.1 + elif self.generation == '3': + target_ssl_bins.insert(0, 'openssl3') # prefer 'openssl3' over 'openssl' with v3 - if not self.system_ssl['bin']: - self.system_ssl['bin'] = which('openssl') + for target_bin in target_ssl_bins: + target_bin_path, target_bin_version = self.get_openssl_bin_version(target_bin) + if target_bin_version == self.system_ssl['version']: + self.system_ssl['bin'] = target_bin_path + break if self.system_ssl['bin']: - self.log.info("System OpenSSL binary found: %s", self.system_ssl['bin']) + self.log.info("System OpenSSL binary for version %s found: %s", self.system_ssl['version'], self.system_ssl['bin']) else: - self.log.info("System OpenSSL binary not found!") + self.log.info("System OpenSSL binary for version %s not found!", self.system_ssl['version']) return # system OpenSSL is fine, change target libraries to the ones found in it @@ -409,6 +411,25 @@ def sanity_check_step(self): super(Bundle, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) + def get_openssl_bin_version(self, bin_name): + """Check OpenSSL executable version""" + bin_path = which(bin_name) + if not bin_path: + self.log.debug("OpenSSL executable '%s' not found", bin_name) + return None, None + + cmd = "%s version" % bin_path + out, _ = run_cmd(cmd, simple=False, log_ok=False, trace=False) + + try: + bin_version = out.split(' ')[1] + except (AttributeError, IndexError): + raise EasyBuildError("Failed to check version of OpenSSL executable: %s", bin_path) + else: + self.log.debug("Version of OpenSSL executable '%s': %s", bin_path, bin_version) + + return bin_path, bin_version + def install_pc_files(self): """Install pkg-config files for the wrapper""" From f54a5fb8dab0b20c16c89aea88ca6fa92fe529fa Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 11:48:14 +0200 Subject: [PATCH 119/134] use pattern matching to sanity check version of openssl executbale in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 26a1fdaa74..1359e33857 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -397,14 +397,9 @@ def sanity_check_step(self): if proxy_parsed.netloc: proxy_arg = ' -proxy %s' % proxy_parsed.netloc - if LooseVersion(self.version) >= LooseVersion('3') and self.version.count('.') == 0: - ssl_ver_comp_chars = 1 - else: - ssl_ver_comp_chars = 3 - custom_commands = [ # make sure that version mentioned in output of 'openssl version' matches version we are using - "ssl_ver=$(openssl version); [ ${ssl_ver:8:%s} == '%s' ]" % (ssl_ver_comp_chars, self.generation), + '[[ "$(openssl version)" =~ ^OpenSSL.%s ]]' % self.generation, ("echo | openssl s_client%s -connect github.com:443 -verify 9 " "| grep 'Verify return code: 0 (ok)'" % proxy_arg), ] From bc1acde23b059f308a73685d94d8325577518d50 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 11:54:34 +0200 Subject: [PATCH 120/134] fix codestyle issues in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 1359e33857..ad33adba2e 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -81,7 +81,7 @@ def __init__(self, *args, **kwargs): err_msg = "Wrapper for OpenSSL v1 version is missing a minor version: %s" raise EasyBuildError(err_msg, self.version) elif LooseVersion(self.version) < LooseVersion('4'): - self.generation = "3" + self.generation = "3" # Set minimum OpenSSL version min_openssl_version = self.cfg.get('minimum_openssl_version') @@ -295,7 +295,8 @@ def __init__(self, *args, **kwargs): break if self.system_ssl['bin']: - self.log.info("System OpenSSL binary for version %s found: %s", self.system_ssl['version'], self.system_ssl['bin']) + log_msg = "System OpenSSL binary for version %s found: %s" + self.log.info(log_msg, self.system_ssl['version'], self.system_ssl['bin']) else: self.log.info("System OpenSSL binary for version %s not found!", self.system_ssl['version']) return From b0cbd354f0cc574eb6080037b26c100dd7562593 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 17:01:28 +0200 Subject: [PATCH 121/134] define version of OpenSSL wrapper from executable and allow mismatch between components --- easybuild/easyblocks/o/openssl_wrapper.py | 68 +++++++++++------------ 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index ad33adba2e..082fdaa09b 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -162,51 +162,48 @@ def __init__(self, *args, **kwargs): # Check the system libraries of OpenSSL # Find library file and compare its version string - target_system_ssl = {} for solibs in system_versioned_libs: - target_system_ssl['version'] = '0' - target_system_ssl['libs'] = [] + target_ssl_libs = [] for solib in solibs: system_solib = find_library_path(solib) - if system_solib: + if not system_solib: + # this OpenSSL library is missing, move on to next group of versioned libs + break + + try: # get version of system library filename + ssl_lib_version = full_version_regex.search(os.path.realpath(system_solib)).group(0) + except AttributeError: + # filename lacks the full version, fallback to version strings within the library + solib_strings = read_file(system_solib, mode="rb").decode('utf-8', 'replace') try: - openssl_version = full_version_regex.search(os.path.realpath(system_solib)).group(0) - except AttributeError: - # filename lacks the full version, fallback to version strings within the library - solib_strings = read_file(system_solib, mode="rb").decode('utf-8', 'replace') - try: - openssl_support_versions = openssl_version_regex.findall(solib_strings) - openssl_support_versions.sort() - dbg_msg = "System OpenSSL library '%s' supports versions: %s" - dbg_msg_support_versions = ', '.join([''.join(v) for v in openssl_support_versions]) - self.log.debug(dbg_msg, system_solib, dbg_msg_support_versions) - # pick highest supported version - openssl_version = openssl_support_versions[-1][0] - except IndexError: - dbg_msg = "Could not detect the full version of system OpenSSL library: %s" - self.log.debug(dbg_msg, system_solib) - # check that system version fulfills requirements - if LooseVersion(openssl_version) >= LooseVersion(min_openssl_version): - dbg_msg = "System OpenSSL library '%s' with version %s fulfills requested version %s" - self.log.debug(dbg_msg, system_solib, openssl_version, min_openssl_version) - target_system_ssl['version'] = openssl_version - target_system_ssl['libs'].append(system_solib) - else: - dbg_msg = "System OpenSSL library '%s' with version %s is older than requested version %s" - self.log.debug(dbg_msg, system_solib, openssl_version, min_openssl_version) + ssl_lib_support_versions = openssl_version_regex.findall(solib_strings) + ssl_lib_support_versions.sort() + dbg_msg = "System OpenSSL library '%s' supports versions: %s" + dbg_msg_support_versions = ', '.join([''.join(v) for v in ssl_lib_support_versions]) + self.log.debug(dbg_msg, system_solib, dbg_msg_support_versions) + # pick highest supported version + ssl_lib_version = ssl_lib_support_versions[-1][0] + except IndexError: + dbg_msg = "Could not detect the full version of system OpenSSL library: %s" + self.log.debug(dbg_msg, system_solib) + # check that system library version fulfills requirements + if LooseVersion(ssl_lib_version) >= LooseVersion(min_openssl_version): + dbg_msg = "System OpenSSL library '%s' with version %s fulfills requested version %s" + self.log.debug(dbg_msg, system_solib, ssl_lib_version, min_openssl_version) + target_ssl_libs.append(system_solib) else: - # one of the OpenSSL libraries is missing, switch to next group of versioned libs - break + dbg_msg = "System OpenSSL library '%s' with version %s is older than requested version %s" + self.log.debug(dbg_msg, system_solib, ssl_lib_version, min_openssl_version) - if len(target_system_ssl['libs']) == len(openssl_libs): + if len(target_ssl_libs) == len(openssl_libs): # target libraries found, ignore further options break - if len(target_system_ssl['libs']) == len(openssl_libs): - self.system_ssl.update(target_system_ssl) + if len(target_ssl_libs) == len(openssl_libs): + self.system_ssl['libs'] = target_ssl_libs info_msg = "Found OpenSSL library version %s in host system: %s" - self.log.info(info_msg, self.system_ssl['version'], os.path.dirname(self.system_ssl['libs'][0])) + self.log.info(info_msg, ssl_lib_version, os.path.dirname(self.system_ssl['libs'][0])) else: self.log.info("OpenSSL library not found in host system, falling back to OpenSSL in EasyBuild") return @@ -290,7 +287,8 @@ def __init__(self, *args, **kwargs): for target_bin in target_ssl_bins: target_bin_path, target_bin_version = self.get_openssl_bin_version(target_bin) - if target_bin_version == self.system_ssl['version']: + if LooseVersion(target_bin_version) >= LooseVersion(min_openssl_version): + self.system_ssl['version'] = target_bin_version self.system_ssl['bin'] = target_bin_path break From e40f78e7ee03dc1e5eaf477bf00ca016a5f650c7 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 18:06:59 +0200 Subject: [PATCH 122/134] define maximum version for OpenSSL wrapper and start with executable detection --- easybuild/easyblocks/o/openssl_wrapper.py | 115 +++++++++++----------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index 082fdaa09b..ebc1cf2e7e 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -84,19 +84,23 @@ def __init__(self, *args, **kwargs): self.generation = "3" # Set minimum OpenSSL version - min_openssl_version = self.cfg.get('minimum_openssl_version') - - if not min_openssl_version: - min_openssl_version = self.version - elif not isinstance(min_openssl_version, string_type): - min_openssl_version = str(min_openssl_version) - + self.min_version = self.cfg.get('minimum_openssl_version') + if not self.min_version: + self.min_version = self.version + elif not isinstance(self.min_version, string_type): + self.min_version = str(self.min_version) # Minimum OpenSSL version can only increase depth of wrapper version - if min_openssl_version.startswith(self.version): - self.log.debug("Requiring minimum OpenSSL version: %s", min_openssl_version) + if self.min_version.startswith(self.version): + self.log.debug("Requiring minimum OpenSSL version: %s", self.min_version) else: err_msg = "Requested minimum OpenSSL version '%s' does not fit in wrapper easyconfig version '%s'" - raise EasyBuildError(err_msg, min_openssl_version, self.version) + raise EasyBuildError(err_msg, self.min_version, self.version) + + # Set maximum OpenSSL version (increase smallest revision by 1) + max_version_parts = [int(subv) for subv in self.version.split('.')] + max_version_parts[-1] += 1 + self.max_version = '.'.join([str(subv) for subv in max_version_parts]) + self.log.debug("Restricting maximum OpenSSL version: %s", self.max_version) # Regex pattern to find version strings in OpenSSL libraries and headers full_version_regex = re.compile(r'[0-9]+\.[0-9]+\.[0-9]+[a-z]?') @@ -134,20 +138,14 @@ def __init__(self, *args, **kwargs): err_msg = "OpenSSL system library for version %s and OS type %s is unsupported" raise EasyBuildError(err_msg, self.generation, os_type) - # by default target the first option of each OpenSSL library, - # which corresponds to installation from source - self.target_ssl_libs = system_versioned_libs[0] - self.log.info("Target OpenSSL libraries: %s", self.target_ssl_libs) - # folders containing engines libraries openssl_engines = { '1.0': 'engines', '1.1': 'engines-1.1', '3': 'engines-3', } - self.target_ssl_engine = openssl_engines[self.generation] - # Paths to system libraries and headers of OpenSSL + # Paths to system components of OpenSSL self.system_ssl = { 'bin': None, 'engines': None, @@ -160,6 +158,30 @@ def __init__(self, *args, **kwargs): self.log.info("Not wrapping system OpenSSL installation by user request") return + # Check system OpenSSL binary + target_ssl_bins = ['openssl'] + if self.generation == '1.1': + target_ssl_bins.insert(0, 'openssl11') # prefer 'openssl11' over 'openssl' with v1.1 + elif self.generation == '3': + target_ssl_bins.insert(0, 'openssl3') # prefer 'openssl3' over 'openssl' with v3 + + for ssl_bin in target_ssl_bins: + ssl_bin_path, ssl_bin_version = self.get_openssl_bin_version(ssl_bin) + if ssl_bin_path: + if LooseVersion(self.min_version) <= LooseVersion(ssl_bin_version) < LooseVersion(self.max_version): + self.system_ssl['version'] = ssl_bin_version + self.system_ssl['bin'] = ssl_bin_path + break + + if self.system_ssl['bin'] and self.system_ssl['version']: + log_msg = "System OpenSSL binary for version %s found: %s" + self.log.info(log_msg, self.system_ssl['version'], self.system_ssl['bin']) + else: + log_msg = "OpenSSL binary for version %s not found in host system! " + log_msg += "Falling back to building OpenSSL from source" + self.log.info(log_msg, self.version) + return + # Check the system libraries of OpenSSL # Find library file and compare its version string for solibs in system_versioned_libs: @@ -188,13 +210,13 @@ def __init__(self, *args, **kwargs): dbg_msg = "Could not detect the full version of system OpenSSL library: %s" self.log.debug(dbg_msg, system_solib) # check that system library version fulfills requirements - if LooseVersion(ssl_lib_version) >= LooseVersion(min_openssl_version): + if LooseVersion(self.min_version) <= LooseVersion(ssl_lib_version) < LooseVersion(self.max_version): dbg_msg = "System OpenSSL library '%s' with version %s fulfills requested version %s" - self.log.debug(dbg_msg, system_solib, ssl_lib_version, min_openssl_version) + self.log.debug(dbg_msg, system_solib, ssl_lib_version, self.min_version) target_ssl_libs.append(system_solib) else: dbg_msg = "System OpenSSL library '%s' with version %s is older than requested version %s" - self.log.debug(dbg_msg, system_solib, ssl_lib_version, min_openssl_version) + self.log.debug(dbg_msg, system_solib, ssl_lib_version, self.min_version) if len(target_ssl_libs) == len(openssl_libs): # target libraries found, ignore further options @@ -205,14 +227,16 @@ def __init__(self, *args, **kwargs): info_msg = "Found OpenSSL library version %s in host system: %s" self.log.info(info_msg, ssl_lib_version, os.path.dirname(self.system_ssl['libs'][0])) else: - self.log.info("OpenSSL library not found in host system, falling back to OpenSSL in EasyBuild") + log_msg = "OpenSSL library for version %s not found in host system! " + log_msg += "Falling back to building OpenSSL from source" + self.log.info(log_msg, self.system_ssl['version']) return # Directory with engine libraries lib_dir = os.path.dirname(self.system_ssl['libs'][0]) lib_engines_dir = [ - os.path.join(lib_dir, 'openssl', self.target_ssl_engine), - os.path.join(lib_dir, self.target_ssl_engine), + os.path.join(lib_dir, 'openssl', openssl_engines[self.generation]), + os.path.join(lib_dir, openssl_engines[self.generation]), ] for engines_path in lib_engines_dir: @@ -222,7 +246,9 @@ def __init__(self, *args, **kwargs): break if not self.system_ssl['engines']: - self.log.info("OpenSSL engines not found in host system, falling back to OpenSSL in EasyBuild") + log_msg = "OpenSSL engines for version %s not found in host system! " + log_msg += "Falling back to building OpenSSL from source" + self.log.info(log_msg, self.system_ssl['version']) return # Check system include paths for OpenSSL headers @@ -256,19 +282,19 @@ def __init__(self, *args, **kwargs): # check version reported by opensslv.h opensslv = read_file(opensslv_path) try: - header_version = openssl_version_regex.search(opensslv).group(1) + ssl_head_version = openssl_version_regex.search(opensslv).group(1) except AttributeError: err_msg = "System OpenSSL header '%s' does not contain any recognizable version string" raise EasyBuildError(err_msg, opensslv_path) - if LooseVersion(header_version) >= LooseVersion(min_openssl_version): + if LooseVersion(self.min_version) <= LooseVersion(ssl_head_version) < LooseVersion(self.max_version): self.system_ssl['include'] = include_dir info_msg = "Found OpenSSL headers v%s in host system: %s" - self.log.info(info_msg, header_version, self.system_ssl['include']) + self.log.info(info_msg, ssl_head_version, self.system_ssl['include']) break else: dbg_msg = "System OpenSSL header version '%s' does not fulfill minimum version requirement '%s'" - self.log.debug(dbg_msg, header_version, min_openssl_version) + self.log.debug(dbg_msg, ssl_head_version, self.min_version) else: self.log.info("System OpenSSL header file %s not found", opensslv_path) @@ -278,31 +304,6 @@ def __init__(self, *args, **kwargs): "source in EasyBuild by setting 'wrap_system_openssl = False' in the OpenSSL easyconfig.") raise EasyBuildError(err_msg, self.version, self.system_ssl['version']) - # Check system OpenSSL binary - target_ssl_bins = ['openssl'] - if self.generation == '1.1': - target_ssl_bins.insert(0, 'openssl11') # prefer 'openssl11' over 'openssl' with v1.1 - elif self.generation == '3': - target_ssl_bins.insert(0, 'openssl3') # prefer 'openssl3' over 'openssl' with v3 - - for target_bin in target_ssl_bins: - target_bin_path, target_bin_version = self.get_openssl_bin_version(target_bin) - if LooseVersion(target_bin_version) >= LooseVersion(min_openssl_version): - self.system_ssl['version'] = target_bin_version - self.system_ssl['bin'] = target_bin_path - break - - if self.system_ssl['bin']: - log_msg = "System OpenSSL binary for version %s found: %s" - self.log.info(log_msg, self.system_ssl['version'], self.system_ssl['bin']) - else: - self.log.info("System OpenSSL binary for version %s not found!", self.system_ssl['version']) - return - - # system OpenSSL is fine, change target libraries to the ones found in it - self.target_ssl_libs = [os.path.basename(solib) for solib in target_system_ssl["libs"]] - self.log.info("Target system OpenSSL libraries: %s", self.target_ssl_libs) - def fetch_step(self, *args, **kwargs): """Fetch sources if OpenSSL component is needed""" if not all(self.system_ssl[key] for key in ('bin', 'engines', 'include', 'libs')): @@ -370,15 +371,15 @@ def sanity_check_step(self): """Custom sanity check for OpenSSL wrapper.""" shlib_ext = get_shared_lib_ext() - ssl_libs = ['%s.%s' % (libso.split('.')[0], shlib_ext) for libso in self.target_ssl_libs] - ssl_libs.extend(self.target_ssl_libs) + ssl_libs = [os.path.basename(solib) for solib in self.system_ssl["libs"]] + ssl_libs.extend(['%s.%s' % (solib.split('.')[0], shlib_ext) for solib in ssl_libs]) ssl_files = [os.path.join('bin', self.name.lower())] ssl_files.extend(os.path.join('lib', libso) for libso in ssl_libs) ssl_dirs = [ os.path.join('include', self.name.lower()), - os.path.join('lib', self.target_ssl_engine), + os.path.join('lib', os.path.basename(self.system_ssl["engines"])), os.path.join('lib', 'pkgconfig'), ] @@ -444,7 +445,7 @@ def install_pc_files(self): 'libcrypto': { 'name': 'OpenSSL-libcrypto', 'description': 'OpenSSL cryptography library', - 'enginesdir': self.target_ssl_engine, + 'enginesdir': os.path.basename(self.system_ssl["engines"]), }, 'libssl': { 'name': 'OpenSSL-libssl', From 48bc68d276cbf60f730813b09431d23e85397a3a Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 18:47:35 +0200 Subject: [PATCH 123/134] define target components per generation in OpenSSL wrapper --- easybuild/easyblocks/o/openssl_wrapper.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index ebc1cf2e7e..d758d684a0 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -145,6 +145,14 @@ def __init__(self, *args, **kwargs): '3': 'engines-3', } + # Define targets for this generation + # They are used to sanity check both installations from source or wrappers + self.generation_targets = { + 'bin': 'openssl', + 'engines': openssl_engines[self.generation], + 'libs': system_versioned_libs[0], # first set of libs match source installs + } + # Paths to system components of OpenSSL self.system_ssl = { 'bin': None, @@ -224,6 +232,7 @@ def __init__(self, *args, **kwargs): if len(target_ssl_libs) == len(openssl_libs): self.system_ssl['libs'] = target_ssl_libs + self.generation_targets['libs'] = [os.path.basename(solib) for solib in target_ssl_libs] info_msg = "Found OpenSSL library version %s in host system: %s" self.log.info(info_msg, ssl_lib_version, os.path.dirname(self.system_ssl['libs'][0])) else: @@ -371,15 +380,15 @@ def sanity_check_step(self): """Custom sanity check for OpenSSL wrapper.""" shlib_ext = get_shared_lib_ext() - ssl_libs = [os.path.basename(solib) for solib in self.system_ssl["libs"]] - ssl_libs.extend(['%s.%s' % (solib.split('.')[0], shlib_ext) for solib in ssl_libs]) + ssl_libs = ['%s.%s' % (solib.split('.')[0], shlib_ext) for solib in self.generation_targets['libs']] + ssl_libs.extend(self.generation_targets['libs']) ssl_files = [os.path.join('bin', self.name.lower())] ssl_files.extend(os.path.join('lib', libso) for libso in ssl_libs) ssl_dirs = [ os.path.join('include', self.name.lower()), - os.path.join('lib', os.path.basename(self.system_ssl["engines"])), + os.path.join('lib', self.generation_targets["engines"]), os.path.join('lib', 'pkgconfig'), ] @@ -445,7 +454,7 @@ def install_pc_files(self): 'libcrypto': { 'name': 'OpenSSL-libcrypto', 'description': 'OpenSSL cryptography library', - 'enginesdir': os.path.basename(self.system_ssl["engines"]), + 'enginesdir': self.generation_targets["engines"], }, 'libssl': { 'name': 'OpenSSL-libssl', From 3128f50e721513ddb3cd53d5e9c05617a5fedd89 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 29 May 2024 18:55:29 +0200 Subject: [PATCH 124/134] use generation target to detect and sanity check OpenSSL executable --- easybuild/easyblocks/o/openssl_wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/o/openssl_wrapper.py b/easybuild/easyblocks/o/openssl_wrapper.py index d758d684a0..d776c43a02 100644 --- a/easybuild/easyblocks/o/openssl_wrapper.py +++ b/easybuild/easyblocks/o/openssl_wrapper.py @@ -167,7 +167,7 @@ def __init__(self, *args, **kwargs): return # Check system OpenSSL binary - target_ssl_bins = ['openssl'] + target_ssl_bins = [self.generation_targets['bin']] if self.generation == '1.1': target_ssl_bins.insert(0, 'openssl11') # prefer 'openssl11' over 'openssl' with v1.1 elif self.generation == '3': @@ -383,7 +383,7 @@ def sanity_check_step(self): ssl_libs = ['%s.%s' % (solib.split('.')[0], shlib_ext) for solib in self.generation_targets['libs']] ssl_libs.extend(self.generation_targets['libs']) - ssl_files = [os.path.join('bin', self.name.lower())] + ssl_files = [os.path.join('bin', self.generation_targets['bin'])] ssl_files.extend(os.path.join('lib', libso) for libso in ssl_libs) ssl_dirs = [ From de01fd1fbdf5369ec6caa6a3ace0119c072e1ed1 Mon Sep 17 00:00:00 2001 From: Ake Sandgren Date: Fri, 31 May 2024 15:30:42 +0200 Subject: [PATCH 125/134] fix issue 3345 --- easybuild/easyblocks/i/intel_compilers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/i/intel_compilers.py b/easybuild/easyblocks/i/intel_compilers.py index c3fce10a99..f633fc4657 100644 --- a/easybuild/easyblocks/i/intel_compilers.py +++ b/easybuild/easyblocks/i/intel_compilers.py @@ -177,7 +177,7 @@ def make_module_extra(self): 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) + multiarch_inc_dir, ec = run_cmd("gcc -E -Wp,-v -xc /dev/null 2>&1 | grep %s$ | grep -v GCCcore" % 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) From 2b207a22eee8028bcb568b8d05b9ca28546229a0 Mon Sep 17 00:00:00 2001 From: Ake Sandgren Date: Fri, 31 May 2024 15:34:37 +0200 Subject: [PATCH 126/134] fix too long line --- easybuild/easyblocks/i/intel_compilers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/i/intel_compilers.py b/easybuild/easyblocks/i/intel_compilers.py index f633fc4657..383018ede2 100644 --- a/easybuild/easyblocks/i/intel_compilers.py +++ b/easybuild/easyblocks/i/intel_compilers.py @@ -177,7 +177,8 @@ def make_module_extra(self): 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$ | grep -v GCCcore" % multiarch_out) + multi_arch_inc_dir_cmd = "gcc -E -Wp,-v -xc /dev/null 2>&1 | grep %s$ | grep -v GCCcore" % multiarch_out + multiarch_inc_dir, ec = run_cmd(multi_arch_inc_dir_cmd) 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) From 81b4294a2b8a9f2fedf90488ce246fc9a5f639b2 Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Fri, 31 May 2024 15:44:00 +0000 Subject: [PATCH 127/134] Allow external PRRTE in openmpi easyblock --- easybuild/easyblocks/o/openmpi.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/o/openmpi.py b/easybuild/easyblocks/o/openmpi.py index 8460aad58a..e8261d0ca3 100644 --- a/easybuild/easyblocks/o/openmpi.py +++ b/easybuild/easyblocks/o/openmpi.py @@ -72,6 +72,8 @@ def config_opt_used(key, enable_opt=False): known_dependencies = ['CUDA', 'hwloc', 'libevent', 'libfabric', 'PMIx', 'UCX'] if LooseVersion(self.version) >= '4.1.4': known_dependencies.append('UCC') + if LooseVersion(self.version) >= '5.0.0': + known_dependencies.append('PRRTE') # Value to use for `--with-=` if the dependency is not specified in the easyconfig # No entry is interpreted as no option added at all @@ -85,6 +87,8 @@ def config_opt_used(key, enable_opt=False): # For these the default is to use an internal copy and not using any is not supported for dep in ('hwloc', 'libevent', 'PMIx'): unused_dep_value[dep] = 'internal' + if LooseVersion(self.version) >= '5.0.0': + unused_dep_value['PRRTE'] = 'internal' # handle dependencies for dep in known_dependencies: @@ -165,7 +169,8 @@ def sanity_check_step(self): bin_names = ['mpicc', 'mpicxx', 'mpif90', 'mpifort', 'mpirun', 'ompi_info', 'opal_wrapper'] if LooseVersion(self.version) >= LooseVersion('5.0.0'): - bin_names.append('prterun') + if not get_software_root('PRRTE'): + bin_names.append('prterun') else: bin_names.append('orterun') bin_files = [os.path.join('bin', x) for x in bin_names] @@ -173,13 +178,14 @@ def sanity_check_step(self): shlib_ext = get_shared_lib_ext() lib_names = ['mpi_mpifh', 'mpi', 'open-pal'] if LooseVersion(self.version) >= LooseVersion('5.0.0'): - lib_names.append('prrte') + if not get_software_root('PRRTE'): + lib_names.append('prrte') else: lib_names.extend(['ompitrace', 'open-rte']) lib_files = [os.path.join('lib', 'lib%s.%s' % (x, shlib_ext)) for x in lib_names] inc_names = ['mpi-ext', 'mpif-config', 'mpif', 'mpi', 'mpi_portable_platform'] - if LooseVersion(self.version) >= LooseVersion('5.0.0'): + if LooseVersion(self.version) >= LooseVersion('5.0.0') and not get_software_root('PRRTE'): inc_names.append('prte') inc_files = [os.path.join('include', x + '.h') for x in inc_names] From ac25414e706a9ca5ed39af8e516d797340d89824 Mon Sep 17 00:00:00 2001 From: Ake Sandgren Date: Fri, 7 Jun 2024 15:03:49 +0200 Subject: [PATCH 128/134] intel_compilers.py: use grep -v /include-fixed/ instead of GCCcore to filter out unwanted include path. --- easybuild/easyblocks/i/intel_compilers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/i/intel_compilers.py b/easybuild/easyblocks/i/intel_compilers.py index 383018ede2..a9c49d04e1 100644 --- a/easybuild/easyblocks/i/intel_compilers.py +++ b/easybuild/easyblocks/i/intel_compilers.py @@ -177,7 +177,11 @@ def make_module_extra(self): multiarch_out, ec = run_cmd("gcc -print-multiarch", simple=False) multiarch_out = multiarch_out.strip() if ec == 0 and multiarch_out: - multi_arch_inc_dir_cmd = "gcc -E -Wp,-v -xc /dev/null 2>&1 | grep %s$ | grep -v GCCcore" % multiarch_out + multi_arch_inc_dir_cmd = '|'.join([ + "gcc -E -Wp,-v -xc /dev/null 2>&1", + "grep %s$" % multiarch_out, + "grep -v /include-fixed/", + ]) multiarch_inc_dir, ec = run_cmd(multi_arch_inc_dir_cmd) if ec == 0 and multiarch_inc_dir: multiarch_inc_dir = multiarch_inc_dir.strip() From 2bb9d17c4aa1c3e87e598606a05d8feeb4f74be9 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 8 Jun 2024 14:14:37 +0200 Subject: [PATCH 129/134] always specify custom value for sanity_check_paths in torchvision easyblock, to fix broken sanity check for bundle that includes torchvision as extension (like PyTorch-bundle) --- easybuild/easyblocks/t/torchvision.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index 18b08d25dc..a780af92b1 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -89,7 +89,10 @@ def configure_step(self): def sanity_check_step(self): """Custom sanity check for torchvision.""" custom_commands = [] - custom_paths = None + custom_paths = { + 'files': [], + 'dirs': [det_pylibdir()], + } # check whether torchvision was indeed built with CUDA support, # cfr. https://discuss.pytorch.org/t/notimplementederror-could-not-run-torchvision-nms-with-arguments-from-\ @@ -103,10 +106,6 @@ def sanity_check_step(self): " print(torchvision.ops.nms(boxes, scores, 0.5))", ]) custom_commands.append('python -c "%s"' % python_code) - custom_paths = { - 'files': [], - 'dirs': [det_pylibdir()], - } if get_software_root('libjpeg-turbo'): # check if torchvision was built with libjpeg support From 53e0dd3570a1610806250b6f4a562207738ca8ef Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Sat, 8 Jun 2024 14:48:35 +0200 Subject: [PATCH 130/134] load module before calling det_pylibdir() in sanity check for torchvision --- easybuild/easyblocks/t/torchvision.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/easybuild/easyblocks/t/torchvision.py b/easybuild/easyblocks/t/torchvision.py index a780af92b1..378b5525a8 100644 --- a/easybuild/easyblocks/t/torchvision.py +++ b/easybuild/easyblocks/t/torchvision.py @@ -88,6 +88,12 @@ def configure_step(self): def sanity_check_step(self): """Custom sanity check for torchvision.""" + + # load module early ourselves rather than letting parent sanity_check_step method do so, + # so the correct 'python' command is used to by det_pylibdir() below; + if hasattr(self, 'sanity_check_module_loaded') and not self.sanity_check_module_loaded: + self.fake_mod_data = self.sanity_check_load_module(extension=self.is_extension) + custom_commands = [] custom_paths = { 'files': [], From d5e1dc942ce59081569b66e52159738c723e9063 Mon Sep 17 00:00:00 2001 From: Sebastian Achilles Date: Mon, 10 Jun 2024 23:13:02 +0200 Subject: [PATCH 131/134] prepare release notes for EasyBuild v4.9.2 + bump version to 4.9.2 --- RELEASE_NOTES | 33 +++++++++++++++++++++++++++++++- easybuild/easyblocks/__init__.py | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 528e94e069..ba3659f632 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,7 +3,38 @@ For more detailed information, please see the git log. These release notes can also be consulted at http://easybuild.readthedocs.org/en/latest/Release_notes.html. -The latest version of easybuild-easyblocks provides 255 software-specific easyblocks and 43 generic easyblocks. +The latest version of easybuild-easyblocks provides 259 software-specific easyblocks and 43 generic easyblocks. + + +v4.9.2 (11 June 2024) +--------------------- + +update/bugfix release + +- 4 new software-specific easyblocks: QuantumESPRESSO with CMake (#3257), aedt (#3281), optiSLang (#3300), MetalWalls (#3311) +- minor enhancements and updates, including: + - refactor GAMESS-US easyblock to directly write install.info (v2) (#3047) + - Add ABAQUS license server to generated module (#3277) + - Allow 'nosource: True' in PythonPackage extensions' (#3305) + - auto-disable FFTW quad precision on RISC-V (#3314) + - use regular `configure` instead of wrapper script in easyblock for UCX plugins (#3315) + - add libjpeg-turbo to include dir for torchvision easyblock (#3322) + - add RISC-V support to Java easyblock (#3323) + - add RISC-V support to Mesa easyblock (#3324) + - add RISC-V support to Clang easyblock (#3325) + - Add a sanity check for OpenFOAM's `wmake` to make sure it finds the compiler commands (#3328) + - Always override the compiler version check for CUDA installations (#3329) + - allow version mismatchs between OpenSSL components in host system as long as they fulfill version requirements (#3340) + - Allow external PRRTE in OpenMPI easyblock (#3347) +- various bug fixes, including: + - don't manipulate setup.py for Python 3.12+ when using alternate sysroot (#3313) + - do not run unit tests on Python 3.5 (#3326) + - Fix for MetalWalls easyblock w.r.t. PLUMED generating patch file inside module location (#3331) + - avoid sanity check on the software itself for CargoPythonBundle easyblock (#3341) + - fix malformed `$CPATH` for intel-compilers on Debian/Ubuntu (#3346) + - always specify custom value for `sanity_check_paths` in custom easyblock for torchvision (#3353) +- other changes: + - Binary easyblock already adds top level directory to PATH, so no need to do it in the Stata easyblock (#3307) v4.9.1 (5 April 2024) diff --git a/easybuild/easyblocks/__init__.py b/easybuild/easyblocks/__init__.py index 56d224f3be..5dfdc5c4f1 100644 --- a/easybuild/easyblocks/__init__.py +++ b/easybuild/easyblocks/__init__.py @@ -43,7 +43,7 @@ # recent setuptools versions will *TRANSFORM* something like 'X.Y.Zdev' into 'X.Y.Z.dev0', with a warning like # UserWarning: Normalizing '2.4.0dev' to '2.4.0.dev0' # This causes problems further up the dependency chain... -VERSION = LooseVersion('4.9.2.dev0') +VERSION = LooseVersion('4.9.2') UNKNOWN = 'UNKNOWN' From 41bd1402d1798087718e0ef8aef4d57e342e5101 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Tue, 11 Jun 2024 08:04:01 +0200 Subject: [PATCH 132/134] minor tweaks to 4.9.2 release notes --- RELEASE_NOTES | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index ba3659f632..6ccd23b091 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,28 +11,24 @@ v4.9.2 (11 June 2024) update/bugfix release -- 4 new software-specific easyblocks: QuantumESPRESSO with CMake (#3257), aedt (#3281), optiSLang (#3300), MetalWalls (#3311) +- 4 new software-specific easyblocks: QuantumESPRESSO with CMake (#3257), aedt (#3281), optiSLang (#3300), MetalWalls (#3311, #3331) - minor enhancements and updates, including: - - refactor GAMESS-US easyblock to directly write install.info (v2) (#3047) - - Add ABAQUS license server to generated module (#3277) - - Allow 'nosource: True' in PythonPackage extensions' (#3305) + - refactor GAMESS-US easyblock to directly write install.info (#3047) + - add ABAQUS license server to generated module (#3277) + - allow 'nosource: True' in PythonPackage extensions (#3305) - auto-disable FFTW quad precision on RISC-V (#3314) - - use regular `configure` instead of wrapper script in easyblock for UCX plugins (#3315) - - add libjpeg-turbo to include dir for torchvision easyblock (#3322) - - add RISC-V support to Java easyblock (#3323) - - add RISC-V support to Mesa easyblock (#3324) - - add RISC-V support to Clang easyblock (#3325) - - Add a sanity check for OpenFOAM's `wmake` to make sure it finds the compiler commands (#3328) - - Always override the compiler version check for CUDA installations (#3329) + - use regular 'configure' instead of wrapper script in easyblock for UCX plugins (#3315) + - add libjpeg-turbo to include dir for torchvision easyblock (#3322, #3353) + - add RISC-V support to custom easyblocks for Clang (#3325), Java (#3323), Mesa (#3324) + - add a sanity check for OpenFOAM's 'wmake' to make sure it finds the compiler commands (#3328) + - always override the compiler version check for CUDA installations (#3329) - allow version mismatchs between OpenSSL components in host system as long as they fulfill version requirements (#3340) - - Allow external PRRTE in OpenMPI easyblock (#3347) + - allow external PRRTE in OpenMPI easyblock (#3347) - various bug fixes, including: - don't manipulate setup.py for Python 3.12+ when using alternate sysroot (#3313) - do not run unit tests on Python 3.5 (#3326) - - Fix for MetalWalls easyblock w.r.t. PLUMED generating patch file inside module location (#3331) - avoid sanity check on the software itself for CargoPythonBundle easyblock (#3341) - - fix malformed `$CPATH` for intel-compilers on Debian/Ubuntu (#3346) - - always specify custom value for `sanity_check_paths` in custom easyblock for torchvision (#3353) + - fix malformed '$CPATH' for intel-compilers on Debian/Ubuntu (#3346) - other changes: - Binary easyblock already adds top level directory to PATH, so no need to do it in the Stata easyblock (#3307) From ac869ebafcbed2e6f83c9ce088703c958ced72e2 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Tue, 11 Jun 2024 20:23:30 +0200 Subject: [PATCH 133/134] bump release date for EasyBuild v4.9.2 to 12 June 2024 --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 6ccd23b091..73f484d0eb 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -6,7 +6,7 @@ These release notes can also be consulted at http://easybuild.readthedocs.org/en The latest version of easybuild-easyblocks provides 259 software-specific easyblocks and 43 generic easyblocks. -v4.9.2 (11 June 2024) +v4.9.2 (12 June 2024) --------------------- update/bugfix release From ba870405758dedd6ba1c9ba7df3aa79e59786cf1 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Tue, 11 Jun 2024 20:49:59 +0200 Subject: [PATCH 134/134] aedt -> AEDT in v4.9.2 release notes --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 73f484d0eb..8050832107 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,7 +11,7 @@ v4.9.2 (12 June 2024) update/bugfix release -- 4 new software-specific easyblocks: QuantumESPRESSO with CMake (#3257), aedt (#3281), optiSLang (#3300), MetalWalls (#3311, #3331) +- 4 new software-specific easyblocks: QuantumESPRESSO with CMake (#3257), AEDT (#3281), optiSLang (#3300), MetalWalls (#3311, #3331) - minor enhancements and updates, including: - refactor GAMESS-US easyblock to directly write install.info (#3047) - add ABAQUS license server to generated module (#3277)