Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 41 additions & 20 deletions easybuild/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ def __init__(self, ec):
# sanity check fail error messages to report (if any)
self.sanity_check_fail_msgs = []

# keep track of whether module is loaded during sanity check step (to avoid re-loading)
self.sanity_check_module_loaded = False
# info required to roll back loading of fake module during sanity check (see _sanity_check_step method)
self.fake_mod_data = None

# robot path
self.robot_path = build_option('robot_path')

Expand Down Expand Up @@ -1618,6 +1623,8 @@ def load_fake_module(self, purge=False, extra_modules=None, verbose=False):
:param purge: boolean indicating whether or not to purge currently loaded modules first
:param extra_modules: list of extra modules to load (these are loaded *before* loading the 'self' module)
"""
self.log.info("Loading fake module (%s)", self.short_mod_name)

# take a copy of the current environment before loading the fake module, so we can restore it
env = copy.deepcopy(os.environ)

Expand Down Expand Up @@ -3346,6 +3353,34 @@ def _sanity_check_step_extensions(self):
self.sanity_check_fail_msgs.append(overall_fail_msg + ', '.join(x[0] for x in failed_exts))
self.sanity_check_fail_msgs.extend(x[1] for x in failed_exts)

def sanity_check_load_module(self, extension=False, extra_modules=None):
"""
Load module to prepare environment for sanity check
"""

# skip loading of fake module when using --sanity-check-only, load real module instead
if build_option('sanity_check_only') and not extension:
self.log.info("Loading real module for %s %s: %s", self.name, self.version, self.short_mod_name)
self.load_module(extra_modules=extra_modules)
self.sanity_check_module_loaded = True

# only load fake module for non-extensions, and not during dry run
elif not (extension or self.dry_run):

if extra_modules:
self.log.info("Loading extra modules for sanity check: %s", ', '.join(extra_modules))

try:
# unload all loaded modules before loading fake module
# this ensures that loading of dependencies is tested, and avoids conflicts with build dependencies
self.fake_mod_data = self.load_fake_module(purge=True, extra_modules=extra_modules, verbose=True)
self.sanity_check_module_loaded = True
except EasyBuildError as err:
self.sanity_check_fail_msgs.append("loading fake module failed: %s" % err)
self.log.warning("Sanity check: %s" % self.sanity_check_fail_msgs[-1])

return self.fake_mod_data

def _sanity_check_step(self, custom_paths=None, custom_commands=None, extension=False, extra_modules=None):
"""
Real version of sanity_check_step method.
Expand Down Expand Up @@ -3410,24 +3445,8 @@ def xs2str(xs):

trace_msg("%s %s found: %s" % (typ, xs2str(xs), ('FAILED', 'OK')[found]))

fake_mod_data = None

# skip loading of fake module when using --sanity-check-only, load real module instead
if build_option('sanity_check_only') and not extension:
self.load_module(extra_modules=extra_modules)

# only load fake module for non-extensions, and not during dry run
elif not (extension or self.dry_run):
try:
# unload all loaded modules before loading fake module
# this ensures that loading of dependencies is tested, and avoids conflicts with build dependencies
fake_mod_data = self.load_fake_module(purge=True, extra_modules=extra_modules, verbose=True)
except EasyBuildError as err:
self.sanity_check_fail_msgs.append("loading fake module failed: %s" % err)
self.log.warning("Sanity check: %s" % self.sanity_check_fail_msgs[-1])

if extra_modules:
self.log.info("Loading extra modules for sanity check: %s", ', '.join(extra_modules))
if not self.sanity_check_module_loaded:
self.fake_mod_data = self.sanity_check_load_module(extension=extension, extra_modules=extra_modules)

# allow oversubscription of P processes on C cores (P>C) for software installed on top of Open MPI;
# this is useful to avoid failing of sanity check commands that involve MPI
Expand Down Expand Up @@ -3463,8 +3482,10 @@ def xs2str(xs):
self.sanity_check_fail_msgs.append(linked_shared_lib_fails)

# cleanup
if fake_mod_data:
self.clean_up_fake_module(fake_mod_data)
if self.fake_mod_data:
self.clean_up_fake_module(self.fake_mod_data)
self.sanity_check_module_loaded = False
self.fake_mod_data = None

if self.toolchain.use_rpath:
rpath_fails = self.sanity_check_rpath()
Expand Down
3 changes: 3 additions & 0 deletions easybuild/framework/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ def __init__(self, mself, ext, extra_params=None):
key, name, version, value)

self.sanity_check_fail_msgs = []
self.sanity_check_module_loaded = False
self.fake_mod_data = None

self.async_cmd_info = None
self.async_cmd_output = None
self.async_cmd_check_cnt = None
Expand Down
5 changes: 3 additions & 2 deletions easybuild/framework/extensioneasyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,9 @@ def sanity_check_step(self, exts_filter=None, custom_paths=None, custom_commands
fake_mod_data = None

# only load fake module + extra modules for stand-alone installations (not for extensions),
# since for extension the necessary modules should already be loaded at this point
if not (self.is_extension or self.dry_run):
# since for extension the necessary modules should already be loaded at this point;
# take into account that module may already be loaded earlier in sanity check
if not (self.sanity_check_module_loaded or self.is_extension or self.dry_run):
# load fake module
fake_mod_data = self.load_fake_module(purge=True, extra_modules=extra_modules)

Expand Down