Cmake include directories - c++

I have a folder structure like this: Project/Libraries/Math, Project/Libraries/Math2.
In the Project folder I have the main.cpp, and the CMakeLists.txt with the following content:
cmake_minimum_required (VERSION 2.6)
project (CppMain)
add_executable(CppMain main.cpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR))
In the Math folder I have the header MyVectors.h and in the Math2 folder I have MyMatrices.h, that I would like to include in the main.cpp file, and this works as:
#include "Libraries/Math/MyVectors.h"
#include "Libraries/Math2/MyMatrices.h"
The problem is that also the header MyVectors.h includes the header MyMatrices.h at the same way, but the linker doesn't find it. What can I modify in the CMakeLists to fix this problem?

This seems to be a classical case of relative paths. You have done this to include the files in main.cpp
#include "Libraries/Math/MyVectors.h"
#include "Libraries/Math2/MyMatrices.h"
In order for a file to access is parent directory you can use ../ The following lines should be introduced to MyVectors.h:
#include "../Math2/MyMatrices.h"
What does it signify? Well your file MyVectors.h is in Math folder when you use ../ it takes you to the parent directory of Math which is Libraries. From there you can simply follow the path to your required directory.
More detail can be found on this answer by me on another question: https://stackoverflow.com/a/35910234/2555668

Related

CMake: Can we specify include directories for a specific set of files not forming an executable or lib?

If I have this source tree:
C:\app:
src:
CMakeLists.txt
main.cpp --> #include "acme/header_only_lib/api.h"
D:\3rdparty\acme\header_only_lib:
api.h --> #include "detail.h"
detail.h
Without using symlink tricks, and without adding files to the 3rdparty folders, if I must retain #include "acme/header_only_lib/api.h" in main.cpp, how should I specify the include directories in CMake such that api.h can see detail.h, without adding global include directory of D:\3rdparty\acme\header_only_lib? The header-only-lib is not an executable nor library target, and its code is not modifiable by me. I also don't want to pollute my global include directories by adding D:\3rdparty\acme\header_only_lib because the filenames inside there are too common and will easily clash with other libraries/future code.
Is there a CMake mechanism where I can say:
Only for D:\3rdparty\acme\header_only_lib\api.h, add D:\3rdparty\acme\header_only_lib as the include directory?
To add a directory to the global list of include directories, you use e.g.
include_directories( ${CMAKE_SOURCE_DIR}/3rdparty )
Note that you should not hardcode absolute paths (like D:\) into your CMakeLists.txt as that makes it impossible to build your project in any other location. CMake offers variables like ${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} for just that purpose.
If you want to add a directory to the list of include directories for a specific part of your build only, you use e.g.
target_include_directories( app PRIVATE ${CMAKE_SOURCE_DIR}/3rdparty )
This adds the directory only for the target (executable / library) app.
Note that, if your acme/header_only_lib is supposed to be installed alongside with the app binaries, this approach won't work, as your acme headers would need to "see" each other on the client's machine, which is unlikely if they reside in the acme/header_only_lib subdirectory but address each other without subdirs. That would require your client (who isn't using your CMakeLists.txt for his builds) to add acme/header_only_lib to the include paths for your header lib to work -- you should not do that.
Use include_directories or target_include_directories:
include_directories("D:\3rdparty")
OR with target_include_directories if you want to make this change only for the main target:
add_executable(main main.cpp)
target_include_directories(main PUBLIC "D:\3rdparty")
Then you can just #include "acme/header_only_lib/api.h" or #include <acme/header_only_lib/api.h>
Header only lib
If you want to do this for header-only-lib only, you need to do this in it's CMake file. First add the library as INTERFACE with no source files:
add_library(header-only INTERFACE)
Then include directories for it:
target_include_directories(header-only INTERFACE include-dir-for-header-only)
Then link it to the main target
find_library(HeaderOnly
NAMES header-only
HINTS "D:\3rdparty\path-to-lib"
)
target_link_libraries(main header-only)

Tell CLion to use header include path with prefix

I have a project layout as follows:
workspace
project_a
project_a -> .h files here
Root -> .cxx files here
project_b
project_b -> .h files here
Root -> .cxx files here
I cannot change the directory layout due to the build system that we're using.
Headers are included as
#include "project_a/some_header.h
also from the corresponding .cxx file.
I've created a CMakeLists.txt file in the root directory, that adds all my projects via include_directories(project_a project_b), which should be the path prefixed before the one given in the #include. CLion does not manage to find and index any of my files.
Additionally, I have an automatically generated directory of headers of structure
include
lib_a -> .h files
lib_b -> .h files
and I've set them up accordingly, but it also does not work.
Does CLion not manage to resolve the prefixed path in the #include or why is this not working?
In CMakeList.txt, which should be located in parent folder, "workspace" folder in that situation, add
set(INCLUDE_DIRECTORIES ./)
If, for example, there is a parent folder, that holds include files:
workspace
includes_folder
project_a
a.h
b.h:
#include <project_a/a.h>
Then CMakeList.txt should contain
set(INCLUDE_DIRECTORIES ./)
include_directories(includes_folder)
If the only thing that doesn't work is Clion's interpretation of your headers then you should check out the Clion FAQ. If Clion's not working the way you expect then your CMake project might not be set up correctly or you might be doing something unintentionally. You should show us your CMakeLists.txt.
From the Clion FAQ:
Q: CLion fails to find some of my headers. Where does it search for them?
A: CLion searches through the same places CMake does. Set the INCLUDE_DIRECTORIES variable in CMake to provide the headers path to the IDE.
By the way, in this wiki you can find a lot of useful CMake variables with descriptions that can be especially helpful if you are new to CMake.
Q: Refactorings are not working and highlighting is wrong, even though the project can be compiled correctly. What’s happened?
A: Most probably CLion is unaware of some files in your project (these files are grayed out in the project tree):
non-project-files
It gets this information from the CMakeLists.txt files in the following way:
set(SOURCE_FILES main.cpp)
add_executable(my_exec ${SOURCE_FILES})
This is how CLion now knows that main.cpp is included in your project. As for now, header files (in case their names differ from the appropriate .cpp files already added to the SOURCE_FILES variable) should also be included in the project in that way.

How to order/design a shared library with CMake that use higher includes

At the moment I have a shared library with around ~30 classes. My idea is to group them into subdirectories, means a subdirectory contains classes that are more or less equals/have the same content (ui, utils, backend etc).
But I ran into a typical problem: I have some export defines/constants that are shared across the project and my first question was: How to include this header from a header in a subdirectory ?
I often see the #include ../Header.h solution but my personal opinion is, that this is quite ugly.
So what I did:
Application/
main.cpp
MyLibrary/
Header.h
foo/
Foo.h (#include <Header.h>
bar/
Bar.h (#include <Header.h> #include <foo/Foo.h>)
And in my library CMakeList I add and include_directory with the root directory of the MyLibrary directory.
My application executable CMakeLists.txt looks something like this (pseudo CMake)
project(application)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)
add_executable(application main.cpp)
target_link_libraries(application mylibrary)
And in the main.cpp I include like this:
#include <MyLibrary/Header.h>
#include <MyLibrary/bar/Bar.h>
The problem now is, that the compiler doesn't know where to look for the included <> INSIDE the library, for example the Header.h includation inside foo.bar points to ${CMAKE_CURRENT_SOURCE_DIR}/Header.h - but CMAKE_CURRENT_SOURCE_DIR is the path of the application and NOT of the library
So I have to add the directory of the library that the compiler can found the other headers of the library (Header in the library that includes another Header in the library via <> and not "")
So I end up with something like this:
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../MyLibrary)
And now Bar.h can find foo/Foo.h, otherwise something goes wrong. And this is even more ugly
So my question: Is there a good/tricky way to solve this problem in CMake ? Or can someone give me tipps about a better project structure ? The solution has to run under MSVC, GCC and clang.
If you think about how your library will look after install you may get some hints about structure. So for example:
<install-prefix>/Foo/foo.hpp -> has `#include <Boo/boo.hpp>`
<install-prefix>/Boo/boo.hpp -> has `#include <Bar/bar.hpp>`
<install-prefix>/Bar/bar.hpp -> has `#include <Bar/details/utils.hpp>`
<install-prefix>/Bar/details/utils.hpp
this is possible layout before install done:
<source-dir>/Sources/Foo/foo.hpp
<source-dir>/Sources/Boo/boo.hpp
<source-dir>/3rdParty/Bar/bar.hpp
<source-dir>/3rdParty/Bar/details/utils.hpp
hence CMakeLists.txt must contains (or better target_include_directories):
include_directories(<source-dir>/Sources)
include_directories(<source-dir>/3rdParty)
so for your case, IMHO it must be something like that:
Application/
main.cpp
MyLibrary/
Header.h
foo/
Foo.h (#include <MyLibrary/Header.h>
bar/
Bar.h (#include <MyLibrary/Header.h> #include <MyLibrary/foo/Foo.h>)
What I've done to solve this problem is have a top level CMakeLists.txt that sets variables that will point to the top of the project directory. In your case this will be the directory containing Application and MyLibrary.
ProjectRoot
CMakeLists.txt // top
Application/
CMakeLists.txt
main.cpp
MyLibrary/
CMakeLists.txt
Header.h
foo/
Foo.h (#include <Header.h>
bar/
Bar.h (#include <Header.h> #include <foo/Foo.h>)
# Top level cmakelists
project (myproject)
set (my_app_src_top "${CMAKE_CURRENT_SOURCE_DIR}" )
set (my_app_build_top "${CMAKE_CURRENT_BINARY_DIR}" )
add_subdirectory( MyLibrary )
add_subdirectory( Application )
Then in your subdirectory CmakeLists, you can add include paths like this:
include_directories( ${my_app_src_top}/MyLibrary )
I also just define a project at the top level CMakeLists.txt. In this case you may be able to reference ${PROJECT_SOURCE_DIR}, but if you define projects in sub directories, then I think this will get reset based on the last sub directory you built.
I think with this structure you should be able to
#include <foo/Foo.h>
#include <bar/Bar.h>
Plus you may want to add ./ to the include_directories for each sub dir.

CMake and handling subfolder header files

I'm trying to set up my project to build several dynamic libraries that encompass its complete functionality. There are subfolders for each library. The subfolder libraries are dependent on each other, so they must reference functions from each other. I seem to have managed to get CMake to run without errors on the project, but when I go to build, I have trouble with my headers finding each other. It seems at build time, the include path isn't set up correctly. How can I fix this? Are there additional steps I need to take to set up the include path correctly?
The structure looks something like this
root
CMakeLists.txt
bin
lib
lib0
CMakeLists.txt
lib0.h
lib0.cpp
lib1
CMakeLists.txt
lib1.h
lib1.cpp
...
In the CMakeLists.txt for the root directory I have declarations like this:
set(ROOT /blah/blah/root)
include_directories(${ROOT}/lib0)
include_directories(${ROOT}/lib1)
add_subdirectory(lib0)
add_subdirectory(lib1)
In the CMakeLists.txt for the subfolders, I have:
set(lib0_SOURCES "")
list(APPEND lib0_SOURCES lib0.cpp)
add_library(lib0_lib ${lib0_SOURCES})
And my headers for the libraries look like (suppose this is lib0.h):
#include "lib1/lib1.h"
...
CMake runs fine with no errors, but when I go to compile, I get an error like:
In file included from /blah/blah/root/lib0/lib0.cpp:1:0:
/blah/blah/root/lib0/lib0.h:1:30: fatal error: lib1/lib1.h: No such file or directory
You told GCC to #include the file "lib1/lib1.h". When you build, CMake will ask to look for extra headers in "${ROOT}/lib0" and "${ROOT}/lib1"
So, GCC is trying "${ROOT}/lib0/lib1/lib1.h" and "${ROOT}/lib1/lib1/lib1.h" Yup, cant work.
To fix it:
you can use in your root CMakeLists.txt : include_directories(".")
keep your CMakeLists but #include the file "lib1.h"
remove the include_directories in CMakeLists and #include the file "../lib1/lib1.h"
IMO, I'd go for the first option!
You need to use the double naming scheme or specify the base directory as the include path:
root
CMakeLists.txt
bin
lib
lib0
CMakeLists.txt
lib0.cpp
lib0
lib0.h
lib1
CMakeLists.txt
lib1.cpp
lib1
lib1.h
...
I would ask CMake to just consider the ROOT directory for C/C++ include look-ups:
set(ROOT /blah/blah/root)
include_directories(${ROOT})
add_subdirectory(lib0)
add_subdirectory(lib1)
Then, in C/C++, use angle braquets ('<' and '>') rather than double quotes ('"'):
#include <lib1/lib1.h>

Xcode 4 C++ header file with relative path to another header

I'm using a library with an include structure where the .h files are all in a single directory. These .h files contains a single line, a #include directive which points to the 'real' header file in specific source folder locations. The #include path in these files is relative.
So, here's an example. The directory structure is:
/project
/sources
<my .cpp files>
<my .cpp files>
...
/include
/component
foo1.h
foo2.h
/platformA/something/foo1.h
/platformB/somethingelse/foo2.h
/include/component/foo1.h contains a single line of code:
#include "../platformA/something/foo1.h"
/include/component/foo2.h contains the single line of code #include "../platformB/somethingelse/foo2.h"
In my sources, I simply have:
#include "component/foo1.h"
The header search path for my project points to /include
Now, Xcode 4 is able to find component/foo1.h in /include, but it's unable to follow the relative include path within those headers and find the 'real' foo1.h in the `/platformA/something' directory, and so on.
I suspect it's because the include paths in the top-level foo1.h file is relative to its location, but Xcode might be treating it as relative to some other location (project root or something)? FWIW, Visual Studio has no problems with an identical configuration.
What can I do to remedy this?
From your directory structure it seems that the directories platformA and platformB are placed outside the include folder. There are two possible solutions to this:
Solution A
Move these
to include folder.
Solution B
Add project/platformA and
project/platformB to the
directories where include files
should be looked for in project
settings.
Don't use relative paths. Seriously, it's implementation-defined behavior how they work, so different compilers/environments/platforms will behave differently, and in your case, Xcode is almost certainly invoking GCC or clang in some sort of "build" directory, which may or may not be a sibling to your sources directory.
It's not worth the headache.
Put platformA and platformB in include, or add another directory (say, platform-include) put them in there, and add that directory to your include path.