7

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 ?

dimitris93
  • 4,155
  • 11
  • 50
  • 86
  • i would suggest , you to use directory structure like this Graph/src/*.cpp , Graph/include/*.h , Dijkstra/src/*.cpp and Dijkstra/include/*.h.. Then try SET(GRAPH_INCLUDE_DIR Graph/include/) , SET(DIJKSTRA_INCLUDE_DIR Dijkstra/include/) INCLUDE_DIRECTORIES(${GRAPH_INCLUDE_DIR} ${DIJKSTRA_INCLUDE_DIR }) – Varun Apr 27 '16 at 10:02
  • Not clear question at all. If you use last variant and add `include_directories(src/Graph src/Dijkstra)` what happens? – fghj Apr 27 '16 at 10:07
  • The way I have suggested is better way making directory structure . .cpp in one directory and .h file in another directory. Why to mix these file in single directory. – Varun Apr 27 '16 at 10:11

2 Answers2

7

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})
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
4

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.

Craig Scott
  • 9,238
  • 5
  • 56
  • 85
  • `include_directories()` **automatically** transforms all relative paths to absolute ones. See [documentation](https://cmake.org/cmake/help/v3.0/command/include_directories.html) for more details. – Tsyvarev Apr 27 '16 at 11:12
  • Indeed you are correct! And I misunderstood the question (missed where include_directories() was being used). I'll leave my answer here for a while to allow those who already read it to see my correction, then I'll delete my answer. Thanks for the correction! – Craig Scott Apr 27 '16 at 11:15