diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst
index 6936b5e4234157cf5eb09b8bc818c4e6dfb3e53e..0294f3274861ad562f8bfca739589e62dea9beff 100644
--- a/lib/spack/docs/packaging_guide.rst
+++ b/lib/spack/docs/packaging_guide.rst
@@ -2090,12 +2090,11 @@ Blas and Lapack libraries
 
 Different packages provide implementation of ``Blas`` and ``Lapack`` routines.
 The names of the resulting static and/or shared libraries differ from package
-to package. In order to make the ``install()`` method indifferent to the
+to package. In order to make the ``install()`` method independent of the
 choice of ``Blas`` implementation, each package which provides it
-sets up ``self.spec.blas_shared_lib`` and ``self.spec.blas_static_lib`` to
-point to the shared and static ``Blas`` libraries, respectively. The same
-applies to packages which provide ``Lapack``. Package developers are advised to
-use these variables, for example ``spec['blas'].blas_shared_lib`` instead of
+sets up ``self.spec.blas_libs`` to point to the correct ``Blas`` libraries.
+The same applies to packages which provide ``Lapack``. Package developers are advised to
+use these variables, for example ``spec['blas'].blas_libs.joined()`` instead of
 hard-coding ``join_path(spec['blas'].prefix.lib, 'libopenblas.so')``.
 
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
index 22ca85abf92b309c24bc1a030e968c2bffa54eb2..c3ecfde4f48b0509185b0ba5fd10aaef8a6ac17d 100644
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -22,18 +22,22 @@
 # License 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 collections
+import errno
+import fileinput
+import getpass
 import glob
+import numbers
+import os
 import re
 import shutil
 import stat
-import errno
-import getpass
-from contextlib import contextmanager
 import subprocess
-import fileinput
+import sys
+from contextlib import contextmanager
 
 import llnl.util.tty as tty
+from llnl.util.lang import dedupe
 
 __all__ = ['set_install_permissions', 'install', 'install_tree',
            'traverse_tree',
@@ -42,8 +46,8 @@
            'filter_file',
            'FileFilter', 'change_sed_delimiter', 'is_exe', 'force_symlink',
            'set_executable', 'copy_mode', 'unset_executable_mode',
-           'remove_dead_links', 'remove_linked_tree', 'find_library_path',
-           'fix_darwin_install_name', 'to_link_flags', 'to_lib_name']
+           'remove_dead_links', 'remove_linked_tree',
+           'fix_darwin_install_name', 'find_libraries', 'LibraryList']
 
 
 def filter_file(regex, repl, *filenames, **kwargs):
@@ -326,7 +330,7 @@ def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
     follow_links = kwargs.get('follow_link', False)
 
     # Yield in pre or post order?
-    order  = kwargs.get('order', 'pre')
+    order = kwargs.get('order', 'pre')
     if order not in ('pre', 'post'):
         raise ValueError("Order must be 'pre' or 'post'.")
 
@@ -338,7 +342,7 @@ def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
         return
 
     source_path = os.path.join(source_root, rel_path)
-    dest_path   = os.path.join(dest_root, rel_path)
+    dest_path = os.path.join(dest_root, rel_path)
 
     # preorder yields directories before children
     if order == 'pre':
@@ -346,8 +350,8 @@ def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
 
     for f in os.listdir(source_path):
         source_child = os.path.join(source_path, f)
-        dest_child   = os.path.join(dest_path, f)
-        rel_child    = os.path.join(rel_path, f)
+        dest_child = os.path.join(dest_path, f)
+        rel_child = os.path.join(rel_path, f)
 
         # Treat as a directory
         if os.path.isdir(source_child) and (
@@ -440,35 +444,162 @@ def fix_darwin_install_name(path):
                         stdout=subprocess.PIPE).communicate()[0]
                     break
 
+# Utilities for libraries
+
 
-def to_lib_name(library):
-    """Transforms a path to the library /path/to/lib<name>.xyz into <name>
+class LibraryList(collections.Sequence):
+    """Sequence of absolute paths to libraries
+
+    Provides a few convenience methods to manipulate library paths and get
+    commonly used compiler flags or names
     """
-    # Assume libXYZ.suffix
-    return os.path.basename(library)[3:].split(".")[0]
 
+    def __init__(self, libraries):
+        self.libraries = list(libraries)
 
-def to_link_flags(library):
-    """Transforms a path to a <library> into linking flags -L<dir> -l<name>.
+    @property
+    def directories(self):
+        """Stable de-duplication of the directories where the libraries
+        reside
 
-    Return:
-      A string of linking flags.
-    """
-    dir  = os.path.dirname(library)
-    name = to_lib_name(library)
-    res = '-L%s -l%s' % (dir, name)
-    return res
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/libc.a'])
+        >>> assert l.directories == ['/dir1', '/dir2']
+        """
+        return list(dedupe(
+            os.path.dirname(x) for x in self.libraries if os.path.dirname(x)
+        ))
+
+    @property
+    def basenames(self):
+        """Stable de-duplication of the base-names in the list
+
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir3/liba.a'])
+        >>> assert l.basenames == ['liba.a', 'libb.a']
+        """
+        return list(dedupe(os.path.basename(x) for x in self.libraries))
+
+    @property
+    def names(self):
+        """Stable de-duplication of library names in the list
+
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir3/liba.so'])
+        >>> assert l.names == ['a', 'b']
+        """
+        return list(dedupe(x.split('.')[0][3:] for x in self.basenames))
+
+    @property
+    def search_flags(self):
+        """Search flags for the libraries
+
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/liba.so'])
+        >>> assert l.search_flags == '-L/dir1 -L/dir2'
+        """
+        return ' '.join(['-L' + x for x in self.directories])
+
+    @property
+    def link_flags(self):
+        """Link flags for the libraries
+
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/liba.so'])
+        >>> assert l.search_flags == '-la -lb'
+        """
+        return ' '.join(['-l' + name for name in self.names])
 
+    @property
+    def ld_flags(self):
+        """Search flags + link flags
 
-def find_library_path(libname, *paths):
-    """Searches for a file called <libname> in each path.
+        >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/liba.so'])
+        >>> assert l.search_flags == '-L/dir1 -L/dir2 -la -lb'
+        """
+        return self.search_flags + ' ' + self.link_flags
 
-    Return:
-      directory where the library was found, if found.  None otherwise.
+    def __getitem__(self, item):
+        cls = type(self)
+        if isinstance(item, numbers.Integral):
+            return self.libraries[item]
+        return cls(self.libraries[item])
 
+    def __add__(self, other):
+        return LibraryList(dedupe(self.libraries + list(other)))
+
+    def __radd__(self, other):
+        return self.__add__(other)
+
+    def __eq__(self, other):
+        return self.libraries == other.libraries
+
+    def __len__(self):
+        return len(self.libraries)
+
+    def joined(self, separator=' '):
+        return separator.join(self.libraries)
+
+    def __repr__(self):
+        return self.__class__.__name__ + '(' + repr(self.libraries) + ')'
+
+    def __str__(self):
+        return self.joined()
+
+
+def find_libraries(args, root, shared=True, recurse=False):
+    """Returns an iterable object containing a list of full paths to
+    libraries if found.
+
+    Args:
+        args: iterable object containing a list of library names to \
+            search for (e.g. 'libhdf5')
+        root: root folder where to start searching
+        shared: if True searches for shared libraries, otherwise for static
+        recurse: if False search only root folder, if True descends top-down \
+            from the root
+
+    Returns:
+        list of full paths to the libraries that have been found
     """
-    for path in paths:
-        library = join_path(path, libname)
-        if os.path.exists(library):
-            return path
-    return None
+    if not isinstance(args, collections.Sequence) or isinstance(args, str):
+        message = '{0} expects a sequence of strings as first argument'
+        message += ' [got {1} instead]'
+        raise TypeError(message.format(find_libraries.__name__, type(args)))
+
+    # Construct the right suffix for the library
+    if shared is True:
+        suffix = 'dylib' if sys.platform == 'darwin' else 'so'
+    else:
+        suffix = 'a'
+    # List of libraries we are searching with suffixes
+    libraries = ['{0}.{1}'.format(lib, suffix) for lib in args]
+    # Search method
+    if recurse is False:
+        search_method = _find_libraries_non_recursive
+    else:
+        search_method = _find_libraries_recursive
+
+    return search_method(libraries, root)
+
+
+def _find_libraries_recursive(libraries, root):
+    library_dict = collections.defaultdict(list)
+    for path, _, files in os.walk(root):
+        for lib in libraries:
+            if lib in files:
+                library_dict[lib].append(
+                    join_path(path, lib)
+                )
+    answer = []
+    for lib in libraries:
+        answer.extend(library_dict[lib])
+    return LibraryList(answer)
+
+
+def _find_libraries_non_recursive(libraries, root):
+
+    def lib_or_none(lib):
+        library = join_path(root, lib)
+        if not os.path.exists(library):
+            return None
+        return library
+
+    return LibraryList(
+        [lib_or_none(lib) for lib in libraries if lib_or_none(lib) is not None]
+    )
diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py
index df32012e2de480f7e13bc95755c72a7dd3a86dfb..253334c416b4c9d0d2607d973031c72f9ff5c465 100644
--- a/lib/spack/llnl/util/lang.py
+++ b/lib/spack/llnl/util/lang.py
@@ -374,6 +374,22 @@ def __iter__(self):
     return wrapper()
 
 
+def dedupe(sequence):
+    """Yields a stable de-duplication of an hashable sequence
+
+    Args:
+        sequence: hashable sequence to be de-duplicated
+
+    Returns:
+        stable de-duplication of the sequence
+    """
+    seen = set()
+    for x in sequence:
+        if x not in seen:
+            yield x
+            seen.add(x)
+
+
 class RequiredAttributeError(ValueError):
 
     def __init__(self, message):
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 8b0486c4da3a23133ad5d8380eb3be41d2fc2ff8..158d76e568720b85d168cc323c8ee65fe1da187a 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -527,6 +527,13 @@ def __init__(self, spec_like, *dep_like, **kwargs):
             # XXX(deptype): default deptypes
             self._add_dependency(spec, ('build', 'link'))
 
+    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
+        package = super(Spec, self).__getattribute__('package')
+        return getattr(package, item)
+
     def get_dependency(self, name):
         dep = self._dependencies.get(name)
         if dep is not None:
diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py
index db683917b56eec23ffb6f176ae9ad573b509b511..0a946ff2fff4836af014e8c2171b793925c3a364 100644
--- a/lib/spack/spack/test/__init__.py
+++ b/lib/spack/spack/test/__init__.py
@@ -53,6 +53,7 @@
     'git_fetch',
     'hg_fetch',
     'install',
+    'library_list',
     'link_tree',
     'lock',
     'make_executable',
diff --git a/lib/spack/spack/test/library_list.py b/lib/spack/spack/test/library_list.py
new file mode 100644
index 0000000000000000000000000000000000000000..7fc2fd222fd14676da45d124e7dfd762b3b5b0b9
--- /dev/null
+++ b/lib/spack/spack/test/library_list.py
@@ -0,0 +1,111 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+
+import unittest
+
+from llnl.util.filesystem import LibraryList
+
+
+class LibraryListTest(unittest.TestCase):
+    def setUp(self):
+        l = [
+            '/dir1/liblapack.a',
+            '/dir2/libfoo.dylib',
+            '/dir1/libblas.a',
+            '/dir3/libbar.so',
+            'libbaz.so'
+        ]
+        self.liblist = LibraryList(l)
+
+    def test_repr(self):
+        x = eval(repr(self.liblist))
+        self.assertEqual(self.liblist, x)
+
+    def test_joined_and_str(self):
+        s1 = self.liblist.joined()
+        self.assertEqual(
+            s1,
+            '/dir1/liblapack.a /dir2/libfoo.dylib /dir1/libblas.a /dir3/libbar.so libbaz.so'  # NOQA: ignore=E501
+        )
+        s2 = str(self.liblist)
+        self.assertEqual(s1, s2)
+        s3 = self.liblist.joined(';')
+        self.assertEqual(
+            s3,
+            '/dir1/liblapack.a;/dir2/libfoo.dylib;/dir1/libblas.a;/dir3/libbar.so;libbaz.so'  # NOQA: ignore=E501
+        )
+
+    def test_flags(self):
+        search_flags = self.liblist.search_flags
+        self.assertTrue('-L/dir1' in search_flags)
+        self.assertTrue('-L/dir2' in search_flags)
+        self.assertTrue('-L/dir3' in search_flags)
+        self.assertTrue(isinstance(search_flags, str))
+
+        link_flags = self.liblist.link_flags
+        self.assertEqual(
+            link_flags,
+            '-llapack -lfoo -lblas -lbar -lbaz'
+        )
+
+        ld_flags = self.liblist.ld_flags
+        self.assertEqual(ld_flags, search_flags + ' ' + link_flags)
+
+    def test_paths_manipulation(self):
+        names = self.liblist.names
+        self.assertEqual(names, ['lapack', 'foo', 'blas', 'bar', 'baz'])
+
+        directories = self.liblist.directories
+        self.assertEqual(directories, ['/dir1', '/dir2', '/dir3'])
+
+    def test_get_item(self):
+        a = self.liblist[0]
+        self.assertEqual(a, '/dir1/liblapack.a')
+
+        b = self.liblist[:]
+        self.assertEqual(type(b), type(self.liblist))
+        self.assertEqual(self.liblist, b)
+        self.assertTrue(self.liblist is not b)
+
+    def test_add(self):
+        pylist = [
+            '/dir1/liblapack.a',  # removed from the final list
+            '/dir2/libbaz.so',
+            '/dir4/libnew.a'
+        ]
+        another = LibraryList(pylist)
+        l = self.liblist + another
+        self.assertEqual(len(l), 7)
+        # Invariant : l == l + l
+        self.assertEqual(l, l + l)
+        # Always produce an instance of LibraryList
+        self.assertEqual(
+            type(self.liblist),
+            type(self.liblist + pylist)
+        )
+        self.assertEqual(
+            type(pylist + self.liblist),
+            type(self.liblist)
+        )
diff --git a/var/spack/repos/builtin/packages/armadillo/package.py b/var/spack/repos/builtin/packages/armadillo/package.py
index 4356f60aca2ef04ecc0d73c531f29a61a4f50d59..fdd682f5e5ade8775d2eb6f1f8b4b23f4b936518 100644
--- a/var/spack/repos/builtin/packages/armadillo/package.py
+++ b/var/spack/repos/builtin/packages/armadillo/package.py
@@ -46,18 +46,20 @@ class Armadillo(Package):
     depends_on('hdf5', when='+hdf5')
 
     def install(self, spec, prefix):
+        arpack = find_libraries(['libarpack'], root=spec[
+                                'arpack-ng'].prefix.lib, shared=True)
+        superlu = find_libraries(['libsuperlu'], root=spec[
+                                 'superlu'].prefix, shared=False, recurse=True)
         cmake_args = [
             # ARPACK support
-            '-DARPACK_LIBRARY={0}/libarpack.{1}'.format(
-                spec['arpack-ng'].prefix.lib, dso_suffix),
+            '-DARPACK_LIBRARY={0}'.format(arpack.joined()),
             # BLAS support
-            '-DBLAS_LIBRARY={0}'.format(spec['blas'].blas_shared_lib),
+            '-DBLAS_LIBRARY={0}'.format(spec['blas'].blas_libs.joined()),
             # LAPACK support
-            '-DLAPACK_LIBRARY={0}'.format(spec['lapack'].lapack_shared_lib),
+            '-DLAPACK_LIBRARY={0}'.format(spec['lapack'].lapack_libs.joined()),
             # SuperLU support
             '-DSuperLU_INCLUDE_DIR={0}'.format(spec['superlu'].prefix.include),
-            '-DSuperLU_LIBRARY={0}/libsuperlu.a'.format(
-                spec['superlu'].prefix.lib64),
+            '-DSuperLU_LIBRARY={0}'.format(superlu.joined()),
             # HDF5 support
             '-DDETECT_HDF5={0}'.format('ON' if '+hdf5' in spec else 'OFF')
         ]
diff --git a/var/spack/repos/builtin/packages/arpack-ng/package.py b/var/spack/repos/builtin/packages/arpack-ng/package.py
index 0e71125d41fa4e7188af1fce0743233fea22d79e..7f92bc1950641a0b7eafd3a1e7b2075d1a6bec8b 100644
--- a/var/spack/repos/builtin/packages/arpack-ng/package.py
+++ b/var/spack/repos/builtin/packages/arpack-ng/package.py
@@ -88,17 +88,16 @@ def install(self, spec, prefix):
         options.append('-DCMAKE_INSTALL_NAME_DIR:PATH=%s/lib' % prefix)
 
         # Make sure we use Spack's blas/lapack:
+        lapack_libs = spec['lapack'].lapack_libs.joined()
+        blas_libs = spec['blas'].blas_libs.joined()
+
         options.extend([
             '-DLAPACK_FOUND=true',
-            '-DLAPACK_INCLUDE_DIRS=%s' % spec['lapack'].prefix.include,
-            '-DLAPACK_LIBRARIES=%s' % (
-                spec['lapack'].lapack_shared_lib if '+shared' in spec else
-                spec['lapack'].lapack_static_lib),
+            '-DLAPACK_INCLUDE_DIRS={0}'.format(spec['lapack'].prefix.include),
+            '-DLAPACK_LIBRARIES={0}'.format(lapack_libs),
             '-DBLAS_FOUND=true',
-            '-DBLAS_INCLUDE_DIRS=%s' % spec['blas'].prefix.include,
-            '-DBLAS_LIBRARIES=%s' % (
-                spec['blas'].blas_shared_lib if '+shared' in spec else
-                spec['blas'].blas_static_lib)
+            '-DBLAS_INCLUDE_DIRS={0}'.format(spec['blas'].prefix.include),
+            '-DBLAS_LIBRARIES={0}'.format(blas_libs)
         ])
 
         if '+mpi' in spec:
@@ -129,19 +128,12 @@ def install(self, spec, prefix):
                 'F77=%s' % spec['mpi'].mpif77
             ])
 
-        if '+shared' in spec:
-            options.extend([
-                '--with-blas=%s' % to_link_flags(
-                    spec['blas'].blas_shared_lib),
-                '--with-lapack=%s' % to_link_flags(
-                    spec['lapack'].lapack_shared_lib)
-            ])
-        else:
-            options.extend([
-                '--with-blas=%s' % spec['blas'].blas_static_lib,
-                '--with-lapack=%s' % spec['lapack'].lapack_static_lib,
-                '--enable-shared=no'
-            ])
+        options.extend([
+            '--with-blas={0}'.format(spec['blas'].blas_libs.ld_flags),
+            '--with-lapack={0}'.format(spec['lapack'].lapack_libs.ld_flags)
+        ])
+        if '+shared' not in spec:
+            options.append('--enable-shared=no')
 
         bootstrap()
         configure(*options)
diff --git a/var/spack/repos/builtin/packages/atlas/package.py b/var/spack/repos/builtin/packages/atlas/package.py
index f9d5da616601f5194809ce306f066c8fa595cfe1..e1914aac98519d2007a807577ba4c080bac6409f 100644
--- a/var/spack/repos/builtin/packages/atlas/package.py
+++ b/var/spack/repos/builtin/packages/atlas/package.py
@@ -51,6 +51,7 @@ class Atlas(Package):
             url='http://sourceforge.net/projects/math-atlas/files/Developer%20%28unstable%29/3.11.34/atlas3.11.34.tar.bz2')
 
     variant('shared', default=True, description='Builds shared library')
+    variant('pthread', default=False, description='Use multithreaded libraries')
 
     provides('blas')
     provides('lapack')
@@ -107,18 +108,32 @@ def install(self, spec, prefix):
             make("install")
             self.install_test()
 
-    def setup_dependent_package(self, module, dspec):
+    @property
+    def blas_libs(self):
         # libsatlas.[so,dylib,dll ] contains all serial APIs (serial lapack,
         # serial BLAS), and all ATLAS symbols needed to support them. Whereas
         # libtatlas.[so,dylib,dll ] is parallel (multithreaded) version.
-        name = 'libsatlas.%s' % dso_suffix
-        libdir = find_library_path(name,
-                                   self.prefix.lib64,
-                                   self.prefix.lib)
-
+        is_threaded = '+pthread' in self.spec
         if '+shared' in self.spec:
-            self.spec.blas_shared_lib   = join_path(libdir, name)
-            self.spec.lapack_shared_lib = self.spec.blas_shared_lib
+            to_find = ['libtatlas'] if is_threaded else ['libsatlas']
+            shared = True
+        else:
+            interfaces = [
+                'libptcblas',
+                'libptf77blas'
+            ] if is_threaded else [
+                'libcblas',
+                'libf77blas'
+            ]
+            to_find = ['liblapack'] + interfaces + ['libatlas']
+            shared = False
+        return find_libraries(
+            to_find, root=self.prefix, shared=shared, recurse=True
+        )
+
+    @property
+    def lapack_libs(self):
+        return self.blas_libs
 
     def install_test(self):
         source_file = join_path(os.path.dirname(self.module.__file__),
@@ -126,9 +141,8 @@ def install_test(self):
         blessed_file = join_path(os.path.dirname(self.module.__file__),
                                  'test_cblas_dgemm.output')
 
-        include_flags = ["-I%s" % join_path(self.spec.prefix, "include")]
-        link_flags = ["-L%s" % join_path(self.spec.prefix, "lib"),
-                      "-lsatlas"]
+        include_flags = ["-I%s" % self.spec.prefix.include]
+        link_flags = self.lapack_libs.ld_flags
 
         output = compile_c_and_execute(source_file, include_flags, link_flags)
         compare_output_file(output, blessed_file)
diff --git a/var/spack/repos/builtin/packages/cp2k/package.py b/var/spack/repos/builtin/packages/cp2k/package.py
index 785de08d34ef9bfbb5955e73eb4284248ac78587..15606cd80afab5ece99f669238f03fc064ffa256 100644
--- a/var/spack/repos/builtin/packages/cp2k/package.py
+++ b/var/spack/repos/builtin/packages/cp2k/package.py
@@ -95,7 +95,8 @@ def install(self, spec, prefix):
             fcflags.extend([
                 '-I' + spec['fftw'].prefix.include
             ])
-            ldflags = ['-L' + spec['fftw'].prefix.lib]
+            fftw = find_libraries(['libfftw3'], root=spec['fftw'].prefix.lib)
+            ldflags = [fftw.search_flags]
             libs = []
             if '+plumed' in self.spec:
                 # Include Plumed.inc in the Makefile
@@ -157,9 +158,8 @@ def install(self, spec, prefix):
                     ),
                     '-I' + join_path(spec['pexsi'].prefix, 'fortran')
                 ])
-                ldflags.extend([
-                    '-L' + spec['scalapack'].prefix.lib
-                ])
+                scalapack = spec['scalapack'].scalapack_libs
+                ldflags.append(scalapack.search_flags)
                 libs.extend([
                     join_path(spec['elpa'].prefix.lib,
                               'libelpa.{0}'.format(dso_suffix)),
@@ -176,20 +176,15 @@ def install(self, spec, prefix):
                         'libmetis.{0}'.format(dso_suffix)
                     ),
                 ])
-                libs.extend(spec['scalapack'].scalapack_shared_libs)
+                libs.extend(scalapack)
                 libs.extend(self.spec['mpi'].mpicxx_shared_libs)
                 libs.extend(self.compiler.stdcxx_libs)
             # LAPACK / BLAS
-            ldflags.extend([
-                '-L' + spec['lapack'].prefix.lib,
-                '-L' + spec['blas'].prefix.lib
-            ])
-            libs.extend([
-                join_path(spec['fftw'].prefix.lib,
-                          'libfftw3.{0}'.format(dso_suffix)),
-                spec['lapack'].lapack_shared_lib,
-                spec['blas'].blas_shared_lib
-            ])
+            lapack = spec['lapack'].lapack_libs
+            blas = spec['blas'].blas_libs
+
+            ldflags.append((lapack + blas).search_flags)
+            libs.extend([str(x) for x in (fftw, lapack, blas)])
 
             # Write compiler flags to file
             mkf.write('CPPFLAGS = {0}\n'.format(' '.join(cppflags)))
diff --git a/var/spack/repos/builtin/packages/dealii/package.py b/var/spack/repos/builtin/packages/dealii/package.py
index 9e8c639128107528eb59153e6843c2b42652c2f3..89732f98b8a652a6986986e27569d025ca31ab62 100644
--- a/var/spack/repos/builtin/packages/dealii/package.py
+++ b/var/spack/repos/builtin/packages/dealii/package.py
@@ -123,6 +123,7 @@ def install(self, spec, prefix):
                 options.remove(word)
 
         dsuf = 'dylib' if sys.platform == 'darwin' else 'so'
+        lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs
         options.extend([
             '-DCMAKE_BUILD_TYPE=DebugRelease',
             '-DDEAL_II_COMPONENT_EXAMPLES=ON',
@@ -135,9 +136,7 @@ def install(self, spec, prefix):
             '-DLAPACK_FOUND=true',
             '-DLAPACK_INCLUDE_DIRS=%s;%s' % (
                 spec['lapack'].prefix.include, spec['blas'].prefix.include),
-            '-DLAPACK_LIBRARIES=%s;%s' % (
-                spec['lapack'].lapack_shared_lib,
-                spec['blas'].blas_shared_lib),
+            '-DLAPACK_LIBRARIES=%s' % lapack_blas.joined(';'),
             '-DMUPARSER_DIR=%s' % spec['muparser'].prefix,
             '-DUMFPACK_DIR=%s' % spec['suite-sparse'].prefix,
             '-DTBB_DIR=%s' % spec['tbb'].prefix,
diff --git a/var/spack/repos/builtin/packages/elk/package.py b/var/spack/repos/builtin/packages/elk/package.py
index b089e585dd15f56f96c3d171cb092e6810aa2597..acaf8639353706212d3e380a1d61062f69cf21f5 100644
--- a/var/spack/repos/builtin/packages/elk/package.py
+++ b/var/spack/repos/builtin/packages/elk/package.py
@@ -87,12 +87,12 @@ def configure(self, spec):
         # BLAS/LAPACK support
         # Note: BLAS/LAPACK must be compiled with OpenMP support
         # if the +openmp variant is chosen
-        blas   = 'blas.a'
+        blas = 'blas.a'
         lapack = 'lapack.a'
         if '+blas' in spec:
-            blas   = spec['blas'].blas_shared_lib
+            blas = spec['blas'].blas_libs.joined()
         if '+lapack' in spec:
-            lapack = spec['lapack'].lapack_shared_lib
+            lapack = spec['lapack'].lapack_libs.joined()
         # lapack must come before blas
         config['LIB_LPK'] = ' '.join([lapack, blas])
 
diff --git a/var/spack/repos/builtin/packages/gmsh/package.py b/var/spack/repos/builtin/packages/gmsh/package.py
index 1d375f21864fc3f4261978d5632dd318dc648a8b..dd142866e54338023aad0275d22f78b828570373 100644
--- a/var/spack/repos/builtin/packages/gmsh/package.py
+++ b/var/spack/repos/builtin/packages/gmsh/package.py
@@ -87,9 +87,9 @@ def install(self, spec, prefix):
         options.append('-DENABLE_OS_SPECIFIC_INSTALL=OFF')
 
         # Make sure GMSH picks up correct BlasLapack by providing linker flags
-        options.append('-DBLAS_LAPACK_LIBRARIES=%s %s' %
-                       (to_link_flags(spec['lapack'].lapack_shared_lib),
-                        to_link_flags(spec['blas'].blas_shared_lib)))
+        blas_lapack = spec['lapack'].lapack_libs + spec['blas'].blas_libs
+        options.append(
+            '-DBLAS_LAPACK_LIBRARIES={0}'.format(blas_lapack.ld_flags))
 
         # Gmsh does not have an option to compile against external metis.
         # Its own Metis, however, fails to build
diff --git a/var/spack/repos/builtin/packages/hpl/package.py b/var/spack/repos/builtin/packages/hpl/package.py
index efd5c8bb1dad3b3f372408dba1293242980e78f5..fa0013de17405ae90b660cf066f1e3e1728d51dd 100644
--- a/var/spack/repos/builtin/packages/hpl/package.py
+++ b/var/spack/repos/builtin/packages/hpl/package.py
@@ -78,7 +78,7 @@ def configure(self, spec, arch):
             'MPlib        = -L{0}'.format(spec['mpi'].prefix.lib),
             # Linear Algebra library (BLAS or VSIPL)
             'LAinc        = {0}'.format(spec['blas'].prefix.include),
-            'LAlib        = {0}'.format(spec['blas'].blas_shared_lib),
+            'LAlib        = {0}'.format(spec['blas'].blas_libs.joined()),
             # F77 / C interface
             'F2CDEFS      = -DAdd_ -DF77_INTEGER=int -DStringSunStyle',
             # HPL includes / libraries / specifics
diff --git a/var/spack/repos/builtin/packages/hypre/package.py b/var/spack/repos/builtin/packages/hypre/package.py
index fdc236dcf41fd304cede0b6aa039bf9a60391988..96ed8411dd570929dc65a6ee9e9a53015af323c5 100644
--- a/var/spack/repos/builtin/packages/hypre/package.py
+++ b/var/spack/repos/builtin/packages/hypre/package.py
@@ -60,13 +60,14 @@ def install(self, spec, prefix):
         # to command the linker to include whole static libs' content into the
         # shared lib
         # Note: --with-(lapack|blas)_libs= needs space separated list of names
+        lapack = spec['lapack'].lapack_libs
+        blas = spec['blas'].blas_libs
+
         configure_args = [
             '--prefix=%s' % prefix,
-            '--with-lapack-libs=%s' % to_lib_name(
-                spec['lapack'].lapack_shared_lib),
+            '--with-lapack-libs=%s' % lapack.names,
             '--with-lapack-lib-dirs=%s' % spec['lapack'].prefix.lib,
-            '--with-blas-libs=%s' % to_lib_name(
-                spec['blas'].blas_shared_lib),
+            '--with-blas-libs=%s' % blas.names,
             '--with-blas-lib-dirs=%s' % spec['blas'].prefix.lib
         ]
 
diff --git a/var/spack/repos/builtin/packages/intel-parallel-studio/package.py b/var/spack/repos/builtin/packages/intel-parallel-studio/package.py
index 65db3351a15d81f59a6b16d78713a34e85acc2b5..74bdba455f8d6ff4b766b59e265e4d4d4a68e078 100644
--- a/var/spack/repos/builtin/packages/intel-parallel-studio/package.py
+++ b/var/spack/repos/builtin/packages/intel-parallel-studio/package.py
@@ -45,6 +45,10 @@ class IntelParallelStudio(IntelInstaller):
     variant('tools', default=True, description="Install the Intel Advisor, "
             "VTune Amplifier, and Inspector tools")
 
+    variant('shared', default=True, description='Builds shared library')
+    variant('ilp64', default=False, description='64 bit integers')
+    variant('openmp', default=False, description='OpenMP multithreading layer')
+
     provides('mpi', when='@cluster:+mpi')
     provides('mkl', when='+mkl')
     provides('daal', when='+daal')
@@ -55,6 +59,28 @@ class IntelParallelStudio(IntelInstaller):
     provides('lapack', when='+mkl')
     # TODO: MKL also provides implementation of Scalapack.
 
+    @property
+    def blas_libs(self):
+        shared = True if '+shared' in self.spec else False
+        suffix = dso_suffix if '+shared' in self.spec else 'a'
+        mkl_integer = ['libmkl_intel_ilp64'] if '+ilp64' in self.spec else ['libmkl_intel_lp64']  # NOQA: ignore=E501
+        mkl_threading = ['libmkl_intel_thread'] if '+openmp' in self.spec else ['libmkl_sequential']  # NOQA: ignore=E501
+        mkl_libs = find_libraries(
+            mkl_integer + ['libmkl_core'] + mkl_threading,
+            root=join_path(self.prefix.lib, 'intel64'),
+            shared=shared
+        )
+        system_libs = [
+            'libpthread.{0}'.format(suffix),
+            'libm.{0}'.format(suffix),
+            'libdl.{0}'.format(suffix)
+        ]
+        return mkl_libs + system_libs
+
+    @property
+    def lapack_libs(self):
+        return self.blas_libs
+
     def check_variants(self, spec):
         error_message = '\t{variant} can not be turned off if "+all" is set'
 
@@ -171,24 +197,6 @@ def install(self, spec, prefix):
         os.symlink(os.path.join(self.prefix.man, "common", "man1"),
                    os.path.join(self.prefix.man, "man1"))
 
-    def setup_dependent_package(self, module, dspec):
-        # For now use Single Dynamic Library:
-        # To set the threading layer at run time, use the
-        # mkl_set_threading_layer function or set MKL_THREADING_LAYER
-        # variable to one of the following values: INTEL, SEQUENTIAL, PGI.
-        # To set interface layer at run time, use the mkl_set_interface_layer
-        # function or set the MKL_INTERFACE_LAYER variable to LP64 or ILP64.
-
-        # Otherwise one would need to specify several libraries
-        # (e.g. mkl_intel_lp64;mkl_sequential;mkl_core), which reflect
-        # different interface and threading layers.
-
-        name = 'libmkl_rt.%s' % dso_suffix
-        libdir = find_library_path(name, self.prefix.lib64, self.prefix.lib)
-
-        self.spec.blas_shared_lib   = join_path(libdir, name)
-        self.spec.lapack_shared_lib = self.spec.blas_shared_lib
-
     def setup_environment(self, spack_env, run_env):
         # TODO: Determine variables needed for the professional edition.
 
diff --git a/var/spack/repos/builtin/packages/mkl/package.py b/var/spack/repos/builtin/packages/mkl/package.py
index 71a233ff3e1b69c188077d1b0bd6c3450a89bd1c..a7353d57c42ae19be49b069d36c6013e9eec7412 100644
--- a/var/spack/repos/builtin/packages/mkl/package.py
+++ b/var/spack/repos/builtin/packages/mkl/package.py
@@ -24,13 +24,40 @@ class Mkl(IntelInstaller):
     version('11.3.3.210', 'f72546df27f5ebb0941b5d21fd804e34',
             url="file://%s/l_mkl_11.3.3.210.tgz" % os.getcwd())
 
+    variant('shared', default=True, description='Builds shared library')
+    variant('ilp64', default=False, description='64 bit integers')
+    variant('openmp', default=False, description='OpenMP multithreading layer')
+
     # virtual dependency
     provides('blas')
     provides('lapack')
     # TODO: MKL also provides implementation of Scalapack.
 
-    def install(self, spec, prefix):
+    @property
+    def blas_libs(self):
+        shared = True if '+shared' in self.spec else False
+        suffix = dso_suffix if '+shared' in self.spec else 'a'
+        mkl_integer = ['libmkl_intel_ilp64'] if '+ilp64' in self.spec else ['libmkl_intel_lp64']  # NOQA: ignore=E501
+        mkl_threading = ['libmkl_sequential']
+        if '+openmp' in spec:
+            mkl_threading = ['libmkl_intel_thread'] if '%intel' in self.spec else ['libmkl_gnu_thread']  # NOQA: ignore=E501
+        mkl_libs = find_libraries(
+            mkl_integer + ['libmkl_core'] + mkl_threading,
+            root=join_path(self.prefix.lib, 'intel64'),
+            shared=shared
+        )
+        system_libs = [
+            'libpthread.{0}'.format(suffix),
+            'libm.{0}'.format(suffix),
+            'libdl.{0}'.format(suffix)
+        ]
+        return mkl_libs + system_libs
+
+    @property
+    def lapack_libs(self):
+        return self.blas_libs
 
+    def install(self, spec, prefix):
         self.intel_prefix = os.path.join(prefix, "pkg")
         IntelInstaller.install(self, spec, prefix)
 
@@ -45,25 +72,6 @@ def install(self, spec, prefix):
             os.symlink(os.path.join(mkl_lib_dir, f),
                        os.path.join(self.prefix, "lib", f))
 
-    def setup_dependent_package(self, module, dspec):
-        # For now use Single Dynamic Library:
-        # To set the threading layer at run time, use the
-        # mkl_set_threading_layer function or set MKL_THREADING_LAYER
-        # variable to one of the following values: INTEL, SEQUENTIAL, PGI.
-        # To set interface layer at run time, use the mkl_set_interface_layer
-        # function or set the MKL_INTERFACE_LAYER variable to LP64 or ILP64.
-
-        # Otherwise one would need to specify several libraries
-        # (e.g. mkl_intel_lp64;mkl_sequential;mkl_core), which reflect
-        # different interface and threading layers.
-
-        name = 'libmkl_rt.%s' % dso_suffix
-        libdir = find_library_path(name, self.prefix.lib64, self.prefix.lib)
-
-        # Now set blas/lapack libs:
-        self.spec.blas_shared_lib   = join_path(libdir, name)
-        self.spec.lapack_shared_lib = self.spec.blas_shared_lib
-
     def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
         # set up MKLROOT for everyone using MKL package
         spack_env.set('MKLROOT', self.prefix)
diff --git a/var/spack/repos/builtin/packages/mumps/package.py b/var/spack/repos/builtin/packages/mumps/package.py
index 32bc42a9c32e900d589980dc2d48139592e91f6e..3466f091a0d6e84b9d794c3ca05750d6d048f401 100644
--- a/var/spack/repos/builtin/packages/mumps/package.py
+++ b/var/spack/repos/builtin/packages/mumps/package.py
@@ -75,9 +75,8 @@ def write_makefile_inc(self):
             raise RuntimeError(
                 'You cannot use the variants parmetis or ptscotch without mpi')
 
-        makefile_conf = ["LIBBLAS = %s" % to_link_flags(
-            self.spec['blas'].blas_shared_lib)
-        ]
+        blas = self.spec['blas'].blas_libs
+        makefile_conf = ["LIBBLAS = %s" % blas.ld_flags]
 
         orderings = ['-Dpord']
 
@@ -136,11 +135,12 @@ def write_makefile_inc(self):
                  'OPTC    = %s -O ' % fpic])
 
         if '+mpi' in self.spec:
+            scalapack = self.spec['scalapack'].scalapack_libs
             makefile_conf.extend(
                 ["CC = %s" % join_path(self.spec['mpi'].prefix.bin, 'mpicc'),
                  "FC = %s" % join_path(self.spec['mpi'].prefix.bin, 'mpif90'),
                  "FL = %s" % join_path(self.spec['mpi'].prefix.bin, 'mpif90'),
-                 "SCALAP = %s" % self.spec['scalapack'].fc_link,
+                 "SCALAP = %s" % scalapack.ld_flags,
                  "MUMPS_TYPE = par"])
         else:
             makefile_conf.extend(
diff --git a/var/spack/repos/builtin/packages/netlib-lapack/package.py b/var/spack/repos/builtin/packages/netlib-lapack/package.py
index 93d64fb46678297acb3e63e6a87aca87e27274ae..b73fe850d76e83a3ba25d69c71cf2a2371785c19 100644
--- a/var/spack/repos/builtin/packages/netlib-lapack/package.py
+++ b/var/spack/repos/builtin/packages/netlib-lapack/package.py
@@ -67,6 +67,20 @@ def patch(self):
                 '${CMAKE_CURRENT_SOURCE_DIR}/cmake/',
                 'CBLAS/CMakeLists.txt', string=True)
 
+    @property
+    def blas_libs(self):
+        shared = True if '+shared' in self.spec else False
+        return find_libraries(
+            ['libblas'], root=self.prefix, shared=shared, recurse=True
+        )
+
+    @property
+    def lapack_libs(self):
+        shared = True if '+shared' in self.spec else False
+        return find_libraries(
+            ['liblapack'], root=self.prefix, shared=shared, recurse=True
+        )
+
     def install_one(self, spec, prefix, shared):
         cmake_args = [
             '-DBUILD_SHARED_LIBS:BOOL=%s' % ('ON' if shared else 'OFF'),
@@ -100,18 +114,3 @@ def install(self, spec, prefix):
         # Build shared libraries if requested.
         if '+shared' in spec:
             self.install_one(spec, prefix, True)
-
-    def setup_dependent_package(self, module, dspec):
-        # This is WIP for a prototype interface for virtual packages.
-        # We can update this as more builds start depending on BLAS/LAPACK.
-        libdir = find_library_path(
-            'libblas.a', self.prefix.lib64, self.prefix.lib)
-
-        self.spec.blas_static_lib   = join_path(libdir, 'libblas.a')
-        self.spec.lapack_static_lib = join_path(libdir, 'liblapack.a')
-
-        if '+shared' in self.spec:
-            self.spec.blas_shared_lib   = join_path(
-                libdir, 'libblas.%s' % dso_suffix)
-            self.spec.lapack_shared_lib = join_path(
-                libdir, 'liblapack.%s' % dso_suffix)
diff --git a/var/spack/repos/builtin/packages/netlib-scalapack/package.py b/var/spack/repos/builtin/packages/netlib-scalapack/package.py
index 13e932e17614aa28a0a6db1a1181226001600643..fe9f1a302351374c61beef5911ea8169ed26dc40 100644
--- a/var/spack/repos/builtin/packages/netlib-scalapack/package.py
+++ b/var/spack/repos/builtin/packages/netlib-scalapack/package.py
@@ -28,10 +28,11 @@
 
 class NetlibScalapack(Package):
     """ScaLAPACK is a library of high-performance linear algebra routines for
-    parallel distributed memory machines"""
+    parallel distributed memory machines
+    """
 
     homepage = "http://www.netlib.org/scalapack/"
-    url      = "http://www.netlib.org/scalapack/scalapack-2.0.2.tgz"
+    url = "http://www.netlib.org/scalapack/scalapack-2.0.2.tgz"
 
     version('2.0.2', '2f75e600a2ba155ed9ce974a1c4b536f')
     version('2.0.1', '17b8cde589ea0423afe1ec43e7499161')
@@ -39,10 +40,16 @@ class NetlibScalapack(Package):
     # versions before 2.0.0 are not using cmake and requires blacs as
     # a separated package
 
-    variant('shared', default=True,
-            description='Build the shared library version')
-    variant('fpic', default=False,
-            description="Build with -fpic compiler option")
+    variant(
+        'shared',
+        default=True,
+        description='Build the shared library version'
+    )
+    variant(
+        'fpic',
+        default=False,
+        description='Build with -fpic compiler option'
+    )
 
     provides('scalapack')
 
@@ -51,6 +58,13 @@ class NetlibScalapack(Package):
     depends_on('blas')
     depends_on('cmake', when='@2.0.0:', type='build')
 
+    @property
+    def scalapack_libs(self):
+        shared = True if '+shared' in self.spec else False
+        return find_libraries(
+            ['libscalapack'], root=self.prefix, shared=shared, recurse=True
+        )
+
     def install(self, spec, prefix):
         options = [
             "-DBUILD_SHARED_LIBS:BOOL=%s" % ('ON' if '+shared' in spec else
@@ -60,14 +74,13 @@ def install(self, spec, prefix):
         ]
 
         # Make sure we use Spack's Lapack:
+        blas = spec['blas'].blas_libs
+        lapack = spec['lapack'].lapack_libs
         options.extend([
             '-DLAPACK_FOUND=true',
-            '-DLAPACK_LIBRARIES=%s' % (
-                spec['lapack'].lapack_shared_lib if '+shared' in spec else
-                spec['lapack'].lapack_static_lib),
-            '-DBLAS_LIBRARIES=%s' % (
-                spec['blas'].blas_shared_lib if '+shared' in spec else
-                spec['blas'].blas_static_lib)
+            '-DLAPACK_INCLUDE_DIRS=%s' % spec['lapack'].prefix.include,
+            '-DLAPACK_LIBRARIES=%s' % (lapack.joined()),
+            '-DBLAS_LIBRARIES=%s' % (blas.joined())
         ])
 
         if '+fpic' in spec:
@@ -86,12 +99,3 @@ def install(self, spec, prefix):
         # The shared libraries are not installed correctly on Darwin:
         if (sys.platform == 'darwin') and ('+shared' in spec):
             fix_darwin_install_name(prefix.lib)
-
-    def setup_dependent_package(self, module, dependent_spec):
-        spec = self.spec
-        lib_suffix = dso_suffix if '+shared' in spec else 'a'
-
-        spec.fc_link = '-L%s -lscalapack' % spec.prefix.lib
-        spec.cc_link = spec.fc_link
-        spec.libraries = [join_path(spec.prefix.lib,
-                                    'libscalapack.%s' % lib_suffix)]
diff --git a/var/spack/repos/builtin/packages/nwchem/package.py b/var/spack/repos/builtin/packages/nwchem/package.py
index 13c710a35a9039cb56af285936535db4b0500602..b15c1c02fdcc97d924efb14e03a2b7a688119a97 100644
--- a/var/spack/repos/builtin/packages/nwchem/package.py
+++ b/var/spack/repos/builtin/packages/nwchem/package.py
@@ -66,6 +66,9 @@ class Nwchem(Package):
     patch('Gcc6_macs_optfix.patch', when='@6.6', level=0)
 
     def install(self, spec, prefix):
+        scalapack = spec['scalapack'].scalapack_libs
+        lapack = spec['lapack'].lapack_libs
+        blas = spec['blas'].blas_libs
         # see http://www.nwchem-sw.org/index.php/Compiling_NWChem
         args = []
         args.extend([
@@ -79,13 +82,11 @@ def install(self, spec, prefix):
             'USE_PYTHONCONFIG=y',
             'PYTHONVERSION=%s' % spec['python'].version.up_to(2),
             'PYTHONHOME=%s' % spec['python'].prefix,
-            'BLASOPT=%s %s' % (
-                to_link_flags(spec['lapack'].lapack_shared_lib),
-                to_link_flags(spec['blas'].blas_shared_lib)),
-            'BLAS_LIB=%s' % to_link_flags(spec['blas'].blas_shared_lib),
-            'LAPACK_LIB=%s' % to_link_flags(spec['lapack'].lapack_shared_lib),
+            'BLASOPT=%s' % ((lapack + blas).ld_flags),
+            'BLAS_LIB=%s' % blas.ld_flags,
+            'LAPACK_LIB=%s' % lapack.ld_flags,
             'USE_SCALAPACK=y',
-            'SCALAPACK=%s' % spec['scalapack'].fc_link,
+            'SCALAPACK=%s' % scalapack.ld_flags,
             'NWCHEM_MODULES=all python',
             'NWCHEM_LONG_PATHS=Y'  # by default NWCHEM_TOP is 64 char max
         ])
diff --git a/var/spack/repos/builtin/packages/octopus/package.py b/var/spack/repos/builtin/packages/octopus/package.py
index ff4a1069408311bb8a2164bd3d30d75fe6c95a46..adb760f06d794b7b3226071d4fae45a4f7d8509b 100644
--- a/var/spack/repos/builtin/packages/octopus/package.py
+++ b/var/spack/repos/builtin/packages/octopus/package.py
@@ -46,13 +46,13 @@ class Octopus(Package):
     # FEAST, Libfm, PFFT, ISF, PNFFT
 
     def install(self, spec, prefix):
+        lapack = spec['lapack'].lapack_libs
+        blas = spec['blas'].blas_libs
         args = []
         args.extend([
             '--prefix=%s' % prefix,
-            '--with-blas=%s' % to_link_flags(
-                spec['blas'].blas_shared_lib),
-            '--with-lapack=%s' % to_link_flags(
-                spec['lapack'].lapack_shared_lib),
+            '--with-blas=%s' % blas.ld_flags,
+            '--with-lapack=%s' % lapack.ld_flags,
             '--with-gsl-prefix=%s' % spec['gsl'].prefix,
             '--with-libxc-prefix=%s' % spec['libxc'].prefix,
             'CC=%s' % spec['mpi'].mpicc,
diff --git a/var/spack/repos/builtin/packages/openblas/package.py b/var/spack/repos/builtin/packages/openblas/package.py
index 23c7b02daf9945aa44afb8937fa78da1eff87067..89c35fb991d80d44b5845603d5b7b541857d18e9 100644
--- a/var/spack/repos/builtin/packages/openblas/package.py
+++ b/var/spack/repos/builtin/packages/openblas/package.py
@@ -30,7 +30,7 @@
 class Openblas(Package):
     """OpenBLAS: An optimized BLAS library"""
     homepage = "http://www.openblas.net"
-    url      = "http://github.com/xianyi/OpenBLAS/archive/v0.2.15.tar.gz"
+    url = "http://github.com/xianyi/OpenBLAS/archive/v0.2.15.tar.gz"
 
     version('0.2.19', '28c998054fd377279741c6f0b9ea7941')
     version('0.2.18', '805e7f660877d588ea7e3792cda2ee65')
@@ -51,6 +51,17 @@ class Openblas(Package):
 
     patch('make.patch')
 
+    @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
+
     def install(self, spec, prefix):
         # As of 06/2016 there is no mechanism to specify that packages which
         # depends on Blas/Lapack need C or/and Fortran symbols. For now
@@ -100,6 +111,9 @@ def install(self, spec, prefix):
         # no quotes around prefix (spack doesn't use a shell)
         make('install', "PREFIX=%s" % prefix, *make_defs)
 
+        # TODO : the links below are mainly there because client
+        # TODO : packages are wrongly written. Check if they can be removed
+
         # Blas virtual package should provide blas.a and libblas.a
         with working_dir(prefix.lib):
             symlink('libopenblas.a', 'blas.a')
@@ -120,21 +134,6 @@ def install(self, spec, prefix):
         # test.
         self.check_install(spec)
 
-    def setup_dependent_package(self, module, dspec):
-        # This is WIP for a prototype interface for virtual packages.
-        # We can update this as more builds start depending on BLAS/LAPACK.
-        libdir = find_library_path('libopenblas.a',
-                                   self.prefix.lib64,
-                                   self.prefix.lib)
-
-        self.spec.blas_static_lib   = join_path(libdir, 'libopenblas.a')
-        self.spec.lapack_static_lib = self.spec.blas_static_lib
-
-        if '+shared' in self.spec:
-            self.spec.blas_shared_lib   = join_path(libdir, 'libopenblas.%s' %
-                                                    dso_suffix)
-            self.spec.lapack_shared_lib = self.spec.blas_shared_lib
-
     def check_install(self, spec):
         source_file = join_path(os.path.dirname(self.module.__file__),
                                 'test_cblas_dgemm.c')
diff --git a/var/spack/repos/builtin/packages/opium/package.py b/var/spack/repos/builtin/packages/opium/package.py
index 2c81d92cc0a24729628bd3a96d3bb6dc8c9bb445..521f9172307f64817f791454494b1ca3d8e6a46c 100644
--- a/var/spack/repos/builtin/packages/opium/package.py
+++ b/var/spack/repos/builtin/packages/opium/package.py
@@ -29,7 +29,7 @@ class Opium(Package):
     """DFT pseudopotential generation project"""
 
     homepage = "https://opium.sourceforge.net/index.html"
-    url      = "https://downloads.sourceforge.net/project/opium/opium/opium-v3.8/opium-v3.8-src.tgz"
+    url = "https://downloads.sourceforge.net/project/opium/opium/opium-v3.8/opium-v3.8-src.tgz"
 
     version('3.8', 'f710c0f869e70352b4a510c31e13bf9f')
 
@@ -37,12 +37,8 @@ class Opium(Package):
     depends_on('lapack')
 
     def install(self, spec, prefix):
-        options = [
-            'LDFLAGS=%s %s' % (
-                to_link_flags(spec['lapack'].lapack_shared_lib),
-                to_link_flags(spec['blas'].blas_shared_lib)
-            )
-        ]
+        libs = spec['lapack'].lapack_libs + spec['blas'].blas_libs
+        options = ['LDFLAGS=%s' % libs.ld_flags]
 
         configure(*options)
         with working_dir("src", create=False):
diff --git a/var/spack/repos/builtin/packages/pexsi/package.py b/var/spack/repos/builtin/packages/pexsi/package.py
index e74ad6df013ec44b99c75b3e1b628af3f1003cda..9fc71d4c52577b5803f67455d3a504376a09922a 100644
--- a/var/spack/repos/builtin/packages/pexsi/package.py
+++ b/var/spack/repos/builtin/packages/pexsi/package.py
@@ -67,8 +67,8 @@ def install(self, spec, prefix):
             '@PARMETIS_PREFIX': self.spec['parmetis'].prefix,
             '@LAPACK_PREFIX': self.spec['lapack'].prefix,
             '@BLAS_PREFIX': self.spec['blas'].prefix,
-            '@LAPACK_LIBS': self.spec['lapack'].lapack_shared_lib,
-            '@BLAS_LIBS': self.spec['lapack'].blas_shared_lib,
+            '@LAPACK_LIBS': self.spec['lapack'].lapack_libs.joined(),
+            '@BLAS_LIBS': self.spec['lapack'].blas_libs.joined(),
             '@STDCXX_LIB': ' '.join(self.compiler.stdcxx_libs)
         }
 
diff --git a/var/spack/repos/builtin/packages/psi4/package.py b/var/spack/repos/builtin/packages/psi4/package.py
index 6296d0cee68d4e4d29096564a2a806fa36dd1374..566aa50f443326ef5eb6df0c2a09ac3191e9a3f5 100644
--- a/var/spack/repos/builtin/packages/psi4/package.py
+++ b/var/spack/repos/builtin/packages/psi4/package.py
@@ -32,7 +32,7 @@ class Psi4(Package):
     a variety of molecular properties."""
 
     homepage = "http://www.psicode.org/"
-    url      = "https://github.com/psi4/psi4/archive/0.5.tar.gz"
+    url = "https://github.com/psi4/psi4/archive/0.5.tar.gz"
 
     version('0.5', '53041b8a9be3958384171d0d22f9fdd0')
 
@@ -62,9 +62,10 @@ class Psi4(Package):
     def install(self, spec, prefix):
         cmake_args = [
             '-DBLAS_TYPE={0}'.format(spec['blas'].name.upper()),
-            '-DBLAS_LIBRARIES={0}'.format(spec['blas'].blas_shared_lib),
+            '-DBLAS_LIBRARIES={0}'.format(spec['blas'].blas_libs.joined()),
             '-DLAPACK_TYPE={0}'.format(spec['lapack'].name.upper()),
-            '-DLAPACK_LIBRARIES={0}'.format(spec['lapack'].lapack_shared_lib),
+            '-DLAPACK_LIBRARIES={0}'.format(
+                spec['lapack'].lapack_libs.joined()),
             '-DBOOST_INCLUDEDIR={0}'.format(spec['boost'].prefix.include),
             '-DBOOST_LIBRARYDIR={0}'.format(spec['boost'].prefix.lib),
             '-DENABLE_CHEMPS2=OFF'
@@ -90,9 +91,9 @@ def filter_compilers(self, spec, prefix):
 
         kwargs = {'ignore_absent': True, 'backup': False, 'string': True}
 
-        cc_files  = ['bin/psi4-config']
+        cc_files = ['bin/psi4-config']
         cxx_files = ['bin/psi4-config', 'include/psi4/psiconfig.h']
-        template  = 'share/psi4/plugin/Makefile.template'
+        template = 'share/psi4/plugin/Makefile.template'
 
         for filename in cc_files:
             filter_file(os.environ['CC'], self.compiler.cc,
diff --git a/var/spack/repos/builtin/packages/py-scipy/package.py b/var/spack/repos/builtin/packages/py-scipy/package.py
index 83a69c56821d8905cfa4c5156609b1c46329def0..68b2cb13e00d66e96a4d466d57799e12842c95c1 100644
--- a/var/spack/repos/builtin/packages/py-scipy/package.py
+++ b/var/spack/repos/builtin/packages/py-scipy/package.py
@@ -47,7 +47,7 @@ def install(self, spec, prefix):
             env['ATLAS'] = join_path(
                 spec['atlas'].prefix.lib, 'libatlas.' + dso_suffix)
         else:
-            env['BLAS']   = spec['blas'].blas_shared_lib
-            env['LAPACK'] = spec['lapack'].lapack_shared_lib
+            env['BLAS'] = spec['blas'].blas_libs.joined()
+            env['LAPACK'] = spec['lapack'].lapack_libs.joined()
 
         python('setup.py', 'install', '--prefix=%s' % prefix)
diff --git a/var/spack/repos/builtin/packages/suite-sparse/package.py b/var/spack/repos/builtin/packages/suite-sparse/package.py
index a71bfd8bd45d9bb113ea7b29af63a5c93693d585..22f069885d4aa115127e623c529ee8e302e5fb3f 100644
--- a/var/spack/repos/builtin/packages/suite-sparse/package.py
+++ b/var/spack/repos/builtin/packages/suite-sparse/package.py
@@ -80,8 +80,8 @@ def install(self, spec, prefix):
 
         # Make sure Spack's Blas/Lapack is used. Otherwise System's
         # Blas/Lapack might be picked up.
-        blas = to_link_flags(spec['blas'].blas_shared_lib)
-        lapack = to_link_flags(spec['lapack'].lapack_shared_lib)
+        blas = spec['blas'].blas_libs.ld_flags
+        lapack = spec['lapack'].lapack_libs.ld_flags
         if '@4.5.1' in spec:
             # 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
diff --git a/var/spack/repos/builtin/packages/sundials/package.py b/var/spack/repos/builtin/packages/sundials/package.py
index 7582954ab1223437580320e39384441aada8aa0c..6ee247b7ea80042c9210b883264ca8e486ecb849 100644
--- a/var/spack/repos/builtin/packages/sundials/package.py
+++ b/var/spack/repos/builtin/packages/sundials/package.py
@@ -31,7 +31,7 @@ class Sundials(Package):
     Solvers)"""
 
     homepage = "http://computation.llnl.gov/casc/sundials/"
-    url      = "http://computation.llnl.gov/projects/sundials-suite-nonlinear-differential-algebraic-equation-solvers/download/sundials-2.6.2.tar.gz"
+    url = "http://computation.llnl.gov/projects/sundials-suite-nonlinear-differential-algebraic-equation-solvers/download/sundials-2.6.2.tar.gz"
 
     version('2.6.2', '3deeb0ede9f514184c6bd83ecab77d95')
 
@@ -79,9 +79,9 @@ def install(self, spec, prefix):
         if '+lapack' in spec:
             cmake_args.extend([
                 '-DLAPACK_ENABLE=ON',
-                '-DLAPACK_LIBRARIES={0};{1}'.format(
-                    spec['lapack'].lapack_shared_lib,
-                    spec['blas'].blas_shared_lib
+                '-DLAPACK_LIBRARIES={0}'.format(
+                    (spec['lapack'].lapack_libs +
+                     spec['blas'].blas_libs).joined(';')
                 )
             ])
         else:
@@ -113,7 +113,7 @@ def install(self, spec, prefix):
             elif '+pthread' in spec:
                 cmake_args.append('-DSUPERLUMT_THREAD_TYPE=Pthread')
             else:
-                msg  = 'You must choose either +openmp or +pthread when '
+                msg = 'You must choose either +openmp or +pthread when '
                 msg += 'building with SuperLU_MT'
                 raise RuntimeError(msg)
         else:
diff --git a/var/spack/repos/builtin/packages/superlu-dist/package.py b/var/spack/repos/builtin/packages/superlu-dist/package.py
index 85b7f689d0f805e43e708adc9f0c55e6aa1b9f3a..a29b74bf0848621e991ad390c50343a067870655 100644
--- a/var/spack/repos/builtin/packages/superlu-dist/package.py
+++ b/var/spack/repos/builtin/packages/superlu-dist/package.py
@@ -46,15 +46,14 @@ class SuperluDist(Package):
     depends_on('metis@5:')
 
     def install(self, spec, prefix):
+        lapack_blas = spec['lapack'].lapack_libs + spec['blas'].blas_libs
         makefile_inc = []
         makefile_inc.extend([
             'PLAT         = _mac_x',
             'DSuperLUroot = %s' % self.stage.source_path,
             'DSUPERLULIB  = $(DSuperLUroot)/lib/libsuperlu_dist.a',
             'BLASDEF      = -DUSE_VENDOR_BLAS',
-            'BLASLIB      = %s %s' %
-                (to_link_flags(spec['lapack'].lapack_shared_lib),
-                 to_link_flags(spec['blas'].blas_shared_lib)),
+            'BLASLIB      = %s' % lapack_blas.ld_flags,
             'METISLIB     = -L%s -lmetis' % spec['metis'].prefix.lib,
             'PARMETISLIB  = -L%s -lparmetis' % spec['parmetis'].prefix.lib,
             'FLIBS        =',
diff --git a/var/spack/repos/builtin/packages/superlu/package.py b/var/spack/repos/builtin/packages/superlu/package.py
index c634c1d1ba690901fd17b87bfcfdb39f7cdea6f4..d9cff650b67ec0c748a6435b5b363925d6a562a4 100644
--- a/var/spack/repos/builtin/packages/superlu/package.py
+++ b/var/spack/repos/builtin/packages/superlu/package.py
@@ -42,7 +42,7 @@ def install(self, spec, prefix):
             '-DCMAKE_POSITION_INDEPENDENT_CODE=ON',
             # BLAS support
             '-Denable_blaslib=OFF',
-            '-DBLAS_blas_LIBRARY={0}'.format(spec['blas'].blas_shared_lib)
+            '-DBLAS_blas_LIBRARY={0}'.format(spec['blas'].blas_libs.joined())
         ]
 
         cmake_args.extend(std_cmake_args)
diff --git a/var/spack/repos/builtin/packages/trilinos/package.py b/var/spack/repos/builtin/packages/trilinos/package.py
index 3a88f673402f98ceb7cd83ea1572940cbda2075f..716d8f8eb6221246a74c7f50d9de56e700a5026b 100644
--- a/var/spack/repos/builtin/packages/trilinos/package.py
+++ b/var/spack/repos/builtin/packages/trilinos/package.py
@@ -132,6 +132,8 @@ def install(self, spec, prefix):
 
         mpi_bin = spec['mpi'].prefix.bin
         # Note: -DXYZ_LIBRARY_NAMES= needs semicolon separated list of names
+        blas = spec['blas'].blas_libs
+        lapack = spec['lapack'].lapack_libs
         options.extend([
             '-DTrilinos_ENABLE_ALL_PACKAGES:BOOL=ON',
             '-DTrilinos_ENABLE_ALL_OPTIONAL_PACKAGES:BOOL=ON',
@@ -145,12 +147,10 @@ def install(self, spec, prefix):
             '-DTPL_ENABLE_MPI:BOOL=ON',
             '-DMPI_BASE_DIR:PATH=%s' % spec['mpi'].prefix,
             '-DTPL_ENABLE_BLAS=ON',
-            '-DBLAS_LIBRARY_NAMES=%s' % to_lib_name(
-                spec['blas'].blas_shared_lib),
+            '-DBLAS_LIBRARY_NAMES=%s' % ';'.join(blas.names),
             '-DBLAS_LIBRARY_DIRS=%s' % spec['blas'].prefix.lib,
             '-DTPL_ENABLE_LAPACK=ON',
-            '-DLAPACK_LIBRARY_NAMES=%s' % to_lib_name(
-                spec['lapack'].lapack_shared_lib),
+            '-DLAPACK_LIBRARY_NAMES=%s' % ';'.join(lapack.names),
             '-DLAPACK_LIBRARY_DIRS=%s' % spec['lapack'].prefix.lib,
             '-DTrilinos_ENABLE_EXPLICIT_INSTANTIATION:BOOL=ON',
             '-DTrilinos_ENABLE_CXX11:BOOL=ON',
diff --git a/var/spack/repos/builtin/packages/wannier90/package.py b/var/spack/repos/builtin/packages/wannier90/package.py
index 189e568cdc6909bad0ced619d4e940aeaf7cac25..119d2cf76956b5619982525250c7342950ee9e15 100644
--- a/var/spack/repos/builtin/packages/wannier90/package.py
+++ b/var/spack/repos/builtin/packages/wannier90/package.py
@@ -47,13 +47,12 @@ class Wannier90(Package):
 
     def install(self, spec, prefix):
 
+        lapack = self.spec['lapack'].lapack_libs
+        blas = self.spec['blas'].blas_libs
         substitutions = {
             '@F90': spack_fc,
             '@MPIF90': self.spec['mpi'].mpifc,
-            '@LIBS': ' '.join([
-                self.spec['lapack'].lapack_shared_lib,
-                self.spec['lapack'].blas_shared_lib
-            ])
+            '@LIBS': (lapack + blas).joined()
         }
         #######
         # TODO : this part is replicated in PEXSI