From 194ef5d47663cc10f006b136720fe7d876efe29a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 15:59:33 +0200 Subject: [PATCH 01/13] Remove super() arguments --- easybuild/easyblocks/l/llvm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 0cc1f17cd7..de448a6693 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -475,7 +475,7 @@ def llvm_src_dir(self): def prepare_step(self, *args, **kwargs): """Prepare step, modified to ensure install dir is deleted before building""" - super(EB_LLVM, self).prepare_step(*args, **kwargs) + super().prepare_step(*args, **kwargs) # re-create installation dir (deletes old installation), # Needed to ensure hardcoded rpath do not point to old installation during runtime builds and testing self.make_installdir() @@ -818,7 +818,7 @@ def configure_step(self): self._prepare_runtimes_rpath_wrappers(self.llvm_obj_dir_stage1) self.add_cmake_opts() trace_msg("Reconfiguring LLVM to use the RPATH wrappers for the runtimes") - super(EB_LLVM, self).configure_step(builddir=self.llvm_obj_dir_stage1, srcdir=src_dir) + super().configure_step(builddir=self.llvm_obj_dir_stage1, srcdir=src_dir) # Pre-create the CFG files in the `build_stage/bin` directory to enforce using the correct dynamic # linker in case of sysroot builds, and to ensure the correct GCC installation is used also for the # runtimes (which would otherwise use the system default dynamic linker) From bb67396d324417a9b3d12b82d9184561b6d861c6 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 4 Jun 2025 16:21:20 +0200 Subject: [PATCH 02/13] Introduce list_to_cmake_arg --- easybuild/easyblocks/generic/cmakemake.py | 7 +++++- easybuild/easyblocks/l/llvm.py | 30 +++++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/easybuild/easyblocks/generic/cmakemake.py b/easybuild/easyblocks/generic/cmakemake.py index ce472f43f7..01e850ab95 100644 --- a/easybuild/easyblocks/generic/cmakemake.py +++ b/easybuild/easyblocks/generic/cmakemake.py @@ -161,6 +161,11 @@ def extra_options(extra_vars=None): }) return extra_vars + @staticmethod + def list_to_cmake_arg(lst): + """Convert iterable of strings to a value that can be passed as a CLI argument to CMake resulting in a list""" + return "'%s'" % ';'.join(lst) + def __init__(self, *args, **kwargs): """Constructor for CMakeMake easyblock""" super().__init__(*args, **kwargs) @@ -356,7 +361,7 @@ def configure_step(self, srcdir=None, builddir=None): options['CMAKE_CUDA_COMPILER'] = which('nvcc') cuda_cc = build_option('cuda_compute_capabilities') or self.cfg['cuda_compute_capabilities'] if cuda_cc: - options['CMAKE_CUDA_ARCHITECTURES'] = '"%s"' % ';'.join([cc.replace('.', '') for cc in cuda_cc]) + options['CMAKE_CUDA_ARCHITECTURES'] = self.list_to_cmake_arg(cc.replace('.', '') for cc in cuda_cc) else: raise EasyBuildError('List of CUDA compute capabilities must be specified, either via ' 'cuda_compute_capabilities easyconfig parameter or via ' diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index de448a6693..baba1ecbf3 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -462,7 +462,7 @@ def __init__(self, *args, **kwargs): self.log.debug("Enabling `amdgpu` offload target") general_opts['CMAKE_BUILD_TYPE'] = self.build_type - general_opts['LLVM_TARGETS_TO_BUILD'] = '"%s"' % ';'.join(build_targets) + general_opts['LLVM_TARGETS_TO_BUILD'] = self.list_to_cmake_arg(build_targets) self._cmakeopts = {} self._cfgopts = list(filter(None, self.cfg.get('configopts', '').split())) @@ -482,14 +482,14 @@ def prepare_step(self, *args, **kwargs): def _add_cmake_runtime_args(self): """Generate the value for 'RUNTIMES_CMAKE_ARGS' and add it to the cmake options.""" - if self.runtimes_cmake_args: - args = [] - for key, val in self.runtimes_cmake_args.items(): - if isinstance(val, list): - val = ' '.join(val) - if val: - args.append('-D%s=%s' % (key, val)) - self._cmakeopts['RUNTIMES_CMAKE_ARGS'] = '"%s"' % ';'.join(args) + args = [] + for key, val in self.runtimes_cmake_args.items(): + if isinstance(val, list): + val = ' '.join(val) + if val: + args.append(f'-D{key}={val}') + if args: + self._cmakeopts['RUNTIMES_CMAKE_ARGS'] = self.list_to_cmake_arg(args) def _configure_general_build(self): """General configuration step for LLVM.""" @@ -498,13 +498,13 @@ def _configure_general_build(self): def _configure_intermediate_build(self): """Configure the intermediate stages of the build.""" - self._cmakeopts['LLVM_ENABLE_PROJECTS'] = '"%s"' % ';'.join(self.intermediate_projects) - self._cmakeopts['LLVM_ENABLE_RUNTIMES'] = '"%s"' % ';'.join(self.intermediate_runtimes) + self._cmakeopts['LLVM_ENABLE_PROJECTS'] = self.list_to_cmake_arg(self.intermediate_projects) + self._cmakeopts['LLVM_ENABLE_RUNTIMES'] = self.list_to_cmake_arg(self.intermediate_runtimes) def _configure_final_build(self): """Configure the final stage of the build.""" - self._cmakeopts['LLVM_ENABLE_PROJECTS'] = '"%s"' % ';'.join(self.final_projects) - self._cmakeopts['LLVM_ENABLE_RUNTIMES'] = '"%s"' % ';'.join(self.final_runtimes) + self._cmakeopts['LLVM_ENABLE_PROJECTS'] = self.list_to_cmake_arg(self.final_projects) + self._cmakeopts['LLVM_ENABLE_RUNTIMES'] = self.list_to_cmake_arg(self.final_runtimes) hwloc_root = get_software_root('hwloc') if hwloc_root: @@ -519,7 +519,7 @@ def _configure_final_build(self): self.runtimes_cmake_args['LIBOMPTARGET_PLUGINS_TO_BUILD'] = '%s' % '|'.join(self.offload_targets) dlopen_plugins = set(self.offload_targets) & set(AVAILABLE_OFFLOAD_DLOPEN_PLUGIN_OPTIONS) if dlopen_plugins: - self._cmakeopts['LIBOMPTARGET_DLOPEN_PLUGINS'] = "'%s'" % ';'.join(dlopen_plugins) + self._cmakeopts['LIBOMPTARGET_DLOPEN_PLUGINS'] = self.list_to_cmake_arg(dlopen_plugins) else: if self.amdgpu_target_cond: self._cmakeopts['LIBOMPTARGET_FORCE_DLOPEN_LIBHSA'] = 'ON' @@ -789,7 +789,7 @@ def configure_step(self): gpu_archs += ['sm_%s' % cc for cc in self.cuda_cc] gpu_archs += self.amd_gfx if gpu_archs: - self.runtimes_cmake_args['LIBOMPTARGET_DEVICE_ARCHITECTURES'] = '%s' % '|'.join(gpu_archs) + self._cmakeopts['LIBOMPTARGET_DEVICE_ARCHITECTURES'] = self.list_to_cmake_arg(gpu_archs) self._configure_general_build() self.add_cmake_opts() From 97d145b37666e2cca2327f042a3a5e21b9c72ddd Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 6 Jun 2025 08:51:11 +0200 Subject: [PATCH 03/13] Don't modify global variables --- easybuild/easyblocks/l/llvm.py | 69 ++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index baba1ecbf3..835a698456 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -81,7 +81,7 @@ 'amdgpu' ] -remove_gcc_dependency_opts = { +GCC_DEPENDENCY_OPTS_DEFAULT = { 'CLANG_DEFAULT_CXX_STDLIB': 'libc++', 'CLANG_DEFAULT_RTLIB': 'compiler-rt', # Moved to general_opts for ease of building with openmp offload (or other multi-stage builds) @@ -117,7 +117,7 @@ 'SANITIZER_USE_STATIC_LLVM_UNWINDER': 'On', } -disable_werror = { +DISABLE_WERROR_OPTS = { 'BENCHMARK_ENABLE_WERROR': 'Off', 'COMPILER_RT_ENABLE_WERROR': 'Off', 'FLANG_ENABLE_WERROR': 'Off', @@ -128,7 +128,7 @@ 'OPENMP_ENABLE_WERROR': 'Off', } -general_opts = { +GENERAL_OPTS = { 'CMAKE_VERBOSE_MAKEFILE': 'ON', 'LLVM_INCLUDE_BENCHMARKS': 'OFF', 'LLVM_INSTALL_UTILS': 'ON', @@ -283,11 +283,13 @@ def __init__(self, *args, **kwargs): if self.cfg['use_pic']: on_opts.append('CMAKE_POSITION_INDEPENDENT_CODE') + self.general_opts = GENERAL_OPTS.copy() + for opt in on_opts: - general_opts[opt] = 'ON' + self.general_opts[opt] = 'ON' for opt in off_opts: - general_opts[opt] = 'OFF' + self.general_opts[opt] = 'OFF' self.full_llvm = self.cfg['full_llvm'] @@ -307,7 +309,7 @@ def __init__(self, *args, **kwargs): self.log.info("Building LLVM without any GCC dependency") if self.cfg['disable_werror']: - general_opts.update(disable_werror) + self.general_opts.update(DISABLE_WERROR_OPTS) if self.cfg['build_runtimes']: self.final_runtimes += ['compiler-rt', 'libunwind', 'libcxx', 'libcxxabi'] @@ -340,30 +342,31 @@ def __init__(self, *args, **kwargs): self.intermediate_projects.append('lld') self.final_projects.append('lld') # This should be the default to make offload multi-stage compilations easier - general_opts['CLANG_DEFAULT_LINKER'] = 'lld' - general_opts['FLANG_DEFAULT_LINKER'] = 'lld' + self.general_opts['CLANG_DEFAULT_LINKER'] = 'lld' + self.general_opts['FLANG_DEFAULT_LINKER'] = 'lld' + self.remove_gcc_dependency_opts = GCC_DEPENDENCY_OPTS_DEFAULT.copy() if self.cfg['build_lldb']: self.final_projects.append('lldb') if self.full_llvm: - remove_gcc_dependency_opts['LLDB_ENABLE_LIBXML2'] = 'Off' - remove_gcc_dependency_opts['LLDB_ENABLE_LZMA'] = 'Off' - remove_gcc_dependency_opts['LLDB_ENABLE_PYTHON'] = 'Off' + self.remove_gcc_dependency_opts['LLDB_ENABLE_LIBXML2'] = 'Off' + self.remove_gcc_dependency_opts['LLDB_ENABLE_LZMA'] = 'Off' + self.remove_gcc_dependency_opts['LLDB_ENABLE_PYTHON'] = 'Off' if self.cfg['build_bolt']: self.final_projects.append('bolt') # Fix for https://github.com/easybuilders/easybuild-easyblocks/issues/3689 if LooseVersion(self.version) < LooseVersion('16'): - general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' + self.general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' # Sysroot self.sysroot = build_option('sysroot') if self.sysroot: if LooseVersion(self.version) < LooseVersion('19'): raise EasyBuildError("Using sysroot is not supported by EasyBuild for LLVM < 19") - general_opts['DEFAULT_SYSROOT'] = self.sysroot - general_opts['CMAKE_SYSROOT'] = self.sysroot + self.general_opts['DEFAULT_SYSROOT'] = self.sysroot + self.general_opts['CMAKE_SYSROOT'] = self.sysroot self._set_dynamic_linker() trace_msg(f"Using '{self.dynamic_linker}' as dynamic linker from sysroot {self.sysroot}") @@ -461,8 +464,8 @@ def __init__(self, *args, **kwargs): self.offload_targets += ['amdgpu'] # Used for LLVM >= 19 self.log.debug("Enabling `amdgpu` offload target") - general_opts['CMAKE_BUILD_TYPE'] = self.build_type - general_opts['LLVM_TARGETS_TO_BUILD'] = self.list_to_cmake_arg(build_targets) + self.general_opts['CMAKE_BUILD_TYPE'] = self.build_type + self.general_opts['LLVM_TARGETS_TO_BUILD'] = self.list_to_cmake_arg(build_targets) self._cmakeopts = {} self._cfgopts = list(filter(None, self.cfg.get('configopts', '').split())) @@ -493,7 +496,7 @@ def _add_cmake_runtime_args(self): def _configure_general_build(self): """General configuration step for LLVM.""" - self._cmakeopts.update(general_opts) + self._cmakeopts.update(self.general_opts) self._add_cmake_runtime_args() def _configure_intermediate_build(self): @@ -596,7 +599,7 @@ def _set_gcc_prefix(self): # https://github.com/llvm/llvm-project/pull/87360 if LooseVersion(self.version) < LooseVersion('19'): self.log.debug("Using GCC_INSTALL_PREFIX") - general_opts['GCC_INSTALL_PREFIX'] = gcc_root + self.general_opts['GCC_INSTALL_PREFIX'] = gcc_root else: # See https://github.com/llvm/llvm-project/pull/85891#issuecomment-2021370667 self.log.debug("Using '--gcc-install-dir' in CMAKE_C_FLAGS and CMAKE_CXX_FLAGS") @@ -696,7 +699,7 @@ def configure_step(self): # CMAKE_INSTALL_PREFIX and LLVM start directory are set here instead of in __init__ to # ensure this easyblock can be used as a Bundle component, see # https://github.com/easybuilders/easybuild-easyblocks/issues/3680 - general_opts['CMAKE_INSTALL_PREFIX'] = self.installdir + self.general_opts['CMAKE_INSTALL_PREFIX'] = self.installdir # Bootstrap self.llvm_obj_dir_stage1 = os.path.join(self.builddir, 'llvm.obj.1') @@ -711,7 +714,7 @@ def configure_step(self): self.log.info("Initialising for single stage build.") self.final_dir = self.llvm_obj_dir_stage1 - general_opts['LLVM_ENABLE_ASSERTIONS'] = 'ON' if self.cfg['assertions'] else 'OFF' + self.general_opts['LLVM_ENABLE_ASSERTIONS'] = 'ON' if self.cfg['assertions'] else 'OFF' # Dependencies based persistent options (should be reused across stages) # Libxml2 @@ -720,36 +723,36 @@ def configure_step(self): if xml2_root: if self.full_llvm: self.log.warning("LLVM is being built in 'full_llvm' mode, libxml2 will not be used") - general_opts['LLVM_ENABLE_LIBXML2'] = 'OFF' + self.general_opts['LLVM_ENABLE_LIBXML2'] = 'OFF' else: - general_opts['LLVM_ENABLE_LIBXML2'] = 'ON' + self.general_opts['LLVM_ENABLE_LIBXML2'] = 'ON' else: - general_opts['LLVM_ENABLE_LIBXML2'] = 'OFF' + self.general_opts['LLVM_ENABLE_LIBXML2'] = 'OFF' # If 'ON', risk finding a system zlib or zstd leading to including /usr/include as -isystem that can lead # to errors during compilation of 'offload.tools.kernelreplay' due to the inclusion of LLVMSupport (19.x) - general_opts['LLVM_ENABLE_ZLIB'] = 'ON' if get_software_root('zlib') else 'OFF' - general_opts['LLVM_ENABLE_ZSTD'] = 'ON' if get_software_root('zstd') else 'OFF' + self.general_opts['LLVM_ENABLE_ZLIB'] = 'ON' if get_software_root('zlib') else 'OFF' + self.general_opts['LLVM_ENABLE_ZSTD'] = 'ON' if get_software_root('zstd') else 'OFF' # Should not use system SWIG if present - general_opts['LLDB_ENABLE_SWIG'] = 'ON' if get_software_root('SWIG') else 'OFF' + self.general_opts['LLDB_ENABLE_SWIG'] = 'ON' if get_software_root('SWIG') else 'OFF' # Avoid using system `gdb` in case it is not provided as a dependency # This could cause the wrong sysroot/dynamic linker being picked up in a sysroot build causing tests to fail - general_opts['LIBOMP_OMPD_GDB_SUPPORT'] = 'ON' if get_software_root('GDB') else 'OFF' + self.general_opts['LIBOMP_OMPD_GDB_SUPPORT'] = 'ON' if get_software_root('GDB') else 'OFF' z3_root = get_software_root("Z3") if z3_root: self.log.info("Using %s as Z3 root", z3_root) - general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'ON' - general_opts['LLVM_Z3_INSTALL_DIR'] = z3_root + self.general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'ON' + self.general_opts['LLVM_Z3_INSTALL_DIR'] = z3_root else: - general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' + self.general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' # update ignore patterns for ignorable test failures self._update_test_ignore_patterns() python_opts = get_cmake_python_config_dict() - general_opts.update(python_opts) + self.general_opts.update(python_opts) self.runtimes_cmake_args.update(python_opts) if self.cfg['bootstrap']: @@ -843,7 +846,7 @@ def configure_step2(self): self._configure_general_build() self._configure_intermediate_build() if self.full_llvm: - self._cmakeopts.update(remove_gcc_dependency_opts) + self._cmakeopts.update(self.remove_gcc_dependency_opts) def configure_step3(self): """Configure the third stage of the bootstrap.""" @@ -854,7 +857,7 @@ def configure_step3(self): # changed when configuring the final build arguments self._add_cmake_runtime_args() if self.full_llvm: - self._cmakeopts.update(remove_gcc_dependency_opts) + self._cmakeopts.update(self.remove_gcc_dependency_opts) def _create_compiler_config_file(self, installdir): """Create a config file for the compiler to point to the correct GCC installation.""" From 2961940547cedadcb8790a57a2499c779e0e2e82 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 15:56:02 +0200 Subject: [PATCH 04/13] Rename usepolly to use_polly --- easybuild/easyblocks/l/llvm.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 835a698456..16fc397895 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -184,7 +184,7 @@ class EB_LLVM(CMakeMake): 'bootstrap', 'full_llvm', 'python_bindings', - 'usepolly', + 'use_polly', ] # Create symlink between equivalent host triples, useful so that other build processes that relies on older @@ -230,7 +230,8 @@ def extra_options(): 'test_suite_timeout_single': [None, "Timeout for each individual test in the test suite", CUSTOM], 'test_suite_timeout_total': [None, "Timeout for total running time of the testsuite", CUSTOM], 'use_pic': [True, "Build with Position Independent Code (PIC)", CUSTOM], - 'usepolly': [False, "Build Clang with polly", CUSTOM], + 'usepolly': [None, "DEPRECATED, alias for 'use_polly'", CUSTOM], + 'use_polly': [False, "Build Clang with polly", CUSTOM], }) return extra_vars @@ -239,6 +240,10 @@ def __init__(self, *args, **kwargs): """Initialize LLVM-specific variables.""" super().__init__(*args, **kwargs) + if self.cfg['usepolly'] is not None: + self.log.deprecated("Use of easyconfig parameter 'usepolly', replace by 'use_polly'", '6.0') + self.cfg['use_polly'] = self.cfg['usepolly'] + self.llvm_obj_dir_stage1 = None self.llvm_obj_dir_stage2 = None self.llvm_obj_dir_stage3 = None @@ -332,7 +337,7 @@ def __init__(self, *args, **kwargs): if not self.cfg['build_openmp']: raise EasyBuildError("Building OpenMP tools requires building OpenMP runtime") - if self.cfg['usepolly']: + if self.cfg['use_polly']: self.final_projects.append('polly') if self.cfg['build_clang_extras']: @@ -548,7 +553,7 @@ def _configure_final_build(self): lit_args += ['--max-time', str(timeout_total)] self._cmakeopts['LLVM_LIT_ARGS'] = '"%s"' % ' '.join(lit_args) - if self.cfg['usepolly']: + if self.cfg['use_polly']: self._cmakeopts['LLVM_POLLY_LINK_INTO_TOOLS'] = 'ON' if not self.cfg['skip_all_tests']: self._cmakeopts['LLVM_INCLUDE_TESTS'] = 'ON' From cb5c9bf8e52136737f3538c8e8a6d825daac0913 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 1 Jul 2025 16:07:30 +0200 Subject: [PATCH 05/13] Don't overwrite use_polly if set --- easybuild/easyblocks/l/llvm.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 16fc397895..1852bc8f7c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -43,7 +43,7 @@ from easybuild.toolchains.compiler.clang import Clang from easybuild.tools import LooseVersion from easybuild.tools.utilities import trace_msg -from easybuild.tools.build_log import EasyBuildError, print_msg +from easybuild.tools.build_log import EasyBuildError, print_msg, print_warning from easybuild.tools.config import ERROR, IGNORE, SEARCH_PATH_LIB_DIRS, build_option from easybuild.tools.environment import setvar from easybuild.tools.filetools import apply_regex_substitutions, change_dir, copy_dir, adjust_permissions @@ -231,7 +231,7 @@ def extra_options(): 'test_suite_timeout_total': [None, "Timeout for total running time of the testsuite", CUSTOM], 'use_pic': [True, "Build with Position Independent Code (PIC)", CUSTOM], 'usepolly': [None, "DEPRECATED, alias for 'use_polly'", CUSTOM], - 'use_polly': [False, "Build Clang with polly", CUSTOM], + 'use_polly': [None, "Build Clang with polly, disabled by default", CUSTOM], }) return extra_vars @@ -242,7 +242,11 @@ def __init__(self, *args, **kwargs): if self.cfg['usepolly'] is not None: self.log.deprecated("Use of easyconfig parameter 'usepolly', replace by 'use_polly'", '6.0') - self.cfg['use_polly'] = self.cfg['usepolly'] + if self.cfg['use_polly'] is None: + self.cfg['use_polly'] = self.cfg['usepolly'] + else: + # Do not overwrite value set via the new name + print_warning("Both 'usepolly' and 'use_polly' are set, please use only 'use_polly'") self.llvm_obj_dir_stage1 = None self.llvm_obj_dir_stage2 = None From 619e7b342c64fb16e96e4276c7b504f65febb4c0 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 15:59:11 +0200 Subject: [PATCH 06/13] Warn when using unknown CPU architecture --- easybuild/easyblocks/l/llvm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 1852bc8f7c..b35702e4a7 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -1332,6 +1332,8 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F arch = 'ppc64' elif arch == AARCH64: arch = 'aarch64' + else: + print_warning("Unknown CPU architecture (%s) for OpenMP and runtime libraries check!" % arch, log=self.log) check_files = [] check_bin_files = [] From 8569dddc4c2d502a5da6e1c737cf1dfff96f8a05 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 16:00:26 +0200 Subject: [PATCH 07/13] Don't check for .mod files --- easybuild/easyblocks/l/llvm.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index b35702e4a7..f79a37503d 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -253,10 +253,12 @@ def __init__(self, *args, **kwargs): self.llvm_obj_dir_stage3 = None self.intermediate_projects = ['llvm', 'clang'] self.intermediate_runtimes = ['compiler-rt', 'libunwind', 'libcxx', 'libcxxabi'] - if not self.cfg['minimal']: - self.final_projects = ['llvm', 'mlir', 'clang', 'flang'] - else: + if self.cfg['minimal']: self.final_projects = ['llvm'] + else: + self.final_projects = ['llvm', 'mlir', 'clang', 'flang'] + # Bypass the .mod file check for GCCcore installs + self.cfg['skip_mod_files_sanity_check'] = True self.final_runtimes = [] self.gcc_prefix = None self.runtimes_cmake_args = { From 4d7f0719d740a59cce095cf6339c18ed792c179c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 16:07:08 +0200 Subject: [PATCH 08/13] Refactor LLVM easyblock - Use f-Strings - Update comments - Use list append/extend --- easybuild/easyblocks/l/llvm.py | 65 +++++++++++++++------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index f79a37503d..4e11e67edd 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -339,9 +339,8 @@ def __init__(self, *args, **kwargs): else: self.log.warning("OpenMP offloading is included with the OpenMP runtime for LLVM < 19") - if self.cfg['build_openmp_tools']: - if not self.cfg['build_openmp']: - raise EasyBuildError("Building OpenMP tools requires building OpenMP runtime") + if self.cfg['build_openmp_tools'] and not self.cfg['build_openmp']: + raise EasyBuildError("Building OpenMP tools requires building OpenMP runtime") if self.cfg['use_polly']: self.final_projects.append('polly') @@ -606,7 +605,8 @@ def _set_gcc_prefix(self): if self.gcc_prefix is None: gcc_root, gcc_prefix = self._get_gcc_prefix() - # --gcc-toolchain and --gcc-install-dir for flang are not supported before LLVM 19 + # For LLVM 18+ config files should be used and this option is deprecated and causes an error in 19 + # But the --gcc-toolchain and --gcc-install-dir for flang are not supported before LLVM 19 # https://github.com/llvm/llvm-project/pull/87360 if LooseVersion(self.version) < LooseVersion('19'): self.log.debug("Using GCC_INSTALL_PREFIX") @@ -614,8 +614,8 @@ def _set_gcc_prefix(self): else: # See https://github.com/llvm/llvm-project/pull/85891#issuecomment-2021370667 self.log.debug("Using '--gcc-install-dir' in CMAKE_C_FLAGS and CMAKE_CXX_FLAGS") - self.runtimes_cmake_args['CMAKE_C_FLAGS'] += ['--gcc-install-dir=%s' % gcc_prefix] - self.runtimes_cmake_args['CMAKE_CXX_FLAGS'] += ['--gcc-install-dir=%s' % gcc_prefix] + self.runtimes_cmake_args['CMAKE_C_FLAGS'].append(f'--gcc-install-dir={gcc_prefix}') + self.runtimes_cmake_args['CMAKE_CXX_FLAGS'].append(f'--gcc-install-dir={gcc_prefix}') self.gcc_prefix = gcc_prefix self.log.debug("Using %s as the gcc install location", self.gcc_prefix) @@ -685,16 +685,15 @@ def configure_step(self): if not self.cfg['minimal'] and LooseVersion(self.version) < LooseVersion('18.1.6'): raise EasyBuildError("LLVM version %s is not supported, please use version 18.1.6 or newer", self.version) - # Allow running with older versions of LLVM for minimal builds in order to replace EB_LLVM easyblock + # Allow running with older versions of GCC for minimal builds in order to replace EB_LLVM easyblock gcc_version = get_software_version('GCCcore') if not self.cfg['minimal'] and LooseVersion(gcc_version) < LooseVersion('13'): raise EasyBuildError("LLVM %s requires GCC 13 or newer, found %s", self.version, gcc_version) # Lit is needed for running tests-suite lit_root = get_software_root('lit') - if not lit_root: - if not self.cfg['skip_all_tests']: - raise EasyBuildError("Can't find 'lit', needed for running tests-suite") + if not lit_root and not self.cfg['skip_all_tests']: + raise EasyBuildError("Can't find 'lit', needed for running tests-suite") timeouts = self.cfg['test_suite_timeout_single'] or self.cfg['test_suite_timeout_total'] if not self.cfg['skip_all_tests'] and timeouts: @@ -949,11 +948,9 @@ def build_with_prev_stage(self, prev_dir, stage_dir): if self.full_llvm: # See https://github.com/llvm/llvm-project/issues/111667 to_add = '--unwindlib=none' - # for flags in ['CMAKE_C_FLAGS', 'CMAKE_CXX_FLAGS']: - for flags in ['CMAKE_EXE_LINKER_FLAGS']: - ptr = self.runtimes_cmake_args[flags] - if to_add not in ptr: - ptr.append(to_add) + flags = self.runtimes_cmake_args['CMAKE_EXE_LINKER_FLAGS'] + if to_add not in flags: + flags.append(to_add) self._add_cmake_runtime_args() @@ -1242,8 +1239,7 @@ def get_runtime_lib_path(self, base_dir, fail_ok=False): # Attempt using the glob based detection of the runtime library directory for runs of # --sanity-check-only/--module-only where the configure step is not used arch = get_arch_prefix() - glob_pattern = os.path.join(base_dir, 'lib', f'{arch}-*') - matches = glob.glob(glob_pattern) + matches = glob.glob(os.path.join(base_dir, 'lib', f'{arch}-*')) if matches: self.host_triple = os.path.basename(matches[0]) else: @@ -1316,7 +1312,7 @@ def _sanity_check_dynamic_linker(self): for suffix in ('.c', '.o', '.x'): remove_file(f'{test_fn}{suffix}') - def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): + def sanity_check_step(self, custom_paths=None, custom_commands=None, *args, **kwargs): """Perform sanity checks on the installed LLVM.""" lib_dir_runtime = None if self.cfg['build_runtimes']: @@ -1325,7 +1321,6 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F resdir_version = self.version.split('.')[0] - # Detect OpenMP support for CPU architecture arch = get_cpu_architecture() # Check architecture explicitly since Clang uses potentially different names if arch == X86_64: @@ -1443,26 +1438,25 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F check_lib_files += ['libbolt_rt_instr.a'] custom_commands += ['llvm-bolt --help'] if 'openmp' in self.final_projects: - omp_lib_files = [] - omp_lib_files += ['libomp.so', 'libompd.so'] + omp_lib_files = ['libomp.so', 'libompd.so'] if self.cfg['build_openmp_offload']: - # Judging from the build process/logs of LLVM 19, the omptarget plugins (rtl..so) are now built - # as static libraries and linked into the libomptarget.so shared library omp_lib_files += ['libomptarget.so'] - if LooseVersion(self.version) < LooseVersion('19'): - omp_lib_files += ['libomptarget.rtl.%s.so' % arch] + # In LLVM 19, the omptarget plugins (rtl..so) are built as static libraries + # and linked into the libomptarget.so shared library + if version < '19': + omp_lib_files += [f'libomptarget.rtl.{arch}.so'] if self.nvptx_target_cond: if LooseVersion(self.version) < LooseVersion('19'): omp_lib_files += ['libomptarget.rtl.cuda.so'] if LooseVersion(self.version) < LooseVersion('20'): - omp_lib_files += ['libomptarget-nvptx-sm_%s.bc' % cc for cc in self.cuda_cc] + omp_lib_files += [f'libomptarget-nvptx-sm_{cc}.bc' for cc in self.cuda_cc] else: omp_lib_files += ['libomptarget-nvptx.bc'] if self.amdgpu_target_cond: if LooseVersion(self.version) < LooseVersion('19'): omp_lib_files += ['libomptarget.rtl.amdgpu.so'] if LooseVersion(self.version) < LooseVersion('20'): - omp_lib_files += ['libomptarget-amdgpu-%s.bc' % gfx for gfx in self.amd_gfx] + omp_lib_files += [f'libomptarget-amdgpu-{gfx}.bc' for gfx in self.amd_gfx] else: omp_lib_files += ['libomptarget-amdgpu.bc'] @@ -1482,20 +1476,19 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F check_files += [os.path.join('lib', 'clang', resdir_version, 'include', 'ompt.h')] if LooseVersion(self.version) < LooseVersion('19'): check_lib_files += ['libarcher.so'] - elif LooseVersion(self.version) >= LooseVersion('19'): + else: check_librt_files += ['libarcher.so'] if self.cfg['python_bindings']: custom_commands += ["python -c 'import clang'"] custom_commands += ["python -c 'import mlir'"] - check_files += [os.path.join('bin', x) for x in check_bin_files] - check_files += [os.path.join('lib', x) for x in check_lib_files] - check_files += [os.path.join(lib_dir_runtime, x) for x in check_librt_files] - check_files += [os.path.join('include', x) for x in check_inc_files] + check_files.extend(os.path.join('bin', x) for x in check_bin_files) + check_files.extend(os.path.join('lib', x) for x in check_lib_files) + check_files.extend(os.path.join(lib_dir_runtime, x) for x in check_librt_files) + check_files.extend(os.path.join('include', x) for x in check_inc_files) - for libso in check_files: - if not libso.endswith('.so'): - continue + so_libs = [lib for lib in check_files if lib.endswith('.so')] + for libso in so_libs: libext = libso.replace('.so', shlib_ext) if libext not in check_files: check_files.remove(libso) @@ -1516,7 +1509,7 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F self._sanity_check_gcc_prefix(gcc_prefix_compilers, self.gcc_prefix, self.installdir) self._sanity_check_dynamic_linker() - return super().sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) + return super().sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands, *args, **kwargs) def make_module_step(self, *args, **kwargs): """ From bfdfd39da6794b5f4664ddbc75991c02b6761d50 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 16:16:04 +0200 Subject: [PATCH 09/13] Don't repeatedly/reduntantly construct a LooseVersion instance `LooseVersion(self.version)` in `sanity_check_step` can be done only once. Comparisons of a LooseVersion to a string already converts the string. --- easybuild/easyblocks/l/llvm.py | 45 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 4e11e67edd..d9795688be 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -333,7 +333,7 @@ def __init__(self, *args, **kwargs): raise EasyBuildError("Building OpenMP offload requires building OpenMP runtime") # LLVM 19 added a new runtime target for explicit offloading # https://discourse.llvm.org/t/llvm-19-1-0-no-library-libomptarget-nvptx-sm-80-bc-found/81343 - if LooseVersion(self.version) >= LooseVersion('19'): + if LooseVersion(self.version) >= '19': self.log.debug("Explicitly enabling OpenMP offloading for LLVM >= 19") self.final_runtimes.append('offload') else: @@ -367,13 +367,13 @@ def __init__(self, *args, **kwargs): self.final_projects.append('bolt') # Fix for https://github.com/easybuilders/easybuild-easyblocks/issues/3689 - if LooseVersion(self.version) < LooseVersion('16'): + if LooseVersion(self.version) < '16': self.general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' # Sysroot self.sysroot = build_option('sysroot') if self.sysroot: - if LooseVersion(self.version) < LooseVersion('19'): + if LooseVersion(self.version) < '19': raise EasyBuildError("Using sysroot is not supported by EasyBuild for LLVM < 19") self.general_opts['DEFAULT_SYSROOT'] = self.sysroot self.general_opts['CMAKE_SYSROOT'] = self.sysroot @@ -458,9 +458,9 @@ def __init__(self, *args, **kwargs): # Enable offload targets for LLVM >= 18 self.cuda_cc = [] self.amd_gfx = [] - if self.cfg['build_openmp_offload'] and LooseVersion(self.version) >= LooseVersion('18'): + if self.cfg['build_openmp_offload'] and LooseVersion(self.version) >= '18': if self.nvptx_target_cond: - if LooseVersion(self.version) < LooseVersion('20') and not cuda_cc_list: + if LooseVersion(self.version) < '20' and not cuda_cc_list: raise EasyBuildError( f"LLVM < 20 requires 'cuda_compute_capabilities' to build with {BUILD_TARGET_NVPTX}" ) @@ -468,7 +468,7 @@ def __init__(self, *args, **kwargs): self.offload_targets += ['cuda'] self.log.debug("Enabling `cuda` offload target") if self.amdgpu_target_cond: - if LooseVersion(self.version) < LooseVersion('20') and not amd_gfx_list: + if LooseVersion(self.version) < '20' and not amd_gfx_list: raise EasyBuildError(f"LLVM < 20 requires 'amd_gfx_list' to build with {BUILD_TARGET_AMDGPU}") self.amd_gfx = amd_gfx_list self.offload_targets += ['amdgpu'] # Used for LLVM >= 19 @@ -528,7 +528,7 @@ def _configure_final_build(self): if 'openmp' in self.final_projects: if self.cfg['build_openmp_offload']: # Force dlopen of the GPU libraries at runtime, not using existing libraries - if LooseVersion(self.version) >= LooseVersion('19'): + if LooseVersion(self.version) >= '19': self.runtimes_cmake_args['LIBOMPTARGET_PLUGINS_TO_BUILD'] = '%s' % '|'.join(self.offload_targets) dlopen_plugins = set(self.offload_targets) & set(AVAILABLE_OFFLOAD_DLOPEN_PLUGIN_OPTIONS) if dlopen_plugins: @@ -608,7 +608,7 @@ def _set_gcc_prefix(self): # For LLVM 18+ config files should be used and this option is deprecated and causes an error in 19 # But the --gcc-toolchain and --gcc-install-dir for flang are not supported before LLVM 19 # https://github.com/llvm/llvm-project/pull/87360 - if LooseVersion(self.version) < LooseVersion('19'): + if LooseVersion(self.version) < '19': self.log.debug("Using GCC_INSTALL_PREFIX") self.general_opts['GCC_INSTALL_PREFIX'] = gcc_root else: @@ -671,7 +671,7 @@ def _update_test_ignore_patterns(self): new_ignore_patterns.append('Flang :: Driver/missing-input.f90') # See https://github.com/llvm/llvm-project/issues/140024 - if LooseVersion(self.version) <= LooseVersion('20.1.5'): + if LooseVersion(self.version) <= '20.1.5': new_ignore_patterns.append('LLVM :: CodeGen/Hexagon/isel/pfalse-v4i1.ll') self.ignore_patterns += new_ignore_patterns @@ -682,12 +682,12 @@ def configure_step(self): Install extra tools in bin/; enable zlib if it is a dep; optionally enable rtti; and set the build target """ # Allow running with older versions of LLVM for minimal builds in order to replace EB_LLVM easyblock - if not self.cfg['minimal'] and LooseVersion(self.version) < LooseVersion('18.1.6'): + if not self.cfg['minimal'] and LooseVersion(self.version) < '18.1.6': raise EasyBuildError("LLVM version %s is not supported, please use version 18.1.6 or newer", self.version) # Allow running with older versions of GCC for minimal builds in order to replace EB_LLVM easyblock gcc_version = get_software_version('GCCcore') - if not self.cfg['minimal'] and LooseVersion(gcc_version) < LooseVersion('13'): + if not self.cfg['minimal'] and LooseVersion(gcc_version) < '13': raise EasyBuildError("LLVM %s requires GCC 13 or newer, found %s", self.version, gcc_version) # Lit is needed for running tests-suite @@ -964,7 +964,7 @@ def build_with_prev_stage(self, prev_dir, stage_dir): self._cmakeopts['CMAKE_ASM_COMPILER_ID'] = 'Clang' # Also runs of the intermediate step compilers should be made aware of the GCC installation - if LooseVersion(self.version) >= LooseVersion('19'): + if LooseVersion(self.version) >= '19': self._create_compiler_config_file(prev_dir) # also pre-create the CFG files in the `build_stage/bin` directory to enforce using the correct dynamic # linker in case of sysroot builds, and to ensure the correct GCC installation is used also for the @@ -1157,7 +1157,7 @@ def test_step(self): """Run tests on final stage (unless disabled).""" if not self.cfg['skip_all_tests']: # Also runs of test suite compilers should be made aware of the GCC installation - if LooseVersion(self.version) >= LooseVersion('19'): + if LooseVersion(self.version) >= '19': self._create_compiler_config_file(self.final_dir) # For nvptx64 tests, find out if 'ptxas' exists in $PATH. If not, ignore all nvptx64 test failures @@ -1213,7 +1213,7 @@ def install_step(self): python_bindings_source_dir = os.path.join(self.start_dir, 'mlir', 'python') copy_dir(python_bindings_source_dir, python_bindins_target_dir, dirs_exist_ok=True) - if LooseVersion(self.version) >= LooseVersion('19'): + if LooseVersion(self.version) >= '19': # For GCC aware installation create config files in order to point to the correct GCC installation # Required as GCC_INSTALL_PREFIX was removed (see https://github.com/llvm/llvm-project/pull/87360) self._create_compiler_config_file(self.installdir) @@ -1320,6 +1320,7 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, *args, **kw shlib_ext = '.' + get_shared_lib_ext() resdir_version = self.version.split('.')[0] + version = LooseVersion(self.version) arch = get_cpu_architecture() # Check architecture explicitly since Clang uses potentially different names @@ -1376,7 +1377,7 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, *args, **kw ] check_dirs += ['include/clang-tidy'] if 'flang' in self.final_projects: - if LooseVersion(self.version) < LooseVersion('19'): + if version < '19': check_bin_files += ['bbc', 'flang-new', 'flang-to-external-fc', 'f18-parse-demo', 'fir-opt', 'tco'] else: check_bin_files += ['bbc', 'flang-new', 'f18-parse-demo', 'fir-opt', 'tco'] @@ -1446,35 +1447,35 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, *args, **kw if version < '19': omp_lib_files += [f'libomptarget.rtl.{arch}.so'] if self.nvptx_target_cond: - if LooseVersion(self.version) < LooseVersion('19'): + if version < '19': omp_lib_files += ['libomptarget.rtl.cuda.so'] - if LooseVersion(self.version) < LooseVersion('20'): + elif version < '20': omp_lib_files += [f'libomptarget-nvptx-sm_{cc}.bc' for cc in self.cuda_cc] else: omp_lib_files += ['libomptarget-nvptx.bc'] if self.amdgpu_target_cond: - if LooseVersion(self.version) < LooseVersion('19'): + if version < '19': omp_lib_files += ['libomptarget.rtl.amdgpu.so'] - if LooseVersion(self.version) < LooseVersion('20'): + elif version < '20': omp_lib_files += [f'libomptarget-amdgpu-{gfx}.bc' for gfx in self.amd_gfx] else: omp_lib_files += ['libomptarget-amdgpu.bc'] - if LooseVersion(self.version) < LooseVersion('19'): + if version < '19': # Before LLVM 19, omp related libraries are installed under 'ROOT/lib'' check_lib_files += omp_lib_files else: # Starting from LLVM 19, omp related libraries are installed the runtime library directory check_librt_files += omp_lib_files check_bin_files += ['llvm-omp-kernel-replay'] - if LooseVersion(self.version) < LooseVersion('20'): + if version < '20': check_bin_files += ['llvm-omp-device-info'] else: check_bin_files += ['llvm-offload-device-info'] if self.cfg['build_openmp_tools']: check_files += [os.path.join('lib', 'clang', resdir_version, 'include', 'ompt.h')] - if LooseVersion(self.version) < LooseVersion('19'): + if version < '19': check_lib_files += ['libarcher.so'] else: check_librt_files += ['libarcher.so'] From d6a7e63a079f5f63b8a008c01c5ae0458a723259 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 6 Jun 2025 13:18:43 +0200 Subject: [PATCH 10/13] Install OpenMP alias symlinks --- easybuild/easyblocks/l/llvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index d9795688be..67d4f44410 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -539,7 +539,7 @@ def _configure_final_build(self): if self.nvptx_target_cond: self._cmakeopts['LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA'] = 'ON' self._cmakeopts['OPENMP_ENABLE_LIBOMPTARGET'] = 'ON' - self._cmakeopts['LIBOMP_INSTALL_ALIASES'] = 'OFF' + self._cmakeopts['LIBOMP_INSTALL_ALIASES'] = 'ON' if not self.cfg['build_openmp_tools']: self._cmakeopts['OPENMP_ENABLE_OMPT_TOOLS'] = 'OFF' From 2f82839fc67f3282e0c48d96e8a831593ba6048d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 30 Jun 2025 16:03:18 +0200 Subject: [PATCH 11/13] Use cfg.get_cuda_cc_template_value to get CUDA CCs --- easybuild/easyblocks/l/llvm.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 67d4f44410..ccdb0e655b 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -382,10 +382,7 @@ def __init__(self, *args, **kwargs): self.ignore_patterns = self.cfg['test_suite_ignore_patterns'] or [] - # list of CUDA compute capabilities to use can be specifed in two ways (where (2) overrules (1)): - # (1) in the easyconfig file, via the custom cuda_compute_capabilities; - # (2) in the EasyBuild configuration, via --cuda-compute-capabilities configuration option; - cuda_cc_list = build_option('cuda_compute_capabilities') or self.cfg['cuda_compute_capabilities'] or [] + cuda_cc_list = self.cfg.get_cuda_cc_template_value("cuda_cc_space_sep", required=False).split() cuda_toolchain = hasattr(self.toolchain, 'COMPILER_CUDA_FAMILY') amd_gfx_list = self.cfg['amd_gfx_list'] or [] @@ -797,9 +794,9 @@ def configure_step(self): if not get_software_root('CUDA'): setvar('CUDA_NVCC_EXECUTABLE', 'IGNORE') - if self.cfg['build_openmp_offload'] and LooseVersion('19') <= LooseVersion(self.version) < LooseVersion('20'): - gpu_archs = [] - gpu_archs += ['sm_%s' % cc for cc in self.cuda_cc] + # 20.1+ uses a generic IR for OpenMP DeviceRTL + if self.cfg['build_openmp_offload'] and LooseVersion(self.version) < '20.1': + gpu_archs = self.cfg.get_cuda_cc_template_value("cuda_sm_space_sep", required=False).split() gpu_archs += self.amd_gfx if gpu_archs: self._cmakeopts['LIBOMPTARGET_DEVICE_ARCHITECTURES'] = self.list_to_cmake_arg(gpu_archs) From 631bb23a8b75ae2a858a60e527a6fb7f031ef153 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 4 Jun 2025 09:25:20 +0200 Subject: [PATCH 12/13] Fix use of CUDA CCs in LLVM easyblock and cleanup --- easybuild/easyblocks/l/llvm.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index ccdb0e655b..31d20037ef 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -526,7 +526,7 @@ def _configure_final_build(self): if self.cfg['build_openmp_offload']: # Force dlopen of the GPU libraries at runtime, not using existing libraries if LooseVersion(self.version) >= '19': - self.runtimes_cmake_args['LIBOMPTARGET_PLUGINS_TO_BUILD'] = '%s' % '|'.join(self.offload_targets) + self._cmakeopts['LIBOMPTARGET_PLUGINS_TO_BUILD'] = self.list_to_cmake_arg(self.offload_targets) dlopen_plugins = set(self.offload_targets) & set(AVAILABLE_OFFLOAD_DLOPEN_PLUGIN_OPTIONS) if dlopen_plugins: self._cmakeopts['LIBOMPTARGET_DLOPEN_PLUGINS'] = self.list_to_cmake_arg(dlopen_plugins) @@ -1457,18 +1457,17 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, *args, **kw omp_lib_files += [f'libomptarget-amdgpu-{gfx}.bc' for gfx in self.amd_gfx] else: omp_lib_files += ['libomptarget-amdgpu.bc'] - - if version < '19': - # Before LLVM 19, omp related libraries are installed under 'ROOT/lib'' - check_lib_files += omp_lib_files + check_bin_files += ['llvm-omp-kernel-replay'] + if version < '20': + check_bin_files += ['llvm-omp-device-info'] else: - # Starting from LLVM 19, omp related libraries are installed the runtime library directory - check_librt_files += omp_lib_files - check_bin_files += ['llvm-omp-kernel-replay'] - if version < '20': - check_bin_files += ['llvm-omp-device-info'] - else: - check_bin_files += ['llvm-offload-device-info'] + check_bin_files += ['llvm-offload-device-info'] + if version < '19': + # Before LLVM 19, omp related libraries are installed under 'ROOT/lib'' + check_lib_files += omp_lib_files + else: + # Starting from LLVM 19, omp related libraries are installed the runtime library directory + check_librt_files += omp_lib_files if self.cfg['build_openmp_tools']: check_files += [os.path.join('lib', 'clang', resdir_version, 'include', 'ompt.h')] From 5ae5722ec5320a185573581e19a59a9bfec86179 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 1 Jul 2025 17:48:25 +0200 Subject: [PATCH 13/13] Set LIBOMPTARGET_DEVICE_ARCHITECTURES only for LLVM 19 This was done by previous versions of the easyblock and not using the default for LLVM 18 (which is "all", i.e. all supported CUDA CCs) might break tests. --- easybuild/easyblocks/l/llvm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 31d20037ef..24124f86d8 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -795,7 +795,8 @@ def configure_step(self): setvar('CUDA_NVCC_EXECUTABLE', 'IGNORE') # 20.1+ uses a generic IR for OpenMP DeviceRTL - if self.cfg['build_openmp_offload'] and LooseVersion(self.version) < '20.1': + # Using the default ("all") for LLVM < 19 to keep behavior of previous versions of the easyblock + if self.cfg['build_openmp_offload'] and '19' <= LooseVersion(self.version) < '20.1': gpu_archs = self.cfg.get_cuda_cc_template_value("cuda_sm_space_sep", required=False).split() gpu_archs += self.amd_gfx if gpu_archs: