Skip to content

Adding dependencies through the hook framework is a bit overly complicated and undocumented #2557

@akesandgren

Description

@akesandgren

The implemented hook framework has no easy way to add dependencies (or remove them).
There are two problems:

  • adding/removing dependencies must be done very early
  • to complete the adding of dependencies one has to call EasyConfig.generate_template_values() and EasyConfig._finalize_dependencies(). Doing that in a hook is a bit awkward.

Adding a dependency_hook in EasyConfig.parse() before the call to self.generate_template_values() would make this much cleaner. One would still have to call self.cfg._parse_dependency() but one could add a helper function in the framework to handle the actual add/remove of a list of dependencies.

The other approach would be to write good documentation on this.

A piece of hook code that works is the following:

from distutils.version import LooseVersion
from easybuild.framework.easyconfig.format.format import DEPENDENCY_PARAMETERS
from easybuild.tools.build_log import EasyBuildError

# Changing dependencies can't be done in start_hook since it doesn't get
# any "self" argument. Use pre_fetch_hook instead since it is as early
# as it gets except start_hook
def pre_fetch_hook(self, *args, **kwargs):

    # Internal helper function
    def add_extra_dependencies(self, dep_type, extra_deps):
        """dep_type: must be in DEPENDENCY_PARAMETERS or 'osdependencies'"""
        self.log.info("[pre-fetch hook] Adding %s: %s" % (dep_type, extra_deps))

        self.cfg.enable_templating = False

        if dep_type in DEPENDENCY_PARAMETERS:
            for dep in extra_deps:
                self.cfg[dep_type].append(self.cfg._parse_dependency(dep))
        elif dep_type == 'osdependencies':
                # This currently don't work. Need to figure out how to do this.
                self.cfg[dep_type].append(extra_deps)
        else:
            raise EasyBuildError("pre_fetch_hook: Incorrect dependency type in add_extra_dependencies: %s" % dep_type)

        self.cfg.enable_templating = True
        self.cfg.generate_template_values()
        self.cfg._finalize_dependencies()

    extra_deps = []
    if self.name == 'OpenMPI':
        if LooseVersion(self.version) >= LooseVersion('2.1'):
            pmix_version = '1.2.5'
            if LooseVersion(self.version) >= LooseVersion('3'):
                pmix_version = '2.1.3'

            ucx_version = '1.3.1'

            extra_deps.append(('PMIx', pmix_version))
            # Use of external PMIx requires external libevent
            # But PMIx already has it as a dependency so we don't need
            # to explicitly set it.

            extra_deps.append(('UCX', ucx_version))

    add_extra_dependencies(self, 'dependencies', extra_deps)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions