cmake: Include directories root? - c++

I'm trying to set up cmake for a project I'm working on, but I have a problem which I can't resolve currently. My project has the following folder structure:
MotorEngine (root dir)
| CMakeLists.txt
| ThirdParty
|-| SDL2
|-|-| include (contains all header files for SDL2)
|-|-| lib
|-|-|-| x64
|-|-|-|-| SDL2.lib (the library file I need to link with)
| Source
|-| CMakeLists.txt
|-| main.cpp
The root CMakeLists.txt file:
cmake_minimum_required(VERSION 2.6)
project(MotorEngine)
# Set an output directory for our binaries
set(BIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Binaries)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Binaries)
set(THIRDPARTY_PATH ${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty)
# Include SDL2
include_directories(${THIRDPARTY_PATH}/SDL2/include)
# Add the engine + third party subdirectory
add_subdirectory(Source)
The Source's CMakeLists.txt:
project(MotorEngine)
add_executable(MotorEngine main.cpp)
target_link_libraries(MotorEngine ${THIRDPARTY_PATH}/SDL2/lib/x64/SDL2.lib)
Now, I want to achieve the following, in the main.cpp I want to write
#include "SDL2/include/SDL2.h"
But currently I have to write
#include "SDL2.h"
Since there will be files with the same name later on, I need to distinguish them in their folders. So the easiest would be to add the "ThirdParty" folder as a root so I can use #include relative to that then, but doing
include_directories(${THIRDPARTY_PATH})
does not work. Any ideas? Thank you!

With help of k.v. I was able to sort this out. I needed to add the following in the CMakeLists.txt in the Source directory:
target_include_directories(MotorEngine PUBLIC ${THIRDPARTY_PATH})

Related

How to clone, build, and link g2o framework in C++

I want to use g2o library in my C++11 project on Ubuntu 18.04, but I cannot make build working. I have all the dependencies. But I cannot link g2o library to my project via CMakeLists.txt
I am a newbie in C++ dependencies.
I've tried cloning https://github.com/RainerKuemmerle/g2o repository and building it with cmake.
The structure is as following:
MY_PROJECT
|__ cmake_modules
|__ project_src
|__ CMakeLists.txt
|__ Thirdparty
|____ g2o
|____ bin
|____ build
|____ cmake_modules # findG2O.cmake
|____ lib # .so shared libraries (all of them, like 20)
|____ g2o
|____ core # headers and source files
|____ solvers
|____ types
|____ CMakeLists.txt
I added cmake_modules from inside g2o to the CMakeLists.txt of my_project
and than try to find it with find_package but it is not found.
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/g2o/cmake_modules)
find_package(G2O REQUIRED)
if(NOT G2O_FOUND)
message(FATAL_ERROR "G2O not found.")
endif()
I left findG2O.cmake untouched as it is in https://github.com/RainerKuemmerle/g2o/blob/master/cmake_modules/FindG2O.cmake
Should I change the findG2O.cmake? I do not really understand what is going on. How should I proceed with building out of the source and linking?
I haven't found precise answer to my problem anywhere on StackOverflow but maybe I just didn't know what I was searching for.
Error message was:
/home/miki/ORB_SLAM2/Thirdparty/g2o/g2o/types/sim3/types_seven_dof_expmap.h:29:10: fatal error: g2o/config.h: No such file or directory #include "g2o/config.h"
When I tried to change to #include "../../config.h" it worked. How can I solve it in CMakeLists so I do not have to change all includes in ThirdParty library?
The config.h is generated after executing the command
cmake ..
in the folder
MY_PROJECT/Thirdparty/g2o/build
, and this file has some information like what type of used floating point or library you try to use. I think such information will be used to modify some code blocks automatically.
By default, the location of file config.h is in the folder
MY_PROJECT/Thirdparty/g2o/build/g2o
Or you can also use the command
make install
to copy this file to the install path.
If your ${CMAKE_PREFIX_INTALL} is /home/user/, then the location of file config.h is in the folder
/home/user/include/g2o
And if you want to find g2o libraries with find_package, then you need to write
set (G2O_ROOT /home/user)
before the find_package.
Finally, add the header path into CMakeLists.txt, like
include_directories(${G2O_INCLUDE_DIR}

Include same header file for different libs

I have a C++ project with the following structure:
CMakeLists.txt
code/
libClient/
CMakeLists.txt
include/
LibClient/
lib_client.h
src/
lib_client.cpp
libServer/
CMakeLists.txt
include/
LibServer/
lib_server.h
src/
lib_server.cpp
libSDK/
include/
CMakeLists.txt
LibSDK/
lib.h
My root CMakeLists.txt has the following content:
cmake_minimum_required(VERSION 3.0)
project(libExample)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
add_subdirectory(code/libClient)
add_subdirectory(code/libServer)
add_subdirectory(code/libSDK)
Now, I would like to build the libs for the server and for the client as .a files. The lib_client.cpp includes the header files with
#include <LibClient/lib_client.h>
Up to here, it is all clear for me, but the header file lib_client.h includes the lib.h which is located at /code/libSDK/include/LibSDK/lib.h with
#ifndef LIBCLIENT_H
#define LIBCLIENT_H
#include <string>
#include <LibSDK/lib.h>
To make this work, I wrote the following content in the CMakelists.txt for the ClientLib:
project(LIBCLIENT)
add_library(
Client_lib STATIC
src/lib_client.cpp
include/LibClient/lib_client.h
)
target_include_directories(egoClient_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_include_directories(egoClient_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../libSDK/include") ###this line I think should be different.
My question is now, is it possible to avoid this line with the hard coded path? This lib.h is also used (included) in other header files in this project.
The CMakelists.txt for this lib.h has up to now only the content:
cmake_minimum_required(VERSION 3.0)
project(LIBSDK)
I thought about using the CMake find_package() method and write a Find<package>.cmake file, but I do not see any advantages of this because inside this file I also have to write the paths?
Thank you very much in advance.
If Client_lib uses SDK_lib, you'll want to use the following in Client_lib's CMakeLists.txt:
target_link_libraries(Client_lib SDK_lib)
This will tell CMake that Client_lib uses SDK_lib. It will also automatically make the PUBLIC or INTERFACE include paths configured on SDK_lib (with target_include_directories in SDK_lib's CMakeLists.txt) available for Client_lib.
Firstly, if your libClient and libServer depend on libSDK, you should rearrange your top-level CMake to look like the below. Also, based on your example project structure, your add_subdirectory() for the SDK should be code/libSDK/include:
cmake_minimum_required(VERSION 3.0)
project(libExample)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
add_subdirectory(code/libSDK/include)
add_subdirectory(code/libClient)
add_subdirectory(code/libServer)
You want to be sure to gather information about you SDK first, before traversing to the client and server directories.
Secondly, if you do not intend to build libSDK into a library, but simply use its headers, you can just define a new variable in your libSDK CMake file to specify the location of the headers:
project(LIBSDK)
set(SDK_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "My SDK headers directory.")
Now, with a cached variable from the libSDK directory, we can use it in the other CMake files:
project(LIBCLIENT)
add_library(Client_lib STATIC
src/lib_client.cpp
)
target_include_directories(Client_lib PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${SDK_INCLUDE_DIRECTORY}"
)
EDIT: As commented, to avoid the use of cache variables, you can also set the include directories variable with PARENT_SCOPE to make the variable accessible from your client and server CMake files:
project(LIBSDK)
set(SDK_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)

using cmake to make header files descendants of the project's source directory

As in Google C++ Style Guide is mentioned all of a project's header files should be listed as descendants of the project's source directory without use of UNIX directory shortcuts . (the current directory) or .. (the parent directory). How can I do that in my project that is shortly described below.
My project directory hierarchy is like this:
GraphicsEngine
header_files.h
source_files.cc
CMakeLists.txt (1)
Light
CMakeLists.txt (2)
header_files.h
source_files.cc
Camera
CMakeLists.txt (3)
header_files.h
source_files.cc
Core
CMakeLists.txt (4)
header_files.h
source_files.cc
These are contents of CMakeLists.txt files:
CMakeLists.txt (1)
add_library(GraphicsEngineLib source_files.cc)
target_link_libraries(GraphicsEngineLib LightLib CameraLib CoreLib)
add_subdirectory(Light)
add_subdirectory(Camera)
add_subdirectory(Core)
CMakeLists.txt (2)
add_library(LightLib source_files.cc)
CMakeLists.txt (3)
add_library(CameraLib source_files.cc)
CMakeLists.txt (4)
add_library(CoreLib source_files.cc)
Now when for example I want to include header files from Camera folder in to files in Core folder, I have to use ../Camera/header_file.h but I want to use GraphicsEngine/Camera/header_file.h. How can I do this?
What I have done in the past is to set this in the top level CMakeLists.txt (which should be in your GraphicsEngine directory):
SET(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
INCLUDE_DIRECTORIES(
${PROJECT_ROOT}
)
where according to this, CMAKE_CURRENT_SOURCE_DIR is
this is the directory where the currently processed CMakeLists.txt is located in
Note that by defining Project_Root in this way, your GraphicsEngine project can also #include headers from sister projects to GraphicsEngine.
Hope this helps.

CMake doesn't include header directory of submodule A within submodule B

I have a CMake project that looks like this:
project/
CMakeLists.txt
subprojectA/
CMakeLists.txt
include/
headerA.hpp
src/
libraryA.cpp
subprojectB/
CMakeLists.txt
src/
mainB.cpp
The "library" subproject, A, is compiled as a static library, becoming libsubprojectA.a. The "main" project, B, is compiled as a binary and depends on the library. mainB.cpp includes a reference to headerA.hpp.
Here is subprojectA/CMakeLists.txt:
project(SubProjectA)
include_directories(include)
add_library(subprojectA STATIC src/libraryA.cpp)
set(${PROJECT_NAME}_INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/include
CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)
And here is subprojectB/CMakeLists.txt:
project(SubProjectB)
include_directories(${SubProjectA_INCLUDE_DIRS})
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
The main Project CMakeLists.txt looks like:
project(Project)
add_subdirectory(subprojectB)
add_subdirectory(subprojectA)
Note that subprojectB, the main project, is listed before subprojectA.
Here's the problem. When I first run "cmake" on this project, ${SubProjectA_INCLUDE_DIRS} is not set within SubProjectB.
What I think is happening is that the CMakeLists for SubProjectB loads first, when ${SubProjectA_INCLUDE_DIRS} has not yet been set. It sets its own include path to an empty string as a result. However, even though libsubprojectA.a gets built successfully before mainBinary, the include path was already set empty beforehand. As a result, I get this error when trying to make mainBinary:
subprojectB/src/mainB.cpp:1:23: fatal error: headerA.hpp: No such file or directory
#include "headerA.hpp"
^
It's a workaround to put subprojectA before subprojectB in the main Project CMakeLists in the declarative world of CMake. What I really want is to know the proper way to indicate to CMake that the include_directories(${SubProjectA_INCLUDE_DIRS}) line depends on the definitions that exist inside SubProjectA's CMakeLists. Is there a better way to do this?
If you want to express that include directory subprojectA/include is an interface of the library subprojectA, attach this property to the target with target_include_directories command:
subprojectA/CMakeLists.txt:
project(SubProjectA)
add_library(subprojectA STATIC src/libraryA.cpp)
# PUBLIC adds both:
# 1) include directories for compile library and
# 2) include directories for library's interface
target_include_directories(subprojectA PUBLIC include)
So any executable(or other library) which linked with subprojectA will have this include directory automatically:
subprojectB/CMakeLists.txt:
project(SubProjectB)
add_executable(mainBinary src/mainB.cpp)
target_link_libraries(mainBinary subprojectA)
Of course, for use last command properly you need to process directory with library before one with executable:
CMakeLists.txt:
project(Project)
add_subdirectory(subprojectA)
add_subdirectory(subprojectB)

CMake link files from subdirectories and parent directories

I have a folder net like:
main
headers
cls1.hpp cls2.hpp ...
sources
cls1.cpp cls2.cpp ...
resources
r1.hpp r2.hpp ...
I have tried more cmake methods to link the files, like
set(SRC ${SRC})
in parent dir and
set(SRC ${SRC} ${CMAKE_CURRENT_SOURCE_DIR}/cls1.cpp PARENT_SCOPE)
in subdir
OR
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE HDR_FILES ${PROJECT_SOURCE_DIR}/*.hpp)
to get the .cpp and .hpp files, but when I do
#include "resources/r1.hpp"
I get error like "resources/r1.hpp" No such a file or directory
Can anyone help me pleas? How can I do linking between files in folders in my case?
To solve this specific problem, in your main CMakeLists.txt add this line before adding subfolders:
include_directories(".")
This will allow the compiler to see the file located in resources/r1.hpp starting from the root path.
However, I suggest you take a look to some CMake projects examples, because it doesn't seem you are doing things in the standard way (e.g. usually a good way is to add a sub directory that creates its own library, that then you link to your main executable)