Repository: spack/spack

Issue:
Spack provides wrong path for include library
I am trying to setup my own package for Spack using a very simple C++ program:

```
// in test.cpp
#include <iostream>
#include <armadillo>

using namespace std;
using namespace arma;

int main()
{
	mat A = randu<mat>(4,5);
	mat B = randu<mat>(4,5);

	cout << A*B.t() << endl;

	return 0;
}
```

The program depends on the library Armadillo. I compile the program using CMake; here is my CMakeLists.txt file:

```
project(test)

# -----------------------------------------------------------------------------

# Require CMake 2.8.
cmake_minimum_required(VERSION 2.8)

# -----------------------------------------------------------------------------
# CMake policies.

# VERSION not allowed in project() unless CMP0048 is set to NEW.
cmake_policy(SET CMP0048 NEW)

# Allow creating targets with reserved names
# or which do not match the validity pattern.
cmake_policy(SET CMP0037 OLD)

# -----------------------------------------------------------------------------

find_package(Armadillo)

if(ARMADILLO_FOUND)
    list(APPEND OLIVE_DEFINITIONS "-DHAVE_ARMA")
    list(APPEND OLIVE_INCLUDE_DIRS "${ARMADILLO_INCLUDE_DIRS}")
else()
    MESSAGE(FATAL_ERROR "A library with Armadillo API is not found.")
endif()

# -----------------------------------------------------------------------------  

find_package(BLAS REQUIRED)

find_package(LAPACK REQUIRED)

if(LAPACK_FOUND)
    list(APPEND OLIVE_LIBRARIES ${LAPACK_LIBRARIES})
else()
    MESSAGE(FATAL_ERROR "A library with LAPACK API is not found.")
endif()
    
# -----------------------------------------------------------------------------  

# Preprocessor definitions.
foreach(OLIVE_DEFINITION ${OLIVE_DEFINITIONS})
    add_definitions(${OLIVE_DEFINITION})
endforeach()

# Include directories.
foreach(OLIVE_INCLUDE_DIR ${OLIVE_INCLUDE_DIRS})
    include_directories(${OLIVE_INCLUDE_DIR})
endforeach()

# Linker directories.
foreach(OLIVE_LIBRARY_DIR ${OLIVE_LIBRARY_DIRS})
    link_directories(${OLIVE_LIBRARY_DIR})
endforeach()

# Executable.
add_executable (test test.cpp)
target_link_libraries(test ${OLIVE_LIBRARIES})
```

Then I create a package using the `spack create` command:

```
from spack import *

class Olive(CMakePackage):

    homepage = "http://www.example.com"
    url      = "file:///home/chvillanuevap/Workspace/olive-1.0.0.tar.gz"

    version('1.0.0', '4d594401468e9a7766c2c2e0f1c0c4e2')

    depends_on('cmake', type='build')
    depends_on('armadillo')

    def cmake_args(self):
        args = []
        return args
```

When I run `spack install olive`, I get the following error:

```
Building CXX object CMakeFiles/test.dir/test.cpp.o
/home/chvillanuevap/Workspace/spack/lib/spack/env/gcc/g++   -DHAVE_ARMA -I/home/chvillanuevap/Workspace/spack/opt/spack/linux-ubuntu16-x86_64/gcc-5.4.0/armadillo-7.500.0-k7fwnukwvvyzgfxhyhhwwxjhaohmdmit/include  -O2 -g -DNDEBUG   -o CMakeFiles/test.dir/test.cpp.o -c /home/chvillanuevap/Workspace/spack/var/spack/stage/olive-1.0.0-io6llpqdxqohx457argmnsjqtq4fpmhr/olive/test.cpp
In file included from /home/chvillanuevap/Workspace/spack/opt/spack/linux-ubuntu16-x86_64/gcc-5.4.0/armadillo-7.500.0-k7fwnukwvvyzgfxhyhhwwxjhaohmdmit/include/armadillo:83:0,
                 from /home/chvillanuevap/Workspace/spack/var/spack/stage/olive-1.0.0-io6llpqdxqohx457argmnsjqtq4fpmhr/olive/test.cpp:2:
/home/chvillanuevap/Workspace/spack/opt/spack/linux-ubuntu16-x86_64/gcc-5.4.0/armadillo-7.500.0-k7fwnukwvvyzgfxhyhhwwxjhaohmdmit/include/armadillo_bits/include_superlu.hpp:91:53: fatal error: /home/chvillanuevap/Workspace/spack/opt/spack/1-ubuntu16-x86_64/gcc-5.4.0/superlu-5.2.1-lrqbalx6k6q6btuxmszymj7p5dal65d2/include/supermatrix.h: No such file or directory
```

Notice how the path for SuperLU (a dependency of Armadillo) says `1-ubuntu16-x86_64` for the architecture instead of the correct `linux-ubuntu16-x86_64`. Why does this happen?


Discussion:
Hi @chvillanuevap, I wrote the Armadillo package for Spack, noticed this exact same bug, contacted the developers, and this is what they have to say:

> Sorry, I won't have time to look into this.  I have too many things on my plate.
>
> You can always install Armadillo manually (see README.txt), and let the user link with SuperLU directly.  Or maybe the user doesn't even require SuperLU.

So basically, we're on our own. If you also contact the developer, perhaps they will notice that it is a common bug and actually do something about it? Or maybe not.

We speculated a bit about what could be causing this issue in #2061. It might be that there is some enum in Armadillo that sets linux to 1, darwin to 2, etc. As far as reproducing the problem, I have a feeling the same bug will occur if you try to build Armadillo and SuperLU outside of Spack as long as the word "linux" is in the installation directory name.

As for a solution, you can either try fixing the directory names manually in the header files or simply comment them out (what I ended up doing). I have no idea what the repurcusions of this are, so don't trust me too much. But the user I have who relies on Armadillo hasn't complained yet, so...

If we determine that either of those two hacks are sufficient, I could add them to Spack and run them after installation to automate the header file hacking.

Hope this helps!

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/armadillo/package.py b/var/spack/repos/builtin/packages/armadillo/package.py
--- a/var/spack/repos/builtin/packages/armadillo/package.py
+++ b/var/spack/repos/builtin/packages/armadillo/package.py
@@ -33,6 +33,9 @@ class Armadillo(CMakePackage):
     homepage = "http://arma.sourceforge.net/"
     url = "http://sourceforge.net/projects/arma/files/armadillo-7.200.1.tar.xz"
 
+    version('8.100.1', 'd9762d6f097e0451d0cfadfbda295e7c')
+    version('7.950.1', 'c06eb38b12cae49cab0ce05f96147147')
+    # NOTE: v7.900.1 download url seems broken is no v7.950.1?
     version('7.900.1', '5ef71763bd429a3d481499878351f3be')
     version('7.500.0', '7d316fdf3c3c7ea92b64704180ae315d')
     version('7.200.2', 'b21585372d67a8876117fd515d8cf0a2')
@@ -47,11 +50,17 @@ class Armadillo(CMakePackage):
     depends_on('superlu@5.2:')
     depends_on('hdf5', when='+hdf5')
 
+    # Adds an `#undef linux` to prevent preprocessor expansion of include
+    # directories with `linux` in them getting transformed into a 1.
+    # E.g. `/path/linux-x86_64/dir` -> `/path/1-x86_64/dir` if/when a linux
+    # platform's compiler is adding `#define linux 1`.
+    patch('undef_linux.patch', when='platform=linux')
+
     def cmake_args(self):
         spec = self.spec
 
         arpack = find_libraries('libarpack', root=spec[
-                                'arpack-ng'].prefix.lib, shared=True)
+                                'arpack-ng'].prefix.lib64, shared=True)
         superlu = find_libraries('libsuperlu', root=spec[
                                  'superlu'].prefix, shared=False, recurse=True)
         return [


Test patch: