From 11cccdc71d470385f4d73c71a8f2398da4fbda53 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 10:58:22 +0200 Subject: [PATCH 01/27] Ensure sysroot dynamic linker is used --- easybuild/easyblocks/l/llvm.py | 61 +++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 2143c1d32f..784da5443c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -354,10 +354,10 @@ def __init__(self, *args, **kwargs): general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' # Sysroot - sysroot = build_option('sysroot') - if sysroot: - general_opts['DEFAULT_SYSROOT'] = sysroot - general_opts['CMAKE_SYSROOT'] = sysroot + self.sysroot = build_option('sysroot') + if self.sysroot: + general_opts['DEFAULT_SYSROOT'] = self.sysroot + general_opts['CMAKE_SYSROOT'] = self.sysroot # 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; @@ -745,13 +745,29 @@ def configure_step3(self): if self.full_llvm: self._cmakeopts.update(remove_gcc_dependency_opts) - @staticmethod - def _create_compiler_config_file(compilers, gcc_prefix, installdir): + def _create_compiler_config_file(self, installdir): """Create a config file for the compiler to point to the correct GCC installation.""" + self._set_gcc_prefix() bin_dir = os.path.join(installdir, 'bin') - prefix_str = '--gcc-install-dir=%s' % gcc_prefix - for comp in compilers: - write_file(os.path.join(bin_dir, f'{comp}.cfg'), prefix_str) + opts = [f'--gcc-toolchain={self.gcc_prefix}'] + + if self.sysroot: + linkers = glob.glob(os.path.join(self.sysroot, '**', 'ld-*.so*')) + for linker in linkers: + if os.path.isfile(linker): + self.log.debug("Using linker %s from sysroot", linker) + opts.append(f'-Wl,-dynamic-linker,{linker}') + else: + msg = f"No linker found in sysroot {self.sysroot}, using default linker" + trace_msg(msg) + self.log.warning(msg) + # The --dyld-prefix flag exists, but beside being poorly documented it is also not supported by flang + # https://reviews.llvm.org/D851 + # prefix = self.sysroot.rstrip('/') + # opts.append(f'--dyld-prefix={prefix}') + + for comp in self.cfg_compilers: + write_file(os.path.join(bin_dir, f'{comp}.cfg'), ' '.join(opts)) def build_with_prev_stage(self, prev_dir, stage_dir): """Build LLVM using the previous stage.""" @@ -826,7 +842,7 @@ def build_with_prev_stage(self, prev_dir, stage_dir): # Also runs of the intermediate step compilers should be made aware of the GCC installation if LooseVersion(self.version) >= LooseVersion('19'): self._set_gcc_prefix() - self._create_compiler_config_file(self.cfg_compilers, self.gcc_prefix, prev_dir) + self._create_compiler_config_file(prev_dir) self.add_cmake_opts() @@ -1011,7 +1027,7 @@ def test_step(self): # Also runs of test suite compilers should be made aware of the GCC installation if LooseVersion(self.version) >= LooseVersion('19'): self._set_gcc_prefix() - self._create_compiler_config_file(self.cfg_compilers, self.gcc_prefix, self.final_dir) + self._create_compiler_config_file(self.final_dir) self.ignore_patterns = self.cfg['test_suite_ignore_patterns'] or [] @@ -1072,7 +1088,7 @@ def install_step(self): # 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._set_gcc_prefix() - self._create_compiler_config_file(self.cfg_compilers, self.gcc_prefix, self.installdir) + self._create_compiler_config_file(self.installdir) # This is needed as some older build system will select a different naming scheme for the library leading to # The correct target <__config_site> and libclang_rt.builtins.a not being found @@ -1138,6 +1154,26 @@ def _sanity_check_gcc_prefix(compilers, gcc_prefix, installdir): error_msg = f"GCC installation path '{check_prefix}' does not match expected path '{gcc_prefix}'" raise EasyBuildError(error_msg) + def _sanity_check_dynamic_linker(self): + """Check if the dynamic linker is correct.""" + if self.sysroot: + c_name = 'abcdefg.c' + o_name = 'abcdefg.o' + x_name = 'abcdefg.x' + with open(c_name, 'w', encoding='utf-8') as f: + f.write('#include \n') + f.write('int main() { printf("Hello World\\n"); return 0; }\n') + cmd = f"{os.path.join(self.installdir, 'bin', 'clang')} -o {o_name} -c {c_name}" + run_shell_cmd(cmd, fail_on_error=True) + cmd = f"{os.path.join(self.installdir, 'bin', 'clang')} -v -o {x_name} {o_name}" + res = run_shell_cmd(cmd, fail_on_error=True) + out = res.output + + # Check if the dynamic linker is set to the sysroot + if self.sysroot not in out: + error_msg = f"Dynamic linker is not set to the sysroot '{self.sysroot}'" + raise EasyBuildError(error_msg) + def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM.""" lib_dir_runtime = None @@ -1333,6 +1369,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) else: 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) From 10c0565468a5882c2d4ea6d71a6a16b7f1aff137 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 11:04:34 +0200 Subject: [PATCH 02/27] Improved sanity_check --- easybuild/easyblocks/l/llvm.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 784da5443c..1bb2a04094 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -1174,6 +1174,16 @@ def _sanity_check_dynamic_linker(self): error_msg = f"Dynamic linker is not set to the sysroot '{self.sysroot}'" raise EasyBuildError(error_msg) + cmd = f'./{x_name}' + res = run_shell_cmd(cmd, fail_on_error=False) + if res.exit_code != EasyBuildExit.SUCCESS: + error_msg = f"Failed to run the compiled executable '{x_name}' for testing the dynamic linker" + raise EasyBuildError(error_msg) + + remove_file(c_name) + remove_file(o_name) + remove_file(x_name) + def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM.""" lib_dir_runtime = None @@ -1367,9 +1377,10 @@ def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=F # Required for 'clang -v' to work if linked to LLVM runtimes with _wrap_env(ld_path=os.path.join(self.installdir, lib_dir_runtime)): self._sanity_check_gcc_prefix(gcc_prefix_compilers, self.gcc_prefix, self.installdir) + self._sanity_check_dynamic_linker() else: self._sanity_check_gcc_prefix(gcc_prefix_compilers, self.gcc_prefix, self.installdir) - self._sanity_check_dynamic_linker() + self._sanity_check_dynamic_linker() return super().sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) From d755cb73f2e4b49ac4cd835cacf55d107d124a6c Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 12:14:01 +0200 Subject: [PATCH 03/27] IMproved logic and logging --- easybuild/easyblocks/l/llvm.py | 36 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 1bb2a04094..c6791f45ae 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -256,6 +256,7 @@ def __init__(self, *args, **kwargs): self.offload_targets = ['host'] # self._added_librt = None self.host_triple = None + self.dynamic_linker = None # Shared off_opts, on_opts = [], [] @@ -354,10 +355,12 @@ def __init__(self, *args, **kwargs): general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' # Sysroot - self.sysroot = build_option('sysroot') - if self.sysroot: - general_opts['DEFAULT_SYSROOT'] = self.sysroot - general_opts['CMAKE_SYSROOT'] = self.sysroot + sysroot = build_option('sysroot') + if sysroot: + general_opts['DEFAULT_SYSROOT'] = sysroot + general_opts['CMAKE_SYSROOT'] = sysroot + self._set_dynamic_linker() + trace_msg(f"Using '{self.dynamic_linker}' as dynamic linker from sysroot {sysroot}") # 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; @@ -566,6 +569,19 @@ def _set_gcc_prefix(self): self.gcc_prefix = gcc_prefix self.log.debug("Using %s as the gcc install location", self.gcc_prefix) + def _set_dynamic_linker(self): + """Set the dynamic linker for the build if not the default one.""" + if self.sysroot: + linkers = glob.glob(os.path.join(self.sysroot, '**', 'ld-*.so*')) + for linker in linkers: + if os.path.isfile(linker): + self.log.info("Using linker %s from sysroot", linker) + self.dynamic_linker = linker + else: + msg = f"No linker found in sysroot {self.sysroot}, using default linker" + trace_msg(msg) + self.log.warning(msg) + def configure_step(self): """ Install extra tools in bin/; enable zlib if it is a dep; optionally enable rtti; and set the build target @@ -751,16 +767,8 @@ def _create_compiler_config_file(self, installdir): bin_dir = os.path.join(installdir, 'bin') opts = [f'--gcc-toolchain={self.gcc_prefix}'] - if self.sysroot: - linkers = glob.glob(os.path.join(self.sysroot, '**', 'ld-*.so*')) - for linker in linkers: - if os.path.isfile(linker): - self.log.debug("Using linker %s from sysroot", linker) - opts.append(f'-Wl,-dynamic-linker,{linker}') - else: - msg = f"No linker found in sysroot {self.sysroot}, using default linker" - trace_msg(msg) - self.log.warning(msg) + if self.dynamic_linker: + opts.append(f'-Wl,-dynamic-linker,{self.dynamic_linker}') # The --dyld-prefix flag exists, but beside being poorly documented it is also not supported by flang # https://reviews.llvm.org/D851 # prefix = self.sysroot.rstrip('/') From a7e531ff5e5f84f7f90ba3c6397e0ce4dd347e18 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 12:15:54 +0200 Subject: [PATCH 04/27] Fix --- easybuild/easyblocks/l/llvm.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index c6791f45ae..3509a8e572 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -355,12 +355,12 @@ def __init__(self, *args, **kwargs): general_opts['LLVM_INCLUDE_GO_TESTS'] = 'OFF' # Sysroot - sysroot = build_option('sysroot') - if sysroot: - general_opts['DEFAULT_SYSROOT'] = sysroot - general_opts['CMAKE_SYSROOT'] = sysroot + self.sysroot = build_option('sysroot') + if self.sysroot: + general_opts['DEFAULT_SYSROOT'] = self.sysroot + general_opts['CMAKE_SYSROOT'] = self.sysroot self._set_dynamic_linker() - trace_msg(f"Using '{self.dynamic_linker}' as dynamic linker from sysroot {sysroot}") + trace_msg(f"Using '{self.dynamic_linker}' as dynamic linker from sysroot {self.sysroot}") # 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; From 1f6b5e7a1585c10f189e2fc178d5bc75f4da76da Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 12:23:56 +0200 Subject: [PATCH 05/27] Fix not escaping loop once linker is found --- easybuild/easyblocks/l/llvm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 3509a8e572..da184e6546 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -577,6 +577,7 @@ def _set_dynamic_linker(self): if os.path.isfile(linker): self.log.info("Using linker %s from sysroot", linker) self.dynamic_linker = linker + break else: msg = f"No linker found in sysroot {self.sysroot}, using default linker" trace_msg(msg) From 10c5d8cf8b033451c05f8867695b1155da761cb1 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 14:08:44 +0200 Subject: [PATCH 06/27] Do not use symlinks as the dynamic linker --- 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 da184e6546..2b8ecd107d 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -574,7 +574,7 @@ def _set_dynamic_linker(self): if self.sysroot: linkers = glob.glob(os.path.join(self.sysroot, '**', 'ld-*.so*')) for linker in linkers: - if os.path.isfile(linker): + if os.path.isfile(linker) and not os.path.islink(linker): self.log.info("Using linker %s from sysroot", linker) self.dynamic_linker = linker break From dfa308fac4396b42a459c80736a04afa073205af Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 14:29:23 +0200 Subject: [PATCH 07/27] Fix wrong parameter name --- 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 2b8ecd107d..3436681185 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -766,7 +766,7 @@ def _create_compiler_config_file(self, installdir): """Create a config file for the compiler to point to the correct GCC installation.""" self._set_gcc_prefix() bin_dir = os.path.join(installdir, 'bin') - opts = [f'--gcc-toolchain={self.gcc_prefix}'] + opts = [f'--gcc-install-dir={self.gcc_prefix}'] if self.dynamic_linker: opts.append(f'-Wl,-dynamic-linker,{self.dynamic_linker}') From f6d7df21c988fa69c02d77139eef92a656e6dc9e Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 21:42:00 +0200 Subject: [PATCH 08/27] Test adding the GCCcore libs to the cfg files --- easybuild/easyblocks/l/llvm.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 3436681185..92d2b0daa3 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -775,6 +775,18 @@ def _create_compiler_config_file(self, installdir): # prefix = self.sysroot.rstrip('/') # opts.append(f'--dyld-prefix={prefix}') + # Check, for a non `full_llvm` build, if GCCcore is in the LIBRARY_PATH, and if not add it + # This is needed as the runtimes tests will not add the -L option to the linker command line for GCCcore + # otherwise + if not self.full_llvm: + gcc_root = get_software_root('GCCcore') + gcc_lib = os.path.join(gcc_root, 'lib64') + library_path = os.getenv('LLIBRARY_PATH', '') + if gcc_lib not in library_path: + self.log.info("Adding GCCcore libraries location `%s` the config files", gcc_lib) + lib_path = f"{gcc_lib}:{lib_path}" if lib_path else gcc_lib + opts.append(f'-L{lib_path}') + for comp in self.cfg_compilers: write_file(os.path.join(bin_dir, f'{comp}.cfg'), ' '.join(opts)) From e156ff21f97485095ca5e65c0cb0f7e2a9d205a4 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 28 May 2025 21:44:29 +0200 Subject: [PATCH 09/27] Fix name --- 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 92d2b0daa3..7519d3dbdd 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -781,8 +781,8 @@ def _create_compiler_config_file(self, installdir): if not self.full_llvm: gcc_root = get_software_root('GCCcore') gcc_lib = os.path.join(gcc_root, 'lib64') - library_path = os.getenv('LLIBRARY_PATH', '') - if gcc_lib not in library_path: + lib_path = os.getenv('LLIBRARY_PATH', '') + if gcc_lib not in lib_path: self.log.info("Adding GCCcore libraries location `%s` the config files", gcc_lib) lib_path = f"{gcc_lib}:{lib_path}" if lib_path else gcc_lib opts.append(f'-L{lib_path}') From 61bce01d8de0cf6b03b2cc01765d016c00111665 Mon Sep 17 00:00:00 2001 From: Davide Grassano <34096612+Crivella@users.noreply.github.com> Date: Wed, 28 May 2025 23:21:42 +0200 Subject: [PATCH 10/27] Update easybuild/easyblocks/l/llvm.py Co-authored-by: ocaisa --- 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 7519d3dbdd..5ed5cd7a6c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -781,7 +781,7 @@ def _create_compiler_config_file(self, installdir): if not self.full_llvm: gcc_root = get_software_root('GCCcore') gcc_lib = os.path.join(gcc_root, 'lib64') - lib_path = os.getenv('LLIBRARY_PATH', '') + lib_path = os.getenv('LIBRARY_PATH', '') if gcc_lib not in lib_path: self.log.info("Adding GCCcore libraries location `%s` the config files", gcc_lib) lib_path = f"{gcc_lib}:{lib_path}" if lib_path else gcc_lib From ff5f64c89b62fb91aa44db18b2b2d30dbd7f49ee Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 2 Jun 2025 10:16:14 +0200 Subject: [PATCH 11/27] WIP: enforce dynamic linker also for runtimes --- easybuild/easyblocks/l/llvm.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 5ed5cd7a6c..865eae07c2 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -864,6 +864,10 @@ def build_with_prev_stage(self, prev_dir, stage_dir): if LooseVersion(self.version) >= LooseVersion('19'): self._set_gcc_prefix() self._create_compiler_config_file(prev_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) + self._create_compiler_config_file(stage_dir) self.add_cmake_opts() From 253bc9997a9d03beeff5cc245eea086d0f38ea23 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 2 Jun 2025 13:32:49 +0200 Subject: [PATCH 12/27] -L only GCCcore --- easybuild/easyblocks/l/llvm.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 865eae07c2..7bdf0f8c4c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -784,8 +784,7 @@ def _create_compiler_config_file(self, installdir): lib_path = os.getenv('LIBRARY_PATH', '') if gcc_lib not in lib_path: self.log.info("Adding GCCcore libraries location `%s` the config files", gcc_lib) - lib_path = f"{gcc_lib}:{lib_path}" if lib_path else gcc_lib - opts.append(f'-L{lib_path}') + opts.append(f'-L{gcc_lib}') for comp in self.cfg_compilers: write_file(os.path.join(bin_dir, f'{comp}.cfg'), ' '.join(opts)) From 0b8e4aed739bbb46d59a80a40770187eb8550509 Mon Sep 17 00:00:00 2001 From: crivella Date: Mon, 2 Jun 2025 13:47:25 +0200 Subject: [PATCH 13/27] Added creation of CFG file also for stage 1 in case of non-bootstrap build --- easybuild/easyblocks/l/llvm.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 7bdf0f8c4c..8df69a0bd6 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -721,14 +721,19 @@ def configure_step(self): else: self.log.warning("`LLVM_HOST_TRIPLE` not found in the output of the configure step") - if not self.cfg['bootstrap'] and build_option('rpath') and self._cmakeopts['LLVM_ENABLE_RUNTIMES'] != '""': - # Ensure RPATH wrappers are used for the runtimes also at the first stage - # Call configure again now that the host triple is known from the previous configure call - remove_dir(self.llvm_obj_dir_stage1) - 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) + if not self.cfg['bootstrap']: + if build_option('rpath') and self._cmakeopts['LLVM_ENABLE_RUNTIMES'] != '""': + # Ensure RPATH wrappers are used for the runtimes also at the first stage + # Call configure again now that the host triple is known from the previous configure call + remove_dir(self.llvm_obj_dir_stage1) + 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) + # 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) + self._create_compiler_config_file(self.llvm_obj_dir_stage1) def disable_sanitizer_tests(self): """Disable the tests of all the sanitizers by removing the test directories from the build system""" From 804b22b400722d2086a5545ea9f690b4eb6035b9 Mon Sep 17 00:00:00 2001 From: crivella Date: Tue, 3 Jun 2025 11:25:26 +0200 Subject: [PATCH 14/27] WIP: Make tests pick up correct `libstdc++.so` --- easybuild/easyblocks/l/llvm.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 8df69a0bd6..7509ce1220 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -550,6 +550,20 @@ def _get_gcc_prefix(): return gcc_root, gcc_prefix + @staticmethod + def _get_gcc_libpath(strict=False): + """Get the GCC library path for the build.""" + gcc_root = get_software_root('GCCcore') + if gcc_root is None: + gcc_root = get_software_root('GCC') + if gcc_root is None: + if strict: + raise EasyBuildError("Can't find GCC or GCCcore to use") + else: + print_msg("Can't find GCC or GCCcore to use, skipping setting of GCC library path", level=IGNORE) + return '' + return os.path.join(gcc_root, 'lib64') + def _set_gcc_prefix(self): """Set the GCC prefix for the build.""" if self.gcc_prefix is None: @@ -784,8 +798,7 @@ def _create_compiler_config_file(self, installdir): # This is needed as the runtimes tests will not add the -L option to the linker command line for GCCcore # otherwise if not self.full_llvm: - gcc_root = get_software_root('GCCcore') - gcc_lib = os.path.join(gcc_root, 'lib64') + gcc_lib = self._get_gcc_libpath(strict=True) lib_path = os.getenv('LIBRARY_PATH', '') if gcc_lib not in lib_path: self.log.info("Adding GCCcore libraries location `%s` the config files", gcc_lib) @@ -999,6 +1012,11 @@ def _para_test_step(self, parallel=1): if self.cfg['build_runtimes']: lib_dir_runtime = self.get_runtime_lib_path(basedir) lib_path = os.path.join(basedir, lib_dir_runtime) + if not self.full_llvm: + # Add the GCC library path to the LD_LIBRARY_PATH if it is not already there to ensure correct + # libstdc++ and libgcc_s.so are used for tests + gcc_lib = self._get_gcc_libpath(strict=True) + lib_path = ':'.join(filter(None, [gcc_lib, lib_path])) with _wrap_env(os.path.join(basedir, 'bin'), lib_path): cmd = f"make -j {parallel} check-all" From 6a2ec62fc939c6299a001eec822bd82c693a1049 Mon Sep 17 00:00:00 2001 From: crivella Date: Tue, 3 Jun 2025 15:41:53 +0200 Subject: [PATCH 15/27] Some ompd tests will end up using the system GDB that can pick the wrong libraries in case of sysroot --- 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 7509ce1220..27013416cd 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -674,6 +674,8 @@ def configure_step(self): # Should not use system SWIG if present general_opts['LLDB_ENABLE_SWIG'] = 'ON' if get_software_root('SWIG') else 'OFF' + 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) From 73f6227e5e8dfab6256c7ea661d82f4ec7c3fd68 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 4 Jun 2025 12:08:32 +0200 Subject: [PATCH 16/27] Add fix to always use default configuration files in `compiler-rt` tests --- easybuild/easyblocks/l/llvm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 27013416cd..f4c3fd7831 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -703,6 +703,15 @@ def configure_step(self): regex_subs.append((r'add_subdirectory\(bindings/python/tests\)', '')) apply_regex_substitutions(cmakelists_tests, regex_subs) + # Remove flags disabling the use of configuration files during compiler-rt tests as we in general relies on + # them (See https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2939404304) + lit_cfg_file = os.path.join(self.llvm_src_dir, 'compiler-rt', 'test', 'lit.common.cfg.py') + regex_subs = [ + (r'^if config.has_no_default_config_flag:', ''), + (r'^\s*config.environment\["CLANG_NO_DEFAULT_CONFIG"\] = "1"', '') + ] + apply_regex_substitutions(lit_cfg_file, regex_subs) + self._set_gcc_prefix() # If we don't want to build with CUDA (not in dependencies) trick CMakes FindCUDA module into not finding it by From 41596a15f939320be07484151f899a140c229348 Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 4 Jun 2025 12:17:05 +0200 Subject: [PATCH 17/27] Added more descriptions --- 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 f4c3fd7831..2b99cab294 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -674,6 +674,8 @@ def configure_step(self): # Should not use system SWIG if present 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' z3_root = get_software_root("Z3") From 735af23141a8ac3ce86b6993d9ed0b2e6c097e1c Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 4 Jun 2025 16:23:25 +0200 Subject: [PATCH 18/27] Ignore tests failing due to hardcoded paths that do no account for `sysroot` in test's `FileCheck` calls --- easybuild/easyblocks/l/llvm.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 2b99cab294..52484b6a5f 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -362,6 +362,8 @@ def __init__(self, *args, **kwargs): self._set_dynamic_linker() trace_msg(f"Using '{self.dynamic_linker}' as dynamic linker from sysroot {self.sysroot}") + 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; @@ -686,6 +688,27 @@ def configure_step(self): else: general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' + if self.sysroot: + # Some tests will run a FileCheck on the output of `clang -v` for `-internal-externc-isystem /usr/include` + # where the path is hardcoded. If sysroot is set we replace that path by prepending the sysroot to it. + # The changes needed varies from file to file and are not the same across versions. + # Since this seems to be more of a problem with the test-suite settings than using the compilers + # we can probably safely ignore these tests. + known_driver_files = [ + 'baremetal.cpp', 'csky-toolchain.c', 'freebsd-include-paths.c', + 'haiku.c', 'hexagon-toolchain-elf.c', 'hexagon-toolchain-linux.c', + 'mips-cs.cpp', 'mips-fsf.cpp', 'mips-img-v2.cpp', 'mips-img.cpp', + 'riscv32-toolchain-extra.c', 'riscv64-toolchain-extra.c', + 'rocm-detect.hip', + ] + known_frontend_files = [ + 'warning-poison-system-directories.c' + ] + for file in known_driver_files: + self.ignore_patterns.append(f'Clang :: Driver/{file}') + for file in known_frontend_files: + self.ignore_patterns.append(f'Clang :: Frontend/{file}') + python_opts = get_cmake_python_config_dict() general_opts.update(python_opts) self.runtimes_cmake_args.update(python_opts) @@ -1089,8 +1112,6 @@ def test_step(self): self._set_gcc_prefix() self._create_compiler_config_file(self.final_dir) - self.ignore_patterns = self.cfg['test_suite_ignore_patterns'] or [] - # For nvptx64 tests, find out if 'ptxas' exists in $PATH. If not, ignore all nvptx64 test failures pxtas_path = which('ptxas', on_error=IGNORE) if self.nvptx_target_cond and not pxtas_path: From 6a44669d9ed78576f5dc9b93983eeef85e7ea24f Mon Sep 17 00:00:00 2001 From: crivella Date: Wed, 4 Jun 2025 16:25:15 +0200 Subject: [PATCH 19/27] More verbose --- easybuild/easyblocks/l/llvm.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 52484b6a5f..b744236597 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -704,10 +704,15 @@ def configure_step(self): known_frontend_files = [ 'warning-poison-system-directories.c' ] + prev = self.ignore_patterns.copy() for file in known_driver_files: self.ignore_patterns.append(f'Clang :: Driver/{file}') for file in known_frontend_files: self.ignore_patterns.append(f'Clang :: Frontend/{file}') + self.log.info( + f"Ignore patterns for tests updated from {prev} to {self.ignore_patterns} to avoid known ignorable " + "failures with sysroot builds." + ) python_opts = get_cmake_python_config_dict() general_opts.update(python_opts) From 917cacb29e7c4f4872c6cee8cef23a489389aa80 Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 5 Jun 2025 13:56:17 +0200 Subject: [PATCH 20/27] Disallow sysroot builds for LLVM older than 19 --- 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 b744236597..eb819a59ba 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -357,6 +357,8 @@ def __init__(self, *args, **kwargs): # 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._set_dynamic_linker() From d53f1d1df0d01832b954783cc35ebb7a176de218 Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 5 Jun 2025 17:01:42 +0200 Subject: [PATCH 21/27] Added new ignore patterns --- easybuild/easyblocks/l/llvm.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index eb819a59ba..e352fb5e9d 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -690,6 +690,7 @@ def configure_step(self): else: general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' + new_ignore_patterns = [] if self.sysroot: # Some tests will run a FileCheck on the output of `clang -v` for `-internal-externc-isystem /usr/include` # where the path is hardcoded. If sysroot is set we replace that path by prepending the sysroot to it. @@ -706,15 +707,29 @@ def configure_step(self): known_frontend_files = [ 'warning-poison-system-directories.c' ] - prev = self.ignore_patterns.copy() for file in known_driver_files: - self.ignore_patterns.append(f'Clang :: Driver/{file}') + new_ignore_patterns.append(f'Clang :: Driver/{file}') for file in known_frontend_files: - self.ignore_patterns.append(f'Clang :: Frontend/{file}') - self.log.info( - f"Ignore patterns for tests updated from {prev} to {self.ignore_patterns} to avoid known ignorable " - "failures with sysroot builds." - ) + new_ignore_patterns.append(f'Clang :: Frontend/{file}') + + # Test related to config files, can fail due to overriding the default config file that we set to + # ensure correct working with sysroot builds + new_ignore_patterns.append('Flang :: Driver/config-file.f90') + + + # See https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2944852391 + # System-related failures due to /etc/timezone behavior + new_ignore_patterns.append('llvm-libc++-shared.cfg.in :: std/time/time.zone/') + + # Can give different behavior based on system Scrt1.o + 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'): + new_ignore_patterns.append('LLVM :: CodeGen/Hexagon/isel/pfalse-v4i1.ll') + + self.ignore_patterns += new_ignore_patterns + self.log.info(f"Ignore patterns added due to known and ignorable test failures: {new_ignore_patterns}") python_opts = get_cmake_python_config_dict() general_opts.update(python_opts) From af94102e29003d1dcc7c75585ac55dc279cec740 Mon Sep 17 00:00:00 2001 From: crivella Date: Thu, 5 Jun 2025 17:03:29 +0200 Subject: [PATCH 22/27] Moved the update of the ignore patterns in a dedicated method --- easybuild/easyblocks/l/llvm.py | 84 ++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index e352fb5e9d..8bbc2417ee 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -601,6 +601,49 @@ def _set_dynamic_linker(self): trace_msg(msg) self.log.warning(msg) + def update_ignore_patterns(self): + """Update the ignore patterns based on known ignorable test failures when running with specific LLVM versions + or with specific dependencies/options.""" + new_ignore_patterns = [] + if self.sysroot: + # Some tests will run a FileCheck on the output of `clang -v` for `-internal-externc-isystem /usr/include` + # where the path is hardcoded. If sysroot is set we replace that path by prepending the sysroot to it. + # The changes needed varies from file to file and are not the same across versions. + # Since this seems to be more of a problem with the test-suite settings than using the compilers + # we can probably safely ignore these tests. + known_driver_files = [ + 'baremetal.cpp', 'csky-toolchain.c', 'freebsd-include-paths.c', + 'haiku.c', 'hexagon-toolchain-elf.c', 'hexagon-toolchain-linux.c', + 'mips-cs.cpp', 'mips-fsf.cpp', 'mips-img-v2.cpp', 'mips-img.cpp', + 'riscv32-toolchain-extra.c', 'riscv64-toolchain-extra.c', + 'rocm-detect.hip', + ] + known_frontend_files = [ + 'warning-poison-system-directories.c' + ] + for file in known_driver_files: + new_ignore_patterns.append(f'Clang :: Driver/{file}') + for file in known_frontend_files: + new_ignore_patterns.append(f'Clang :: Frontend/{file}') + + # Test related to config files, can fail due to overriding the default config file that we set to + # ensure correct working with sysroot builds + new_ignore_patterns.append('Flang :: Driver/config-file.f90') + + # See https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2944852391 + # System-related failures due to /etc/timezone behavior + new_ignore_patterns.append('llvm-libc++-shared.cfg.in :: std/time/time.zone/') + + # Can give different behavior based on system Scrt1.o + 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'): + new_ignore_patterns.append('LLVM :: CodeGen/Hexagon/isel/pfalse-v4i1.ll') + + self.ignore_patterns += new_ignore_patterns + self.log.info(f"Ignore patterns added due to known and ignorable test failures: {new_ignore_patterns}") + def configure_step(self): """ Install extra tools in bin/; enable zlib if it is a dep; optionally enable rtti; and set the build target @@ -690,46 +733,7 @@ def configure_step(self): else: general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' - new_ignore_patterns = [] - if self.sysroot: - # Some tests will run a FileCheck on the output of `clang -v` for `-internal-externc-isystem /usr/include` - # where the path is hardcoded. If sysroot is set we replace that path by prepending the sysroot to it. - # The changes needed varies from file to file and are not the same across versions. - # Since this seems to be more of a problem with the test-suite settings than using the compilers - # we can probably safely ignore these tests. - known_driver_files = [ - 'baremetal.cpp', 'csky-toolchain.c', 'freebsd-include-paths.c', - 'haiku.c', 'hexagon-toolchain-elf.c', 'hexagon-toolchain-linux.c', - 'mips-cs.cpp', 'mips-fsf.cpp', 'mips-img-v2.cpp', 'mips-img.cpp', - 'riscv32-toolchain-extra.c', 'riscv64-toolchain-extra.c', - 'rocm-detect.hip', - ] - known_frontend_files = [ - 'warning-poison-system-directories.c' - ] - for file in known_driver_files: - new_ignore_patterns.append(f'Clang :: Driver/{file}') - for file in known_frontend_files: - new_ignore_patterns.append(f'Clang :: Frontend/{file}') - - # Test related to config files, can fail due to overriding the default config file that we set to - # ensure correct working with sysroot builds - new_ignore_patterns.append('Flang :: Driver/config-file.f90') - - - # See https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2944852391 - # System-related failures due to /etc/timezone behavior - new_ignore_patterns.append('llvm-libc++-shared.cfg.in :: std/time/time.zone/') - - # Can give different behavior based on system Scrt1.o - 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'): - new_ignore_patterns.append('LLVM :: CodeGen/Hexagon/isel/pfalse-v4i1.ll') - - self.ignore_patterns += new_ignore_patterns - self.log.info(f"Ignore patterns added due to known and ignorable test failures: {new_ignore_patterns}") + self.update_ignore_patterns() python_opts = get_cmake_python_config_dict() general_opts.update(python_opts) From 28ef722be41708021eabd97f9fa208b471130ea8 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Fri, 6 Jun 2025 17:55:11 +0200 Subject: [PATCH 23/27] minor tweaks to LLVM easyblock --- easybuild/easyblocks/l/llvm.py | 41 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 8bbc2417ee..5acf2dbed0 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -254,7 +254,6 @@ def __init__(self, *args, **kwargs): 'CMAKE_EXE_LINKER_FLAGS': [], } self.offload_targets = ['host'] - # self._added_librt = None self.host_triple = None self.dynamic_linker = None @@ -601,7 +600,7 @@ def _set_dynamic_linker(self): trace_msg(msg) self.log.warning(msg) - def update_ignore_patterns(self): + def _update_ignore_patterns(self): """Update the ignore patterns based on known ignorable test failures when running with specific LLVM versions or with specific dependencies/options.""" new_ignore_patterns = [] @@ -733,7 +732,8 @@ def configure_step(self): else: general_opts['LLVM_ENABLE_Z3_SOLVER'] = 'OFF' - self.update_ignore_patterns() + # update ignore patterns for ignorable test failures + self._update_test_ignore_patterns() python_opts = get_cmake_python_config_dict() general_opts.update(python_opts) @@ -754,8 +754,8 @@ def configure_step(self): regex_subs.append((r'add_subdirectory\(bindings/python/tests\)', '')) apply_regex_substitutions(cmakelists_tests, regex_subs) - # Remove flags disabling the use of configuration files during compiler-rt tests as we in general relies on - # them (See https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2939404304) + # Remove flags disabling the use of configuration files during compiler-rt tests as we in general rely on them + # (see https://github.com/easybuilders/easybuild-easyblocks/pull/3741#issuecomment-2939404304) lit_cfg_file = os.path.join(self.llvm_src_dir, 'compiler-rt', 'test', 'lit.common.cfg.py') regex_subs = [ (r'^if config.has_no_default_config_flag:', ''), @@ -856,7 +856,7 @@ def _create_compiler_config_file(self, installdir): # prefix = self.sysroot.rstrip('/') # opts.append(f'--dyld-prefix={prefix}') - # Check, for a non `full_llvm` build, if GCCcore is in the LIBRARY_PATH, and if not add it + # Check, for a non `full_llvm` build, if GCCcore is in the LIBRARY_PATH, and if not add it; # This is needed as the runtimes tests will not add the -L option to the linker command line for GCCcore # otherwise if not self.full_llvm: @@ -943,7 +943,7 @@ def build_with_prev_stage(self, prev_dir, stage_dir): if LooseVersion(self.version) >= LooseVersion('19'): self._set_gcc_prefix() self._create_compiler_config_file(prev_dir) - # Pre-create the CFG files in the `build_stage/bin` directory to enforce using the correct dynamic + # 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 # runtimes (which would otherwise use the system default dynamic linker) self._create_compiler_config_file(stage_dir) @@ -1264,15 +1264,17 @@ def _sanity_check_gcc_prefix(compilers, gcc_prefix, installdir): def _sanity_check_dynamic_linker(self): """Check if the dynamic linker is correct.""" if self.sysroot: - c_name = 'abcdefg.c' - o_name = 'abcdefg.o' - x_name = 'abcdefg.x' - with open(c_name, 'w', encoding='utf-8') as f: - f.write('#include \n') - f.write('int main() { printf("Hello World\\n"); return 0; }\n') - cmd = f"{os.path.join(self.installdir, 'bin', 'clang')} -o {o_name} -c {c_name}" + # compile & test trivial C program to verify that works + test_fn = 'test123' + test_txt = '#include \n' + test_txt += 'int main() { printf("Hello World\\n"); return 0; }\n' + write_file(test_fn + '.c', test_txt) + + clang = os.path.join(self.installdir, 'bin', 'clang') + cmd = f"{clang} -o {test_fn}.o -c {test_fn}.c" run_shell_cmd(cmd, fail_on_error=True) - cmd = f"{os.path.join(self.installdir, 'bin', 'clang')} -v -o {x_name} {o_name}" + + cmd = f"{clang} -v -o {test_fn}.x {test_fn}.o" res = run_shell_cmd(cmd, fail_on_error=True) out = res.output @@ -1281,15 +1283,14 @@ def _sanity_check_dynamic_linker(self): error_msg = f"Dynamic linker is not set to the sysroot '{self.sysroot}'" raise EasyBuildError(error_msg) - cmd = f'./{x_name}' + cmd = f'./{test_fn}.x' res = run_shell_cmd(cmd, fail_on_error=False) if res.exit_code != EasyBuildExit.SUCCESS: - error_msg = f"Failed to run the compiled executable '{x_name}' for testing the dynamic linker" + error_msg = f"Failed to run the compiled executable '{cmd}' for testing the dynamic linker" raise EasyBuildError(error_msg) - remove_file(c_name) - remove_file(o_name) - remove_file(x_name) + for suffix in ('.c', '.o', '.x'): + remove_file('{test_fn}{suffix}') def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM.""" From 079e0e1f1444ae30572fb7de7f23329dddae591b Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 6 Jun 2025 18:50:42 +0200 Subject: [PATCH 24/27] Missing f-string classifier --- easybuild/easyblocks/l/llvm.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index 5acf2dbed0..65434a869b 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -42,18 +42,24 @@ from easybuild.framework.easyconfig import CUSTOM 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.config import ERROR, IGNORE, SEARCH_PATH_LIB_DIRS, build_option +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 -from easybuild.tools.filetools import mkdir, remove_file, symlink, which, write_file, remove_dir -from easybuild.tools.modules import MODULE_LOAD_ENV_HEADERS, get_software_root, get_software_version -from easybuild.tools.run import run_shell_cmd, EasyBuildExit -from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, RISCV64, X86_64, POWER_LE -from easybuild.tools.systemtools import get_cpu_architecture, get_cpu_family, get_shared_lib_ext +from easybuild.tools.filetools import (adjust_permissions, + apply_regex_substitutions, change_dir, + copy_dir, mkdir, remove_dir, + remove_file, symlink, which, write_file) +from easybuild.tools.modules import (MODULE_LOAD_ENV_HEADERS, + get_software_root, get_software_version) +from easybuild.tools.run import EasyBuildExit, run_shell_cmd +from easybuild.tools.systemtools import (AARCH32, AARCH64, POWER, POWER_LE, + RISCV64, X86_64, get_cpu_architecture, + get_cpu_family, get_shared_lib_ext) +from easybuild.tools.utilities import trace_msg -from easybuild.easyblocks.generic.cmakemake import CMakeMake, get_cmake_python_config_dict +from easybuild.easyblocks.generic.cmakemake import ( + CMakeMake, get_cmake_python_config_dict) BUILD_TARGET_AMDGPU = 'AMDGPU' BUILD_TARGET_NVPTX = 'NVPTX' @@ -1290,7 +1296,7 @@ def _sanity_check_dynamic_linker(self): raise EasyBuildError(error_msg) for suffix in ('.c', '.o', '.x'): - remove_file('{test_fn}{suffix}') + remove_file(f'{test_fn}{suffix}') def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM.""" From c825c94a84af33e82314f4e0b99ce4dc00c314ac Mon Sep 17 00:00:00 2001 From: Davide Grassano <34096612+Crivella@users.noreply.github.com> Date: Fri, 6 Jun 2025 18:54:14 +0200 Subject: [PATCH 25/27] Update easybuild/easyblocks/l/llvm.py Co-authored-by: Kenneth Hoste --- 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 65434a869b..f5bfd3d090 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -606,7 +606,7 @@ def _set_dynamic_linker(self): trace_msg(msg) self.log.warning(msg) - def _update_ignore_patterns(self): + def _update_test_ignore_patterns(self): """Update the ignore patterns based on known ignorable test failures when running with specific LLVM versions or with specific dependencies/options.""" new_ignore_patterns = [] From ced857fbc2ff05ad344eb5f0a8124ba46fd6ac68 Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 6 Jun 2025 19:00:33 +0200 Subject: [PATCH 26/27] Revert "Missing f-string classifier" This reverts commit 079e0e1f1444ae30572fb7de7f23329dddae591b. --- easybuild/easyblocks/l/llvm.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/easybuild/easyblocks/l/llvm.py b/easybuild/easyblocks/l/llvm.py index f5bfd3d090..f6cd4a4e4c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -42,24 +42,18 @@ from easybuild.framework.easyconfig import CUSTOM 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.config import (ERROR, IGNORE, SEARCH_PATH_LIB_DIRS, - build_option) +from easybuild.tools.config import ERROR, IGNORE, SEARCH_PATH_LIB_DIRS, build_option from easybuild.tools.environment import setvar -from easybuild.tools.filetools import (adjust_permissions, - apply_regex_substitutions, change_dir, - copy_dir, mkdir, remove_dir, - remove_file, symlink, which, write_file) -from easybuild.tools.modules import (MODULE_LOAD_ENV_HEADERS, - get_software_root, get_software_version) -from easybuild.tools.run import EasyBuildExit, run_shell_cmd -from easybuild.tools.systemtools import (AARCH32, AARCH64, POWER, POWER_LE, - RISCV64, X86_64, get_cpu_architecture, - get_cpu_family, get_shared_lib_ext) -from easybuild.tools.utilities import trace_msg +from easybuild.tools.filetools import apply_regex_substitutions, change_dir, copy_dir, adjust_permissions +from easybuild.tools.filetools import mkdir, remove_file, symlink, which, write_file, remove_dir +from easybuild.tools.modules import MODULE_LOAD_ENV_HEADERS, get_software_root, get_software_version +from easybuild.tools.run import run_shell_cmd, EasyBuildExit +from easybuild.tools.systemtools import AARCH32, AARCH64, POWER, RISCV64, X86_64, POWER_LE +from easybuild.tools.systemtools import get_cpu_architecture, get_cpu_family, get_shared_lib_ext -from easybuild.easyblocks.generic.cmakemake import ( - CMakeMake, get_cmake_python_config_dict) +from easybuild.easyblocks.generic.cmakemake import CMakeMake, get_cmake_python_config_dict BUILD_TARGET_AMDGPU = 'AMDGPU' BUILD_TARGET_NVPTX = 'NVPTX' @@ -1296,7 +1290,7 @@ def _sanity_check_dynamic_linker(self): raise EasyBuildError(error_msg) for suffix in ('.c', '.o', '.x'): - remove_file(f'{test_fn}{suffix}') + remove_file('{test_fn}{suffix}') def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM.""" From edd5e7a4967daff8c3e722d9375f212113b75e2e Mon Sep 17 00:00:00 2001 From: crivella Date: Fri, 6 Jun 2025 19:01:06 +0200 Subject: [PATCH 27/27] Missing f-string classifier without isort --- 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 f6cd4a4e4c..4fd479dc2c 100644 --- a/easybuild/easyblocks/l/llvm.py +++ b/easybuild/easyblocks/l/llvm.py @@ -1290,7 +1290,7 @@ def _sanity_check_dynamic_linker(self): raise EasyBuildError(error_msg) for suffix in ('.c', '.o', '.x'): - remove_file('{test_fn}{suffix}') + remove_file(f'{test_fn}{suffix}') def sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None): """Perform sanity checks on the installed LLVM."""