290

About a year ago I asked about header dependencies in CMake.

I realized recently that the issue seemed to be that CMake considered those header files to be external to the project. At least, when generating a Code::Blocks project the header files do not appear within the project (the source files do). It therefore seems to me that CMake consider those headers to be external to the project, and does not track them in the depends.

A quick search in the CMake tutorial only pointed to include_directories which does not seem to do what I wish...

What is the proper way to signal to CMake that a particular directory contains headers to be included, and that those headers should be tracked by the generated Makefile?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Matthieu M.
  • 251,718
  • 39
  • 369
  • 642
  • 1
    The edits made to this question makes it confusing. The original question and answers were how to track Header Files in a IDE. This is quite different from a generated Makefile missing header file dependencies and how to resolve that issue. – fdk1342 Jan 01 '19 at 17:39
  • @Fred: I have no idea what you are talking about. As the edit revision clearly shows, the last sentence has **always** been there. Only cosmetic edits were made on this question, and no word was introduced (or removed). – Matthieu M. Jan 01 '19 at 17:45
  • Then that is my misunderstanding. It looked liked to me an entire paragraph was added. https://stackoverflow.com/questions/13703647/how-to-properly-add-include-directories-with-cmake?noredirect=1#comment29340346_13703745 says the common understanding was how to list the header file in the IDE. This would have been referring to the `.cbp` project file. Now if the cmake dependency scanner fails to correctly identify a header file as a dependency for a Makefile there are ways to fix that but in some cases it will get it wrong because it doesn't include a full preprocessor. – fdk1342 Jan 01 '19 at 18:28

7 Answers7

307

Two things must be done.

First add the directory to be included:

target_include_directories(test PRIVATE ${YOUR_DIRECTORY})

In case you are stuck with a very old CMake version (2.8.10 or older) without support for target_include_directories, you can also use the legacy include_directories instead:

include_directories(${YOUR_DIRECTORY})

Then you also must add the header files to the list of your source files for the current target, for instance:

set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(test ${SOURCES})

This way, the header files will appear as dependencies in the Makefile, and also for example in the generated Visual Studio project, if you generate one.

How to use those header files for several targets:

set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)

add_library(mylib libsrc.cpp ${HEADER_FILES})
target_include_directories(mylib PRIVATE ${YOUR_DIRECTORY})
add_executable(myexec execfile.cpp ${HEADER_FILES})
target_include_directories(myexec PRIVATE ${YOUR_DIRECTORY})
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
SirDarius
  • 36,426
  • 7
  • 79
  • 95
  • Ah! I knew it must be something stupid. Indeed, I did not listed the headers... Do I need to list the headers of just this library, or also all the headers that it might depend on (on top of declaring the dependency on the library) ? It's a growing project and I quite dread the idea of adding a header to *all* the dependencies when I add one in the root library. – Matthieu M. Dec 04 '12 at 13:13
  • To allow for better dependency tracking (for example to make sure modifying a header file triggers compilation for all affected targets), yes. However you can use cmake variables to list the header files only once and use them in several places, see my edit. – SirDarius Dec 04 '12 at 13:15
  • 1
    My question was more in the sense that I have several libraries which depend from each other: libroot, liba depends on libroot, libb depends on libroot. Can I use the `LIBROOT_HEADER_FILES` variable in `liba/CMakefile` and `libb/CMakefile` then ? – Matthieu M. Dec 04 '12 at 13:37
  • If you have several CMakeLists.txt files, you can SET your variable in the libroot subdirectory using the PARENT_SCOPE option, which will make the variable known in the parent CmakeLists.txt file, therefore available for the other subdirectories. – SirDarius Dec 04 '12 at 13:48
  • Thanks, this seems to completely cover my needs, I'll need to test it out (obviously) but so far it looks great :) – Matthieu M. Dec 04 '12 at 14:16
  • Instead of putting the `${HEADER_FILE}` inside both the `add_library()`and the `add_executable()` macros, is it also possible to put them in a `include_directories()` immediately after `set()`, and leave them out in the last 2 macros? – TemplateRex May 06 '13 at 20:33
  • @rhalbersma the add_* commands are not macros, and include_directories() is not used to list header files, but **directories** containing header files in order for the compiler to find them, therefore, the answer is no. This command does not magically add file dependency tracking. – SirDarius May 06 '13 at 20:39
  • @SirDarius OK, thanks. I am trying to get a test-suite of a header-only template library to work, and I got confused between the headers of the test-suite and those of the library itself, might ask a question about it later if I can't figure it out. – TemplateRex May 06 '13 at 20:41
  • 4
    This is wrong, you should _never_ use `include_directories` over `target_include_directories`. The former sets it recursively for all targets in that directory; whereas the latter sets it for a target. Doing the former breaks the notion of a target graph in CMake, and instead relies on side effects to your file hierarchy. – Andy Aug 10 '17 at 01:47
  • 1
    I edited the answer to reflect the current notion of preferring `target_include_directories` for modern CMake code. Feel free to invite me to a chat if you disagree with the changes. – ComicSansMS Feb 06 '18 at 12:10
  • Is there any way to include whole directory without adding each file one-by-one? The directory that I want to include contains nearly 100 header files. – J K May 31 '18 at 20:06
  • Why do you have to explicitly list the `.h` files in your executable's source files? Surely you should just specify the path to your headers then use `#include ` from your implementation `.cpp` files? – donturner Dec 13 '18 at 14:07
  • 1
    @donturner You don't have to add `.h` files into `add_executable`. But, It does have the nice benefit of making the files show up in `Visual Studio` projects in the expected location. `Makefiles` uses the internal `cmake -E cmake_depends` to generate dependencies from the source files (header files in `add_executable` are skipped). There are known [issues](https://gitlab.kitware.com/cmake/cmake/issues/16277) with this the scanner. Also ` CMake's Makefile generator dependency scanner does only approximate preprocessing.` Computed header includes and that sort of thing will not work. – fdk1342 Jan 01 '19 at 07:12
  • But how do you figure out the directory? Say I'm trying to find D:/TeamCity/mod/thirdparty/vcpkg-msvc_15.9.21-2d63525/installed/x64-windows-custom/include/aws/core/Aws.h> and msvc cannot find #include and the 'vcpkg-msvc_15.9.21-2d63525' portion of the path isn't constant? I see things like ${_VCPKG_INSTALLED_DIR} and ${THIRDPARTY_LIB_DIR} but I can't figure out what permutation of things I need to get a working path targeted. Especially when the above dir and the src are in two completely different places. – JoeManiaci Jun 19 '19 at 18:13
84

First, you use include_directories() to tell CMake to add the directory as -I to the compilation command line. Second, you list the headers in your add_executable() or add_library() call.

As an example, if your project's sources are in src, and you need headers from include, you could do it like this:

include_directories(include)

add_executable(MyExec
  src/main.c
  src/other_source.c
  include/header1.h
  include/header2.h
)
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Angew is no longer proud of SO
  • 156,801
  • 13
  • 318
  • 412
  • 29
    Do you really need to add headers to `add_executable`? I thought CMake figured out the include file dependencies automatically. – Colin D Bennett Nov 02 '13 at 17:40
  • 68
    @ColinDBennett You don't have to list them for dependency reasons - CMake figures out build dependencies just fine if you don't. But if you list them, they are considered part of the project, and will be listed as such in IDEs (which was the topic of the question). – Angew is no longer proud of SO Nov 02 '13 at 18:57
  • At least for QtCreator it is not necessary to add class.h in case a class.cpp exists. Only lonely.h needs to be added to source. See tutorial at [www.th-thielemann.de/cmake](http://www.th-thielemann.de/cmake) – Th. Thielemann Jan 22 '18 at 18:47
26

CMake is more like a script language if comparing it with other ways to create Makefile (e.g. make or qmake). It is not very cool like Python, but still.

There are no such thing like a "proper way" if looking in various opensource projects how people include directories. But there are two ways to do it.

  1. Crude include_directories will append a directory to the current project and all other descendant projects which you will append via a series of add_subdirectory commands. Sometimes people say that such approach is legacy.

  2. A more elegant way is with target_include_directories. It allows to append a directory for a specific project/target without (maybe) unnecessary inheritance or clashing of various include directories. Also allow to perform even a subtle configuration and append one of the following markers for this command.

PRIVATE - use only for this specified build target

PUBLIC - use it for specified target and for targets which links with this project

INTERFACE -- use it only for targets which links with the current project

PS:

  1. Both commands allow to mark a directory as SYSTEM to give a hint that it is not your business that specified directories will contain warnings.

  2. A similar answer is with other pairs of commands target_compile_definitions/add_definitions, target_compile_options/CMAKE_C_FLAGS

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
bruziuz
  • 4,177
  • 2
  • 33
  • 37
21

Add include_directories("/your/path/here").

This will be similar to calling gcc with -I/your/path/here/ option.

Make sure you put double quotes around the path. Other people didn't mention that and it made me stuck for 2 days. So this answer is for people who are very new to CMake and very confused.

off99555
  • 2,671
  • 2
  • 24
  • 36
7

I had the same problem.

My project directory was like this:

    --project
    ---Classes
    ----Application
    -----.h and .c files
    ----OtherFolders
    --main.cpp

And what I used to include the files in all those folders:

    file(GLOB source_files
            "*.h"
            "*.cpp"
            "Classes/*/*.cpp"
            "Classes/*/*.h"
    )

    add_executable(Server ${source_files})

And it totally worked.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
  • 2
    Remembering that cmake is a 'build system generator' and not a 'build system' using file glob is not a good idea in modern cmake (CMake with versions 3.0 and above) because file globs are evaluated at 'build' time and not 'build system generation' time. See link : https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1 – ggulgulia Mar 21 '20 at 10:34
  • Just add `CONFIGURE_DEPENDS`. – letmaik Jul 06 '20 at 10:33
  • `CONFIGURE_DEPENDS` is slow on Windows, not guaranteed to be supported on all future generators, and makes it harder to do git bisects with incremental builds. The maintainers still (at time of writing) discourage its use for collecting lists of source files. – Alex Reinking Aug 27 '20 at 10:54
2

This worked for me:

set(SOURCE main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE})

# target_include_directories must be added AFTER add_executable
target_include_directories(${PROJECT_NAME} PUBLIC ${INTERNAL_INCLUDES})
-1

I am using CLion also my project structure is the following :

--main.cpp
--Class.cpp
--Class.h
--CMakeLists.txt

The CMakeLists.txt before the change:

add_executable(ProjectName main.cpp)

The CMakeLists.txt after the change:

add_executable(ProjectName main.cpp Class.cpp Class.h)

By doing that the program compiled successfully.

konmaz
  • 1
  • 1