1

I am trying to compile a code snippet with Eigen using CMake, but CMake seems to have trouble finding the correct path, even if the source code is there.

This is my CMakeLists.txt file.

cmake_minimum_required(VERSION 3.14.2)
project(test)

# set default build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()


find_package(OpenCV 3 REQUIRED)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)

include_directories(
        include
        ${OpenCV_INCLUDE_DIRS}
        ${EIGEN3_INCLUDE_DIR}
)


add_executable(playground playground.cpp)
target_link_libraries(playground ${OpenCV_LIBS} Eigen3::Eigen)

This is how I import headers in playground.cpp:

#include <iostream>
#include <vector>
#include <map>
#include <math.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>
#include <Eigen>

My Eigen is installed under /usr/include/eigen3, here is the directory structure:

yuqiong@yuqiong-G7-7588:/usr/include/eigen3$ ls
Eigen  signature_of_eigen3_matrix_library  unsupported

So the correct path to Eigen library is /usr/include/eigen3/Eigen.

However, when I run cmake .. and then make for the aforementioned CMakeLists.txt file, with the -LH flag, CMake complains it can't find Eigen. This is the path it thinks where Eigen is:

yuqiong@yuqiong-G7-7588:/media/yuqiong/DATA/vignetting/catkin_ws/src/vig2/src/build$ cmake -LH ..
-- Configuring done
-- Generating done
-- Build files have been written to: /media/yuqiong/DATA/vignetting/catkin_ws/src/vig2/src/build
-- Cache values
// Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ...
CMAKE_BUILD_TYPE:STRING=

// Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local

// The directory containing a CMake configuration file for Eigen3.
Eigen3_DIR:PATH=/usr/local/share/eigen3/cmake

// The directory containing a CMake configuration file for OpenCV.
OpenCV_DIR:PATH=/opt/ros/kinetic/share/OpenCV-3.3.1-dev

This is the structure of the folder where it think Eigen is:

yuqiong@yuqiong-G7-7588:/usr/local/share/eigen3$ tree
.
└── cmake
    ├── Eigen3Config.cmake
    ├── Eigen3ConfigVersion.cmake
    ├── Eigen3Targets.cmake
    └── UseEigen3.cmake

I am confused why CMake has such behavior? How can I let it find the correct path of Eigen in this case?

All this environment set-ups are so tricky to get it right...

yuqli
  • 4,461
  • 8
  • 26
  • 46
  • 1
    Are you sure `#include ` even refers to an actual file? Maybe try `#include ` instead? – lubgr Sep 10 '19 at 06:46
  • @lubgr I'm going to say something stupid, but do we need to refer to an actual file when doing `#include`? For some libaries we just use `#include `> – yuqli Sep 10 '19 at 06:49
  • @lubgr also I just deleted the path I thought was wrong --- the path full of `cmake` files. Now CMake can't find anything. I'll re-download `Eigen` and try your suggestion. Thanks! – yuqli Sep 10 '19 at 06:50
  • 1
    Not a stupid question. You can only `#include` files, not directories. – lubgr Sep 10 '19 at 06:51
  • 1
    @yuqli string is an actual file with that name, located with the rest of the c++ standard library. On ubuntu it's commonly under /usr/include/c++ subdirectories. Not much magic to preprocessing, just textual substitutions.. – Yuri Feldman Sep 10 '19 at 07:02
  • There is no problem with CMake. You have Eigen **include directory** `/usr/include`, where it have installed the header files. Note, include directory doesn't have `eigen3` component at the end. So you need to use appropriate `#include` statements. As for `Eigen3_DIR` variable in the cache (equal to `/usr/local/share/eigen3/cmake`), it denotes the directory with **configuration files**. It is not a problem that this directory differs from the include directory: these directories are used for different purposes.(However, I find it strange that one directory contains `share` but another doesn't) – Tsyvarev Sep 10 '19 at 07:42
  • 1
    Oh, `but CMake seems to have trouble finding the correct path, even if the **source** code is there.` - Have you just placed Eigen **source files** under `/usr/include/eigen3`? Because this is not an **installation**, it has no `Eigen3Config.cmake` file which helps `find_package` to locate it. Instead, you need to get `FindEigen3.cmake` script somewhere, and hint it about this directory (e.g. with `CMAKE_LIBRARY_PATH` variable). But it is simpler to **install** Eigen (with `cmake`, `make`, `make install`), so `find_package` will be able to find it automatically. – Tsyvarev Sep 10 '19 at 08:10

1 Answers1

1

Thanks for the comments above. I think the issue might be the Eigen team changed their directory structure somehow between different versions, and the old include path does not work anymore.

The solution for me was to change #include <Eigen/Dense> to #include <eigen3/Eigen/Dense>. After that g++ and CMake can find the path.

I did install Eigen following this official doc, which was why I was surprised the installation is still problematic.

This answer solved my problem.

This answer also solves the problem.

On another note, my CMake file was a bit messed up, with both include_directories and target_link_libraries.

yuqli
  • 4,461
  • 8
  • 26
  • 46