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:
Gauthier Folzan 2020-05-16 01:36:48 +02:00
parent ba7b5cc439
commit 5c7a84b747
1 changed files with 81 additions and 62 deletions

View File

@ -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: