From 0e8b180133ec5c9f97827cb04762a51c26b8a7b1 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 16 Sep 2020 18:59:30 +0200 Subject: [PATCH 1/7] add easyblock for RAxML --- easybuild/easyblocks/r/raxml.py | 153 ++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 easybuild/easyblocks/r/raxml.py diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py new file mode 100644 index 0000000000..0c16f68cc6 --- /dev/null +++ b/easybuild/easyblocks/r/raxml.py @@ -0,0 +1,153 @@ +## +# 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 building and installing RAxML, implemented as an easyblock +@author: Alex Domingo (Vrije Universiteit Brussel) +""" +import os + +import easybuild.tools.environment as env +from easybuild.easyblocks.generic.makecp import MakeCp +from easybuild.framework.easyconfig import CUSTOM +from easybuild.tools.systemtools import get_cpu_features + + +class EB_RAxML(MakeCp): + """Support for building and installing MSM.""" + @staticmethod + def extra_options(extra_vars=None): + """Change default values of options""" + extra = MakeCp.extra_options() + # files_to_copy is not mandatory here + extra['files_to_copy'][2] = CUSTOM + return extra + + def __init__(self, *args, **kwargs): + """RAxML easyblock constructor, define class variables.""" + super(EB_RAxML, self).__init__(*args, **kwargs) + + # Set optmization of RAxML build for host micro-architecture + cpuopt_label = { + 'sse3': 'SSE3', + 'sse4_1': 'SSE3', + 'sse4_2': 'SSE3', + 'avx': 'AVX', + 'avx1.0': 'AVX', # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' + 'avx2': 'AVX2', + } + cpu_features = set([label for feat, label in cpuopt_label.items() if feat in get_cpu_features()]) + self.log.debug("Enabling the following CPU optimizations for RAxML: %s", ', '.join(cpu_features)) + cpu_features.update([None]) # add generic build + + # Build features supported by RAxML, grouped in non-MPI and MPI + build_labels = {'nompi': [None, 'PTHREADS'], 'mpi': ['MPI', 'HYBRID']} + + # List of Makefiles in the build + makefile = ('Makefile', 'gcc', '.') + # Always build non-MPI variants + self.target_makefiles = { + 'nompi': self.make_filename_variants(cpu_features, build_labels['nompi'], *makefile), + } + if self.toolchain.options.get('usempi', None): + # Add MPI variants in their own group + self.target_makefiles.update({ + 'mpi': self.make_filename_variants(cpu_features, build_labels['mpi'], *makefile), + }) + + # List of binaries in the installation + binary = ('raxmlHPC', None, '-') + self.target_bin = self.make_filename_variants(build_labels['nompi'], cpu_features, *binary) + if 'mpi' in self.target_makefiles: + self.target_bin.extend(self.make_filename_variants(build_labels['mpi'], cpu_features, *binary)) + + def make_filename_variants(self, main_feature, extra_feature, prefix, suffix, divider): + """Returns list of RAxML filenames for the combination of all given features""" + + # Features are expected as lists + if not isinstance(main_feature, list): + main_feature = list(main_feature) + if not isinstance(extra_feature, list): + extra_feature = list(extra_feature) + + # Permutations of features + if extra_feature: + raxml_variants = [(mf, xf) for mf in main_feature for xf in extra_feature] + else: + raxml_variants = main_feature + + # Prepend/Append prefix/suffix + for n, variant in enumerate(raxml_variants): + full_filename = (prefix,) + variant + (suffix,) + full_filename = tuple(filter(None, full_filename)) # avoid doubling the divider + raxml_variants[n] = divider.join(full_filename) + + return raxml_variants + + def configure_step(self): + """No custom configuration step for RAxML""" + pass + + def build_step(self): + """Build all binaries of RAxML compatible with host CPU architecture""" + + # Compiler is manually set through 'buildopts' + cc = os.getenv('CC') + # Always use non-MPI compiler for non-MPI Makefiles + if 'mpi' in self.target_makefiles: + cc_seq = os.getenv('CC_SEQ') + else: + cc_seq = os.getenv('CC') + + # Build selected RAxML makefiles + user_buildopts = self.cfg['buildopts'] + + self.log.debug("Building makefiles of RAxML with %s: %s", cc_seq, ', '.join(self.target_makefiles['nompi'])) + for mf in self.target_makefiles['nompi']: + self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc_seq, user_buildopts) + super(EB_RAxML, self).build_step() + + if 'mpi' in self.target_makefiles: + self.log.debug("Building makefiles of RAxML with %s: %s", cc, ', '.join(self.target_makefiles['mpi'])) + for mf in self.target_makefiles['mpi']: + self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc, user_buildopts) + super(EB_RAxML, self).build_step() + + def install_step(self): + """Copy files into installation directory""" + + self.cfg['files_to_copy'] = [ + (self.target_bin, 'bin'), + (['README', 'manual', 'usefulScripts'], 'share'), + ] + super(EB_RAxML, self).install_step() + + def sanity_check_step(self): + """Custom sanity check for RAxML.""" + + custom_paths = { + 'files': [os.path.join('bin', x) for x in self.target_bin], + 'dirs': ['share/manual', 'share/usefulScripts'] + } + super(EB_RAxML, self).sanity_check_step(custom_paths=custom_paths) From 5b40659fe3028814308c17716670b0a83e379c44 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 16 Sep 2020 19:47:17 +0200 Subject: [PATCH 2/7] remove easybuild.tools.environment from raxml --- easybuild/easyblocks/r/raxml.py | 1 - 1 file changed, 1 deletion(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index 0c16f68cc6..ff68734a17 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -28,7 +28,6 @@ """ import os -import easybuild.tools.environment as env from easybuild.easyblocks.generic.makecp import MakeCp from easybuild.framework.easyconfig import CUSTOM from easybuild.tools.systemtools import get_cpu_features From f7afebdd183da07959f1fa9300501ee4923e1fad Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 23 Sep 2020 17:09:24 +0200 Subject: [PATCH 3/7] fix formatting of raxml.py --- easybuild/easyblocks/r/raxml.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index ff68734a17..9fd95efc30 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -34,7 +34,7 @@ class EB_RAxML(MakeCp): - """Support for building and installing MSM.""" + """Support for building and installing RAxML.""" @staticmethod def extra_options(extra_vars=None): """Change default values of options""" @@ -61,7 +61,10 @@ def __init__(self, *args, **kwargs): cpu_features.update([None]) # add generic build # Build features supported by RAxML, grouped in non-MPI and MPI - build_labels = {'nompi': [None, 'PTHREADS'], 'mpi': ['MPI', 'HYBRID']} + build_labels = { + 'nompi': [None, 'PTHREADS'], + 'mpi': ['MPI', 'HYBRID'], + } # List of Makefiles in the build makefile = ('Makefile', 'gcc', '.') From 71d922ed95cdb013ba37317746c3cc0d8ba7eb2f Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 24 Feb 2023 10:57:01 +0100 Subject: [PATCH 4/7] refactor CPU features detection and build variants in RAxML --- easybuild/easyblocks/r/raxml.py | 159 ++++++++++++++++---------------- 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index 9fd95efc30..f306cceab1 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2020 Ghent University +# Copyright 2020-2023 Vrije Universiteit Brussel # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -24,14 +24,28 @@ ## """ EasyBuild support for building and installing RAxML, implemented as an easyblock + @author: Alex Domingo (Vrije Universiteit Brussel) """ import os from easybuild.easyblocks.generic.makecp import MakeCp from easybuild.framework.easyconfig import CUSTOM -from easybuild.tools.systemtools import get_cpu_features - +from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.systemtools import get_cpu_features, HAVE_ARCHSPEC + +RAXML_BINARY_NAME = "raxmlHPC" +# Supported CPU features grouped by each instruction label +RAXML_CPU_FEATURES = { + 'SSE3': ['sse3', 'see4_1', 'sse4_2'], + 'AVX': ['avx', 'avx1.0'], + 'AVX2': ['avx2'], +} +# Supported parallelization features grouped in non-MPI and MPI +RAXML_PARALLEL_FEATURES = { + 'nompi': [None, 'PTHREADS'], + 'mpi': ['MPI', 'HYBRID'], +} class EB_RAxML(MakeCp): """Support for building and installing RAxML.""" @@ -39,7 +53,7 @@ class EB_RAxML(MakeCp): def extra_options(extra_vars=None): """Change default values of options""" extra = MakeCp.extra_options() - # files_to_copy is not mandatory here + # files_to_copy is not mandatory extra['files_to_copy'][2] = CUSTOM return extra @@ -47,100 +61,81 @@ def __init__(self, *args, **kwargs): """RAxML easyblock constructor, define class variables.""" super(EB_RAxML, self).__init__(*args, **kwargs) - # Set optmization of RAxML build for host micro-architecture - cpuopt_label = { - 'sse3': 'SSE3', - 'sse4_1': 'SSE3', - 'sse4_2': 'SSE3', - 'avx': 'AVX', - 'avx1.0': 'AVX', # on macOS, AVX is indicated with 'avx1.0' rather than 'avx' - 'avx2': 'AVX2', - } - cpu_features = set([label for feat, label in cpuopt_label.items() if feat in get_cpu_features()]) - self.log.debug("Enabling the following CPU optimizations for RAxML: %s", ', '.join(cpu_features)) - cpu_features.update([None]) # add generic build - - # Build features supported by RAxML, grouped in non-MPI and MPI - build_labels = { - 'nompi': [None, 'PTHREADS'], - 'mpi': ['MPI', 'HYBRID'], - } - - # List of Makefiles in the build - makefile = ('Makefile', 'gcc', '.') - # Always build non-MPI variants - self.target_makefiles = { - 'nompi': self.make_filename_variants(cpu_features, build_labels['nompi'], *makefile), - } + def has_cpu_feature(feature): + """ + Check if host CPU architecture has given feature + """ + if HAVE_ARCHSPEC: + import archspec.cpu + host = archspec.cpu.host() + return feature.lower() in host + else: + try: + return any(f in get_cpu_features() for f in RAXML_CPU_FEATURES[feature]) + except KeyError: + raise EasyBuildError("Unknown CPU feature level for RAxML: %s", feature) + + def list_filename_variants(main_features, extra_features, prefix, suffix, divider): + """Returns list of RAxML filenames for the combination of all given features""" + + # Features are expected as lists + if not isinstance(main_features, list): + main_features = list(main_features) + if not isinstance(extra_features, list): + extra_features = list(extra_features) + + # Permutations of features + all_features = [(mf, xf) for mf in main_features for xf in extra_features] + + # Prepend/Append prefix/suffix + print(all_features) + file_variants = [(prefix,) + variant + (suffix,) for variant in all_features] + file_variants = [divider.join([segment for segment in variant if segment]) for variant in file_variants] + print(file_variants) + + return file_variants + + # Set optimization level of RAxML for host micro-architecture + host_cpu_features = [feat for feat in RAXML_CPU_FEATURES if has_cpu_feature(feat)] + self.log.debug("Enabling the following CPU optimizations for RAxML: %s", ', '.join(host_cpu_features)) + # Add generic build + host_cpu_features.append(None) + + # Set parallelization level of RAxML for current toolchain + parallel_features = RAXML_PARALLEL_FEATURES['nompi'] if self.toolchain.options.get('usempi', None): - # Add MPI variants in their own group - self.target_makefiles.update({ - 'mpi': self.make_filename_variants(cpu_features, build_labels['mpi'], *makefile), - }) - - # List of binaries in the installation - binary = ('raxmlHPC', None, '-') - self.target_bin = self.make_filename_variants(build_labels['nompi'], cpu_features, *binary) - if 'mpi' in self.target_makefiles: - self.target_bin.extend(self.make_filename_variants(build_labels['mpi'], cpu_features, *binary)) - - def make_filename_variants(self, main_feature, extra_feature, prefix, suffix, divider): - """Returns list of RAxML filenames for the combination of all given features""" - - # Features are expected as lists - if not isinstance(main_feature, list): - main_feature = list(main_feature) - if not isinstance(extra_feature, list): - extra_feature = list(extra_feature) - - # Permutations of features - if extra_feature: - raxml_variants = [(mf, xf) for mf in main_feature for xf in extra_feature] - else: - raxml_variants = main_feature - - # Prepend/Append prefix/suffix - for n, variant in enumerate(raxml_variants): - full_filename = (prefix,) + variant + (suffix,) - full_filename = tuple(filter(None, full_filename)) # avoid doubling the divider - raxml_variants[n] = divider.join(full_filename) - - return raxml_variants - - def configure_step(self): - """No custom configuration step for RAxML""" - pass + parallel_features.extend(RAXML_PARALLEL_FEATURES['mpi']) + + # List of builds to carry out + self.target_makefiles = list_filename_variants(host_cpu_features, parallel_features, 'Makefile', 'gcc', '.') + self.target_bins = list_filename_variants(parallel_features, host_cpu_features, RAXML_BINARY_NAME, None, '-') def build_step(self): """Build all binaries of RAxML compatible with host CPU architecture""" # Compiler is manually set through 'buildopts' - cc = os.getenv('CC') - # Always use non-MPI compiler for non-MPI Makefiles - if 'mpi' in self.target_makefiles: - cc_seq = os.getenv('CC_SEQ') - else: - cc_seq = os.getenv('CC') + compiler = os.getenv('CC') + compiler_nompi = compiler + if self.toolchain.options.get('usempi', None): + compiler_nompi = os.getenv('CC_SEQ') # Build selected RAxML makefiles user_buildopts = self.cfg['buildopts'] - self.log.debug("Building makefiles of RAxML with %s: %s", cc_seq, ', '.join(self.target_makefiles['nompi'])) - for mf in self.target_makefiles['nompi']: - self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc_seq, user_buildopts) + for mf in self.target_makefiles: + cc_opt = compiler + if not any(feature in mf for feature in RAXML_PARALLEL_FEATURES['mpi']): + cc_opt = compiler_nompi + self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc_opt, user_buildopts) + self.log.debug("Building RAxML makefile with %s: %s", cc_opt, mf) super(EB_RAxML, self).build_step() - if 'mpi' in self.target_makefiles: - self.log.debug("Building makefiles of RAxML with %s: %s", cc, ', '.join(self.target_makefiles['mpi'])) - for mf in self.target_makefiles['mpi']: - self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc, user_buildopts) - super(EB_RAxML, self).build_step() def install_step(self): """Copy files into installation directory""" self.cfg['files_to_copy'] = [ - (self.target_bin, 'bin'), + (self.target_bins, 'bin'), (['README', 'manual', 'usefulScripts'], 'share'), ] super(EB_RAxML, self).install_step() @@ -149,7 +144,7 @@ def sanity_check_step(self): """Custom sanity check for RAxML.""" custom_paths = { - 'files': [os.path.join('bin', x) for x in self.target_bin], + 'files': [os.path.join('bin', x) for x in self.target_bins], 'dirs': ['share/manual', 'share/usefulScripts'] } super(EB_RAxML, self).sanity_check_step(custom_paths=custom_paths) From e5f511483b26ac849a268ea5ed0b651a2138da1f Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 27 Feb 2023 00:56:01 +0100 Subject: [PATCH 5/7] follow optarch settings in RAxML easyblock --- easybuild/easyblocks/r/raxml.py | 119 +++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index f306cceab1..725444661e 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -31,54 +31,91 @@ from easybuild.easyblocks.generic.makecp import MakeCp from easybuild.framework.easyconfig import CUSTOM -from easybuild.tools.build_log import EasyBuildError +from easybuild.tools.build_log import EasyBuildError, print_warning +from easybuild.tools.config import build_option from easybuild.tools.systemtools import get_cpu_features, HAVE_ARCHSPEC +from easybuild.tools.toolchain.compiler import OPTARCH_GENERIC RAXML_BINARY_NAME = "raxmlHPC" -# Supported CPU features grouped by each instruction label +# Supported instruction sets ordered by priority (high to low) and related CPU features +RAXML_INSTRUCT_SETS = ["AVX2", "AVX", "SSE3"] RAXML_CPU_FEATURES = { - 'SSE3': ['sse3', 'see4_1', 'sse4_2'], - 'AVX': ['avx', 'avx1.0'], - 'AVX2': ['avx2'], + "SSE3": ["sse3", "see4_1", "sse4_2"], + "AVX": ["avx", "avx1.0"], + "AVX2": ["avx2"], } # Supported parallelization features grouped in non-MPI and MPI RAXML_PARALLEL_FEATURES = { - 'nompi': [None, 'PTHREADS'], - 'mpi': ['MPI', 'HYBRID'], + "nompi": [None, "PTHREADS"], + "mpi": ["MPI", "HYBRID"], } + class EB_RAxML(MakeCp): """Support for building and installing RAxML.""" + @staticmethod def extra_options(extra_vars=None): """Change default values of options""" extra = MakeCp.extra_options() # files_to_copy is not mandatory - extra['files_to_copy'][2] = CUSTOM + extra["files_to_copy"][2] = CUSTOM return extra def __init__(self, *args, **kwargs): """RAxML easyblock constructor, define class variables.""" super(EB_RAxML, self).__init__(*args, **kwargs) + def filter_optarch_features(support_features): + """ + Filter list of supported CPU instruction sets based on optarch string + """ + if not isinstance(support_features, list): + support_features = list(support_features) + unfilter_features = [feat.upper() for feat in support_features] + + optarch = build_option("optarch") or self.toolchain.options.get("optarch") or "" + if isinstance(optarch, dict): + # optarch is a dictionary with settings per compiler family + comp_fam = self.toolchain.comp_family() + optarch = optarch.get(comp_fam, "") + optarch = optarch.upper() + + # check for generic build + if optarch == OPTARCH_GENERIC: + self.log.debug("Building generic RAxML per optarch setting: %s", optarch) + return [None] + # check for supported labels in optarch (by given priority order) + for instruct_set in unfilter_features: + if instruct_set in optarch: + dbg_msg = "Restricting supported features in RAxML to '%s' per optarch: %s" + self.log.debug(dbg_msg, instruct_set, optarch) + return [instruct_set] + # anything else is unsupported + if optarch: + print_warning("Unsupported 'optarch' configuration setting for RAxML, ignoring: %s" % optarch) + + return support_features + def has_cpu_feature(feature): """ Check if host CPU architecture has given feature """ if HAVE_ARCHSPEC: import archspec.cpu + host = archspec.cpu.host() return feature.lower() in host - else: - try: - return any(f in get_cpu_features() for f in RAXML_CPU_FEATURES[feature]) - except KeyError: - raise EasyBuildError("Unknown CPU feature level for RAxML: %s", feature) - def list_filename_variants(main_features, extra_features, prefix, suffix, divider): - """Returns list of RAxML filenames for the combination of all given features""" + try: + return any(f in get_cpu_features() for f in RAXML_CPU_FEATURES[feature]) + except KeyError: + raise EasyBuildError("Unknown CPU feature level for RAxML: %s", feature) - # Features are expected as lists + def list_filename_variants(main_features, extra_features, prefix, suffix, divider): + """ + Returns list of RAxML filenames for the combination of all given features + """ if not isinstance(main_features, list): main_features = list(main_features) if not isinstance(extra_features, list): @@ -88,55 +125,57 @@ def list_filename_variants(main_features, extra_features, prefix, suffix, divide all_features = [(mf, xf) for mf in main_features for xf in extra_features] # Prepend/Append prefix/suffix - print(all_features) file_variants = [(prefix,) + variant + (suffix,) for variant in all_features] file_variants = [divider.join([segment for segment in variant if segment]) for variant in file_variants] - print(file_variants) return file_variants - # Set optimization level of RAxML for host micro-architecture - host_cpu_features = [feat for feat in RAXML_CPU_FEATURES if has_cpu_feature(feat)] - self.log.debug("Enabling the following CPU optimizations for RAxML: %s", ', '.join(host_cpu_features)) - # Add generic build - host_cpu_features.append(None) + # Filter target CPU instructions sets according to optarch + cpu_features = filter_optarch_features(RAXML_INSTRUCT_SETS) + + if len(cpu_features) > 1: + # unrestricted optimization settings, set optimization level for host micro-architecture + cpu_features = [feat for feat in cpu_features if has_cpu_feature(feat)] + dbg_msg = "Enabling the following CPU optimizations for RAxML by autodetection: %s" + self.log.debug(dbg_msg, ", ".join(cpu_features)) + # add generic build + cpu_features.append(None) # Set parallelization level of RAxML for current toolchain - parallel_features = RAXML_PARALLEL_FEATURES['nompi'] - if self.toolchain.options.get('usempi', None): - parallel_features.extend(RAXML_PARALLEL_FEATURES['mpi']) + parallel_features = RAXML_PARALLEL_FEATURES["nompi"] + if self.toolchain.options.get("usempi", None): + parallel_features.extend(RAXML_PARALLEL_FEATURES["mpi"]) # List of builds to carry out - self.target_makefiles = list_filename_variants(host_cpu_features, parallel_features, 'Makefile', 'gcc', '.') - self.target_bins = list_filename_variants(parallel_features, host_cpu_features, RAXML_BINARY_NAME, None, '-') + self.target_makefiles = list_filename_variants(cpu_features, parallel_features, "Makefile", "gcc", ".") + self.target_bins = list_filename_variants(parallel_features, cpu_features, RAXML_BINARY_NAME, None, "-") def build_step(self): """Build all binaries of RAxML compatible with host CPU architecture""" # Compiler is manually set through 'buildopts' - compiler = os.getenv('CC') + compiler = os.getenv("CC") compiler_nompi = compiler - if self.toolchain.options.get('usempi', None): - compiler_nompi = os.getenv('CC_SEQ') + if self.toolchain.options.get("usempi", None): + compiler_nompi = os.getenv("CC_SEQ") # Build selected RAxML makefiles - user_buildopts = self.cfg['buildopts'] + user_buildopts = self.cfg["buildopts"] for mf in self.target_makefiles: cc_opt = compiler - if not any(feature in mf for feature in RAXML_PARALLEL_FEATURES['mpi']): + if not any(feature in mf for feature in RAXML_PARALLEL_FEATURES["mpi"]): cc_opt = compiler_nompi - self.cfg['buildopts'] = '-f %s CC="%s" %s' % (mf, cc_opt, user_buildopts) + self.cfg["buildopts"] = '-f %s CC="%s" %s' % (mf, cc_opt, user_buildopts) self.log.debug("Building RAxML makefile with %s: %s", cc_opt, mf) super(EB_RAxML, self).build_step() - def install_step(self): """Copy files into installation directory""" - self.cfg['files_to_copy'] = [ - (self.target_bins, 'bin'), - (['README', 'manual', 'usefulScripts'], 'share'), + self.cfg["files_to_copy"] = [ + (self.target_bins, "bin"), + (["README", "manual", "usefulScripts"], "share"), ] super(EB_RAxML, self).install_step() @@ -144,7 +183,7 @@ def sanity_check_step(self): """Custom sanity check for RAxML.""" custom_paths = { - 'files': [os.path.join('bin', x) for x in self.target_bins], - 'dirs': ['share/manual', 'share/usefulScripts'] + "files": [os.path.join("bin", x) for x in self.target_bins], + "dirs": ["share/manual", "share/usefulScripts"], } super(EB_RAxML, self).sanity_check_step(custom_paths=custom_paths) From 8b338076da4cf54754260b477519753cbcd34aee Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 27 Feb 2023 01:05:02 +0100 Subject: [PATCH 6/7] fix optarch fallback chain in RAxML easyblock --- easybuild/easyblocks/r/raxml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index 725444661e..0c7f0401c7 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -74,7 +74,7 @@ def filter_optarch_features(support_features): support_features = list(support_features) unfilter_features = [feat.upper() for feat in support_features] - optarch = build_option("optarch") or self.toolchain.options.get("optarch") or "" + optarch = build_option("optarch") or self.toolchain.options.get("optarch", "") if isinstance(optarch, dict): # optarch is a dictionary with settings per compiler family comp_fam = self.toolchain.comp_family() From 7466ce815ebb933f156b587da987f19bf255c900 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Mon, 27 Feb 2023 01:24:39 +0100 Subject: [PATCH 7/7] consider boolean optarch settings from toolchianopts in RAxML easyblock --- easybuild/easyblocks/r/raxml.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/r/raxml.py b/easybuild/easyblocks/r/raxml.py index 0c7f0401c7..505a6cf453 100644 --- a/easybuild/easyblocks/r/raxml.py +++ b/easybuild/easyblocks/r/raxml.py @@ -75,10 +75,15 @@ def filter_optarch_features(support_features): unfilter_features = [feat.upper() for feat in support_features] optarch = build_option("optarch") or self.toolchain.options.get("optarch", "") + # optarch is a dictionary with settings per compiler family if isinstance(optarch, dict): - # optarch is a dictionary with settings per compiler family comp_fam = self.toolchain.comp_family() optarch = optarch.get(comp_fam, "") + # convert boolean optarch settings to string equivalents + if optarch is False: + optarch = OPTARCH_GENERIC + elif optarch is True: + optarch = "" optarch = optarch.upper() # check for generic build