New interface for passing build information among specs (#1875)

- Added a new interface for Specs to pass build information
  - Calls forwarded from Spec to Package are now explicit
  - Added descriptor within Spec to manage forwarding
  - Added state in Spec to maintain query information
  - Modified a few packages (the one involved in spack install pexsi) to showcase changes

- This uses an object wrapper to `spec` to implement the `libs` sub-calls.
  - wrapper is returned from `__getitem__` only if spec is concrete
  - allows packagers to access build information easily
This commit is contained in:
Massimiliano Culpo 2017-03-02 19:01:29 +01:00 committed by Todd Gamblin
parent 5ce926d2d1
commit ed582cef68
45 changed files with 390 additions and 148 deletions

View File

@ -374,3 +374,17 @@ def duplicate_stream(original):
:rtype: file like object :rtype: file like object
""" """
return os.fdopen(os.dup(original.fileno())) return os.fdopen(os.dup(original.fileno()))
class ObjectWrapper(object):
"""Base class that wraps an object. Derived classes can add new behavior
while staying undercover.
This class is modeled after the stackoverflow answer:
- http://stackoverflow.com/a/1445289/771663
"""
def __init__(self, wrapped_object):
wrapped_cls = type(wrapped_object)
wrapped_name = wrapped_cls.__name__
self.__class__ = type(wrapped_name, (type(self), wrapped_cls), {})
self.__dict__ = wrapped_object.__dict__

View File

@ -42,7 +42,6 @@
import sys import sys
import textwrap import textwrap
import time import time
from StringIO import StringIO
import llnl.util.lock import llnl.util.lock
import llnl.util.tty as tty import llnl.util.tty as tty
@ -57,6 +56,7 @@
import spack.repository import spack.repository
import spack.url import spack.url
import spack.util.web import spack.util.web
from StringIO import StringIO
from llnl.util.filesystem import * from llnl.util.filesystem import *
from llnl.util.lang import * from llnl.util.lang import *
from llnl.util.link_tree import LinkTree from llnl.util.link_tree import LinkTree
@ -1053,6 +1053,10 @@ def do_fake_install(self):
touch(join_path(self.prefix.bin, 'fake')) touch(join_path(self.prefix.bin, 'fake'))
mkdirp(self.prefix.include) mkdirp(self.prefix.include)
mkdirp(self.prefix.lib) mkdirp(self.prefix.lib)
library_name = 'lib' + self.name
dso_suffix = 'dylib' if sys.platform == 'darwin' else 'so'
touch(join_path(self.prefix.lib, library_name + dso_suffix))
touch(join_path(self.prefix.lib, library_name + '.a'))
mkdirp(self.prefix.man1) mkdirp(self.prefix.man1)
def _if_make_target_execute(self, target): def _if_make_target_execute(self, target):

View File

@ -96,32 +96,35 @@
expansion when it is the first character in an id typed on the command line. expansion when it is the first character in an id typed on the command line.
""" """
import base64 import base64
import hashlib import collections
import csv
import ctypes import ctypes
from StringIO import StringIO import hashlib
import itertools
from operator import attrgetter from operator import attrgetter
from yaml.error import MarkedYAMLError import cStringIO
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.lang import *
from llnl.util.tty.color import *
import spack import spack
import spack.architecture import spack.architecture
import spack.store
import spack.compilers as compilers import spack.compilers as compilers
import spack.error import spack.error
import spack.parse import spack.parse
from spack.build_environment import get_path_from_module, load_module import spack.store
from spack.util.prefix import Prefix
from spack.util.string import *
import spack.util.spack_yaml as syaml
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.util.spack_yaml import syaml_dict import spack.util.spack_yaml as syaml
from spack.util.crypto import prefix_bits from cStringIO import StringIO
from spack.version import * from llnl.util.filesystem import find_libraries
from llnl.util.lang import *
from llnl.util.tty.color import *
from spack.build_environment import get_path_from_module, load_module
from spack.provider_index import ProviderIndex from spack.provider_index import ProviderIndex
from spack.util.crypto import prefix_bits
from spack.util.prefix import Prefix
from spack.util.spack_yaml import syaml_dict
from spack.util.string import *
from spack.version import *
from yaml.error import MarkedYAMLError
__all__ = [ __all__ = [
'Spec', 'Spec',
@ -750,6 +753,161 @@ def __str__(self):
return "{deps: %s}" % ', '.join(str(d) for d in sorted(self.values())) return "{deps: %s}" % ', '.join(str(d) for d in sorted(self.values()))
def _libs_default_handler(descriptor, spec, cls):
"""Default handler when looking for 'libs' attribute. The default
tries to search for 'lib{spec.name}' recursively starting from
`spec.prefix`.
:param ForwardQueryToPackage descriptor: descriptor that triggered
the call
:param Spec spec: spec that is being queried
:param type(spec) cls: type of spec, to match the signature of the
descriptor `__get__` method
"""
name = 'lib' + spec.name
shared = '+shared' in spec
return find_libraries(
[name], root=spec.prefix, shared=shared, recurse=True
)
def _cppflags_default_handler(descriptor, spec, cls):
"""Default handler when looking for cppflags attribute. The default
just returns '-I{spec.prefix.include}'.
:param ForwardQueryToPackage descriptor: descriptor that triggered
the call
:param Spec spec: spec that is being queried
:param type(spec) cls: type of spec, to match the signature of the
descriptor `__get__` method
"""
return '-I' + spec.prefix.include
class ForwardQueryToPackage(object):
"""Descriptor used to forward queries from Spec to Package"""
def __init__(self, attribute_name, default_handler=None):
"""Initializes the instance of the descriptor
:param str attribute_name: name of the attribute to be
searched for in the Package instance
:param callable default_handler: [optional] default function
to be called if the attribute was not found in the Package
instance
"""
self.attribute_name = attribute_name
# Turn the default handler into a function with the right
# signature that always returns None
if default_handler is None:
default_handler = lambda descriptor, spec, cls: None
self.default = default_handler
def __get__(self, instance, cls):
"""Retrieves the property from Package using a well defined chain
of responsibility.
The order of call is :
1. if the query was through the name of a virtual package try to
search for the attribute `{virtual_name}_{attribute_name}`
in Package
2. try to search for attribute `{attribute_name}` in Package
3. try to call the default handler
The first call that produces a value will stop the chain.
If no call can handle the request or a None value is produced,
then AttributeError is raised.
"""
pkg = instance.package
try:
query = instance.last_query
except AttributeError:
# There has been no query yet: this means
# a spec is trying to access its own attributes
_ = instance[instance.name] # NOQA: ignore=F841
query = instance.last_query
callbacks_chain = []
# First in the chain : specialized attribute for virtual packages
if query.isvirtual:
specialized_name = '{0}_{1}'.format(
query.name, self.attribute_name
)
callbacks_chain.append(lambda: getattr(pkg, specialized_name))
# Try to get the generic method from Package
callbacks_chain.append(lambda: getattr(pkg, self.attribute_name))
# Final resort : default callback
callbacks_chain.append(lambda: self.default(self, instance, cls))
# Trigger the callbacks in order, the first one producing a
# value wins
value = None
for f in callbacks_chain:
try:
value = f()
break
except AttributeError:
pass
# 'None' value raises AttributeError : this permits to 'disable'
# the call in a particular package by returning None from the
# queried attribute, or will trigger an exception if things
# searched for were not found
if value is None:
fmt = '\'{name}\' package has no relevant attribute \'{query}\'\n' # NOQA: ignore=E501
fmt += '\tspec : \'{spec}\'\n'
fmt += '\tqueried as : \'{spec.last_query.name}\'\n'
fmt += '\textra parameters : \'{spec.last_query.extra_parameters}\'\n' # NOQA: ignore=E501
message = fmt.format(
name=pkg.name,
query=self.attribute_name,
spec=instance
)
raise AttributeError(message)
return value
def __set__(self, instance, value):
cls_name = type(instance).__name__
msg = "'{0}' object attribute '{1}' is read-only"
raise AttributeError(msg.format(cls_name, self.attribute_name))
class SpecBuildInterface(ObjectWrapper):
libs = ForwardQueryToPackage(
'libs',
default_handler=_libs_default_handler
)
cppflags = ForwardQueryToPackage(
'cppflags',
default_handler=_cppflags_default_handler
)
def __init__(self, spec, name, query_parameters):
super(SpecBuildInterface, self).__init__(spec)
# Represents a query state in a BuildInterface object
QueryState = collections.namedtuple(
'QueryState', ['name', 'extra_parameters', 'isvirtual']
)
is_virtual = Spec.is_virtual(name)
self._query_to_package = QueryState(
name=name,
extra_parameters=query_parameters,
isvirtual=is_virtual
)
@property
def last_query(self):
return self._query_to_package
@key_ordering @key_ordering
class Spec(object): class Spec(object):
@ -818,14 +976,6 @@ def __init__(self, spec_like, *dep_like, **kwargs):
self._add_dependency(spec, deptypes) self._add_dependency(spec, deptypes)
deptypes = () deptypes = ()
def __getattr__(self, item):
"""Delegate to self.package if the attribute is not in the spec"""
# This line is to avoid infinite recursion in case package is
# not present among self attributes
if item.endswith('libs'):
return getattr(self.package, item)
raise AttributeError(item)
def get_dependency(self, name): def get_dependency(self, name):
dep = self._dependencies.get(name) dep = self._dependencies.get(name)
if dep is not None: if dep is not None:
@ -2239,22 +2389,46 @@ def version(self):
return self.versions[0] return self.versions[0]
def __getitem__(self, name): def __getitem__(self, name):
"""Get a dependency from the spec by its name.""" """Get a dependency from the spec by its name. This call implicitly
for spec in self.traverse(): sets a query state in the package being retrieved. The behavior of
if spec.name == name: packages may be influenced by additional query parameters that are
return spec passed after a colon symbol.
if Spec.is_virtual(name): Note that if a virtual package is queried a copy of the Spec is
# TODO: this is a kind of kludgy way to find providers returned while for non-virtual a reference is returned.
# TODO: should we just keep virtual deps in the DAG instead of """
# TODO: removing them on concretize? query_parameters = name.split(':')
for spec in self.traverse(): if len(query_parameters) > 2:
if spec.virtual: msg = 'key has more than one \':\' symbol.'
continue msg += ' At most one is admitted.'
if spec.package.provides(name): raise KeyError(msg)
return spec
raise KeyError("No spec with name %s in %s" % (name, self)) name, query_parameters = query_parameters[0], query_parameters[1:]
if query_parameters:
# We have extra query parameters, which are comma separated
# values
f = cStringIO.StringIO(query_parameters.pop())
try:
query_parameters = next(csv.reader(f, skipinitialspace=True))
except StopIteration:
query_parameters = ['']
try:
value = next(
itertools.chain(
# Regular specs
(x for x in self.traverse() if x.name == name),
(x for x in self.traverse()
if (not x.virtual) and x.package.provides(name))
)
)
except StopIteration:
raise KeyError("No spec with name %s in %s" % (name, self))
if self._concrete:
return SpecBuildInterface(value, name, query_parameters)
return value
def __contains__(self, spec): def __contains__(self, spec):
"""True if this spec satisfies the provided spec, or if any dependency """True if this spec satisfies the provided spec, or if any dependency

View File

@ -103,6 +103,18 @@ def _mock_remove(spec):
spec.package.do_uninstall(spec) spec.package.do_uninstall(spec)
def test_default_queries(database):
install_db = database.mock.db
rec = install_db.get_record('zmpi')
spec = rec.spec
libraries = spec['zmpi'].libs
assert len(libraries) == 1
cppflags_expected = '-I' + spec.prefix.include
assert spec['zmpi'].cppflags == cppflags_expected
def test_005_db_exists(database): def test_005_db_exists(database):
"""Make sure db cache file exists after creating.""" """Make sure db cache file exists after creating."""
install_path = database.mock.path install_path = database.mock.path

View File

@ -24,9 +24,6 @@
############################################################################## ##############################################################################
""" """
These tests check Spec DAG operations using dummy packages. These tests check Spec DAG operations using dummy packages.
You can find the dummy packages here::
spack/lib/spack/spack/test/mock_packages
""" """
import pytest import pytest
import spack import spack
@ -690,3 +687,47 @@ def test_copy_deptypes(self):
s4 = s3.copy() s4 = s3.copy()
self.check_diamond_deptypes(s4) self.check_diamond_deptypes(s4)
def test_getitem_query(self):
s = Spec('mpileaks')
s.concretize()
# Check a query to a non-virtual package
a = s['callpath']
query = a.last_query
assert query.name == 'callpath'
assert len(query.extra_parameters) == 0
assert not query.isvirtual
# Check a query to a virtual package
a = s['mpi']
query = a.last_query
assert query.name == 'mpi'
assert len(query.extra_parameters) == 0
assert query.isvirtual
# Check a query to a virtual package with
# extra parameters after query
a = s['mpi:cxx,fortran']
query = a.last_query
assert query.name == 'mpi'
assert len(query.extra_parameters) == 2
assert 'cxx' in query.extra_parameters
assert 'fortran' in query.extra_parameters
assert query.isvirtual
def test_getitem_exceptional_paths(self):
s = Spec('mpileaks')
s.concretize()
# Needed to get a proxy object
q = s['mpileaks']
# Test that the attribute is read-only
with pytest.raises(AttributeError):
q.libs = 'foo'
with pytest.raises(AttributeError):
q.libs

View File

@ -42,6 +42,9 @@ class Mpileaks(Package):
depends_on("mpi") depends_on("mpi")
depends_on("callpath") depends_on("callpath")
# Will be used to try raising an exception
libs = None
def install(self, spec, prefix): def install(self, spec, prefix):
pass pass

View File

@ -127,13 +127,13 @@ def install(self, spec, prefix):
# BLAS/LAPACK # BLAS/LAPACK
if '+scalapack' in spec: if '+scalapack' in spec:
oapp("--with-linalg-flavor=custom+scalapack") oapp("--with-linalg-flavor=custom+scalapack")
linalg = (spec['scalapack'].scalapack_libs + linalg = (spec['scalapack'].libs +
spec['lapack'].lapack_libs + spec['blas'].blas_libs) spec['lapack'].libs + spec['blas'].libs)
# elif '+elpa' in spec: # elif '+elpa' in spec:
else: else:
oapp("--with-linalg-flavor=custom") oapp("--with-linalg-flavor=custom")
linalg = spec['lapack'].lapack_libs + spec['blas'].blas_libs linalg = spec['lapack'].libs + spec['blas'].libs
oapp("--with-linalg-libs=%s" % linalg.ld_flags) oapp("--with-linalg-libs=%s" % linalg.ld_flags)

View File

@ -55,9 +55,9 @@ def install(self, spec, prefix):
# ARPACK support # ARPACK support
'-DARPACK_LIBRARY={0}'.format(arpack.joined()), '-DARPACK_LIBRARY={0}'.format(arpack.joined()),
# BLAS support # BLAS support
'-DBLAS_LIBRARY={0}'.format(spec['blas'].blas_libs.joined()), '-DBLAS_LIBRARY={0}'.format(spec['blas'].libs.joined()),
# LAPACK support # LAPACK support
'-DLAPACK_LIBRARY={0}'.format(spec['lapack'].lapack_libs.joined()), '-DLAPACK_LIBRARY={0}'.format(spec['lapack'].libs.joined()),
# SuperLU support # SuperLU support
'-DSuperLU_INCLUDE_DIR={0}'.format(spec['superlu'].prefix.include), '-DSuperLU_INCLUDE_DIR={0}'.format(spec['superlu'].prefix.include),
'-DSuperLU_LIBRARY={0}'.format(superlu.joined()), '-DSuperLU_LIBRARY={0}'.format(superlu.joined()),

View File

@ -88,8 +88,8 @@ def install(self, spec, prefix):
options.append('-DCMAKE_INSTALL_NAME_DIR:PATH=%s/lib' % prefix) options.append('-DCMAKE_INSTALL_NAME_DIR:PATH=%s/lib' % prefix)
# Make sure we use Spack's blas/lapack: # Make sure we use Spack's blas/lapack:
lapack_libs = spec['lapack'].lapack_libs.joined(';') lapack_libs = spec['lapack'].libs.joined(';')
blas_libs = spec['blas'].blas_libs.joined(';') blas_libs = spec['blas'].libs.joined(';')
options.extend([ options.extend([
'-DLAPACK_FOUND=true', '-DLAPACK_FOUND=true',
@ -129,8 +129,8 @@ def install(self, spec, prefix):
]) ])
options.extend([ options.extend([
'--with-blas={0}'.format(spec['blas'].blas_libs.ld_flags), '--with-blas={0}'.format(spec['blas'].libs.ld_flags),
'--with-lapack={0}'.format(spec['lapack'].lapack_libs.ld_flags) '--with-lapack={0}'.format(spec['lapack'].libs.ld_flags)
]) ])
if '+shared' not in spec: if '+shared' not in spec:
options.append('--enable-shared=no') options.append('--enable-shared=no')

View File

@ -112,8 +112,7 @@ def install(self, spec, prefix):
make("install") make("install")
self.install_test() self.install_test()
@property def libs(self):
def blas_libs(self):
# libsatlas.[so,dylib,dll ] contains all serial APIs (serial lapack, # libsatlas.[so,dylib,dll ] contains all serial APIs (serial lapack,
# serial BLAS), and all ATLAS symbols needed to support them. Whereas # serial BLAS), and all ATLAS symbols needed to support them. Whereas
# libtatlas.[so,dylib,dll ] is parallel (multithreaded) version. # libtatlas.[so,dylib,dll ] is parallel (multithreaded) version.
@ -135,10 +134,6 @@ def blas_libs(self):
to_find, root=self.prefix, shared=shared, recurse=True to_find, root=self.prefix, shared=shared, recurse=True
) )
@property
def lapack_libs(self):
return self.blas_libs
def install_test(self): def install_test(self):
source_file = join_path(os.path.dirname(self.module.__file__), source_file = join_path(os.path.dirname(self.module.__file__),
'test_cblas_dgemm.c') 'test_cblas_dgemm.c')
@ -146,7 +141,7 @@ def install_test(self):
'test_cblas_dgemm.output') 'test_cblas_dgemm.output')
include_flags = ["-I%s" % self.spec.prefix.include] include_flags = ["-I%s" % self.spec.prefix.include]
link_flags = self.lapack_libs.ld_flags.split() link_flags = self.libs.ld_flags.split()
output = compile_c_and_execute(source_file, include_flags, link_flags) output = compile_c_and_execute(source_file, include_flags, link_flags)
compare_output_file(output, blessed_file) compare_output_file(output, blessed_file)

View File

@ -49,7 +49,7 @@ class Atompaw(Package):
def install(self, spec, prefix): def install(self, spec, prefix):
options = ['--prefix=%s' % prefix] options = ['--prefix=%s' % prefix]
linalg = spec['lapack'].lapack_libs + spec['blas'].blas_libs linalg = spec['lapack'].libs + spec['blas'].libs
options.extend([ options.extend([
"--with-linalg-libs=%s" % linalg.ld_flags, "--with-linalg-libs=%s" % linalg.ld_flags,
"--enable-libxc", "--enable-libxc",

View File

@ -85,7 +85,7 @@ def install(self, spec, prefix):
# BLAS/LAPACK support # BLAS/LAPACK support
if '+lapack' in spec: if '+lapack' in spec:
lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs lapack_blas = spec['lapack'].libs + spec['blas'].libs
options.extend([ options.extend([
'blas_lapack_libs={0}'.format(','.join(lapack_blas.names)), 'blas_lapack_libs={0}'.format(','.join(lapack_blas.names)),
'blas_lapack_dir={0}'.format(spec['lapack'].prefix.lib) 'blas_lapack_dir={0}'.format(spec['lapack'].prefix.lib)

View File

@ -88,12 +88,10 @@ def install(self, spec, prefix):
cppflags = [ cppflags = [
'-D__FFTW3', '-D__FFTW3',
'-D__LIBINT', '-D__LIBINT',
'-I' + spec['fftw'].prefix.include spec['fftw'].cppflags
] ]
fcflags = copy.deepcopy(optflags[self.spec.compiler.name]) fcflags = copy.deepcopy(optflags[self.spec.compiler.name])
fcflags.extend([ fcflags.append(spec['fftw'].cppflags)
'-I' + spec['fftw'].prefix.include
])
fftw = find_libraries(['libfftw3'], root=spec['fftw'].prefix.lib) fftw = find_libraries(['libfftw3'], root=spec['fftw'].prefix.lib)
ldflags = [fftw.search_flags] ldflags = [fftw.search_flags]
libs = [ libs = [
@ -154,15 +152,17 @@ def install(self, spec, prefix):
'-D__SCALAPACK' '-D__SCALAPACK'
]) ])
fcflags.extend([ fcflags.extend([
# spec['elpa:fortran'].cppflags
'-I' + join_path( '-I' + join_path(
spec['elpa'].prefix, spec['elpa'].prefix,
'include', 'include',
'elpa-{0}'.format(str(spec['elpa'].version)), 'elpa-{0}'.format(str(spec['elpa'].version)),
'modules' 'modules'
), ),
# spec[pexsi:fortran].cppflags
'-I' + join_path(spec['pexsi'].prefix, 'fortran') '-I' + join_path(spec['pexsi'].prefix, 'fortran')
]) ])
scalapack = spec['scalapack'].scalapack_libs scalapack = spec['scalapack'].libs
ldflags.append(scalapack.search_flags) ldflags.append(scalapack.search_flags)
libs.extend([ libs.extend([
join_path(spec['elpa'].prefix.lib, join_path(spec['elpa'].prefix.lib,
@ -184,8 +184,8 @@ def install(self, spec, prefix):
libs.extend(self.spec['mpi'].mpicxx_shared_libs) libs.extend(self.spec['mpi'].mpicxx_shared_libs)
libs.extend(self.compiler.stdcxx_libs) libs.extend(self.compiler.stdcxx_libs)
# LAPACK / BLAS # LAPACK / BLAS
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
blas = spec['blas'].blas_libs blas = spec['blas'].libs
ldflags.append((lapack + blas).search_flags) ldflags.append((lapack + blas).search_flags)
libs.extend([str(x) for x in (fftw, lapack, blas)]) libs.extend([str(x) for x in (fftw, lapack, blas)])

View File

@ -145,7 +145,7 @@ def cmake_args(self):
options = [] options = []
cxx_flags = [] cxx_flags = []
lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs lapack_blas = spec['lapack'].libs + spec['blas'].libs
options.extend([ options.extend([
'-DDEAL_II_COMPONENT_EXAMPLES=ON', '-DDEAL_II_COMPONENT_EXAMPLES=ON',
'-DDEAL_II_WITH_THREADS:BOOL=ON', '-DDEAL_II_WITH_THREADS:BOOL=ON',

View File

@ -90,9 +90,9 @@ def configure(self, spec):
blas = 'blas.a' blas = 'blas.a'
lapack = 'lapack.a' lapack = 'lapack.a'
if '+blas' in spec: if '+blas' in spec:
blas = spec['blas'].blas_libs.joined() blas = spec['blas'].libs.joined()
if '+lapack' in spec: if '+lapack' in spec:
lapack = spec['lapack'].lapack_libs.joined() lapack = spec['lapack'].libs.joined()
# lapack must come before blas # lapack must come before blas
config['LIB_LPK'] = ' '.join([lapack, blas]) config['LIB_LPK'] = ' '.join([lapack, blas])

View File

@ -59,16 +59,16 @@ def install(self, spec, prefix):
'FC={0}'.format(self.spec['mpi'].mpifc), 'FC={0}'.format(self.spec['mpi'].mpifc),
'CXX={0}'.format(self.spec['mpi'].mpicxx), 'CXX={0}'.format(self.spec['mpi'].mpicxx),
'FCFLAGS={0}'.format( 'FCFLAGS={0}'.format(
spec['lapack'].lapack_libs.joined() spec['lapack'].libs.joined()
), ),
'LDFLAGS={0}'.format( 'LDFLAGS={0}'.format(
spec['lapack'].lapack_libs.joined() spec['lapack'].libs.joined()
), ),
'SCALAPACK_FCFLAGS={0}'.format( 'SCALAPACK_FCFLAGS={0}'.format(
spec['scalapack'].scalapack_libs.joined() spec['scalapack'].libs.joined()
), ),
'SCALAPACK_LDFLAGS={0}'.format( 'SCALAPACK_LDFLAGS={0}'.format(
spec['scalapack'].scalapack_libs.joined() spec['scalapack'].libs.joined()
), ),
'--prefix={0}'.format(self.prefix) '--prefix={0}'.format(self.prefix)
] ]

View File

@ -88,7 +88,7 @@ def cmake_args(self):
options.append('-DENABLE_OS_SPECIFIC_INSTALL=OFF') options.append('-DENABLE_OS_SPECIFIC_INSTALL=OFF')
# Make sure GMSH picks up correct BlasLapack by providing linker flags # Make sure GMSH picks up correct BlasLapack by providing linker flags
blas_lapack = spec['lapack'].lapack_libs + spec['blas'].blas_libs blas_lapack = spec['lapack'].libs + spec['blas'].libs
options.append( options.append(
'-DBLAS_LAPACK_LIBRARIES={0}'.format(blas_lapack.ld_flags)) '-DBLAS_LAPACK_LIBRARIES={0}'.format(blas_lapack.ld_flags))

View File

@ -78,7 +78,7 @@ def configure(self, spec, arch):
'MPlib = -L{0}'.format(spec['mpi'].prefix.lib), 'MPlib = -L{0}'.format(spec['mpi'].prefix.lib),
# Linear Algebra library (BLAS or VSIPL) # Linear Algebra library (BLAS or VSIPL)
'LAinc = {0}'.format(spec['blas'].prefix.include), 'LAinc = {0}'.format(spec['blas'].prefix.include),
'LAlib = {0}'.format(spec['blas'].blas_libs.joined()), 'LAlib = {0}'.format(spec['blas'].libs.joined()),
# F77 / C interface # F77 / C interface
'F2CDEFS = -DAdd_ -DF77_INTEGER=int -DStringSunStyle', 'F2CDEFS = -DAdd_ -DF77_INTEGER=int -DStringSunStyle',
# HPL includes / libraries / specifics # HPL includes / libraries / specifics

View File

@ -62,8 +62,8 @@ def install(self, spec, prefix):
os.environ['F77'] = spec['mpi'].mpif77 os.environ['F77'] = spec['mpi'].mpif77
# Note: --with-(lapack|blas)_libs= needs space separated list of names # Note: --with-(lapack|blas)_libs= needs space separated list of names
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
blas = spec['blas'].blas_libs blas = spec['blas'].libs
configure_args = [ configure_args = [
'--prefix=%s' % prefix, '--prefix=%s' % prefix,

View File

@ -83,7 +83,7 @@ def blas_libs(self):
@property @property
def lapack_libs(self): def lapack_libs(self):
return self.blas_libs return self.libs
@property @property
def scalapack_libs(self): def scalapack_libs(self):

View File

@ -127,7 +127,7 @@ def blas_libs(self):
@property @property
def lapack_libs(self): def lapack_libs(self):
return self.blas_libs return self.libs
@property @property
def scalapack_libs(self): def scalapack_libs(self):

View File

@ -53,8 +53,8 @@ def install(self, spec, prefix):
mumps_flags = "-ldmumps -lmumps_common -lpord -lmpiseq" mumps_flags = "-ldmumps -lmumps_common -lpord -lmpiseq"
mumps_libcmd = "-L%s " % mumps_dir.lib + mumps_flags mumps_libcmd = "-L%s " % mumps_dir.lib + mumps_flags
blas_lib = spec['blas'].blas_libs.ld_flags blas_lib = spec['blas'].libs.ld_flags
lapack_lib = spec['lapack'].lapack_libs.ld_flags lapack_lib = spec['lapack'].libs.ld_flags
configure_args = [ configure_args = [
"--prefix=%s" % prefix, "--prefix=%s" % prefix,

View File

@ -102,7 +102,7 @@ def install(self, spec, prefix):
options = ['PREFIX=%s' % prefix] options = ['PREFIX=%s' % prefix]
if '+lapack' in spec: if '+lapack' in spec:
lapack_lib = (spec['lapack'].lapack_libs + spec['blas'].blas_libs).ld_flags # NOQA: ignore=E501 lapack_lib = (spec['lapack'].libs + spec['blas'].libs).ld_flags # NOQA: ignore=E501
options.extend([ options.extend([
'MFEM_USE_LAPACK=YES', 'MFEM_USE_LAPACK=YES',
'LAPACK_OPT=-I%s' % spec['lapack'].prefix.include, 'LAPACK_OPT=-I%s' % spec['lapack'].prefix.include,

View File

@ -82,8 +82,8 @@ 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'].lapack_libs + lapack_blas = (self.spec['lapack'].libs +
self.spec['blas'].blas_libs) self.spec['blas'].libs)
makefile_conf = ["LIBBLAS = %s" % lapack_blas.ld_flags] makefile_conf = ["LIBBLAS = %s" % lapack_blas.ld_flags]
orderings = ['-Dpord'] orderings = ['-Dpord']
@ -156,7 +156,7 @@ 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'].scalapack_libs scalapack = self.spec['scalapack'].libs
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),

View File

@ -113,7 +113,7 @@ def install_one(self, spec, prefix, shared):
if '+external-blas' in spec: if '+external-blas' in spec:
cmake_args.extend([ cmake_args.extend([
'-DUSE_OPTIMIZED_BLAS:BOOL=ON', '-DUSE_OPTIMIZED_BLAS:BOOL=ON',
'-DBLAS_LIBRARIES:PATH=%s' % spec['blas'].blas_libs.joined(';') '-DBLAS_LIBRARIES:PATH=%s' % spec['blas'].libs.joined(';')
]) ])
cmake_args.extend(std_cmake_args) cmake_args.extend(std_cmake_args)

View File

@ -74,8 +74,8 @@ def install(self, spec, prefix):
] ]
# Make sure we use Spack's Lapack: # Make sure we use Spack's Lapack:
blas = spec['blas'].blas_libs blas = spec['blas'].libs
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
options.extend([ options.extend([
'-DLAPACK_FOUND=true', '-DLAPACK_FOUND=true',
'-DLAPACK_INCLUDE_DIRS=%s' % spec['lapack'].prefix.include, '-DLAPACK_INCLUDE_DIRS=%s' % spec['lapack'].prefix.include,

View File

@ -73,9 +73,9 @@ class Nwchem(Package):
patch(url, when=condition, level=0, md5=md5) patch(url, when=condition, level=0, md5=md5)
def install(self, spec, prefix): def install(self, spec, prefix):
scalapack = spec['scalapack'].scalapack_libs scalapack = spec['scalapack'].libs
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
blas = spec['blas'].blas_libs blas = spec['blas'].libs
# see http://www.nwchem-sw.org/index.php/Compiling_NWChem # see http://www.nwchem-sw.org/index.php/Compiling_NWChem
args = [] args = []
args.extend([ args.extend([

View File

@ -108,8 +108,8 @@ def configure_args(self):
# Required dependencies # Required dependencies
config_args.extend([ config_args.extend([
"--with-blas=%s" % spec['blas'].blas_libs.ld_flags, "--with-blas=%s" % spec['blas'].libs.ld_flags,
"--with-lapack=%s" % spec['lapack'].lapack_libs.ld_flags "--with-lapack=%s" % spec['lapack'].libs.ld_flags
]) ])
# Strongly recommended dependencies # Strongly recommended dependencies

View File

@ -71,8 +71,8 @@ def url_for_version(self, version):
def install(self, spec, prefix): def install(self, spec, prefix):
arpack = find_libraries(['libarpack'], root=spec[ arpack = find_libraries(['libarpack'], root=spec[
'arpack-ng'].prefix.lib, shared=True) 'arpack-ng'].prefix.lib, shared=True)
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
blas = spec['blas'].blas_libs blas = spec['blas'].libs
args = [] args = []
args.extend([ args.extend([
'--prefix=%s' % prefix, '--prefix=%s' % prefix,
@ -105,8 +105,8 @@ def install(self, spec, prefix):
]) ])
if '+scalapack' in spec: if '+scalapack' in spec:
args.extend([ args.extend([
'--with-blacs=%s' % spec['scalapack'].scalapack_libs, '--with-blacs=%s' % spec['scalapack'].libs,
'--with-scalapack=%s' % spec['scalapack'].scalapack_libs, '--with-scalapack=%s' % spec['scalapack'].libs,
]) ])
# --with-etsf-io-prefix= # --with-etsf-io-prefix=
# --with-sparskit=${prefix}/lib/libskit.a # --with-sparskit=${prefix}/lib/libskit.a

View File

@ -59,17 +59,6 @@ class Openblas(MakefilePackage):
parallel = False parallel = False
@property
def blas_libs(self):
shared = True if '+shared' in self.spec else False
return find_libraries(
['libopenblas'], root=self.prefix, shared=shared, recurse=True
)
@property
def lapack_libs(self):
return self.blas_libs
@run_before('edit') @run_before('edit')
def check_compilers(self): def check_compilers(self):
# As of 06/2016 there is no mechanism to specify that packages which # As of 06/2016 there is no mechanism to specify that packages which
@ -151,13 +140,15 @@ def check_install(self):
blessed_file = join_path(os.path.dirname(self.module.__file__), blessed_file = join_path(os.path.dirname(self.module.__file__),
'test_cblas_dgemm.output') 'test_cblas_dgemm.output')
include_flags = ["-I%s" % join_path(spec.prefix, "include")] include_flags = spec.cppflags
link_flags = self.lapack_libs.ld_flags.split() link_flags = spec.libs.ld_flags
if self.compiler.name == 'intel': if self.compiler.name == 'intel':
link_flags.extend(["-lifcore"]) link_flags += ' -lifcore'
link_flags.extend(["-lpthread"]) link_flags += ' -lpthread'
if '+openmp' in spec: if '+openmp' in spec:
link_flags.extend([self.compiler.openmp_flag]) link_flags += ' ' + self.compiler.openmp_flag
output = compile_c_and_execute(source_file, include_flags, link_flags) output = compile_c_and_execute(
source_file, [include_flags], link_flags.split()
)
compare_output_file(output, blessed_file) compare_output_file(output, blessed_file)

View File

@ -116,6 +116,18 @@ def url_for_version(self, version):
return "http://www.open-mpi.org/software/ompi/v%s/downloads/openmpi-%s.tar.bz2" % ( return "http://www.open-mpi.org/software/ompi/v%s/downloads/openmpi-%s.tar.bz2" % (
version.up_to(2), version) version.up_to(2), version)
@property
def libs(self):
query_parameters = self.spec.last_query.extra_parameters
libraries = ['libmpi']
if 'cxx' in query_parameters:
libraries = ['libmpi_cxx'] + libraries
return find_libraries(
libraries, root=self.prefix, shared=True, recurse=True
)
def setup_dependent_environment(self, spack_env, run_env, dependent_spec): def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
spack_env.set('MPICC', join_path(self.prefix.bin, 'mpicc')) spack_env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
spack_env.set('MPICXX', join_path(self.prefix.bin, 'mpic++')) spack_env.set('MPICXX', join_path(self.prefix.bin, 'mpic++'))

View File

@ -37,7 +37,7 @@ class Opium(Package):
depends_on('lapack') depends_on('lapack')
def install(self, spec, prefix): def install(self, spec, prefix):
libs = spec['lapack'].lapack_libs + spec['blas'].blas_libs libs = spec['lapack'].libs + spec['blas'].libs
options = ['LDFLAGS=%s' % libs.ld_flags] options = ['LDFLAGS=%s' % libs.ld_flags]
configure(*options) configure(*options)

View File

@ -161,7 +161,7 @@ def install(self, spec, prefix):
]) ])
# Make sure we use exactly the same Blas/Lapack libraries # Make sure we use exactly the same Blas/Lapack libraries
# across the DAG. To that end list them explicitly # across the DAG. To that end list them explicitly
lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs lapack_blas = spec['lapack'].libs + spec['blas'].libs
options.extend([ options.extend([
'--with-blas-lapack-lib=%s' % lapack_blas.joined() '--with-blas-lapack-lib=%s' % lapack_blas.joined()
]) ])

View File

@ -36,7 +36,7 @@ DSUPERLU_INCLUDE = -I${DSUPERLU_DIR}/include
INCLUDES = ${PEXSI_INCLUDE} ${DSUPERLU_INCLUDE} INCLUDES = ${PEXSI_INCLUDE} ${DSUPERLU_INCLUDE}
# Libraries # Libraries
CPP_LIB = @STDCXX_LIB @MPICXX_LIB CPP_LIB = @MPICXX_LIB @STDCXX_LIB
#GFORTRAN_LIB = /usr/lib/gcc/x86_64-linux-gnu/4.8/libgfortran.a #GFORTRAN_LIB = /usr/lib/gcc/x86_64-linux-gnu/4.8/libgfortran.a
LAPACK_LIB = @LAPACK_LIBS LAPACK_LIB = @LAPACK_LIBS
BLAS_LIB = @BLAS_LIBS BLAS_LIB = @BLAS_LIBS

View File

@ -59,7 +59,7 @@ def install(self, spec, prefix):
'@MPICC': self.spec['mpi'].mpicc, '@MPICC': self.spec['mpi'].mpicc,
'@MPICXX': self.spec['mpi'].mpicxx, '@MPICXX': self.spec['mpi'].mpicxx,
'@MPIFC': self.spec['mpi'].mpifc, '@MPIFC': self.spec['mpi'].mpifc,
'@MPICXX_LIB': ' '.join(self.spec['mpi'].mpicxx_shared_libs), '@MPICXX_LIB': self.spec['mpi:cxx'].libs.joined(),
'@RANLIB': 'ranlib', '@RANLIB': 'ranlib',
'@PEXSI_STAGE': self.stage.source_path, '@PEXSI_STAGE': self.stage.source_path,
'@SUPERLU_PREFIX': self.spec['superlu-dist'].prefix, '@SUPERLU_PREFIX': self.spec['superlu-dist'].prefix,
@ -67,8 +67,9 @@ def install(self, spec, prefix):
'@PARMETIS_PREFIX': self.spec['parmetis'].prefix, '@PARMETIS_PREFIX': self.spec['parmetis'].prefix,
'@LAPACK_PREFIX': self.spec['lapack'].prefix, '@LAPACK_PREFIX': self.spec['lapack'].prefix,
'@BLAS_PREFIX': self.spec['blas'].prefix, '@BLAS_PREFIX': self.spec['blas'].prefix,
'@LAPACK_LIBS': self.spec['lapack'].lapack_libs.joined(), '@LAPACK_LIBS': self.spec['lapack'].libs.joined(),
'@BLAS_LIBS': self.spec['lapack'].blas_libs.joined(), '@BLAS_LIBS': self.spec['blas'].libs.joined(),
# FIXME : what to do with compiler provided libraries ?
'@STDCXX_LIB': ' '.join(self.compiler.stdcxx_libs) '@STDCXX_LIB': ' '.join(self.compiler.stdcxx_libs)
} }

View File

@ -62,10 +62,10 @@ class Psi4(Package):
def install(self, spec, prefix): def install(self, spec, prefix):
cmake_args = [ cmake_args = [
'-DBLAS_TYPE={0}'.format(spec['blas'].name.upper()), '-DBLAS_TYPE={0}'.format(spec['blas'].name.upper()),
'-DBLAS_LIBRARIES={0}'.format(spec['blas'].blas_libs.joined()), '-DBLAS_LIBRARIES={0}'.format(spec['blas'].libs.joined()),
'-DLAPACK_TYPE={0}'.format(spec['lapack'].name.upper()), '-DLAPACK_TYPE={0}'.format(spec['lapack'].name.upper()),
'-DLAPACK_LIBRARIES={0}'.format( '-DLAPACK_LIBRARIES={0}'.format(
spec['lapack'].lapack_libs.joined()), spec['lapack'].libs.joined()),
'-DBOOST_INCLUDEDIR={0}'.format(spec['boost'].prefix.include), '-DBOOST_INCLUDEDIR={0}'.format(spec['boost'].prefix.include),
'-DBOOST_LIBRARYDIR={0}'.format(spec['boost'].prefix.lib), '-DBOOST_LIBRARYDIR={0}'.format(spec['boost'].prefix.lib),
'-DENABLE_CHEMPS2=OFF' '-DENABLE_CHEMPS2=OFF'

View File

@ -70,10 +70,10 @@ def patch(self):
# for build notes see http://www.scipy.org/scipylib/building/linux.html # for build notes see http://www.scipy.org/scipylib/building/linux.html
lapackblas = LibraryList('') lapackblas = LibraryList('')
if '+lapack' in spec: if '+lapack' in spec:
lapackblas += spec['lapack'].lapack_libs lapackblas += spec['lapack'].libs
if '+blas' in spec: if '+blas' in spec:
lapackblas += spec['blas'].blas_libs lapackblas += spec['blas'].libs
if '+blas' in spec or '+lapack' in spec: if '+blas' in spec or '+lapack' in spec:
# note that one should not use [blas_opt] and [lapack_opt], see # note that one should not use [blas_opt] and [lapack_opt], see

View File

@ -101,8 +101,8 @@ def install(self, spec, prefix):
# Make sure Spack's Blas/Lapack is used. Otherwise System's # Make sure Spack's Blas/Lapack is used. Otherwise System's
# Blas/Lapack might be picked up. # Blas/Lapack might be picked up.
blas = spec['blas'].blas_libs.ld_flags blas = spec['blas'].libs.ld_flags
lapack = spec['lapack'].lapack_libs.ld_flags lapack = spec['lapack'].libs.ld_flags
if '@4.5.1' in spec: if '@4.5.1' in spec:
# adding -lstdc++ is clearly an ugly way to do this, but it follows # adding -lstdc++ is clearly an ugly way to do this, but it follows
# with the TCOV path of SparseSuite 4.5.1's Suitesparse_config.mk # with the TCOV path of SparseSuite 4.5.1's Suitesparse_config.mk

View File

@ -80,8 +80,8 @@ def install(self, spec, prefix):
cmake_args.extend([ cmake_args.extend([
'-DLAPACK_ENABLE=ON', '-DLAPACK_ENABLE=ON',
'-DLAPACK_LIBRARIES={0}'.format( '-DLAPACK_LIBRARIES={0}'.format(
(spec['lapack'].lapack_libs + (spec['lapack'].libs +
spec['blas'].blas_libs).joined(';') spec['blas'].libs).joined(';')
) )
]) ])
else: else:

View File

@ -53,7 +53,7 @@ class SuperluDist(Package):
depends_on('metis@5:') depends_on('metis@5:')
def install(self, spec, prefix): def install(self, spec, prefix):
lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs lapack_blas = spec['lapack'].libs + spec['blas'].libs
makefile_inc = [] makefile_inc = []
makefile_inc.extend([ makefile_inc.extend([
'PLAT = _mac_x', 'PLAT = _mac_x',
@ -61,17 +61,17 @@ def install(self, spec, prefix):
'DSUPERLULIB = $(DSuperLUroot)/lib/libsuperlu_dist.a', 'DSUPERLULIB = $(DSuperLUroot)/lib/libsuperlu_dist.a',
'BLASDEF = -DUSE_VENDOR_BLAS', 'BLASDEF = -DUSE_VENDOR_BLAS',
'BLASLIB = %s' % lapack_blas.ld_flags, 'BLASLIB = %s' % lapack_blas.ld_flags,
'METISLIB = -L%s -lmetis' % spec['metis'].prefix.lib, 'METISLIB = %s' % spec['metis'].libs.ld_flags,
'PARMETISLIB = -L%s -lparmetis' % spec['parmetis'].prefix.lib, 'PARMETISLIB = %s' % spec['parmetis'].libs.ld_flags,
'FLIBS =', 'FLIBS =',
'LIBS = $(DSUPERLULIB) $(BLASLIB) $(PARMETISLIB) $(METISLIB)', # noqa 'LIBS = $(DSUPERLULIB) $(BLASLIB) $(PARMETISLIB) $(METISLIB)', # noqa
'ARCH = ar', 'ARCH = ar',
'ARCHFLAGS = cr', 'ARCHFLAGS = cr',
'RANLIB = true', 'RANLIB = true',
'CC = {0}'.format(self.spec['mpi'].mpicc), 'CC = {0}'.format(self.spec['mpi'].mpicc),
'CFLAGS = -fPIC -std=c99 -O2 -I%s -I%s %s' % ( 'CFLAGS = -fPIC -std=c99 -O2 %s %s %s' % (
spec['parmetis'].prefix.include, spec['parmetis'].cppflags,
spec['metis'].prefix.include, spec['metis'].cppflags,
'-D_LONGINT' if '+int64' in spec else ''), '-D_LONGINT' if '+int64' in spec else ''),
'NOOPTS = -fPIC -std=c99', 'NOOPTS = -fPIC -std=c99',
'FORTRAN = {0}'.format(self.spec['mpi'].mpif77), 'FORTRAN = {0}'.format(self.spec['mpi'].mpif77),

View File

@ -86,7 +86,7 @@ def configure(self, spec):
if '+blas' in spec: if '+blas' in spec:
config.extend([ config.extend([
'BLASDEF = -DUSE_VENDOR_BLAS', 'BLASDEF = -DUSE_VENDOR_BLAS',
'BLASLIB = {0}'.format(spec['blas'].blas_libs.ld_flags) 'BLASLIB = {0}'.format(spec['blas'].libs.ld_flags)
]) ])
else: else:
config.append('BLASLIB = ../lib/libblas$(PLAT).a') config.append('BLASLIB = ../lib/libblas$(PLAT).a')

View File

@ -48,7 +48,7 @@ class Superlu(Package):
def install(self, spec, prefix): def install(self, spec, prefix):
cmake_args = [ cmake_args = [
'-Denable_blaslib=OFF', '-Denable_blaslib=OFF',
'-DBLAS_blas_LIBRARY={0}'.format(spec['blas'].blas_libs.joined()) '-DBLAS_blas_LIBRARY={0}'.format(spec['blas'].libs.joined())
] ]
if '+fpic' in spec: if '+fpic' in spec:
@ -76,7 +76,7 @@ def install(self, spec, prefix):
'SUPERLULIB = $(SuperLUroot)/lib/libsuperlu_{0}.a' \ 'SUPERLULIB = $(SuperLUroot)/lib/libsuperlu_{0}.a' \
.format(self.spec.version), .format(self.spec.version),
'BLASDEF = -DUSE_VENDOR_BLAS', 'BLASDEF = -DUSE_VENDOR_BLAS',
'BLASLIB = {0}'.format(spec['blas'].blas_libs.ld_flags), 'BLASLIB = {0}'.format(spec['blas'].libs.ld_flags),
# or BLASLIB = -L/usr/lib64 -lblas # or BLASLIB = -L/usr/lib64 -lblas
'TMGLIB = libtmglib.a', 'TMGLIB = libtmglib.a',
'LIBS = $(SUPERLULIB) $(BLASLIB)', 'LIBS = $(SUPERLULIB) $(BLASLIB)',

View File

@ -147,8 +147,8 @@ def cmake_args(self):
mpi_bin = spec['mpi'].prefix.bin mpi_bin = spec['mpi'].prefix.bin
# Note: -DXYZ_LIBRARY_NAMES= needs semicolon separated list of names # Note: -DXYZ_LIBRARY_NAMES= needs semicolon separated list of names
blas = spec['blas'].blas_libs blas = spec['blas'].libs
lapack = spec['lapack'].lapack_libs lapack = spec['lapack'].libs
options.extend([ options.extend([
'-DTrilinos_ENABLE_ALL_PACKAGES:BOOL=ON', '-DTrilinos_ENABLE_ALL_PACKAGES:BOOL=ON',
'-DTrilinos_ENABLE_ALL_OPTIONAL_PACKAGES:BOOL=ON', '-DTrilinos_ENABLE_ALL_OPTIONAL_PACKAGES:BOOL=ON',

View File

@ -44,17 +44,12 @@ class Veclibfort(Package):
provides('blas') provides('blas')
provides('lapack') provides('lapack')
@property def libs(self):
def blas_libs(self):
shared = True if '+shared' in self.spec else False shared = True if '+shared' in self.spec else False
return find_libraries( return find_libraries(
['libvecLibFort'], root=self.prefix, shared=shared, recurse=True ['libvecLibFort'], root=self.prefix, shared=shared, recurse=True
) )
@property
def lapack_libs(self):
return self.blas_libs
def install(self, spec, prefix): def install(self, spec, prefix):
if sys.platform != 'darwin': if sys.platform != 'darwin':
raise InstallError('vecLibFort can be installed on macOS only') raise InstallError('vecLibFort can be installed on macOS only')
@ -65,6 +60,6 @@ def install(self, spec, prefix):
# test # test
fc = which('fc') fc = which('fc')
flags = ['-o', 'tester', '-O', 'tester.f90'] flags = ['-o', 'tester', '-O', 'tester.f90']
flags.extend(self.lapack_libs.ld_flags.split()) flags.extend(spec.libs.ld_flags.split())
fc(*flags) fc(*flags)
Executable('./tester')() Executable('./tester')()

View File

@ -47,8 +47,8 @@ class Wannier90(Package):
def install(self, spec, prefix): def install(self, spec, prefix):
lapack = self.spec['lapack'].lapack_libs lapack = self.spec['lapack'].libs
blas = self.spec['blas'].blas_libs blas = self.spec['blas'].libs
substitutions = { substitutions = {
'@F90': spack_fc, '@F90': spack_fc,
'@MPIF90': self.spec['mpi'].mpifc, '@MPIF90': self.spec['mpi'].mpifc,