dimitris93
dimitris93

Reputation: 4273

Including directories in Clion

Whenever I wanted to include a directory that was located outside of my project with Clion I would use the -I somedir flag. This time however, what I want to do is to have a hierarchy like this:

/project
   CMakeLists.txt
   /src
      /Graph
         Graph.h
         Graph.cpp
      /Dijkstra
         Dijkstra.h
         Dijstra.cpp

I want my code in a /src directory. And not only that, but also, for example, inside the file Dijkstra.h I want to include the Graph.h like this: #include "Graph/Graph.h and not like this: #include "../Graph/Graph.h.

If I only add an -I src flag, then if I am inside the Dijkstra.h file and I wanted to include Graph.h, I would have to write #include "../Graph/Graph.h, which is not what I want.

So I tried to also add INCLUDE_DIRECTORIES(src). That fixed the problem above, however when tried to compiled, I got a linker error undefined reference to....

So I tried adding the files one by one like this:

set(SOURCE_FILES
        src/Dijkstra/Dijkstra.h
        src/Dijkstra/Dijkstra.cpp
        src/Graph/Graph.h
        src/Graph/Graph.cpp)
add_executable(someprojectname ${SOURCE_FILES})

and that brought back the previous problem, where I had to include the files like this: #include "../Graph/Graph.h".

How can I do this properly to get the behavior I want ?

Upvotes: 7

Views: 27523

Answers (2)

Craig Scott
Craig Scott

Reputation: 10137

UPDATE: @Tsyvarev's answer is correct. I've edited this answer to remove the incorrect part and keep the comments relating to target_include_directories(), but it should be viewed as additional to Tsyvarev's answer.

INCLUDE_DIRECTORIES(src) will make the src directory get added as a search path to all targets defined from that point on. It does not add sources to any targets. The search path will be relative to the current source directory and CMake will adjust it as appropriate when descending into subdirectories via add_subdirectory(). While this is fine if that's what you want, as the project gets bigger and more complicated, you may find you would prefer to apply the include path settings to just some targets. For that, use target_include_directories() instead:

target_include_directories(someprojectname "${CMAKE_CURRENT_SOURCE_DIR}/src")

This will have the same effect, but it restricts the use of the added include path to just the someprojectname target. If you later define some other target which doesn't need the include path, it won't be added. This can help prevent situations like unexpected files being picked up if you have deep directory hierarchies and you re-use directory names in different places, for example).

The target_include_directories() command has additional benefits when applied to library targets because CMake has the ability to carry the include path through to anything you link against that library too. Doesn't sound like much, but for large projects which define and link many libraries, it can be a huge help. There are other target-specific commands which have similar benefits too. This article may give you a bit of a feel for what is possible (disclaimer: I wrote the article). It is more focused on target_sources(), but the discussion around carrying dependencies through to other targets may be useful.

Upvotes: 4

Tsyvarev
Tsyvarev

Reputation: 65870

Command INCLUDE_DIRECTORIES doesn't add any source file for compile!

Instead, this command defines directories for search header files.

You need to list all source files in add_executable() call in any case:

include_directories(src)
set(SOURCE_FILES
    src/Dijkstra/Dijkstra.cpp
    src/Graph/Graph.cpp)
add_executable(someprojectname ${SOURCE_FILES})

Upvotes: 7

Related Questions