diff --git a/EESSI-install-software.sh b/EESSI-install-software.sh index a6f34413..7801a70c 100755 --- a/EESSI-install-software.sh +++ b/EESSI-install-software.sh @@ -490,6 +490,12 @@ else # full EasyBuild command for this easystack file (also shown in the debug shell messages) if [[ ${easystack_file} == *"/rebuilds/"* ]]; then eb_cmd="${EB} --easystack ${easystack_file} --rebuild" + # for rebuilds on a CVMFS repository, we assume an overlay is used, + # and we can safely enable the hook that removes the existing installation directory at the start of the build + if [[ ${EASYBUILD_INSTALLPATH} == "/cvmfs"* ]]; then + echo "This is a rebuild, so setting EESSI_FORCE_EARLY_REMOVAL_OF_INSTALL_DIR=1" + export EESSI_FORCE_EARLY_REMOVAL_OF_INSTALL_DIR=1 + fi else eb_cmd="${EB} --easystack ${easystack_file} --robot" fi diff --git a/eb_hooks.py b/eb_hooks.py index fd3aed75..33e39388 100644 --- a/eb_hooks.py +++ b/eb_hooks.py @@ -21,7 +21,7 @@ from easybuild.tools.build_log import EasyBuildError, print_msg, print_warning from easybuild.tools.config import build_option, install_path, update_build_option from easybuild.tools.config import ERROR -from easybuild.tools.filetools import apply_regex_substitutions, copy_dir, copy_file, remove_file, symlink, which +from easybuild.tools.filetools import apply_regex_substitutions, copy_dir, copy_file, remove_dir, remove_file, symlink, which from easybuild.tools.modules import get_software_root, get_software_root_env_var_name from easybuild.tools.run import run_cmd from easybuild.tools.systemtools import AARCH64, POWER, X86_64, det_parallelism, get_cpu_architecture, get_cpu_features, get_gpu_info @@ -501,6 +501,9 @@ def pre_prepare_hook(self, *args, **kwargs): # Always trigger this, regardless of ec.name pre_prepare_hook_cuda_dependant(self, *args, **kwargs) + # Always trigger this, regardless of ec.name + pre_prepare_hook_remove_install_dir_for_rebuilds(self, *args, **kwargs) + def post_prepare_hook_gcc_prefixed_ld_rpath_wrapper(self, *args, **kwargs): """ @@ -1164,6 +1167,27 @@ def pre_prepare_hook_llvm_a64fx(self, *args, **kwargs): update_build_option('optarch', 'march=armv8.2-a') +def pre_prepare_hook_remove_install_dir_for_rebuilds(self, *args, **kwargs): + """ + Rebuilds of an existing installation may pick up files from the original installation in e.g. the test step, + because the installation directory only gets removed/wiped at the install step. + To prevent such issues, we do a hard removal early on, unless this is explicitly disabled. + Also see https://github.com/easybuilders/easybuild-framework/issues/5362. + """ + if build_option('rebuild') and os.path.exists(self.installdir) and len(os.listdir(self.installdir)) > 0: + if os.getenv('EESSI_FORCE_EARLY_REMOVAL_OF_INSTALL_DIR'): + print_msg(f'Removing existing installation directory {self.installdir}...') + remove_dir(self.installdir) + else: + warning_msg = 'You are rebuilding software, and the installation directory already exists and is non-empty. ' + warning_msg += 'Be aware that the build may pick up files from the existing installation, because RPATH is enabled and ' + warning_msg += 'the existing installation only gets wiped at the install step. Set EESSI_FORCE_EARLY_REMOVAL_OF_INSTALL_DIR ' + warning_msg += 'to a non-zero value to make sure that the existing installation is wiped at the start of the rebuild. ' + warning_msg += 'Do note that it may mean that the installation is gone for a while if you are building on a ' + warning_msg += 'writable shared filesystem without e.g. an overlay or bubblewrap!' + print_warning(warning_msg) + + def pre_prepare_hook_coordgenlibs_a64fx(self, *args, **kwargs): """ Solve issues with compiling coordgenlibs on a64fx with the 2026.1 stack. The specific error is: