Introduce variant dependency
The previous approach had the big downside of bypassing the specified variants through the specified dependencies of variants. E.g. dune+pdelab~functions would silently ignore the ~functions aspect, because +pdelab enforces the installation of dune-functions. There is no direct mechanism in Spack to specify such dependencies in a way that enforces the correct variants on dependent modules. I have now added conflicts between variants that reflect the Dune module dependencies. In that case dune+pdelab~functions would throw an error. This comes at the cost that a command such as spack install dune+pdelab is not possible anymore. Instead the user needs to specify the dependent modules as well: spack install dune+pdelab+functions+typetree Note that in order to remove some burden from users, I removed the variants for the core modules - they are always installed.
This commit is contained in:
parent
d74cbb85a8
commit
c930ddd5f0
|
@ -41,6 +41,58 @@ class Dune(CMakePackage):
|
|||
("master" , "master"),
|
||||
]
|
||||
|
||||
# This defines the mapping of the variant names for Dune modules and the
|
||||
# resource names that we assign later on.
|
||||
dune_variants_to_resources = {
|
||||
'alugrid' : 'dune-alugrid',
|
||||
'codegen' : 'dune-codegen',
|
||||
'fem' : 'dune-fem',
|
||||
'foamgrid' : 'dune-foamgrid',
|
||||
'functions': 'dune-functions',
|
||||
'gridglue' : 'dune-grid-glue',
|
||||
'multidomaingrid' : 'dune-multidomaingrid',
|
||||
'pdelab' : 'dune-pdelab',
|
||||
'polygongrid' : 'dune-polygongrid',
|
||||
'spgrid' : 'dune-spgrid',
|
||||
'testtools' : 'dune-testtools',
|
||||
'typetree' : 'dune-typetree',
|
||||
'uggrid' : 'dune-uggrid',
|
||||
}
|
||||
|
||||
# Define the inverse mapping
|
||||
dune_resources_to_variants = {v: k for k, v in dune_variants_to_resources.items()}
|
||||
|
||||
# Dependencies between modules - not necessarily the full set
|
||||
# as the closure of module dependencies is built later on.
|
||||
# dune-common does not need to be named.
|
||||
module_dependencies = {
|
||||
'dune-alugrid': ['dune-grid'],
|
||||
'dune-codegen': ['dune-pdelab', 'dune-testtools', 'dune-alugrid'],
|
||||
'dune-fem': ['dune-grid'],
|
||||
'dune-fempy': ['dune-fem'],
|
||||
'dune-foamgrid': ['dune-grid'],
|
||||
'dune-functions': ["dune-grid", "dune-typetree", "dune-localfunctions", "dune-istl"],
|
||||
'dune-grid': ['dune-geometry'],
|
||||
'dune-grid-glue': ['dune-grid'],
|
||||
'dune-localfunctions': ['dune-geometry'],
|
||||
'dune-multidomaingrid': ['dune-grid', 'dune-typetree'],
|
||||
'dune-pdelab': ['dune-istl', 'dune-functions'],
|
||||
'dune-polygongrid': ['dune-grid'],
|
||||
}
|
||||
|
||||
# Build the closure of above module dependency list
|
||||
for module in module_dependencies:
|
||||
closure = set(module_dependencies[module])
|
||||
old_closure = set()
|
||||
while (len(closure) > len(old_closure)):
|
||||
old_closure = closure.copy()
|
||||
|
||||
for res in old_closure:
|
||||
for mod in module_dependencies.get(res, []):
|
||||
closure.add(mod)
|
||||
|
||||
module_dependencies[module] = list(closure)
|
||||
|
||||
# Variants for the general build process
|
||||
variant('shared', default=True, description='Enables the build of shared libraries.')
|
||||
|
||||
|
@ -68,25 +120,16 @@ 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('codegen', default=False, description='Build with dune-codegen module')
|
||||
variant('fem', default=False, description='Build with dune-fem(py) module')
|
||||
variant('foamgrid', default=False, description='Build with dune-foamgrid 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('gridglue', default=False, description='Build with dune-grid-glue module')
|
||||
variant('istl', default=True, description='Build with dune-istl module')
|
||||
variant('localfunctions', default=True, description='Build with dune-localfunctions module')
|
||||
variant('multidomaingrid', default=False, description='Build with dune-multidomaingrid module')
|
||||
variant('pdelab', default=False, description='Build with dune-pdelab module')
|
||||
variant('polygongrid', default=False, description='Build with dune-polygongrid module')
|
||||
variant('spgrid', default=False, description='Build with dune-spgrid module')
|
||||
variant('testtools', default=False, description='Build with dune-testtools module')
|
||||
variant('typetree', default=False, description='Build with dune-typetree module')
|
||||
variant('uggrid', default=False, description='Build with dune-uggrid module')
|
||||
# Define one variant for each non-core Dune module that we have.
|
||||
for var, res in dune_variants_to_resources.items():
|
||||
variant(var, default=False, description='Build with the %s module' % res)
|
||||
|
||||
# Define conflicts between Dune module variants. These conflicts are of the following type:
|
||||
# conflicts('dune~functions', when='+pdelab') -> dune-pdelab cannot be built without dune-functions
|
||||
for var, res in dune_variants_to_resources.items():
|
||||
for dep in module_dependencies.get(res, []):
|
||||
if dep in dune_resources_to_variants:
|
||||
conflicts('dune~%s' % dune_resources_to_variants[dep], when='+%s' % var)
|
||||
|
||||
# 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
|
||||
|
@ -98,28 +141,28 @@ class Dune(CMakePackage):
|
|||
name='dune-geometry',
|
||||
git='https://gitlab.dune-project.org/core/dune-geometry.git',
|
||||
branch=branch,
|
||||
when='@%s+geometry' % vers,
|
||||
when='@%s' % vers,
|
||||
)
|
||||
|
||||
resource(
|
||||
name='dune-grid',
|
||||
git='https://gitlab.dune-project.org/core/dune-grid.git',
|
||||
branch=branch,
|
||||
when='@%s+grid' % vers,
|
||||
when='@%s' % vers,
|
||||
)
|
||||
|
||||
resource(
|
||||
name='dune-istl',
|
||||
git='https://gitlab.dune-project.org/core/dune-istl.git',
|
||||
branch=branch,
|
||||
when='@%s+istl' % vers,
|
||||
when='@%s' % vers,
|
||||
)
|
||||
|
||||
resource(
|
||||
name='dune-localfunctions',
|
||||
git='https://gitlab.dune-project.org/core/dune-localfunctions.git',
|
||||
branch=branch,
|
||||
when='@%s+localfunctions' % vers,
|
||||
when='@%s' % vers,
|
||||
)
|
||||
|
||||
resource(
|
||||
|
@ -232,29 +275,7 @@ class Dune(CMakePackage):
|
|||
submodules=True,
|
||||
)
|
||||
|
||||
# Dependencies between modules - not necessarily the full set
|
||||
# as the closure of module dependencies is built later on.
|
||||
module_dependencies = {}
|
||||
module_dependencies["dune-alugrid"] = ["dune-grid", "dune-geometry", "dune-common"]
|
||||
module_dependencies["dune-codegen"] = ["dune-pdelab", "dune-testtools", "dune-alugrid"]
|
||||
module_dependencies["dune-common"] = []
|
||||
module_dependencies["dune-fem"] = ["dune-grid"]
|
||||
module_dependencies["fune-fempy"] = ["dune-fem"]
|
||||
module_dependencies["dune-foamgrid"] = ["dune-grid"]
|
||||
module_dependencies["dune-functions"] = ["dune-grid", "dune-typetree", "dune-localfunctions", "dune-istl"]
|
||||
module_dependencies["dune-geometry"] = ["dune-common"]
|
||||
module_dependencies["dune-grid"] = ["dune-common", "dune-geometry"]
|
||||
module_dependencies["dune-grid-glue"] = ["dune-grid"]
|
||||
module_dependencies["dune-istl"] = ["dune-common"]
|
||||
module_dependencies["dune-localfunctions"] = ["dune-common", "dune-geometry"]
|
||||
module_dependencies["dune-multidomaingrid"] = ["dune-grid", "dune-typetree"]
|
||||
module_dependencies["dune-pdelab"] = ["dune-common", "dune-grid", "dune-istl", "dune-functions"]
|
||||
module_dependencies["dune-polygongrid"] = ["dune-grid"]
|
||||
module_dependencies["dune-python"] = ["dune-common"]
|
||||
module_dependencies["dune-testtools"] = ["dune-common"]
|
||||
module_dependencies["dune-typetree"] = ["dune-common"]
|
||||
module_dependencies["dune-uggrid"] = ["dune-common"]
|
||||
|
||||
# Make sure that Python components integrate well into Spack
|
||||
extends('python')
|
||||
python_components = [ 'dune' ]
|
||||
|
||||
|
@ -280,13 +301,9 @@ class Dune(CMakePackage):
|
|||
depends_on('python@3.0:', type=('build', 'run'))
|
||||
depends_on('py-setuptools', type='build', when='+python')
|
||||
depends_on('py-numpy', type=('build', 'run'), when='+python')
|
||||
depends_on('py-pip', type=('build', 'run'), when='+codegen')
|
||||
depends_on('py-pip', type=('build', 'run'), when='+python')
|
||||
depends_on('py-pip', type=('build', 'run'), when='+testtools')
|
||||
depends_on('py-pip', type=('build', 'run'))
|
||||
depends_on('py-sphinx', type=('build', 'run'), when='+doc')
|
||||
depends_on('py-wheel', type='build', when='+codegen')
|
||||
depends_on('py-wheel', type='build', when='+python')
|
||||
depends_on('py-wheel', type='build', when='+testtools')
|
||||
depends_on('py-wheel', type='build')
|
||||
depends_on('scotch+mpi', when='+ptscotch')
|
||||
depends_on('sionlib', when='+sionlib')
|
||||
depends_on('suite-sparse', when='+suitesparse')
|
||||
|
@ -297,9 +314,8 @@ class Dune(CMakePackage):
|
|||
|
||||
# Apply patches
|
||||
patch('virtualenv_from_envvariable.patch', when='+testtools')
|
||||
patch('virtualenv_from_envvariable.patch', when='+codegen')
|
||||
|
||||
# Some conflicts
|
||||
# Some additional variant conflicts of Dune modules and upstream dependencies
|
||||
conflicts('dune~superlu', when='+codegen')
|
||||
|
||||
def setup_build_environment(self, env):
|
||||
|
@ -356,7 +372,7 @@ class Dune(CMakePackage):
|
|||
'-DCMAKE_DISABLE_FIND_PACKAGE_ZOLTAN:BOOL=%s' % nvariant_bool('+zoltan'),
|
||||
]
|
||||
|
||||
if '+testtools' in spec or '+codegen' in spec:
|
||||
if '+testtools' in spec:
|
||||
cmake_args.append('-DDUNE_PYTHON_VIRTUALENV_SETUP:BOOL=ON')
|
||||
cmake_args.append('-DDUNE_PYTHON_ALLOW_GET_PIP:BOOL=ON')
|
||||
cmake_args.append('-DDUNE_PYTHON_VIRTUALENV_PATH:STRING="%s"' % join_path(Path.home(), '.cache', 'dune-python-env', self.spec.dag_hash()))
|
||||
|
@ -370,34 +386,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):
|
||||
# dune-codegen delivers its own set of patches for its submodules
|
||||
# that we can apply with a script delivered by dune-codegen.
|
||||
|
|
Loading…
Reference in New Issue