[MUMPS] Various improvements in the package.
* Fix a bug when checking for 'xl' or 'xl_r' compiler. * Add support for parallel build - the 's', 'c', 'd', and 'z' targets are build separately allowing parallel builds. * When build '+shared', inject all dependencies into the link lines of the mumps libraries. * Run the examples only when installing with the '--test' Spack option.
This commit is contained in:
parent
106827db03
commit
ae795d8184
1 changed files with 83 additions and 39 deletions
|
@ -85,16 +85,26 @@ def write_makefile_inc(self):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'You cannot use the variants parmetis or ptscotch without mpi')
|
'You cannot use the variants parmetis or ptscotch without mpi')
|
||||||
|
|
||||||
lapack_blas = (self.spec['lapack'].libs +
|
# The makefile variables LIBBLAS, LSCOTCH, LMETIS, and SCALAP are only
|
||||||
self.spec['blas'].libs)
|
# used to link the examples, so if building '+shared' there is no need
|
||||||
makefile_conf = ["LIBBLAS = %s" % lapack_blas.ld_flags]
|
# to explicitly link with the respective libraries because we make sure
|
||||||
|
# the mumps shared libraries are already linked with them. See also the
|
||||||
|
# comment below about 'inject_libs'. This behaviour may cause problems
|
||||||
|
# if building '+shared' and the used libraries were build static
|
||||||
|
# without the PIC option.
|
||||||
|
shared = '+shared' in self.spec
|
||||||
|
|
||||||
|
lapack_blas = (self.spec['lapack'].libs + self.spec['blas'].libs)
|
||||||
|
makefile_conf = ["LIBBLAS = %s" %
|
||||||
|
lapack_blas.ld_flags if not shared else '']
|
||||||
|
|
||||||
orderings = ['-Dpord']
|
orderings = ['-Dpord']
|
||||||
|
|
||||||
if '+ptscotch' in self.spec or '+scotch' in self.spec:
|
if '+ptscotch' in self.spec or '+scotch' in self.spec:
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
"ISCOTCH = -I%s" % self.spec['scotch'].prefix.include,
|
"ISCOTCH = -I%s" % self.spec['scotch'].prefix.include,
|
||||||
"LSCOTCH = {0}".format(self.spec['scotch'].libs.ld_flags)
|
"LSCOTCH = {0}".format(
|
||||||
|
self.spec['scotch'].libs.ld_flags if not shared else '')
|
||||||
])
|
])
|
||||||
|
|
||||||
orderings.append('-Dscotch')
|
orderings.append('-Dscotch')
|
||||||
|
@ -104,16 +114,19 @@ def write_makefile_inc(self):
|
||||||
if '+parmetis' in self.spec and '+metis' in self.spec:
|
if '+parmetis' in self.spec and '+metis' in self.spec:
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
"IMETIS = -I%s" % self.spec['parmetis'].prefix.include,
|
"IMETIS = -I%s" % self.spec['parmetis'].prefix.include,
|
||||||
"LMETIS = -L%s -l%s -L%s -l%s" % (
|
("LMETIS = -L%s -l%s -L%s -l%s" % (
|
||||||
self.spec['parmetis'].prefix.lib, 'parmetis',
|
self.spec['parmetis'].prefix.lib, 'parmetis',
|
||||||
self.spec['metis'].prefix.lib, 'metis')
|
self.spec['metis'].prefix.lib, 'metis')) if not shared
|
||||||
|
else 'LMETIS ='
|
||||||
])
|
])
|
||||||
|
|
||||||
orderings.append('-Dparmetis')
|
orderings.append('-Dparmetis')
|
||||||
elif '+metis' in self.spec:
|
elif '+metis' in self.spec:
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
"IMETIS = -I%s" % self.spec['metis'].prefix.include,
|
"IMETIS = -I%s" % self.spec['metis'].prefix.include,
|
||||||
"LMETIS = -L%s -l%s" % (self.spec['metis'].prefix.lib, 'metis')
|
("LMETIS = -L%s -l%s" % (
|
||||||
|
self.spec['metis'].prefix.lib, 'metis')) if not shared
|
||||||
|
else 'LMETIS ='
|
||||||
])
|
])
|
||||||
|
|
||||||
orderings.append('-Dmetis')
|
orderings.append('-Dmetis')
|
||||||
|
@ -127,6 +140,7 @@ def write_makefile_inc(self):
|
||||||
# TODO: test this part, it needs a full blas, scalapack and
|
# TODO: test this part, it needs a full blas, scalapack and
|
||||||
# partitionning environment with 64bit integers
|
# partitionning environment with 64bit integers
|
||||||
|
|
||||||
|
using_xl = self.compiler.name in ['xl', 'xl_r']
|
||||||
if '+int64' in self.spec:
|
if '+int64' in self.spec:
|
||||||
if self.compiler.name == "xl" or self.compiler.name == "xl_r":
|
if self.compiler.name == "xl" or self.compiler.name == "xl_r":
|
||||||
makefile_conf.extend(
|
makefile_conf.extend(
|
||||||
|
@ -142,7 +156,7 @@ def write_makefile_inc(self):
|
||||||
'OPTL = %s -O ' % fpic,
|
'OPTL = %s -O ' % fpic,
|
||||||
'OPTC = %s -O -DINTSIZE64' % fpic])
|
'OPTC = %s -O -DINTSIZE64' % fpic])
|
||||||
else:
|
else:
|
||||||
if self.compiler.name == "xl" or self.compiler.name == "xl_r":
|
if using_xl:
|
||||||
makefile_conf.extend(
|
makefile_conf.extend(
|
||||||
['OPTF = -O3 -qfixed',
|
['OPTF = -O3 -qfixed',
|
||||||
'OPTL = %s -O3' % fpic,
|
'OPTL = %s -O3' % fpic,
|
||||||
|
@ -154,13 +168,16 @@ def write_makefile_inc(self):
|
||||||
'OPTC = %s -O ' % fpic])
|
'OPTC = %s -O ' % fpic])
|
||||||
|
|
||||||
if '+mpi' in self.spec:
|
if '+mpi' in self.spec:
|
||||||
scalapack = self.spec['scalapack'].libs
|
scalapack = self.spec['scalapack'].libs if not shared \
|
||||||
|
else LibraryList([])
|
||||||
makefile_conf.extend(
|
makefile_conf.extend(
|
||||||
['CC = {0}'.format(self.spec['mpi'].mpicc),
|
['CC = {0}'.format(self.spec['mpi'].mpicc),
|
||||||
'FC = {0}'.format(self.spec['mpi'].mpifc),
|
'FC = {0}'.format(self.spec['mpi'].mpifc),
|
||||||
"SCALAP = %s" % scalapack.ld_flags,
|
"SCALAP = %s" % scalapack.ld_flags,
|
||||||
"MUMPS_TYPE = par"])
|
"MUMPS_TYPE = par"])
|
||||||
if (self.spec.satisfies('%xl_r' or '%xl')) and self.spec.satisfies('^spectrum-mpi'): # noqa
|
# The FL makefile variable is used for linking the examples and
|
||||||
|
# linking the shared mumps libraries (in some cases).
|
||||||
|
if using_xl and self.spec.satisfies('^spectrum-mpi'):
|
||||||
makefile_conf.extend(
|
makefile_conf.extend(
|
||||||
['FL = {0}'.format(self.spec['mpi'].mpicc)])
|
['FL = {0}'.format(self.spec['mpi'].mpicc)])
|
||||||
else:
|
else:
|
||||||
|
@ -181,28 +198,54 @@ def write_makefile_inc(self):
|
||||||
# hack defined by _DMAIN_COMP (see examples/c_example.c)
|
# hack defined by _DMAIN_COMP (see examples/c_example.c)
|
||||||
makefile_conf.append("CDEFS = -DAdd_ -DMAIN_COMP")
|
makefile_conf.append("CDEFS = -DAdd_ -DMAIN_COMP")
|
||||||
else:
|
else:
|
||||||
if self.compiler.name != "xl" and self.compiler.name != "xl_r":
|
if not using_xl:
|
||||||
makefile_conf.append("CDEFS = -DAdd_")
|
makefile_conf.append("CDEFS = -DAdd_")
|
||||||
|
|
||||||
if '+shared' in self.spec:
|
if '+shared' in self.spec:
|
||||||
|
# All Mumps libraries will be linked with 'inject_libs'.
|
||||||
|
# Usually, the rpaths will be injected by the Spack compiler
|
||||||
|
# wrapper, however some MPI wrappers may not call the Spack
|
||||||
|
# compiler wrapper.
|
||||||
|
inject_libs = [self.rpath_args]
|
||||||
|
if '+mpi' in self.spec:
|
||||||
|
inject_libs += [self.spec['scalapack'].libs.ld_flags]
|
||||||
|
if '+ptscotch' in self.spec or '+scotch' in self.spec:
|
||||||
|
inject_libs += [self.spec['scotch'].libs.ld_flags]
|
||||||
|
if '+parmetis' in self.spec and '+metis' in self.spec:
|
||||||
|
inject_libs += [
|
||||||
|
"-L%s -l%s -L%s -l%s" % (
|
||||||
|
self.spec['parmetis'].prefix.lib, 'parmetis',
|
||||||
|
self.spec['metis'].prefix.lib, 'metis')]
|
||||||
|
elif '+metis' in self.spec:
|
||||||
|
inject_libs += [
|
||||||
|
"-L%s -l%s" % (self.spec['metis'].prefix.lib, 'metis')]
|
||||||
|
inject_libs += [lapack_blas.ld_flags]
|
||||||
|
inject_libs = ' '.join(inject_libs)
|
||||||
|
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
# Building dylibs with mpif90 causes segfaults on 10.8 and
|
# Building dylibs with mpif90 causes segfaults on 10.8 and
|
||||||
# 10.10. Use gfortran. (Homebrew)
|
# 10.10. Use gfortran. (Homebrew)
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
'LIBEXT=.dylib',
|
'LIBEXT=.dylib',
|
||||||
'AR=%s -dynamiclib -Wl,-install_name -Wl,%s/$(notdir $@) -undefined dynamic_lookup -o ' % (os.environ['FC'], prefix.lib), # noqa
|
'AR=%s -dynamiclib -Wl,-install_name -Wl,%s/$(notdir $@)'
|
||||||
|
' -undefined dynamic_lookup %s -o ' %
|
||||||
|
(os.environ['FC'], prefix.lib, inject_libs),
|
||||||
'RANLIB=echo'
|
'RANLIB=echo'
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
'LIBEXT=.so',
|
'LIBEXT=.so',
|
||||||
'AR=$(FL) -shared -Wl,-soname -Wl,%s/$(notdir $@) -o' % prefix.lib, # noqa
|
'AR=$(FL) -shared -Wl,-soname -Wl,%s/$(notdir $@) %s -o' %
|
||||||
|
(prefix.lib, inject_libs),
|
||||||
'RANLIB=echo'
|
'RANLIB=echo'
|
||||||
])
|
])
|
||||||
|
|
||||||
if self.compiler.name == 'xl' or self.compiler.name == 'xl_r':
|
if using_xl:
|
||||||
|
# The patches for xl + spectrum-mpi use SAR for linking
|
||||||
|
# libpord.
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
'SAR=/bin/xlc -shared -Wl,-soname -Wl,%s/$(notdir $@) -o' % prefix.lib # noqa
|
'SAR=%s -shared -Wl,-soname -Wl,%s/$(notdir $@) %s -o'
|
||||||
|
% (env['CC'], prefix.lib, inject_libs)
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
makefile_conf.extend([
|
makefile_conf.extend([
|
||||||
|
@ -222,24 +265,17 @@ def write_makefile_inc(self):
|
||||||
fh.write(makefile_inc)
|
fh.write(makefile_inc)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
make_libs = []
|
|
||||||
|
|
||||||
# the choice to compile ?examples is to have kind of a sanity
|
|
||||||
# check on the libraries generated.
|
|
||||||
if '+float' in spec:
|
|
||||||
make_libs.append('sexamples')
|
|
||||||
if '+complex' in spec:
|
|
||||||
make_libs.append('cexamples')
|
|
||||||
|
|
||||||
if '+double' in spec:
|
|
||||||
make_libs.append('dexamples')
|
|
||||||
if '+complex' in spec:
|
|
||||||
make_libs.append('zexamples')
|
|
||||||
|
|
||||||
self.write_makefile_inc()
|
self.write_makefile_inc()
|
||||||
|
|
||||||
# Build fails in parallel
|
# Build fails in parallel
|
||||||
make(*make_libs, parallel=False)
|
# That is why we split the builds of 's', 'c', 'd', and/or 'z' which
|
||||||
|
# can be build one after the other, each using a parallel build.
|
||||||
|
letters_variants = [
|
||||||
|
['s', '+float'], ['c', '+complex+float'],
|
||||||
|
['d', '+double'], ['z', '+complex+double']]
|
||||||
|
for l, v in letters_variants:
|
||||||
|
if v in spec:
|
||||||
|
make(l + 'examples')
|
||||||
|
|
||||||
install_tree('lib', prefix.lib)
|
install_tree('lib', prefix.lib)
|
||||||
install_tree('include', prefix.include)
|
install_tree('include', prefix.include)
|
||||||
|
@ -253,15 +289,23 @@ def install(self, spec, prefix):
|
||||||
|
|
||||||
# FIXME: extend the tests to mpirun -np 2 when build with MPI
|
# FIXME: extend the tests to mpirun -np 2 when build with MPI
|
||||||
# FIXME: use something like numdiff to compare output files
|
# FIXME: use something like numdiff to compare output files
|
||||||
|
# Note: In some cases, when 'mpi' is enabled, the examples below cannot
|
||||||
|
# be run without 'mpirun', so we enabled the tests only if explicitly
|
||||||
|
# requested with the Spack '--test' option.
|
||||||
|
if self.run_tests:
|
||||||
with working_dir('examples'):
|
with working_dir('examples'):
|
||||||
if '+float' in spec:
|
if '+float' in spec:
|
||||||
os.system('./ssimpletest < input_simpletest_real')
|
ssimpletest = Executable('./ssimpletest')
|
||||||
|
ssimpletest(input='input_simpletest_real')
|
||||||
if '+complex' in spec:
|
if '+complex' in spec:
|
||||||
os.system('./csimpletest < input_simpletest_real')
|
csimpletest = Executable('./csimpletest')
|
||||||
|
csimpletest(input='input_simpletest_cmplx')
|
||||||
if '+double' in spec:
|
if '+double' in spec:
|
||||||
os.system('./dsimpletest < input_simpletest_real')
|
dsimpletest = Executable('./dsimpletest')
|
||||||
|
dsimpletest(input='input_simpletest_real')
|
||||||
if '+complex' in spec:
|
if '+complex' in spec:
|
||||||
os.system('./zsimpletest < input_simpletest_cmplx')
|
zsimpletest = Executable('./zsimpletest')
|
||||||
|
zsimpletest(input='input_simpletest_cmplx')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def libs(self):
|
def libs(self):
|
||||||
|
|
Loading…
Reference in a new issue