Merge Kevin, Ben, and Saravan's contributions into develop

- includes ATLAS, BLAS, LAPACK, other FastMATH packages.
This commit is contained in:
Todd Gamblin 2015-06-07 16:10:32 -07:00
commit 1857b7736f
22 changed files with 580 additions and 58 deletions

View file

@ -126,14 +126,7 @@ def main():
try:
return_val = command(parser, args)
except SpackError, e:
if spack.debug:
# In debug mode, raise with a full stack trace.
raise
elif e.long_message:
tty.die(e.message, e.long_message)
else:
tty.die(e.message)
e.die()
except KeyboardInterrupt:
sys.stderr.write('\n')
tty.die("Keyboard interrupt.")

View file

@ -25,7 +25,7 @@
__all__ = ['set_install_permissions', 'install', 'install_tree', 'traverse_tree',
'expand_user', 'working_dir', 'touch', 'touchp', 'mkdirp',
'force_remove', 'join_path', 'ancestor', 'can_access', 'filter_file',
'change_sed_delimiter', 'is_exe', 'force_symlink']
'FileFilter', 'change_sed_delimiter', 'is_exe', 'force_symlink']
import os
import sys
@ -40,7 +40,6 @@
import llnl.util.tty as tty
from spack.util.compression import ALLOWED_ARCHIVE_TYPES
def filter_file(regex, repl, *filenames, **kwargs):
"""Like sed, but uses python regular expressions.
@ -97,6 +96,15 @@ def groupid_to_group(x):
shutil.rmtree(backup, ignore_errors=True)
class FileFilter(object):
"""Convenience class for calling filter_file a lot."""
def __init__(self, *filenames):
self.filenames = filenames
def filter(self, regex, repl, **kwargs):
return filter_file(regex, repl, *self.filenames, **kwargs)
def change_sed_delimiter(old_delim, new_delim, *filenames):
"""Find all sed search/replace commands and change the delimiter.
e.g., if the file contains seds that look like 's///', you can

View file

@ -280,6 +280,10 @@ def child_fun():
# Use os._exit here to avoid raising a SystemExit exception,
# which interferes with unit tests.
os._exit(0)
except spack.error.SpackError, e:
e.die()
except:
# Child doesn't raise or return to main spack code.
# Just runs default exception handler and exits.

View file

@ -75,7 +75,23 @@ def concretize_version(self, spec):
if valid_versions:
spec.versions = ver([valid_versions[-1]])
else:
raise NoValidVersionError(spec)
# We don't know of any SAFE versions that match the given
# spec. Grab the spec's versions and grab the highest
# *non-open* part of the range of versions it specifies.
# Someone else can raise an error if this happens,
# e.g. when we go to fetch it and don't know how. But it
# *might* work.
if not spec.versions or spec.versions == VersionList([':']):
raise NoValidVersionError(spec)
else:
last = spec.versions[-1]
if isinstance(last, VersionRange):
if last.end:
spec.versions = ver([last.end])
else:
spec.versions = ver([last.start])
else:
spec.versions = ver([last])
def concretize_architecture(self, spec):
@ -174,8 +190,8 @@ def __init__(self, compiler_spec):
class NoValidVersionError(spack.error.SpackError):
"""Raised when there is no available version for a package that
satisfies a spec."""
"""Raised when there is no way to have a concrete version for a
particular spec."""
def __init__(self, spec):
super(NoValidVersionError, self).__init__(
"No available version of %s matches '%s'" % (spec.name, spec.versions))
"There are no valid versions for %s that match '%s'" % (spec.name, spec.versions))

View file

@ -22,6 +22,10 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import os
import sys
import llnl.util.tty as tty
import spack
class SpackError(Exception):
"""This is the superclass for all Spack errors.
@ -38,6 +42,17 @@ def long_message(self):
return self._long_message
def die(self):
if spack.debug:
sys.excepthook(*sys.exc_info())
os._exit(1)
else:
tty.error(self.message)
if self.long_message:
print self.long_message
os._exit(1)
def __str__(self):
msg = self.message
if self.long_message:

View file

@ -471,13 +471,18 @@ def extendee_spec(self):
"""Spec of the extendee of this package, or None if it is not an extension."""
if not self.extendees:
return None
name = next(iter(self.extendees))
if not name in self.spec:
spec, kwargs = self.extendees[name]
return spec
# Need to do this to get the concrete version of the spec
return self.spec[name]
# TODO: allow more than one extendee.
name = next(iter(self.extendees))
# If the extendee is in the spec's deps already, return that.
for dep in self.spec.traverse():
if name == dep.name:
return dep
# Otherwise return the spec from the extends() directive
spec, kwargs = self.extendees[name]
return spec
@property
@ -542,7 +547,7 @@ def preorder_traversal(self, visited=None, **kwargs):
def provides(self, vpkg_name):
"""True if this package provides a virtual package with the specified name."""
return vpkg_name in self.provided
return any(s.name == vpkg_name for s in self.provided)
def virtual_dependencies(self, visited=None):
@ -561,8 +566,11 @@ def installed_dependents(self):
on this one."""
dependents = []
for spec in spack.db.installed_package_specs():
if self.name != spec.name and self.spec in spec:
dependents.append(spec)
if self.name == spec.name:
continue
for dep in spec.traverse():
if spec == dep:
dependents.append(spec)
return dependents
@ -816,17 +824,8 @@ def real_work():
except ProcessError, e:
# Annotate with location of build log.
e.build_log = log_path
# One of the processes returned an error code.
# Suppress detailed stack trace here unless in debug mode
if spack.debug:
raise e
else:
tty.error(e)
# Still need to clean up b/c there was an error.
cleanup()
os._exit(1)
raise e
except:
# other exceptions just clean up and raise.
@ -994,10 +993,13 @@ def do_deactivate(self, **kwargs):
activated = spack.install_layout.extension_map(self.extendee_spec)
for name, aspec in activated.items():
if aspec != self.spec and self.spec in aspec:
raise ActivationError(
"Cannot deactivate %s beacuse %s is activated and depends on it."
% (self.spec.short_spec, aspec.short_spec))
if aspec == self.spec:
continue
for dep in aspec.traverse():
if self.spec == dep:
raise ActivationError(
"Cannot deactivate %s beacuse %s is activated and depends on it."
% (self.spec.short_spec, aspec.short_spec))
self.extendee_spec.package.deactivate(self, **self.extendee_args)

View file

@ -498,7 +498,13 @@ def virtual(self):
Possible idea: just use conventin and make virtual deps all
caps, e.g., MPI vs mpi.
"""
return not spack.db.exists(self.name)
return Spec.is_virtual(self.name)
@staticmethod
def is_virtual(name):
"""Test if a name is virtual without requiring a Spec."""
return not spack.db.exists(name)
@property
@ -1224,7 +1230,17 @@ def satisfies(self, other, deps=True, strict=False):
"""
other = self._autospec(other)
# First thing we care about is whether the name matches
# A concrete provider can satisfy a virtual dependency.
if not self.virtual and other.virtual:
pkg = spack.db.get(self.name)
if pkg.provides(other.name):
for provided, when_spec in pkg.provided.items():
if self.satisfies(when_spec, deps=False, strict=strict):
if provided.satisfies(other):
return True
return False
# Otherwise, first thing we care about is whether the name matches
if self.name != other.name:
return False
@ -1364,11 +1380,21 @@ def version(self):
def __getitem__(self, name):
"""TODO: reconcile __getitem__, _add_dependency, __contains__"""
"""Get a dependency from the spec by its name."""
for spec in self.traverse():
if spec.name == name:
return spec
if Spec.is_virtual(name):
# TODO: this is a kind of kludgy way to find providers
# TODO: should we just keep virtual deps in the DAG instead of
# TODO: removing them on concretize?
for spec in self.traverse():
if spec.virtual:
continue
if spec.package.provides(name):
return spec
raise KeyError("No spec with name %s in %s" % (name, self))
@ -1380,6 +1406,7 @@ def __contains__(self, spec):
for s in self.traverse():
if s.satisfies(spec, strict=True):
return True
return False

View file

@ -152,7 +152,10 @@ def test_virtual_is_fully_expanded_for_callpath(self):
spec.concretize()
self.assertTrue('zmpi' in spec.dependencies)
self.assertFalse('mpi' in spec)
self.assertTrue(all(not 'mpi' in d.dependencies for d in spec.traverse()))
self.assertTrue('zmpi' in spec)
self.assertTrue('mpi' in spec)
self.assertTrue('fake' in spec.dependencies['zmpi'])
@ -168,7 +171,9 @@ def test_virtual_is_fully_expanded_for_mpileaks(self):
self.assertTrue('zmpi' in spec.dependencies['callpath'].dependencies)
self.assertTrue('fake' in spec.dependencies['callpath'].dependencies['zmpi'].dependencies)
self.assertFalse('mpi' in spec)
self.assertTrue(all(not 'mpi' in d.dependencies for d in spec.traverse()))
self.assertTrue('zmpi' in spec)
self.assertTrue('mpi' in spec)
def test_my_dep_depends_on_provider_of_my_virtual_dep(self):

View file

@ -167,12 +167,15 @@ def test_handle_unknown_package(self):
def test_find(self):
"""Test that finding specs within an install layout works."""
packages = list(spack.db.all_packages())[:max_packages]
# Create install prefixes for all packages in the list
installed_specs = {}
for pkg in packages:
spec = pkg.spec.concretized()
installed_specs[spec.name] = spec
self.layout.create_install_directory(spec)
# Make sure all the installed specs appear in DirectoryLayout.all_specs()
found_specs = dict((s.name, s) for s in self.layout.all_specs())
for name, spec in found_specs.items():
self.assertTrue(name in found_specs)

View file

@ -189,6 +189,67 @@ def test_unsatisfiable_variant_mismatch(self):
self.check_unsatisfiable('mpich+foo', 'mpich~foo')
def test_satisfies_virtual(self):
self.assertTrue(Spec('mpich').satisfies(Spec('mpi')))
self.assertTrue(Spec('mpich2').satisfies(Spec('mpi')))
self.assertTrue(Spec('zmpi').satisfies(Spec('mpi')))
# ================================================================================
# Indexing specs
# ================================================================================
def test_self_index(self):
s = Spec('callpath')
self.assertTrue(s['callpath'] == s)
def test_dep_index(self):
s = Spec('callpath')
s.normalize()
self.assertTrue(s['callpath'] == s)
self.assertTrue(type(s['dyninst']) == Spec)
self.assertTrue(type(s['libdwarf']) == Spec)
self.assertTrue(type(s['libelf']) == Spec)
self.assertTrue(type(s['mpi']) == Spec)
self.assertTrue(s['dyninst'].name == 'dyninst')
self.assertTrue(s['libdwarf'].name == 'libdwarf')
self.assertTrue(s['libelf'].name == 'libelf')
self.assertTrue(s['mpi'].name == 'mpi')
def test_spec_contains_deps(self):
s = Spec('callpath')
s.normalize()
self.assertTrue('dyninst' in s)
self.assertTrue('libdwarf' in s)
self.assertTrue('libelf' in s)
self.assertTrue('mpi' in s)
def test_virtual_index(self):
s = Spec('callpath')
s.concretize()
s_mpich = Spec('callpath ^mpich')
s_mpich.concretize()
s_mpich2 = Spec('callpath ^mpich2')
s_mpich2.concretize()
s_zmpi = Spec('callpath ^zmpi')
s_zmpi.concretize()
self.assertTrue(s['mpi'].name != 'mpi')
self.assertTrue(s_mpich['mpi'].name == 'mpich')
self.assertTrue(s_mpich2['mpi'].name == 'mpich2')
self.assertTrue(s_zmpi['zmpi'].name == 'zmpi')
for spec in [s, s_mpich, s_mpich2, s_zmpi]:
self.assertTrue('mpi' in spec)
# ================================================================================
# Constraints

View file

@ -124,6 +124,11 @@ def __repr__(self):
return "<exe: %s>" % self.exe
def __str__(self):
return ' '.join(self.exe)
def which(name, **kwargs):
"""Finds an executable in the path like command-line which."""
path = kwargs.get('path', os.environ.get('PATH', '').split(os.pathsep))

View file

@ -0,0 +1,41 @@
from spack import *
import os
import shutil
class Arpack(Package):
"""A collection of Fortran77 subroutines designed to solve large scale
eigenvalue problems.
"""
homepage = "http://www.caam.rice.edu/software/ARPACK/"
url = "http://www.caam.rice.edu/software/ARPACK/SRC/arpack96.tar.gz"
version('96', 'fffaa970198b285676f4156cebc8626e')
depends_on('blas')
depends_on('lapack')
def patch(self):
# Filter the cray makefile to make a spack one.
shutil.move('ARMAKES/ARmake.CRAY', 'ARmake.inc')
makefile = FileFilter('ARmake.inc')
# Be sure to use Spack F77 wrapper
makefile.filter('^FC.*', 'FC = f77')
makefile.filter('^FFLAGS.*', 'FFLAGS = -O2 -g')
# Set up some variables.
makefile.filter('^PLAT.*', 'PLAT = ')
makefile.filter('^home.*', 'home = %s' % os.getcwd())
makefile.filter('^BLASdir.*', 'BLASdir = %s' % self.spec['blas'].prefix)
makefile.filter('^LAPACKdir.*', 'LAPACKdir = %s' % self.spec['lapack'].prefix)
# build the library in our own prefix.
makefile.filter('^ARPACKLIB.*', 'ARPACKLIB = %s/libarpack.a' % os.getcwd())
def install(self, spec, prefix):
with working_dir('SRC'):
make('all')
mkdirp(prefix.lib)
install('libarpack.a', prefix.lib)

View file

@ -0,0 +1,60 @@
from spack import *
from spack.util.executable import Executable
import os
class Atlas(Package):
"""
Automatically Tuned Linear Algebra Software, generic shared
ATLAS is an approach for the automatic generation and optimization of
numerical software. Currently ATLAS supplies optimized versions for the
complete set of linear algebra kernels known as the Basic Linear Algebra
Subroutines (BLAS), and a subset of the linear algebra routines in the
LAPACK library.
"""
homepage = "http://math-atlas.sourceforge.net/"
version('3.11.34', '0b6c5389c095c4c8785fd0f724ec6825',
url='http://sourceforge.net/projects/math-atlas/files/Developer%20%28unstable%29/3.11.34/atlas3.11.34.tar.bz2/download')
version('3.10.2', 'a4e21f343dec8f22e7415e339f09f6da',
url='http://downloads.sourceforge.net/project/math-atlas/Stable/3.10.2/atlas3.10.2.tar.bz2')
# TODO: make this provide BLAS once it works better. Create a way
# TODO: to mark "beta" packages and require explicit invocation.
# provides('blas')
def patch(self):
# Disable thraed check. LLNL's environment does not allow
# disabling of CPU throttling in a way that ATLAS actually
# understands.
filter_file(r'^\s+if \(thrchk\) exit\(1\);', 'if (0) exit(1);',
'CONFIG/src/config.c')
# TODO: investigate a better way to add the check back in
# TODO: using, say, MSRs. Or move this to a variant.
@when('@:3.10')
def install(self, spec, prefix):
with working_dir('ATLAS-Build', create=True):
configure = Executable('../configure')
configure('--prefix=%s' % prefix, '-C', 'ic', 'cc', '-C', 'if', 'f77', "--dylibs")
make()
make('check')
make('ptcheck')
make('time')
make("install")
def install(self, spec, prefix):
with working_dir('ATLAS-Build', create=True):
configure = Executable('../configure')
configure('--incdir=%s' % prefix.include,
'--libdir=%s' % prefix.lib,
'--cc=cc',
"--shared")
make()
make('check')
make('ptcheck')
make('time')
make("install")

View file

@ -0,0 +1,25 @@
from spack import *
class Boxlib(Package):
"""BoxLib, a software framework for massively parallel
block-structured adaptive mesh refinement (AMR) codes."""
homepage = "https://ccse.lbl.gov/BoxLib/"
url = "https://ccse.lbl.gov/pub/Downloads/BoxLib.git";
# TODO: figure out how best to version this. No tags in the repo!
version('master', git='https://ccse.lbl.gov/pub/Downloads/BoxLib.git')
depends_on('mpi')
def install(self, spec, prefix):
args = std_cmake_args
args += ['-DCCSE_ENABLE_MPI=1',
'-DCMAKE_C_COMPILER=%s' % which('mpicc'),
'-DCMAKE_CXX_COMPILER=%s' % which('mpicxx'),
'-DCMAKE_Fortran_COMPILER=%s' % which('mpif90')]
cmake('.', *args)
make()
make("install")

View file

@ -0,0 +1,32 @@
from spack import *
import os
class Cblas(Package):
"""The BLAS (Basic Linear Algebra Subprograms) are routines that
provide standard building blocks for performing basic vector and
matrix operations."""
homepage = "http://www.netlib.org/blas/_cblas/"
# tarball has no version, but on the date below, this MD5 was correct.
version('2015-06-06', '1e8830f622d2112239a4a8a83b84209a',
url='http://www.netlib.org/blas/blast-forum/cblas.tgz')
depends_on('blas')
parallel = False
def patch(self):
mf = FileFilter('Makefile.in')
mf.filter('^BLLIB =.*', 'BLLIB = %s/libblas.a' % self.spec['blas'].prefix.lib)
mf.filter('^CC =.*', 'CC = cc')
mf.filter('^FC =.*', 'FC = f90')
def install(self, spec, prefix):
make('all')
mkdirp(prefix.lib)
# Rename the generated lib file to libcblas.a
install('./lib/cblas_LINUX.a', '%s/libcblas.a' % prefix.lib)

View file

@ -0,0 +1,30 @@
from spack import *
class Cgm(Package):
"""The Common Geometry Module, Argonne (CGMA) is a code library
which provides geometry functionality used for mesh generation and
other applications."""
homepage = "http://trac.mcs.anl.gov/projects/ITAPS/wiki/CGM"
url = "http://ftp.mcs.anl.gov/pub/fathom/cgm13.1.1.tar.gz"
version('13.1.1', '4e8dbc4ba8f65767b29f985f7a23b01f')
version('13.1.0', 'a6c7b22660f164ce893fb974f9cb2028')
version('13.1' , '95f724bda04919fc76818a5b7bc0b4ed')
depends_on("mpi")
def patch(self):
filter_file('^(#include "CGMParallelConventions.h")',
'//\1',
'geom/parallel/CGMReadParallel.cpp')
def install(self, spec, prefix):
configure("--with-mpi",
"--prefix=%s" % prefix,
"CFLAGS=-static",
"CXXFLAGS=-static",
"FCFLAGS=-static")
make()
make("install")

View file

@ -0,0 +1,32 @@
from spack import *
class Hypre(Package):
"""Hypre is a library of high performance preconditioners that
features parallel multigrid methods for both structured and
unstructured grid problems."""
homepage = "https://computation.llnl.gov/project/linear_solvers/software.php"
url = "https://computation.llnl.gov/project/linear_solvers/download/hypre-2.10.0b.tar.gz"
version('2.10.0b', '768be38793a35bb5d055905b271f5b8e')
depends_on("mpi")
depends_on("blas")
depends_on("lapack")
def install(self, spec, prefix):
blas_dir = spec['blas'].prefix
lapack_dir = spec['lapack'].prefix
# Hypre's source is staged under ./src so we'll have to manually
# cd into it.
with working_dir("src"):
configure(
"--prefix=%s" % prefix,
"--with-blas-libs=blas",
"--with-blas-lib-dirs=%s/lib" % blas_dir,
"--with-lapack-libs=\"lapack blas\"",
"--with-lapack-lib-dirs=%s/lib" % lapack_dir,
"--with-MPI")
make()
make("install")

View file

@ -0,0 +1,45 @@
from spack import *
class Lapack(Package):
"""
LAPACK version 3.X is a comprehensive FORTRAN library that does
linear algebra operations including matrix inversions, least
squared solutions to linear sets of equations, eigenvector
analysis, singular value decomposition, etc. It is a very
comprehensive and reputable package that has found extensive
use in the scientific community.
"""
homepage = "http://www.netlib.org/lapack/"
url = "http://www.netlib.org/lapack/lapack-3.5.0.tgz"
version('3.5.0', 'b1d3e3e425b2e44a06760ff173104bdf')
version('3.4.2', '61bf1a8a4469d4bdb7604f5897179478')
version('3.4.1', '44c3869c38c8335c2b9c2a8bb276eb55')
version('3.4.0', '02d5706ec03ba885fc246e5fa10d8c70')
version('3.3.1', 'd0d533ec9a5b74933c2a1e84eedc58b4')
# blas is a virtual dependency.
depends_on('blas')
# Doesn't always build correctly in parallel
parallel = False
@when('^netlib-blas')
def get_blas_libs(self):
blas = self.spec['netlib-blas']
return [join_path(blas.prefix.lib, 'blas.a')]
@when('^atlas')
def get_blas_libs(self):
blas = self.spec['atlas']
return [join_path(blas.prefix.lib, l)
for l in ('libf77blas.a', 'libatlas.a')]
def install(self, spec, prefix):
blas_libs = ";".join(self.get_blas_libs())
cmake(".", '-DBLAS_LIBRARIES=' + blas_libs, *std_cmake_args)
make()
make("install")

View file

@ -5,28 +5,23 @@ class Metis(Package):
partitioning finite element meshes, and producing fill reducing
orderings for sparse matrices. The algorithms implemented in
METIS are based on the multilevel recursive-bisection,
multilevel k-way, and multi-constraint partitioning schemes
developed in our lab."""
multilevel k-way, and multi-constraint partitioning schemes."""
homepage = "http://glaros.dtc.umn.edu/gkhome/metis/metis/overview"
url = "http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz"
version('5.1.0', '5465e67079419a69e0116de24fce58fe')
# FIXME: Add dependencies if this package requires them.
# depends_on("foo")
def patch(self):
filter_file(r'#define IDXTYPEWIDTH 32', '#define IDXTYPEWIDTH 64', 'include/metis.h',
string=True)
depends_on('mpi')
def install(self, spec, prefix):
with working_dir('spack-build', create=True):
cmake('..',
'-DGKLIB_PATH=../GKlib',
'-DBUILD_SHARED_LIBS=TRUE',
*std_cmake_args)
make()
make("install")
cmake(".",
'-DGKLIB_PATH=%s/GKlib' % pwd(),
'-DSHARED=1',
'-DCMAKE_C_COMPILER=mpicc',
'-DCMAKE_CXX_COMPILER=mpicxx',
'-DSHARED=1',
*std_cmake_args)
make()
make("install")

View file

@ -0,0 +1,40 @@
from spack import *
import os
class NetlibBlas(Package):
"""Netlib reference BLAS"""
homepage = "http://www.netlib.org/lapack/"
url = "http://www.netlib.org/lapack/lapack-3.5.0.tgz"
version('3.5.0', 'b1d3e3e425b2e44a06760ff173104bdf')
# virtual dependency
provides('blas')
# Doesn't always build correctly in parallel
parallel = False
def patch(self):
os.symlink('make.inc.example', 'make.inc')
mf = FileFilter('make.inc')
mf.filter('^FORTRAN.*', 'FORTRAN = f90')
mf.filter('^LOADER.*', 'LOADER = f90')
mf.filter('^CC =.*', 'CC = cc')
def install(self, spec, prefix):
make('blaslib')
# Tests that blas builds correctly
make('blas_testing')
# No install provided
mkdirp(prefix.lib)
install('librefblas.a', prefix.lib)
# Blas virtual package should provide blas.a and libblas.a
with working_dir(prefix.lib):
symlink('librefblas.a', 'blas.a')
symlink('librefblas.a', 'libblas.a')

View file

@ -0,0 +1,43 @@
from spack import *
import os
import shutil
class Parpack(Package):
"""ARPACK is a collection of Fortran77 subroutines designed to solve large
scale eigenvalue problems."""
homepage = "http://www.caam.rice.edu/software/ARPACK/download.html"
url = "http://www.caam.rice.edu/software/ARPACK/SRC/parpack96.tar.Z"
version('96', 'a175f70ff71837a33ff7e4b0b6054f43')
depends_on('mpi')
depends_on('blas')
depends_on('lapack')
def patch(self):
# Filter the CJ makefile to make a spack one.
shutil.move('ARMAKES/ARmake.CJ', 'ARmake.inc')
mf = FileFilter('ARmake.inc')
# Be sure to use Spack F77 wrapper
mf.filter('^FC.*', 'FC = f77')
mf.filter('^FFLAGS.*', 'FFLAGS = -O2 -g')
# Set up some variables.
mf.filter('^PLAT.*', 'PLAT = ')
mf.filter('^home.*', 'home = %s' % os.getcwd())
mf.filter('^BLASdir.*', 'BLASdir = %s' % self.spec['blas'].prefix)
mf.filter('^LAPACKdir.*', 'LAPACKdir = %s' % self.spec['lapack'].prefix)
mf.filter('^MAKE.*', 'MAKE = make')
# build the library in our own prefix.
mf.filter('^ARPACKLIB.*', 'PARPACKLIB = %s/libparpack.a' % os.getcwd())
def install(self, spec, prefix):
with working_dir('PARPACK/SRC/MPI'):
make('all')
mkdirp(prefix.lib)
install('libparpack.a', prefix.lib)

View file

@ -0,0 +1,40 @@
from spack import *
class Petsc(Package):
"""PETSc is a suite of data structures and routines for the
scalable (parallel) solution of scientific applications modeled by
partial differential equations."""
homepage = "http://www.mcs.anl.gov/petsc/index.html"
url = "http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-3.5.3.tar.gz"
version('3.5.3', 'd4fd2734661e89f18ac6014b5dd1ef2f')
version('3.5.2', 'ad170802b3b058b5deb9cd1f968e7e13')
version('3.5.1', 'a557e029711ebf425544e117ffa44d8f')
depends_on("boost")
depends_on("blas")
depends_on("lapack")
depends_on("hypre")
depends_on("parmetis")
depends_on("metis")
depends_on("hdf5")
depends_on("mpi")
def install(self, spec, prefix):
configure("--prefix=%s" % prefix,
"CC=cc",
"CXX=c++",
"FC=f90",
"--with-blas-lib=%s/libblas.a" % spec['blas'].prefix.lib,
"--with-lapack-lib=%s/liblapack.a" % spec['lapack'].prefix.lib,
"--with-boost-dir=%s" % spec['boost'].prefix,
"--with-hypre-dir=%s" % spec['hypre'].prefix,
"--with-parmetis-dir=%s" % spec['parmetis'].prefix,
"--with-metis-dir=%s" % spec['metis'].prefix,
"--with-hdf5-dir=%s" % spec['hdf5'].prefix,
"--with-shared-libraries=0")
# PETSc has its own way of doing parallel make.
make('MAKE_NP=%s' % make_jobs, parallel=False)
make("install")