Blog

Fixing Psi4's Eigen include path mismatch

April 30, 2026

While trying to build Psi4 against an Eigen3 installation managed by Spack, CMake configuration succeeded — Found Eigen3 showed up in the output — but the build failed as soon as it hit the first compile that needed an Eigen header. The compiler was looking for eigen3/Eigen/Core underneath the include directory CMake had handed it, and the resulting path had a doubled eigen3/eigen3/... that didn't exist on disk.

The cause is a mismatch between how Psi4 includes Eigen and how Eigen's CMake config exports its include directory. Psi4's source uses #include <eigen3/Eigen/Core> — with the eigen3/ prefix baked into the include statement. Eigen's Eigen3Config.cmake exports <prefix>/include/eigen3 as the include directory, expecting consumers to write #include <Eigen/Core> (no prefix). The two stack: CMake adds the eigen3/-suffixed include dir, the source asks for an eigen3/-prefixed path, and the compiler dutifully concatenates them.

The fix is to also put the parent directory — the one above eigen3/ — on the include path, so the eigen3/-prefixed includes can resolve. The cleanest way is to push it through CMAKE_CXX_FLAGS:

-DCMAKE_CXX_FLAGS="-I$VIEW/include"

Where $VIEW is the Spack environment's .spack-env/view directory. Folded into the full invocation:

cmake -S . -B build \
  -DPython_ROOT_DIR=$VIEW/bin \
  -DCMAKE_INSTALL_PREFIX=$HOME/.local \
  -DBLAS_TYPE=OPENBLAS -DLAPACK_TYPE=OPENBLAS \
  -DEigen3_DIR=$VIEW/share/eigen3/cmake \
  -DCMAKE_PREFIX_PATH=$VIEW \
  -DCMAKE_CXX_FLAGS="-I$VIEW/include"

Wipe build/ before re-running — the failed configure is cached, and CMake will happily reuse the bad state otherwise.

A couple of notes. The same flag clears up the same error in bundled subprojects (libint2, etc.) since it's appended to the global compile flags rather than scoped to Psi4's own targets. A symlink hack also works — ln -s . eigen3 inside the eigen3/ include dir, so the doubled prefix happens to resolve — but that mutates the Spack view, which I'd rather leave alone. Longer term this is really a Psi4 bug; <eigen3/Eigen/Core> isn't the portable spelling Eigen recommends. The CXX flag is the workaround most people land on.