CMake INCLUDE_DIRS variable doesn't contain the right path - cmake

I have a project that I'm trying to compile on a Linux-based HPC system using CMake. The project relies on the Eigen3 package, so I specified the path to the Eigen3 config file in the CMAKE_PREFIX_PATH variable as below (an excerpt from my CMakeLists.txt file).
set(CMAKE_PREFIX_PATH "/gpfs/loomis/apps/avx/software/Eigen/3.3.7")
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
message(STATUS ${EIGEN3_INCLUDE_DIR})
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
Note: the directory # CMAKE_PREFIX_PATH contains the installation tree /share/eigen3/cmake, where the config file is located. The CMAKE_PREFIX_PATH also contains an /include directory. So find_package shouldn't have any difficulty retrieving Eigen3's location, from my understanding.
However, the result of the message command is:
-- /gpfs/loomis/apps/avx/software/Eigen/3.3.7//gpfs/loomis/apps/avx/software/Eigen/3.3.7/include
not /gpfs/loomis/apps/avx/software/Eigen/3.3.7/include as desired. So include_directories isn't actually passing the correct package path. How do I fix this?
Thank you in advance!

Related

How do I link SDL2 using CMake?

I used the .cmake files from https://github.com/brendan-w/collector/tree/master/cmake, and I put them in the same directory as my CMakeLists.txt, then I used the code:
set(CMAKE_MODULE_PATH FindSDL2.cmake FindSDL2_image.cmake)
find_package(SDL2 REQUIRED)
but I'm getting the error:
CMake Error at CMakeLists.txt:26 (find_package):
By not providing "FindSDL2.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "SDL2", but
CMake did not find one.
Could not find a package configuration file provided by "SDL2" with any of
the following names:
SDL2Config.cmake
sdl2-config.cmake
Add the installation prefix of "SDL2" to CMAKE_PREFIX_PATH or set
"SDL2_DIR" to a directory containing one of the above files. If "SDL2"
provides a separate development package or SDK, be sure it has been
installed.
The CMAKE_MODULE_PATH variable contains a list of paths to your CMake modules (FindSDL2.cmake, FindSDL2_image.cmake, etc. are your modules). You should append the full path to these modules on your machine to this variable:
list(APPEND CMAKE_MODULE_PATH /path/to/your/SDL2/modules)
find_package(SDL2 REQUIRED)
More recently, SDL2 provides a CMake configuration file, that can be used to help CMake find your SDL2 installation. Your error message explicitly describes this, and states the package configuration names (SDL2Config.cmake and sdl2-config.cmake). To allow CMake to find SDL2 using this method instead, use CMAKE_PREFIX_PATH:
list(APPEND CMAKE_PREFIX_PATH /path/to/your/SDL2/config/files)
find_package(SDL2 REQUIRED)
Once CMake finds the package, it will define some SDL2_* variables that can be used in your CMake project:
...
add_executable(MySDL2Executable main.cpp)
include_directories(MySDL2Executable PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(MySDL2Executable PRIVATE ${SDL2_LIBRARIES})
Note, these variable names may differ based on your SDL2 version. Consult the CMake module files or package configuration files themselves for the list of SDL2_* variable names that are defined.

Issues Configuring CLion, Cmake, and SFML

I am currently trying to configure my Cmake file to include the SFML libraries.
My CMakeLists.txt. I'm using OS X Yosemite if that matter at all.
cmake_minimum_required(VERSION 2.8.4)
project(SFMLTest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=lib++")
set(SOURCE_FILES main.cpp)
add_executable(SFMLTest ${SOURCE_FILES})
#Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Users/Home/SFML-2.2-osx-clang-universal/cmake/Modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2.2 REQUIRED system window graphics network audio)
if (SFML_FOUND)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(${main.cpp} ${SFML_Libraries})
endif()
and the error I am currently getting is
Error:By not providing "FindSFML.cmake" in CMAKE_MODULE_PATH this project has asked
CMake to find a package configuration file provided by "SFML", but CMake did notfind one.
Could not find a package configuration file provided by "SFML" (requested version 2.2)
with any of the following names:
SFMLConfig.cmake sfml-config.cmake
Add the installation prefix of "SFML" to CMAKE_PREFIX_PATH or
set "SFML_DIR"to a directory containing one of the above files.
If "SFML" provides a separate development package or SDK, be sure it has been installed.
my FindSFML.cmake is located at
/Users/Home/SFML-2.2-osx-clang-universal/cmake/Modules
Your question says the full path to the find module is
/Users/Home/SFML-2.2-osx-clang-universal/cmake/Modules/FindSFML.cmake
But you're adding ${CMAKE_SOURCE_DIR}/Users/Home/SFML-2.2-osx-clang-universal/cmake/Modules to your CMAKE_MODULE_PATH. ${CMAKE_SOURCE_DIR} is the absolute path to the directory containing the top-level CMakeLists.txt file. If you know the absolute path to the module file you want to include, you should most certainly not prefix it with the source tree path. Just change the line to this:
set(CMAKE_MODULE_PATH "/Users/Home/SFML-2.2-osx-clang-universal/cmake/Modules" ${CMAKE_MODULE_PATH})
Also note that since you have REQUIRED specified among the arguments to find_package(), CMake will terminate with an error if the package cannot be found. Having if(SFML_FOUND) is therefore pointless.
This solution is perfect: https://oxymeos.shost.ca/article.php?about=work_with_the_SFML_in_CLion. I recommend it! It worked for me
You create a folder named "cmake_modules" at the root of the project and you place in this folder the "FindSFML.cmake" file (on Windows and Mac OS X: "[Your_SFML Location]/cmake/Modules/FindSFML.cmake", and on Linux: "[Your_SFML_location]/share/SFML/cmake/Modules/FindSFML.cmake".
The CMake configuration file (CMakeLists.txt) is then presented in this form:
cmake_minimum_required(VERSION 3.7)
project([your_project])
# Define the source and the executable
set(EXECUTABLE_NAME "[name_executable]")
add_executable(${EXECUTABLE_NAME} [project_files])
# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}" ${CMAKE_MODULE_PATH})
find_package(SFML 2 REQUIRED system window graphics network audio)
if(SFML_FOUND)
include_directories(${SFML_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
endif()

Add executable from parent directory cmake

I'm trying to compile executable files in a subdirectory project/model/tests for testing and need to link my model files which reside at project/model. However, I can't get it to work. I've successfully added the parent directory but cmake keeps telling me no source file found for foo.cpp, which is in the parent directory, while bar.cpp, which is in the current directory, is added correctly.
cmake_minimum_required(VERSION 2.6)
# get parent directory
get_filename_component(MODEL_DIR ${CMAKE_CURRENT_SOURCE_DIR} PATH)
# Locate GTest
find_package(GTest REQUIRED)
# Add parent directory
include_directories(${GTEST_INCLUDE_DIRS} ${MODEL_DIR})
link_directories(${MODEL_DIR})
# all included directories are printed out correctly
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
# foo.cpp, which is in the parent directory is not found
add_executable(runTests foo.cpp bar.cpp)
target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)
Thank you.
When files listed in add_executable() and add_library() are given as relative paths (which they almost always are), they are interpretedd relative to CMAKE_CURRENT_SOURCE_DIR. In other words, you have to do one of these:
add_executable(runTests ../foo.cpp bar.cpp)
Or:
add_executable(runTests ${MODEL_DIR}/foo.cpp bar.cpp)
Side note: it's almost never a good idea to use link_directories(); that command is genrally more trouble than it's worth. The preferred alternative is to provide full paths to target_link_libraries() where necessary.

Find package Eigen3 for CMake

CMake cannot find my Eigen3 package. I set an environment variable called
EIGEN3_INCLUDE_DIR
pointing to the path where FindEigen3.cmake is.
Then in the CMakelists.txt I wrote:
find_package( Eigen3 REQUIRED )
include_directories( EIGEN3_INCLUDE_DIR )
I get next message of error:
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:91 (MESSAGE):
Could NOT find Eigen3 (missing: EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
(Required is at least version "2.91.0")
Call Stack (most recent call first):
C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:252 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindEigen3.cmake:76 (find_package_handle_standard_args)
test/test_quaternion/CMakeLists.txt:25 (find_package)
Any idea on what I am missing or doing wrong?
Since Eigen3 is completely header only, all you ever need is the path to the include directory. And this one, you are already defining manually anyway. So there is no real need for a FindEigen3.cmake or FIND_PACKAGE call.
Simply use
INCLUDE_DIRECTORIES ( "$ENV{EIGEN3_INCLUDE_DIR}" )
or
SET( EIGEN3_INCLUDE_DIR "$ENV{EIGEN3_INCLUDE_DIR}" )
IF( NOT EIGEN3_INCLUDE_DIR )
MESSAGE( FATAL_ERROR "Please point the environment variable EIGEN3_INCLUDE_DIR to the include directory of your Eigen3 installation.")
ENDIF()
INCLUDE_DIRECTORIES ( "${EIGEN3_INCLUDE_DIR}" )
A few notes:
If you want to access the content of a CMake variable, make sure to use ${...}
$ENV{....} accesses environment variables.
The second example will stop with an error if the environment variable is not set (and, thus, EIGEN3_INCLUDE_DIR cmake variable is empty)
Be careful to use quotation marks around (evaluated) variables if they could contain whitespace. Otherwise, CMake will interpret it as a list.
If you want to use custom find modules, make sure to either place them in you CMake installation or, as #Fraser pointed out above, make sure to point CMAKE_MODULE_PATH to the directory where it is. Not sure, but it could be that CMake checks the current directory as well automatically (where your CMakeLists.txt resides. Anyhow, setting EIGEN3_INCLUDE_DIR is totally unrelated to the location of FindEigen3.cmake
However, it could be that your FindEigen3 script evaluates this variable to determine the location of your Eigen3 installation.
Alternatively, self-built CMake-based projects often provide a <PackageName>Config.cmake. If you point a variable called <PackageName>_DIR to the directory containing this file, you can use FIND_PACKAGE( <PackageName> ...) as normal. See documentation of FIND_PACKAGE for details.
Eigen >= 3.3 has direct CMake integration, so it seems yours isn't set up correctly.
Assume Eigen has been installed to /opt/eigen/3.3 with default settings. Append or prepend the the location /opt/eigen/3.3 to the environment variable CMAKE_PREFIX_PATH e.g in bash:
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH:/opt/eigen/3.3"
Then CMake should pick it up.
If you are writing your own CMakeLists.txt that uses Eigen I suggest using code like this:
find_package (Eigen3 3.3 REQUIRED)
add_executable (example example.cpp)
target_link_libraries (example Eigen3::Eigen)
You should not use include_directories since CMake 3 was released -- the targets approach should be preferred whenever available.
First, make sure Eigen is properly installed. Refer to the INSTALL file that comes with the tarball.
Second, copy the cmake/FindEigen3.cmake file from the tarball to the directory containing your CMakeLists.txt.
In your CMakeLists.txt add:
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
Now you should be able to do e.g. #include <Eigen/Core>.
All of this comes (mostly) from this source.
This approach has the advantage over e.g. include_directories("$ENV{EIGEN3_INCLUDE_DIR}") that it the uses CMake's standard mechanism for finding external dependencies, making it easier for someone else (or your future self) to pick up the project, possibly on another platform.
(However, it would be nice if Eigen itself installed an EigenConfig.cmake file, making it accessible through the find_package mechanism without any extra paths.)
I found another solution here (which referred to here) which uses the pkg-config file :
find_package(PkgConfig)
pkg_search_module(Eigen3 REQUIRED eigen3)
As a detailed explanation of the note 7 from the top answer of Johannes. By using the "Config mode" rather than "Module mode" of CMake find_packate(), only writing
find_package( Eigen3 REQUIRED )
include_directories( EIGEN3_INCLUDE_DIR )
in CMakeLists.txt is enough.
Please refer to the INSTALL guidance text file contained in the eigen source code directory (eg. extracted from eigen-3.3.7.tar.gz downloaded from official website), which said:
Method 2. Installing using CMake
********************************
Let's call this directory 'source_dir' (where this INSTALL file is).
Before starting, create another directory which we will call 'build_dir'.
Do:
cd build_dir
cmake source_dir
make install
The "make install" step may require administrator privileges.
You can adjust the installation destination (the "prefix")
by passing the -DCMAKE_INSTALL_PREFIX=myprefix option to cmake, as is
explained in the message that cmake prints at the end.
Just like installing usual CMake projects to your machine.
The difference from directly including the /usr/include/eigne3 or /usr/local/include/eigen3 directory is that, a configuration directory called eigen3/cmake will also be installed to /usr/share or usr/local/share. This configuration directory contains the Eigen3Config.cmake file, which can automatically be found by CMake to locate the eigen3 directory.
If you have not added Eigen Library to environment variable then do the following in CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(ProjectName)
set(CMAKE_CXX_STANDARD 11)
# set EIGEN_DIR variable to Eigen Library Path
set(EIGEN_DIR "C:\\Eigendir\\Eigen")
# include the directory
include_directories(${EIGEN_DIR})
add_executable(ProjectName main.cpp)
target_link_libraries(ProjectName ${EIGEN_DIR})
Another simple way that doesn't require adding an environment variable is to simply find eigen with the cmake find_path function https://cmake.org/cmake/help/v3.6/command/find_path.html. The example code finds the directory "Eigen" in paths "/usr/include/" and "/usr/local/include" with an additional search in subdirectory "eigen3".
find_path(EIGEN3_INCLUDE_DIRS "Eigen" paths "/usr/include" "/usr/local/include" path_suffixes "eigen3")
message(${EIGEN3_INCLUDE_DIRS})
if ( NOT EIGEN3_INCLUDE_DIRS )
message(FATAL_ERROR "CMake variable EIGEN3_INCLUDE_DIRS not found.")
endif()
include_directories ( "${EIGEN3_INCLUDE_DIRS}" )
You could try setting the CMAKE_MODULE_PATH to the location of Eigen subdirectory named "cmake":
cmake . -DCMAKE_MODULE_PATH=<Eigen root dir>/cmake/
I had a similar problem when run cmake .. && make on Google Colab on a project clone from github. I fixed it by editing CMakeLists.txt file and adding this line to it:
set(EIGEN3_INCLUDE_DIR "/usr/include/eigen3")
As you can see, my eigen3 was in /usr/include/eigen3 path (and I had installed it using !sudo apt-get install build-essential cmake libeigen3-dev)
When installing on Kubuntu 20.04 following steps from INSTALL:
Do:
cd build_dir
cmake source_dir
make install
using -DCMAKE_INSTALL_PREFIX=/usr/local/eigen-3.4.0 and sudo
FindEigen3.cmake is not installed. However, using
set(Eigen3_DIR "/usr/local/eigen/share/eigen3/cmake")
seem to work. FindEigen3.cmake is in the build directory
but it is not copied to the installation directory tree.
This worked:
Changed c++11 to c++14
Changed find_package(Eigen3 QUIET) to find_package(Eigen3 CONFIG)
Another simple way is:
if the Eigen library is in /opt/eigen/3.3/Eigen
include_directories(/opt/eigen/3.3)
which is equivalent to what Jai suggested
set(EIGEN_DIR "/opt/eigen/3.3")
include_directories(${EIGEN_DIR})
You need to read official documentation:
Click here
After install Eigen from tar and compile it correctly.
CMakeLists.txt will looks like this:
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
add_executable(${PROJECT_NAME} something.cpp)
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen)
It will be fine work.

How to point cmake at specific directory for library?

I have a CMake project where I am using a library and now I want to test my code with a different version of that library. I can set INCLUDE_DIRECTORIES (and possibly later also linking) in the below example. But because I only want to do this temporarily, I'd like to manually set this path with ccmake/cmake-gui.
How do I do this?
project(min_example)
cmake_minimum_required(VERSION 2.8)
find_package(OpenCV REQUIRED)
# Without the following line please:
INCLUDE_DIRECTORIES("/home/me/src/opencv/install/include")
add_executable(min_example main.cpp)
target_link_libraries(min_example ${OpenCV_LIBS})
This should be possible by setting the CMAKE_PREFIX_PATH variable upon configuring your build. In your project directory generate a test_build directory and run:
mkdir test_build
cd test_build
cmake -DCMAKE_PREFIX_PATH=/home/me/src/opencv/install ..
Setting the CMAKE_PREFIX_PATH variable will make the find_package(OpenCV REQUIRED) command pick your OpenCV installation in /home/me/src/opencv and set the OpenCV_LIBS and OpenCV_INCLUDE_DIR variables accordingly.
Alternatively you can edit a CMakeCache.txt file of an existing build directory with the CMake GUI editor and add the CMAKE_PREFIX_PATH definition there. You have to re-configure your project then.
Using config in find_package will restrict search path to OpenCV_DIR. This will use the cmake config that opencv generates at build time to setup paths to include and libs
set(OpenCV_DIR "<cusompath>" CACHE PATH '' ${SHOULD_FORCE_CACHE})
find_package(OpenCV REQUIRED CONFIG)