From c96c38a08fce651bedf612e7b95257e09616726c Mon Sep 17 00:00:00 2001 From: David Wells Date: Mon, 29 Oct 2018 14:50:43 -0400 Subject: Expand the libMesh dependency list (#9642) This commit overhauls the libMesh package script in a number of ways: * We now inherit from AutotoolsPackage. * libMesh contains about a dozen third-party dependencies that can only be provided by the copy bundled with libMesh. This patch enumerates all such bundled dependencies and disables all of them by default. * libMesh supports compilation with external installations of boost, eigen, hdf5, slepc, and tbb; this patch adds all of them to package.py. * libMesh will look for a few system executables (xz, bzip, gdb) by default. This is now disabled. * libMesh will now used a copy of perl installed by spack instead of trying to find the system copy. * Compilation with non-system MPI installations requires an additional flag (--with-mpi=); this has been added. --- .../repos/builtin/packages/libmesh/package.py | 199 +++++++++++++++++++-- 1 file changed, 182 insertions(+), 17 deletions(-) (limited to 'var') diff --git a/var/spack/repos/builtin/packages/libmesh/package.py b/var/spack/repos/builtin/packages/libmesh/package.py index 2f7eb2c713..d21e056b33 100644 --- a/var/spack/repos/builtin/packages/libmesh/package.py +++ b/var/spack/repos/builtin/packages/libmesh/package.py @@ -6,7 +6,7 @@ from spack import * -class Libmesh(Package): +class Libmesh(AutotoolsPackage): """The libMesh library provides a framework for the numerical simulation of partial differential equations using arbitrary unstructured discretizations on serial and parallel platforms.""" @@ -19,29 +19,194 @@ class Libmesh(Package): version('1.2.1', sha256='11c22c7d96874a17de6b8c74caa45d6745d40bf3610e88b2bd28fd3381f5ba70') version('1.0.0', 'cb464fc63ea0b71b1e69fa3f5d4f93a4') + # support for libraries that are only available through the bundled copies: + # TODO libMesh 1.2.1 gained the ability to specify a path to capnproto + variant('capnproto', default=False, description='Compile with the bundled capnproto serialization library') + variant('exodusii', default=False, description='Compile with the bundled ExodusII output library') + variant('fparser', default=False, description='Compile with the bundled fparser function parser library') + variant('gmv', default=False, description='Compile with the bundled gmv format IO library') + variant('laspack', default=False, description='Compile with the bundled laspack interative solver library') + variant('libhilbert', default=False, description='Compile with the bundled libHilbert partitioning library') + variant('metaphysicl', default=False, description='Compile with the bundled metaphysicl AD library') + variant('metis', default=False, description='Compile with the bundled METIS graph partitioning library') + variant('nanoflann', default=False, description='Compile with the bundled nanoflann graph library') + variant('nemesis', default=False, description='Compile with the bundled nemesis IO library') + variant('netcdf', default=False, description='Compile with the bundled NETCDF IO library') + # TODO the copy of parmetis bundled with libMesh assumes that we use the + # bundled copy of metis, but previous versions of this build script use an + # external metis installation. Be conservative and completely disable + # parmetis support to preserve the old behavior (and to prevent compiling + # with two different copies of metis). + # + # variant('parmetis', default=False, + # description='Compile with the bundled PARMETIS graph library') + variant('qhull', default=False, description='Compile with the bundled qhull mesh generation library') + variant('sfc', default=False, description='Compile with the bundled sfcurves partitioning library') + variant('tetgen', default=False, description='Compile with the bundled tetgen mesh generation library') + variant('triangle', default=False, description='Compile with the bundled Triangle mesh generation library') + + # support for libraries that may be externally installed: + variant('boost', default=False, description='Compile with components dependent on boost') + variant('eigen', default=False, description='support for dense linear algebra with Eigen') + variant('hdf5', default=False, description='Compile with support for HDF5 files') + variant('slepc', default=False, description='Compile with support for the SLEPc eigensolver') + + # other features: + variant('debug', default=False, description='Compile with support for debugging') variant('mpi', default=True, description='Enables MPI parallelism') - variant('slepc', default=False, description='SLEPc eigensolver') + # While it is possible to configure libMesh to use openMP with neither + # pthreads nor TBB, no openMP code can actually be reached without enabling + # pthreads as well. Hence, since enabling openMP while disabling pthreads + # is not useful, we include openMP in the same variant to make it clear + # which scheduler is ultimately used. + variant('threads', default='none', + description='Enable threading support (with a particular ' + 'scheduler, in the case of openmp and tbb)', + values=('none', 'pthreads', 'tbb', 'openmp'), multi=False) + + conflicts('+metaphysicl', when='@:1.2.999', + msg='The interface to metaphysicl is not available in libMesh ' + 'versions older than 1.3.0. Please explicitly disable this ' + 'variant.') - # Parallel version of libMesh needs MPI & parallel solvers + depends_on('boost', when='+boost') + # The Scotch dependency of Eigen is not used by libMesh. Since Scotch can + # only be used with certain versions of flex it conflicts with several + # versions of GCC, so explicitly disable it. + depends_on('eigen~scotch', when='+eigen') + depends_on('hdf5+mpi', when='+hdf5+mpi') depends_on('mpi', when='+mpi') + depends_on('mpi', when='+slepc') + # compilation dependencies depend on perl + depends_on('perl') depends_on('petsc+mpi', when='+mpi') - - # SLEPc version needs SLEPc and requires MPI + depends_on('petsc+metis', when='+metis') depends_on('slepc', when='+slepc') - conflicts('~mpi', when='+slepc') + depends_on('tbb', when='threads=tbb') + + def configure_args(self): + options = [] + + # GLIBCXX debugging is not, by default, supported by other libraries, + # so unconditionally disable it for libmesh + options.append('--enable-glibcxx-debugging=no') + + # All bundled dependencies are explicitly disabled, so we do not need + # to perform this check: + options.append('--disable-strict-lgpl') + + # The Hinnant unique pointer implementation is incompatible with boost + # (and not necessary with C++11 support), so unconditionally disable + # it: + options.append('--disable-hinnant-unique-ptr') + # libMesh does not allow for us to specify an installation location for + # zlib, an undocumented dependency of gzstreams: hence we must + # unconditionally disable gzstreams. + options.append('--enable-gzstreams=no') + # Similarly, since we cannot specify a location for bzip2 or xz, so + # disable them to avoid picking up system installations: + options.append('--disable-bzip2') + options.append('--disable-xz') + # TODO enable GDB backtracing. Disable for now to avoid picking up the + # system gdb installation: + options.append('--without-gdb-command') + + # TODO add X11 as a dependency to get tecplot working + options.append('--enable-tecio=no') + options.append('--enable-tecplot=no') + + # handle the bundled libraries that are not themselves dependencies of + # other bundled libaries: + for bundled_library in ['capnproto', 'exodusii', 'fparser', 'gmv', + 'laspack', 'libHilbert', 'metaphysicl', + 'nanoflann', 'nemesis', 'parmetis', 'qhull', + 'sfc', 'tetgen', 'triangle']: + if '+' + bundled_library.lower() in self.spec: + options.append('--enable-' + bundled_library + "=yes") + else: + options.append('--enable-' + bundled_library + "=no") + + # and the ones which are dependencies of other bundled libraries: + if '+exodusii' in self.spec or '+netcdf' in self.spec: + options.append('--enable-netcdf=yes') + else: + options.append('--enable-netcdf=no') + + # handle external library dependencies: + if '+boost' in self.spec: + options.append('--with-boost=%s' % self.spec['boost'].prefix) + else: + options.append('--enable-boost=no') + + if '+eigen' in self.spec: + options.append('--with-eigen=%s' % self.spec['eigen'].prefix) + else: + options.append('--enable-eigen=no') + + if '+hdf5' in self.spec: + options.append('--with-hdf5=%s' % self.spec['hdf5'].prefix) + else: + options.append('--enable-hdf5=no') + # This is necessary with libMesh 1.2.1 to prevent a configure + # error: + if '+netcdf' not in self.spec: + options.append('--disable-netcdf-4') + + if '+metis' in self.spec: + options.append('--with-metis=PETSc') + + if '+petsc' in self.spec: + options.append('--enable-petsc=yes') + options.append('PETSC_DIR=%s' % self.spec['petsc'].prefix) + else: + options.append('--enable-petsc=no') + + if '+slepc' in self.spec: + options.append('SLEPC_DIR=%s' % self.spec['slepc'].prefix) + else: + options.append('--enable-slepc=no') + + # and, finally, other things: + if '+debug' in self.spec: + options.append('--with-methods=dbg') + else: + options.append('--with-methods=opt') + + if '+mpi' in self.spec: + options.append('CC=%s' % self.spec['mpi'].mpicc) + options.append('CXX=%s' % self.spec['mpi'].mpicxx) + options.append('--with-mpi=%s' % self.spec['mpi'].prefix) + else: + options.append('--disable-mpi') + # libMesh will try to link with the system MPI library unless we + # provide explicit overrides + options.append('CC=%s' % self.compiler.cc) + options.append('CXX=%s' % self.compiler.cxx) - def install(self, spec, prefix): - config_args = ["--prefix=%s" % prefix] + if 'threads=openmp' in self.spec: + # OpenMP cannot be used if pthreads is not available: see + # parallel/threads_pthread.h and parallel/threads.h + options.append('--enable-openmp=yes') + options.append('--with-thread-model=pthread') + options.append('--enable-pthreads=yes') + else: + options.append('--enable-openmp=no') - if '+mpi' in spec: - config_args.append('CC=%s' % spec['mpi'].mpicc) - config_args.append('CXX=%s' % spec['mpi'].mpicxx) - config_args.append('PETSC_DIR=%s' % spec['petsc'].prefix) + if 'threads=pthreads' in self.spec: + options.append('--with-thread-model=pthread') + options.append('--enable-pthreads=yes') + else: + if 'threads=openmp' not in self.spec: + options.append('--enable-pthreads=no') - if '+slepc' in spec: - config_args.append('SLEPC_DIR=%s' % spec['slepc'].prefix) + if 'threads=tbb' in self.spec: + options.append('--with-thread-model=tbb') + options.append('--enable-tbb=yes') + options.append('--with-tbb=%s' % self.spec['tbb'].prefix) + else: + options.append('--enable-tbb=no') - configure(*config_args) + return options - make() - make('install') + def setup_dependent_environment(self, spack_env, run_env, dependent_spec): + spack_env.append_flags('PERL', self.spec['perl'].command.path) -- cgit v1.2.3-70-g09d2