# the usage of target\_include\_directories vs target\_link\_libraries

**URL:** https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914
**Category:** Usage
**Created:** [April 16, 2023, 5:17am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914 "2023-04-16T05:17:17Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![alice](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alice/32/1615_2.png) [@alice](https://discourse.cmake.org/u/alice)
#### Post date: [April 16, 2023, 5:17am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/1 "2023-04-16T05:17:17Z")

</div>

anyone know the reason?  
why `target_include_directories` need to set the ${FMT\_INCLUDE\_DIRS} but not set the ${OpenCV\_INCLUDE\_DIRS}

```auto
target_include_directories(myapp PUBLIC
		${FMT_INCLUDE_DIRS}
	)
target_link_libraries(myapp
		${OpenCV_LIBRARIES}
		${FMT_LIBRARIES}
	)

```

---

<div class="post-metadata">

### Author: ![Joseph](https://discourse.cmake.org/user_avatar/discourse.cmake.org/joseph/32/3344_2.png) [@Joseph](https://discourse.cmake.org/u/Joseph)
#### Post date: [April 16, 2023, 6:43am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/2 "2023-04-16T06:43:01Z")

</div>

Where does this code comes from? I don’t think it is correct. if `myapp` doesn’t include `${OpenCV_INCLUDE_DIRS}`, the source code won’t be able to find opencv headers.

The only explaination if this code works, it that `${OpenCV_INCLUDE_DIRS}` are added globally for all targets by `include_directories`, or my app doesn’t uses opencv headers at all.

---

<div class="post-metadata">

### Author: ![alice](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alice/32/1615_2.png) [@alice](https://discourse.cmake.org/u/alice)
#### Post date: [April 17, 2023, 2:02am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/3 "2023-04-17T02:02:19Z")

</div>

thanks

by the way,  
do you know how to usage the private and public?

1. 

here is the fix by me and the original is on the button of the page .

If I want to generate two exe with different \*.cpp (main.cpp and main2.cpp)

Is it right? I am confused on public and private  
if there are the example, it is great.

```auto
target_include_directories(tensorrt_cpp_api PUBLIC ${OpenCV_INCLUDE_DIRS} ${CUDA_INCLUDE_DIRS} ${TensorRT_INCLUDE_DIRS})
target_link_libraries(tensorrt_cpp_api PUBLIC ${OpenCV_LIBS} ${CUDA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${TensorRT_LIBRARIES})

add_executable(driver src/main.cpp)
target_link_libraries(driver tensorrt_cpp_api)

add_executable(driver2 src/main2.cpp)
target_link_libraries(driver2 tensorrt_cpp_api)

```

here is the original:

> <https://github.com/cyrusbehr/tensorrt-cpp-api/blob/main/CMakeLists.txt>

---

<div class="post-metadata">

### Author: ![Joseph](https://discourse.cmake.org/user_avatar/discourse.cmake.org/joseph/32/3344_2.png) [@Joseph](https://discourse.cmake.org/u/Joseph)
#### Post date: [April 17, 2023, 5:11am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/4 "2023-04-17T05:11:17Z")

</div>

Your fixed code is correct. `tensorrt_cpp_api` is a lib, so link publically will always works no matter it is static or shared.

There are three modes for a target to link another lib, or include a directory: PUBLIC, PRIVATE and INTERFACE. For example: we have lib A and B, and a executable C. B links to A, and C links to B.

Pubic link:

```cmake
target_link_libraries(B PUBLIC A)
target_link_libraries(C PRIVATE B)

```

B will link to A, and C will be linked to both A and B.

Private link:

```cmake
target_link_libraries(B PRIVATE A)
target_link_libraries(C PRIVATE B)

```

B will link to A, and C will link to only B.

Interface link:

```cmake
target_link_libraries(B INTERFACE A)
target_link_libraries(C PRIVATE B)

```

B will not link to A, but C will link to both B and A.

In summary, PUBLIC is contagious, and PRIVATE is not contagious. INTERFACE is only used when B doesn’t actually requires A, but most targets that links to B requires A. INTERFACE is rarely used.

---

<div class="post-metadata">

### Author: ![Joseph](https://discourse.cmake.org/user_avatar/discourse.cmake.org/joseph/32/3344_2.png) [@Joseph](https://discourse.cmake.org/u/Joseph)
#### Post date: [April 17, 2023, 5:14am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/5 "2023-04-17T05:14:48Z")

</div>

In my point of view, a static lib should always links PUBLIC ly to its dependencies, and a shared lib should link PRIVATE ly to its dependencies. For executables, PUBLIC and PRIVATE have no difference, because no targets can link to a executable.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 17, 2023, 7:49am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/6 "2023-04-17T07:49:16Z")

</div>

Hi IMHO, I partially agree for the executable part but not for the library one.  
First of all it does not depend on the shared/static status.  
Let say a lib A depends on a lib B.  
If the headers of A that may be included by an application that links A contains symbols from B then `target_link_libraries(A PUBLIC B)`  
otherwise `target_link_libraries(A PRIVATE B)`  
another situation may arise: B symbols are only present in A headers but are not used for A sources.  
then `target_link_libraries(A INTERFACE B)`

for applications I agree that `PUBLIC` or `PRIVATE` should not make a difference, yet its cleaner then to use `PRIVATE`.

I sum up it in the following way (`for target_compile_definitions` and `target_link_libraries`):  
`PRIVATE`: the target uses the definition/dependency only to be build, not its clients  
`PUBLIC`: the target uses the definition/dependency when it is built, its clients also use it  
`INTERFACE`: the target does not uses the definition/dependency when it is built, but its clients use it

---

<div class="post-metadata">

### Author: ![hsattler](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/59ef9b/32.png) [@hsattler](https://discourse.cmake.org/u/hsattler)
#### Post date: [April 17, 2023, 7:49am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/7 "2023-04-17T07:49:30Z")

</div>

Not quite. Shared libraries can also link publicly when their header files expose e.g types from the linked library.  
For executables, the only use case I know is that loadable modules may link to it on some platforms.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 17, 2023, 7:55am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/8 "2023-04-17T07:55:48Z")

</div>

NB there is a scenario that may be confusing:  
A uses B privately (no trace of B in its API)  
an application C uses A and B

it would be tempting to `target_link_libraries(A PUBLIC B)` and `target_link_libraries(C PRIVATE A)` but it would be wrong even if it would work I think.  
I would go for:  
`target_link_libraries(A PRIVATE B)`  
`target_link_libraries(C PRIVATE A)`  
`target_link_libraries(C PRIVATE B)`  
which describes exactly the nature of the dependencies

At least, it is my understanding.  
A.

---

<div class="post-metadata">

### Author: ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)
#### Post date: [April 17, 2023, 7:57am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/9 "2023-04-17T07:57:17Z")

</div>

Other possibility is that `OpenCV_LIBRARIES` actually contains CMake targets, but `FMT_LIBRARIES` only contains path(s) to the libraries.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [April 17, 2023, 8:39am UTC](https://discourse.cmake.org/t/the-usage-of-target-include-directories-vs-target-link-libraries/7914/10 "2023-04-17T08:39:50Z")

</div>

As for `target_include_directories`, it depends on the target nature.  
for headers only libraries, I would use `INTERFACE` for the `INSTALL_INTERFACE`  
For other libraries, I would put headers that may be include by third-party target in a different directory than the one used only by the target.  
The first one will be declared `PUBLIC` for the `BUILD_INTERFACE` and `INSTALL_INTERFACE`.  
For applications, I would declare only `PRIVATE` for the `BUILD_INTERFACE` and `INSTALL_INTERFACE`.

A.
