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
26 changes: 19 additions & 7 deletions easybuild/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import functools
import glob
import inspect
import itertools
import json
import os
import random
Expand All @@ -71,7 +72,7 @@
from easybuild.framework.easyconfig.easyconfig import ITERATE_OPTIONS, EasyConfig, ActiveMNS, get_easyblock_class
from easybuild.framework.easyconfig.easyconfig import get_module_path, letter_dir_for, resolve_template
from easybuild.framework.easyconfig.format.format import SANITY_CHECK_PATHS_DIRS, SANITY_CHECK_PATHS_FILES
from easybuild.framework.easyconfig.parser import fetch_parameters_from_easyconfig
from easybuild.framework.easyconfig.parser import fetch_parameters_from_easyconfig, ALTERNATIVE_EASYCONFIG_PARAMETERS
from easybuild.framework.easyconfig.style import MAX_LINE_LENGTH
from easybuild.framework.easyconfig.tools import dump_env_easyblock, get_paths_for
from easybuild.framework.easyconfig.templates import TEMPLATE_NAMES_EASYBLOCK_RUN_STEP, template_constant_dict
Expand Down Expand Up @@ -581,11 +582,17 @@ def fetch_patches(self, patch_specs=None, extension=False, checksums=None):
Add a list of patches.
All patches will be checked if a file exists (or can be located)
"""
post_install_patches = []
if patch_specs is None:
# if no patch_specs are specified, use all pre-install and post-install patches
post_install_patches = self.cfg['postinstallpatches']
patch_specs = self.cfg['patches'] + post_install_patches
elif isinstance(patch_specs, list):
post_install_patches = []
else:
if not isinstance(patch_specs, tuple) or len(patch_specs) != 2:
raise EasyBuildError('Patch specs must be a tuple of (patches, post-install patches) or a list')
post_install_patches = patch_specs[1]
patch_specs = itertools.chain(*patch_specs)

patches = []
for index, patch_spec in enumerate(patch_specs):
Expand Down Expand Up @@ -765,11 +772,15 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True):
)

# locate extension patches (if any), and verify checksums
ext_patches = resolve_template(ext_options.get('patches', []), template_values)
ext_patch_specs = resolve_template((
ext_options.get('patches', []),
ext_options.get(ALTERNATIVE_EASYCONFIG_PARAMETERS['post_install_patches'],
ext_options.get('post_install_patches', []))
), template_values)
if fetch_files:
ext_patches = self.fetch_patches(patch_specs=ext_patches, extension=True)
ext_patches = self.fetch_patches(patch_specs=ext_patch_specs, extension=True)
else:
ext_patches = [create_patch_info(p) for p in ext_patches]
ext_patches = [create_patch_info(p) for p in itertools.chain(*ext_patch_specs)]

if ext_patches:
self.log.debug('Found patches for extension %s: %s', ext_name, ext_patches)
Expand Down Expand Up @@ -3264,11 +3275,12 @@ def apply_post_install_patches(self, patches=None):
# To allow postinstallpatches for Bundle, and derived, easyblocks we directly call EasyBlock.patch_step
EasyBlock.patch_step(self, beginpath=self.installdir, patches=patches)

def print_post_install_messages(self):
def print_post_install_messages(self, msgs=None):
"""
Print post-install messages that are specified via the 'postinstallmsgs' easyconfig parameter.
"""
msgs = self.cfg['postinstallmsgs'] or []
if msgs is None:
msgs = self.cfg['postinstallmsgs'] or []
for msg in msgs:
print_msg(msg, log=self.log)

Expand Down
2 changes: 2 additions & 0 deletions easybuild/framework/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def post_install_extension(self):
Stuff to do after installing a extension.
"""
self.master.run_post_install_commands(commands=self.cfg.get('postinstallcmds', []))
self.master.apply_post_install_patches(patches=[p for p in self.patches if p['postinstall']])
self.master.print_post_install_messages(msgs=self.cfg.get('postinstallmsgs', []))

def install_extension_substep(self, substep, *args, **kwargs):
"""
Expand Down
38 changes: 22 additions & 16 deletions test/framework/toy_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,25 +1355,27 @@ def test_toy_extension_patches_postinstallcmds(self):
write_file(os.path.join(self.test_prefix, 'test.txt'), 'test123')

test_ec = os.path.join(self.test_prefix, 'test.eb')
test_ec_txt = '\n'.join([
toy_ec_txt,
'exts_defaultclass = "DummyExtension"',
'exts_list = [',
' ("bar", "0.0", {',
' "buildopts": " && ls -l test.txt",',
' "patches": [',
' "bar-0.0_fix-silly-typo-in-printf-statement.patch",', # normal patch
' ("bar-0.0_fix-very-silly-typo-in-printf-statement.patch", 0),', # patch with patch level
' ("test.txt", "."),', # file to copy to build dir (not a real patch file)
' ],',
' "postinstallcmds": ["touch %(installdir)s/created-via-postinstallcmds.txt"],',
' }),',
']',
])
test_ec_txt = f"{toy_ec_txt}\n" + textwrap.dedent("""
exts_defaultclass = "DummyExtension"
exts_list = [
("bar", "0.0", {
"buildopts": " && ls -l test.txt",
"patches": [
"bar-0.0_fix-silly-typo-in-printf-statement.patch", # normal patch
("bar-0.0_fix-very-silly-typo-in-printf-statement.patch", 0), # patch with patch level
("test.txt", "."), # file to copy to build dir (not a real patch file)
],
"post_install_cmds": ["touch %(installdir)s/created-via-postinstallcmds.txt"],
"post_install_patches": [("test.txt", "test_ext.txt")],
"post_install_msgs": ["Hello World!"],
}),
]
""")
write_file(test_ec, test_ec_txt)

with self.mocked_stdout_stderr():
self._test_toy_build(ec_file=test_ec)
self._test_toy_build(ec_file=test_ec, extra_args=['--disable-cleanup-builddir'])
self.assertIn("Hello World!", self.get_stdout())

installdir = os.path.join(self.test_installpath, 'software', 'toy', '0.0')

Expand All @@ -1386,6 +1388,10 @@ def test_toy_extension_patches_postinstallcmds(self):
# verify that post-install command for 'bar' extension was executed
fn = 'created-via-postinstallcmds.txt'
self.assertExists(os.path.join(installdir, fn))
# Same for all patches
self.assertExists(os.path.join(self.test_buildpath, 'toy', '0.0', 'system-system',
'bar', 'bar-0.0', 'test.txt'))
self.assertExists(os.path.join(installdir, 'test_ext.txt'))

# make sure that patch file for extension was copied to 'easybuild' subdir in installation directory
easybuild_subdir = os.path.join(installdir, 'easybuild')
Expand Down