Repository: spack/spack

Issue:
OpenBLAS post-installation tests fail
```
==> '/Users/Adam/spack/lib/spack/env/cc' '-c' '-I/Users/Adam/spack/opt/spack/darwin-sierra-x86_64/clang-8.1.0-apple/openblas-0.2.20-dravpszbgy6i7a6l25xmvnnsyqlrnqq7/include ' '/Users/Adam/spack/var/spack/repos/builtin/packages/openblas/test_cblas_dgemm.c'
/Users/Adam/spack/var/spack/repos/builtin/packages/openblas/test_cblas_dgemm.c:1:10: fatal error: 'cblas.h' file not found
#include <cblas.h>
         ^
1 error generated.
```
If I skip the tests, `cblas.h` is correctly installed:
```
$ ls /Users/Adam/spack/opt/spack/darwin-sierra-x86_64/clang-8.1.0-apple/openblas-0.2.20-dravpszbgy6i7a6l25xmvnnsyqlrnqq7/include/
cblas.h            lapacke.h          lapacke_mangling.h openblas_config.h
f77blas.h          lapacke_config.h   lapacke_utils.h
```
Not sure why it can't find it.


Discussion:
Is it, by any chance, running before installation?
Nope, it was definitely post-installation. I saw the "generating cblas.h file in <prefix>/include directory" message.
weird.... Compiler wrappers won't have the prefix of the package being installed, but we add it manually via `-L`, IIRC. So this should be ok.
Hmm, I wonder if it's because of that space at the end of the `-I` line. That's the only thing I can think of.
Removing the space at the end of the `-I` line worked! I'll write up a PR to fix this.

Resolving patch:
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -549,7 +549,7 @@ def find(root, files, recurse=True):
             if True descends top-down from the root. Defaults to True.
 
     Returns:
-        :func:`list`: The files that have been found
+        list of strings: The files that have been found
     """
     if isinstance(files, six.string_types):
         files = [files]
@@ -618,9 +618,14 @@ def directories(self):
         """Stable de-duplication of the directories where the files reside.
 
         >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/libc.a'])
-        >>> assert l.directories == ['/dir1', '/dir2']
+        >>> l.directories
+        ['/dir1', '/dir2']
         >>> h = HeaderList(['/dir1/a.h', '/dir1/b.h', '/dir2/c.h'])
-        >>> assert h.directories == ['/dir1', '/dir2']
+        >>> h.directories
+        ['/dir1', '/dir2']
+
+        Returns:
+            list of strings: A list of directories
         """
         return list(dedupe(
             os.path.dirname(x) for x in self.files if os.path.dirname(x)
@@ -631,18 +636,27 @@ 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']
+        >>> l.basenames
+        ['liba.a', 'libb.a']
         >>> h = HeaderList(['/dir1/a.h', '/dir2/b.h', '/dir3/a.h'])
-        >>> assert h.basenames == ['a.h', 'b.h']
+        >>> h.basenames
+        ['a.h', 'b.h']
+
+        Returns:
+            list of strings: A list of base-names
         """
         return list(dedupe(os.path.basename(x) for x in self.files))
 
     @property
     def names(self):
-        """Stable de-duplication of file names in the list
+        """Stable de-duplication of file names in the list without extensions
 
         >>> h = HeaderList(['/dir1/a.h', '/dir2/b.h', '/dir3/a.h'])
-        >>> assert h.names == ['a', 'b']
+        >>> h.names
+        ['a', 'b']
+
+        Returns:
+            list of strings: A list of files without extensions
         """
         return list(dedupe(x.split('.')[0] for x in self.basenames))
 
@@ -688,6 +702,11 @@ def __init__(self, files):
 
     @property
     def headers(self):
+        """Stable de-duplication of the headers.
+
+        Returns:
+            list of strings: A list of header files
+        """
         return self.files
 
     @property
@@ -695,7 +714,11 @@ def include_flags(self):
         """Include flags
 
         >>> h = HeaderList(['/dir1/a.h', '/dir1/b.h', '/dir2/c.h'])
-        >>> assert h.cpp_flags == '-I/dir1 -I/dir2'
+        >>> h.include_flags
+        '-I/dir1 -I/dir2'
+
+        Returns:
+            str: A joined list of include flags
         """
         return ' '.join(['-I' + x for x in self.directories])
 
@@ -706,7 +729,11 @@ def macro_definitions(self):
         >>> h = HeaderList(['/dir1/a.h', '/dir1/b.h', '/dir2/c.h'])
         >>> h.add_macro('-DBOOST_LIB_NAME=boost_regex')
         >>> h.add_macro('-DBOOST_DYN_LINK')
-        >>> assert h.macro_definitions == '-DBOOST_LIB_NAME=boost_regex -DBOOST_DYN_LINK'  # noqa
+        >>> h.macro_definitions
+        '-DBOOST_LIB_NAME=boost_regex -DBOOST_DYN_LINK'
+
+        Returns:
+            str: A joined list of macro definitions
         """
         return ' '.join(self._macro_definitions)
 
@@ -715,13 +742,26 @@ def cpp_flags(self):
         """Include flags + macro definitions
 
         >>> h = HeaderList(['/dir1/a.h', '/dir1/b.h', '/dir2/c.h'])
+        >>> h.cpp_flags
+        '-I/dir1 -I/dir2'
         >>> h.add_macro('-DBOOST_DYN_LINK')
-        >>> assert h.macro_definitions == '-I/dir1 -I/dir2 -DBOOST_DYN_LINK'
+        >>> h.cpp_flags
+        '-I/dir1 -I/dir2 -DBOOST_DYN_LINK'
+
+        Returns:
+            str: A joined list of include flags and macro definitions
         """
-        return self.include_flags + ' ' + self.macro_definitions
+        cpp_flags = self.include_flags
+        if self.macro_definitions:
+            cpp_flags += ' ' + self.macro_definitions
+        return cpp_flags
 
     def add_macro(self, macro):
-        """Add a macro definition"""
+        """Add a macro definition
+
+        Parameters:
+            macro (str): The macro to add
+        """
         self._macro_definitions.append(macro)
 
 
@@ -775,6 +815,11 @@ class LibraryList(FileList):
 
     @property
     def libraries(self):
+        """Stable de-duplication of library files.
+
+        Returns:
+            list of strings: A list of library files
+        """
         return self.files
 
     @property
@@ -782,7 +827,11 @@ 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']
+        >>> l.names
+        ['a', 'b']
+
+        Returns:
+            list of strings: A list of library names
         """
         return list(dedupe(x.split('.')[0][3:] for x in self.basenames))
 
@@ -791,7 +840,11 @@ 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'
+        >>> l.search_flags
+        '-L/dir1 -L/dir2'
+
+        Returns:
+            str: A joined list of search flags
         """
         return ' '.join(['-L' + x for x in self.directories])
 
@@ -800,7 +853,11 @@ 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'
+        >>> l.link_flags
+        '-la -lb'
+
+        Returns:
+            str: A joined list of link flags
         """
         return ' '.join(['-l' + name for name in self.names])
 
@@ -809,7 +866,11 @@ def ld_flags(self):
         """Search flags + link flags
 
         >>> l = LibraryList(['/dir1/liba.a', '/dir2/libb.a', '/dir1/liba.so'])
-        >>> assert l.search_flags == '-L/dir1 -L/dir2 -la -lb'
+        >>> l.ld_flags
+        '-L/dir1 -L/dir2 -la -lb'
+
+        Returns:
+            str: A joined list of search flags and link flags
         """
         return self.search_flags + ' ' + self.link_flags
 


Test patch: