246

I have a directory structure for my C++ code which goes like this :

|
|->include
|->src

I am writing a CMakeLists.txt file for my code. I want to understand the difference between include_directories and target_include_directories in CMake.

What is the difference between their usage and in order to add my include file path which one should I be using?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Ujjwal Aryan
  • 3,827
  • 3
  • 20
  • 31
  • 187
    There is no clarity in the documentation. I read it and surmised what Angew has written in his answer, but there are no descriptions, no examples and for a system that is meant for project building, there are no project based examples in CMake documentation. Had there been a good and exhaustive documentation of CMake, I would not have been burdening the community with these questions. – Ujjwal Aryan Aug 12 '15 at 15:45
  • 9
    Concepts of cmake is poorly documented. Particularly target and “untargeted”. – John Greene Jul 19 '19 at 10:54
  • 7
    Agree that CMake documentation is bad, how much effort do they save to not provide examples? When I was new to CMake I was often confused with old/new syntaxes. – Tien Do Oct 22 '20 at 02:25
  • 7
    30 years of coding experience has taught me that undocumented software is as good as non-existent software and poorly documented software is worse than code that doesn't even compile. As such I think this question should be treated like a bug report. – Coder Guy Feb 18 '21 at 02:31

3 Answers3

254

include_directories(x/y) affects directory scope. All targets in this CMakeList, as well as those in all subdirectories added after the point of its call, will have the path x/y added to their include path.

target_include_directories(t x/y) has target scope—it adds x/y to the include path for target t.

You want the former one if all of your targets use the include directories in question. You want the latter one if the path is specific to a target, or if you want finer control of the path's visibility. The latter comes from the fact that target_include_directories() supports the PRIVATE, PUBLIC, and INTERFACE qualifiers.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • 46
    I think the latter one should generally be preferred (as long as one is using cmake 3). It has the added benefit of putting ``x/y`` in the include path of any dependent targets that use ``t`` in their ``target_link_libraries`` commands. Of course there is a place for the former, but I believe the latter is generally better. – Phil Aug 12 '15 at 16:11
  • 2
    The original answer stated that only targets and subdirs added after `include_directories` will be affected. I'm editing the answer: the documentation clearly states that *all* targets in the current CMakeLists are affected. The documentation does not mention but only subdirs after the call are affected (as was correctly stated in the original answer) – tamas.kenez Aug 12 '15 at 17:07
  • @Phil, `target_include_directories` has been introduced in CMake 2.8.11 (May 2013) – tamas.kenez Aug 12 '15 at 17:11
  • @tamas.kenez Thanks for bringing this to my attention, fixed. I was quite convinced it was a "from now on" thing. – Angew is no longer proud of SO Aug 13 '15 at 15:30
  • 1
    I should Greasemonkey your answer onto the official documentation for `include_directories`, concise and clear, thank you! So then `target_include_directories` is a carpenter's hammer and `include_directories` is a sledge hammer. – Coder Guy Feb 18 '21 at 02:34
  • so can we say that include_directories will need more compile time than target_include_directories since every library will need to search the directories in include_directories ? – BruceSun Dec 29 '21 at 01:54
  • 100x clearer than the docs. as of July 2022 they never mention "include path" anywhere and all I needed was these two little words put next to each other – ljleb Jul 23 '22 at 06:35
  • Anyone know how to print out the directories stored by target_include_directories? I tried the code provided here, and the result is always empty: https://stackoverflow.com/questions/6902149/listing-include-directories-in-cmake – Oscar Aug 25 '22 at 20:43
  • 1
    @Oscar You need to retrieve the property `INCLUDE_DIRECTORIES` of the *target.* The question you're linking to retrieves the property of the *directory.* – Angew is no longer proud of SO Aug 26 '22 at 05:47
  • @AngewisnolongerproudofSO Thanks! I did realize that at some point and got it working. – Oscar Aug 26 '22 at 22:12
68

Beside what Angew's answer correctly says, another very important difference between include_directories and target_include_directories is that, when used with PUBLIC or INTERFACE, the latter populate the INTERFACE_INCLUDE_DIRECTORIES property of the target. This property is useful when another target uses target_link_libraries to link to the original target, as the linking target will have automatically those include directories added. See example.

This important feature is pretty well hidden in the documentation: target_include_directories mention populating INTERFACE_INCLUDE_DIRECTORIES, whose documentation says:

When target dependencies are specified using target_link_libraries(), CMake will read this property from all target dependencies to determine the build properties of the consumer.

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 4
    This is the first time I ever read an understandable explanation of the ```PUBLIC``` etc. properties! Thanks :D – RL-S Mar 18 '20 at 18:27
  • Removing the ambiguity: when you use `PUBLIC` or `INTERFACE` with `target_include_directories`, the property `INTERFACE_INCLUDE_DIRECTORIES` is filled with the include directories required to compile against the headers for the target. – nav Sep 14 '20 at 15:06
  • 4
    Check [here](https://stackoverflow.com/questions/26243169/cmake-target-include-directories-meaning-of-scope_) if you want know more about the meaning of the keywords `PRIVATE`, `PUBLIC` and `INTERFACE` using `target_include_directories` – nav Sep 14 '20 at 15:42
7

As @Angew said, the very difference is :

1, include_directories() is accessible for all the files in the source-tree 2, target_include_directories() is-only accessible for a specific target when compile.

Nick.Rhan
  • 167
  • 2
  • 7