1

I am having difficulty using a header-only library (Eigen) in my CMake project. When i take off all the portion related to Eigen library it compiles, but not sure how to build with (Eigen). Note that Eigen has a CmakeLists.txt in Eigen folder, and it has /src folder having (*.h and *.cpp) related to Matrix operation etc...

The structure of my program is as follow

Myproject (folder) is composed of :

  • CmakeLists.txt
  • /Build
  • /Source

The Source folder has bunch of my files (*.h and *.cpp) and the /Eigen (folder).

what i did is :

FIND_PACKAGE(PkgConfig REQUIRED)
PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0)
LIST(APPEND CMAKE_CXX_FLAGS 
    "-std=c++0x
     -pthread 
     ${CMAKE_CXX_FLAGS} 
     -g 
    -Wall -Wextra ")

ADD_LIBRARY(Eigen ${CMAKE_SOURCE_DIR}/Eigen)
TARGET_INCLUDE_DIRECTORIES(Eigen INTERFACE
 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
 $<INSTALL_INTERFACE:include/Eigen>
)

INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS})
ADD_DEFINITIONS(${GTK3_CFLAGS_OTHERS})
INCLUDE_DIRECTORIES(include)
ADD_LIBRARY(RTT 
        Def.cpp 
        Def.h       
        krnel.cpp 
        krnel.h 
        Mesh.cpp 
        Mesh.h 
        Mcom.cpp 
        Mcom.h 
        timer.h 
        Identifier.h)       

ADD_EXECUTABLE(Rdrtst main.cpp)
TARGET_LINK_LIBRARIES(Rdrtst RTT ${GTK3_LIBRARIES} Eigen)

When i cd to /Build and type (Cmake ../Source )

I get the following :

[/../Build]$ cmake ../Source
-- Configuring done
CMake Error: Cannot determine link language for target "Eigen".
CMake Error: CMake can not determine linker language for target:Eigen
-- Generating done
-- Build files have been written to: /../../MyProject/Build

The eigen folder has the CMakeLists.txt with the following content :

include(RegexUtils)
test_escape_string_as_regex()

file(GLOB Eigen_directory_files "*")

escape_string_as_regex(ESCAPED_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")

foreach(f ${Eigen_directory_files})
  if(NOT f MATCHES "\\.txt" AND NOT f MATCHES "${ESCAPED_CMAKE_CURRENT_SOURCE_DIR}/[.].+" AND NOT f MATCHES "${ESCAPED_CMAKE_CURRENT_SOURCE_DIR}/src")
    list(APPEND Eigen_directory_files_to_install ${f})
  endif()
endforeach(f ${Eigen_directory_files})

install(FILES
  ${Eigen_directory_files_to_install}
  DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen COMPONENT Devel
  )

add_subdirectory(src)
Sam Gomari
  • 733
  • 4
  • 13
  • 37

3 Answers3

1

You are trying to include Eigen as a compiled library. However, as you have stated, Eigen is really a header only library and does not need to be compiled, just included. There should be no .cpp files at all.

Remove the line

ADD_LIBRARY(Eigen ${CMAKE_SOURCE_DIR}/Eigen)

as that is meant for static or shared libraries. Now that you're not building Eigen, you can remove the line

TARGET_INCLUDE_DIRECTORIES(Eigen ...

The Eigen CMakeLists file really just copies the Eigen header files to an include directory and doesn't compile anything. See this link for an example of how to use Eigen with CMake.

Avi Ginsburg
  • 10,323
  • 3
  • 29
  • 56
  • I did exactly what's instructed in the link, but Cmake output (cmake .. in the build folder) says "Could not find a package configuration file provided by Eigen" . When i downloaded from the Eigen websites the library, i used only the Eigen folder of the unzipped downloaded folder in my Source directory, i used a file FindEigen.cmake and copied it in a cmake folder that i created under the Source folder (the same folder having the Eigen folder). Obviously i'm missing something – Sam Gomari Feb 02 '15 at 14:46
  • Can somebody rescue with this ? – Sam Gomari Feb 02 '15 at 19:08
  • @SamGomari [Less verbose](http://stackoverflow.com/a/28306976/2899559) than what I said, but essentially the same. Stop trying to build Eigen. It just needs to be included. Make sure it's in one of the include paths. – Avi Ginsburg Feb 03 '15 at 20:18
  • say Eigen folder (has /src folder) which is included in my /Source folder, i did this , it didn't work INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/Eigen) – Sam Gomari Feb 03 '15 at 21:14
  • : Should i delete the CMakeLists.txt file that's in the Eigen folder – Sam Gomari Feb 03 '15 at 21:14
  • @SamGomari You have a line like `#included "Eigen/Core"` which in turn includes files in the /src directory. Don't place the /src in your /Source, place the entire Eigen directory. – Avi Ginsburg Feb 04 '15 at 03:53
  • Sounds good , appreciated... but while Cmake doesn't complain, make does , it complains with the following error: Build files have been written to: /home/rgn/Documents/Backup/ps/ral/Build Source/CMakeFiles/RTT.dir/flags.make:6: *** recipe commences before first target. Stop. make[1]: *** [Source/CMakeFiles/RTT.dir/all] Error 2 make: *** [all] Error 2 – Sam Gomari Feb 04 '15 at 07:36
  • @SamGomari Try looking at the [error messages](https://www.gnu.org/software/make/manual/html_node/Error-Messages.html) make can give. [These](http://stackoverflow.com/questions/2912689/commence-before-first-target-stop-error) [questions](http://stackoverflow.com/questions/7783920/gnu-make-yields-commands-commence-before-first-target-error) might also be of help. – Avi Ginsburg Feb 04 '15 at 07:52
  • the make is generated by Cmake, and it doesn't look it has issues. However, the make itself contains some unfamiliar (far from being an expert in make) code for compilation. BTW, to include Eigen , i used NCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/Eigen) , is this correct ? – Sam Gomari Feb 04 '15 at 14:39
  • @SamGomari I'm not quite sure what your project looks like, so my only recommendation is to start with a 'Hello world' [example](http://eigen.tuxfamily.org/dox/GettingStarted.html) before using (C)make. Try the one on the Eigen site. Note that [here](http://eigen.tuxfamily.org/dox/GettingStarted.html#GettingStartedCompiling) the `-I /path/to/eigen/` should be something like `-I /sourcePath/` and not `-I /sourcePath/Eigen`. – Avi Ginsburg Feb 09 '15 at 06:44
  • @ AviGinsburg i only found a fix around it, but not the solution, what did for fix, is copy the Eigen folder to /usr/local/include ....then cmake works (out source build). But what i wanted to do is use the Eigen folder (that has all *.h and resides in /Source) instead of it "like installed" . Can you help with this , pls ? – Sam Gomari Feb 10 '15 at 16:41
  • @SamGomari Did you ever add `INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})` to your cmake file? – Avi Ginsburg Feb 11 '15 at 06:48
  • @ AviGinsburg , i removed the Eigen folder from /usr/local/include and added the `INCLUDE_DIRECTORIES($(CMAKE_SOURCE_DIR})` to the CMakeLists.txt in the /Source folder. But it didn't work.... ????? – Sam Gomari Feb 11 '15 at 21:58
  • @SamGomari After trying it myself (and reading [this](http://stackoverflow.com/a/26741728/2899559) answer), I found the issue to be: `INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})` should be replaced with `INCLUDE_DIRECTORIES("./")`. Kind of annoying. Let me know if that worked. – Avi Ginsburg Feb 12 '15 at 08:28
1

You just need the correct path in INCLUDE_DIRECTORIES (also make sure to include the correct folder or subfolder, depending if in your c++ file you are using #include Eigen/something.h or #include something.h ) So, remove the lines ADD_LIBRARY(Eigen ... and TARGET_LINK_LIBRARIES Eigen.

For troubleshooting, you can also include the absolute path of the Eigen folder , and then when you get it working, transform it in a relative path

lib
  • 2,918
  • 3
  • 27
  • 53
0

This is a late answer, but it might help someone else. These are the precise steps I took in order to include the Eigen lib into my project with CMake files.

First, assuming your project already include the Eigen sub-directory, e.g., at src/third_party/eigen, copy-paste FindEigen3.cmake file into src/cmake.

Second, you might want to edit the FindEigen3.cmake to include your own location hints that you will provide from you CMake file. For example:

find_path( EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
    HINTS "${EIGEN3_ROOT}" "$ENV{EIGEN3_ROOT_DIR}" "${EIGEN3_INCLUDE_DIR_HINTS}"
    # ... leave the rest as it is
)

Third, "include" the Eigen from your CMakeLists.txt by specifying the hint EIGEN3_ROOT and the location of the FindEigen3.cmake file:

message(STATUS "Trying to include Eigen library")
set(EIGEN3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/eigen)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(Eigen3 3.2.0 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
message(STATUS "EIGEN: " ${EIGEN3_VERSION} " (internal)")

Forth, start using Eigen from within your project:

#include <Eigen/Dense>
using Eigen::MatrixXd;
// ...
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
vicrucann
  • 1,703
  • 1
  • 24
  • 34