From 5c7a84b74780e5d4ed45b1a7271355eb144c32fc Mon Sep 17 00:00:00 2001 From: Gauthier Folzan Date: Sat, 16 May 2020 01:36:48 +0200 Subject: [PATCH] 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 --- packages/dune/package.py | 143 ++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 62 deletions(-) diff --git a/packages/dune/package.py b/packages/dune/package.py index c172af9..1b4f439 100644 --- a/packages/dune/package.py +++ b/packages/dune/package.py @@ -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: