Using a unique multi-valued variant for defining the modules:
CON : - Users have to give explicitly the list of required modules but the error message gives all the modules to add PRO : - Does not hide automatic installed dependecies (with the one module - one variant, a module can be installed and the corresponding variant set to false) - Module dependencies is done when checking the arguments - Does not tamper with spack resource fetching
This commit is contained in:
		@ -22,7 +22,11 @@
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
from spack import *
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from collections.abc import Sequence
 | 
			
		||||
except ImportError:
 | 
			
		||||
    from collections import Sequence
 | 
			
		||||
import spack.error as error
 | 
			
		||||
 | 
			
		||||
class Dune(CMakePackage):
 | 
			
		||||
    """
 | 
			
		||||
@ -64,17 +68,72 @@ class Dune(CMakePackage):
 | 
			
		||||
    # Some variants that were here that are on my todo list
 | 
			
		||||
    # variant('jupyter', default=False, description='Build with Jupyter support')
 | 
			
		||||
 | 
			
		||||
    # Define one variant for each Dune module that we have. Only core modules
 | 
			
		||||
    # are activated by default.
 | 
			
		||||
    variant('alugrid', default=False, description='Build with dune-alugrid module')
 | 
			
		||||
    variant('functions', default=False, description='Build with dune-functions module')
 | 
			
		||||
    variant('geometry', default=True, description='Build with dune-geometry module')
 | 
			
		||||
    variant('grid', default=True, description='Build with dune-grid module')
 | 
			
		||||
    variant('istl', default=True, description='Build with dune-istl module')
 | 
			
		||||
    variant('localfunctions', default=True, description='Build with dune-localfunctions module')
 | 
			
		||||
    variant('spgrid', default=False, description='Build with dune-spgrid module')
 | 
			
		||||
    variant('typetree', default=False, description='Build with dune-typetree module')
 | 
			
		||||
    variant('uggrid', default=False, description='Build with dune-uggrid module')
 | 
			
		||||
    # Define a multi-valued variant for defining the modules
 | 
			
		||||
 | 
			
		||||
    class dune_module_set(Sequence):
 | 
			
		||||
        """Define the possible values for the DUNE modules variants"""
 | 
			
		||||
        def __init__(self):
 | 
			
		||||
            self.module_dependencies={}
 | 
			
		||||
            self.module_dependencies["common"]=[]
 | 
			
		||||
            self.module_dependencies["geometry"]=["common"]
 | 
			
		||||
            self.module_dependencies["grid"]=["common","geometry"]
 | 
			
		||||
            self.module_dependencies["uggrid"]=["common"]
 | 
			
		||||
            self.module_dependencies["istl"]=["common"]
 | 
			
		||||
            self.module_dependencies["localfunctions"]=["common","geometry"]
 | 
			
		||||
            self.module_dependencies["functions"]=["grid","typetree","localfunctions","istl"]
 | 
			
		||||
            self.module_dependencies["typetree"]=["common"]
 | 
			
		||||
            self.module_dependencies["python"]=[]
 | 
			
		||||
            self.module_dependencies["spgrid"]=[]
 | 
			
		||||
            self.module_dependencies["alugrid"]=["grid","geometry","common"]
 | 
			
		||||
            self.sets=[]
 | 
			
		||||
            for key in self.module_dependencies:
 | 
			
		||||
                self.sets.append(key)
 | 
			
		||||
            self.feature_values = tuple(self.sets)
 | 
			
		||||
            self.default = ("common","grid")
 | 
			
		||||
            self.multi = True
 | 
			
		||||
 | 
			
		||||
        def __getitem__(self, idx):
 | 
			
		||||
            return self.feature_values[idx]
 | 
			
		||||
 | 
			
		||||
        def __len__(self):
 | 
			
		||||
            return len(self.feature_values)
 | 
			
		||||
 | 
			
		||||
        @property
 | 
			
		||||
        def validator(self):
 | 
			
		||||
            def module_dependency_closure(modlist):
 | 
			
		||||
                closure = set(modlist)
 | 
			
		||||
                old_closure = set()
 | 
			
		||||
                while (len(closure) > len(old_closure)):
 | 
			
		||||
                    old_closure = closure.copy()
 | 
			
		||||
                    for res in old_closure:
 | 
			
		||||
                        for mod in self.module_dependencies.get(res):
 | 
			
		||||
                            closure.add(mod)
 | 
			
		||||
                return closure
 | 
			
		||||
            def _dune_modules_set_validator(pkg_name, variant_name, values):
 | 
			
		||||
                ok=True
 | 
			
		||||
                msg='Missing module dependencies: '
 | 
			
		||||
                for s in values:
 | 
			
		||||
                    req_mod=module_dependency_closure({s})
 | 
			
		||||
                    for req in req_mod:
 | 
			
		||||
                        if(not req in values):
 | 
			
		||||
                            msg+=req+','
 | 
			
		||||
                            ok=False
 | 
			
		||||
                if(ok):
 | 
			
		||||
                    return
 | 
			
		||||
                msg = msg[:-1]
 | 
			
		||||
                format_args = {
 | 
			
		||||
                    'variant': variant_name, 'package': pkg_name, 'values': values
 | 
			
		||||
                }
 | 
			
		||||
                msg = msg + \
 | 
			
		||||
                    " @*r{{[{package}, variant '{variant}']}}"
 | 
			
		||||
                msg = llnl.util.tty.color.colorize(msg.format(**format_args))
 | 
			
		||||
                raise error.SpecError(msg)
 | 
			
		||||
            return _dune_modules_set_validator
 | 
			
		||||
 | 
			
		||||
    variant( 'modules', 
 | 
			
		||||
        values=dune_module_set(),
 | 
			
		||||
        description='Installed dune module')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # Iterate over all available Dune versions and define resources for all Dune modules
 | 
			
		||||
    # If a Dune module behaves differently for different versions (e.g. dune-python got
 | 
			
		||||
@ -86,84 +145,72 @@ class Dune(CMakePackage):
 | 
			
		||||
            name='dune-geometry',
 | 
			
		||||
            git='https://gitlab.dune-project.org/core/dune-geometry.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+geometry' % vers,
 | 
			
		||||
            when='@%s modules=geometry' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-grid',
 | 
			
		||||
            git='https://gitlab.dune-project.org/core/dune-grid.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+grid' % vers,
 | 
			
		||||
            when='@%s modules=grid' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-istl',
 | 
			
		||||
            git='https://gitlab.dune-project.org/core/dune-istl.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+istl' % vers,
 | 
			
		||||
            when='@%s modules=istl' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-localfunctions',
 | 
			
		||||
            git='https://gitlab.dune-project.org/core/dune-localfunctions.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+localfunctions' % vers,
 | 
			
		||||
            when='@%s modules=localfunctions' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-functions',
 | 
			
		||||
            git='https://gitlab.dune-project.org/staging/dune-functions.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+functions' % vers,
 | 
			
		||||
            when='@%s modules=functions' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-typetree',
 | 
			
		||||
            git='https://gitlab.dune-project.org/staging/dune-typetree.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+typetree' % vers,
 | 
			
		||||
            when='@%s modules=typetree' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-alugrid',
 | 
			
		||||
            git='https://gitlab.dune-project.org/extensions/dune-alugrid.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+alugrid' % vers,
 | 
			
		||||
            when='@%s modules=alugrid' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-uggrid',
 | 
			
		||||
            git='https://gitlab.dune-project.org/staging/dune-uggrid.git',
 | 
			
		||||
            branch='releases/2.7',
 | 
			
		||||
            when='@%s+uggrid' % vers,
 | 
			
		||||
            when='@%s modules=uggrid' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        resource(
 | 
			
		||||
            name='dune-spgrid',
 | 
			
		||||
            git='https://gitlab.dune-project.org/extensions/dune-spgrid.git',
 | 
			
		||||
            branch=branch,
 | 
			
		||||
            when='@%s+spgrid' % vers,
 | 
			
		||||
            when='@%s modules=spgrid' % vers,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    resource(
 | 
			
		||||
        name='dune-python',
 | 
			
		||||
        git='https://gitlab.dune-project.org/staging/dune-python.git',
 | 
			
		||||
        branch=branch,
 | 
			
		||||
        when='@2.7+python',
 | 
			
		||||
        when='@2.7 modules=python',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Dependencies between modules
 | 
			
		||||
    module_dependencies={"dune-common":[]}
 | 
			
		||||
    module_dependencies["dune-geometry"]=["dune-common"]
 | 
			
		||||
    module_dependencies["dune-grid"]=["dune-common","dune-geometry"]
 | 
			
		||||
    module_dependencies["dune-uggrid"]=["dune-common"]
 | 
			
		||||
    module_dependencies["dune-istl"]=["dune-common"]
 | 
			
		||||
    module_dependencies["dune-localfunctions"]=["dune-common","dune-geometry"]
 | 
			
		||||
    module_dependencies["dune-functions"]=["dune-grid","dune-typetree","dune-localfunctions","dune-istl"]
 | 
			
		||||
    module_dependencies["dune-typetree"]=["dune-common"]
 | 
			
		||||
    module_dependencies["dune-python"]=[]
 | 
			
		||||
    module_dependencies["dune-alugrid"]=["dune-grid","dune-geometry","dune-common"]
 | 
			
		||||
 | 
			
		||||
    extends('python')
 | 
			
		||||
    python_components = [ 'dune' ]
 | 
			
		||||
 | 
			
		||||
@ -251,34 +298,6 @@ class Dune(CMakePackage):
 | 
			
		||||
 | 
			
		||||
        return cmake_args
 | 
			
		||||
 | 
			
		||||
    def module_dependency_closure(self, when, reslist):
 | 
			
		||||
        # Get a list of all modules that share the version requirement
 | 
			
		||||
        all_resources = []
 | 
			
		||||
        for w, rl in self.resources.items():
 | 
			
		||||
            if w.version == when.version:
 | 
			
		||||
                all_resources.extend(rl)
 | 
			
		||||
 | 
			
		||||
        # And build the closure of modules from the given reslist
 | 
			
		||||
        closure = set(reslist)
 | 
			
		||||
        old_closure = set()
 | 
			
		||||
        while (len(closure) > len(old_closure)):
 | 
			
		||||
            old_closure = closure.copy()
 | 
			
		||||
 | 
			
		||||
            for res in old_closure:
 | 
			
		||||
                for mod in self.module_dependencies.get(res.name, []):
 | 
			
		||||
                    for r in all_resources:
 | 
			
		||||
                        if r.name == mod:
 | 
			
		||||
                            closure.add(r)
 | 
			
		||||
 | 
			
		||||
        return list(closure)
 | 
			
		||||
 | 
			
		||||
    def _get_needed_resources(self):
 | 
			
		||||
        # Modify the list of resources by building a transitive closure of Dune module dependencies.
 | 
			
		||||
        self.resources = {when: self.module_dependency_closure(when, reslist) for when, reslist in self.resources.items()}
 | 
			
		||||
 | 
			
		||||
        # and call the original implementation
 | 
			
		||||
        return CMakePackage._get_needed_resources(self)
 | 
			
		||||
 | 
			
		||||
    def cmake(self, spec, prefix):
 | 
			
		||||
        # Write an opts file for later use
 | 
			
		||||
        with open(join_path(self.stage.source_path, "..", "dune.opts"), "w") as optFile:
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user