# How to idiomatically add include path flags inside add\_custom\_command?

**URL:** https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843
**Category:** Code
**Tags:** gen:ninja
**Created:** [March 28, 2025, 1:01pm UTC](https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843 "2025-03-28T13:01:43Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Time0o](https://discourse.cmake.org/user_avatar/discourse.cmake.org/time0o/32/5295_2.png) [@Time0o](https://discourse.cmake.org/u/Time0o)
#### Post date: [March 28, 2025, 1:01pm UTC](https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843/1 "2025-03-28T13:01:43Z")

</div>

This is pattern I’ve had to use multiple times and I keep thinking that the “correct” way to do it should be something like:

```cmake
add_custom_command(
  # ...
  COMMAND ${CMAKE_COMMAND} -E env my_compiler some_file "-I$<JOIN:${MY_INCLUDE_DIRS}, -I>"
  # ...
)

```

But this does not work because CMake escapes whitespace between flags. The obvious alternative would be getting rid of the quotes around the generator expression but that causes it to not be expanded at all in `build.ninja` (or similar)!

Is there really no way to achieve this without “manual” string operations?

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [March 28, 2025, 1:09pm UTC](https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843/2 "2025-03-28T13:09:24Z")

</div>

There is an example showing precisely this in the [genex documentation](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#whitespace-and-quoting). The example builds it up in several steps, but here are the two final forms it offers:

#### Using `$<JOIN>`:

> ```auto
> # The $<BOOL:...> check prevents adding anything if the property is empty,
> # assuming the property value cannot be one of CMake's false constants.
> set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
> add_custom_target(run_some_tool
> COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
> COMMAND_EXPAND_LISTS
> VERBATIM
> )
> 
> ```

#### Using `$<LIST>`:

> ```auto
> add_custom_target(run_some_tool
> COMMAND some_tool "$<LIST:TRANSFORM,$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,PREPEND,-I>"
> COMMAND_EXPAND_LISTS
> VERBATIM
> )
> 
> ```

---

<div class="post-metadata">

### Author: ![Time0o](https://discourse.cmake.org/user_avatar/discourse.cmake.org/time0o/32/5295_2.png) [@Time0o](https://discourse.cmake.org/u/Time0o)
#### Post date: [March 28, 2025, 1:12pm UTC](https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843/3 "2025-03-28T13:12:42Z")

</div>

Thanks @Petr! With the linked section I think I’ve now finally understood this, I should probably read the whole page…

---

<div class="post-metadata">

### Author: ![chillenb](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chillenb/32/5666_2.png) [@chillenb](https://discourse.cmake.org/u/chillenb)
#### Post date: [July 12, 2025, 11:58pm UTC](https://discourse.cmake.org/t/how-to-idiomatically-add-include-path-flags-inside-add-custom-command/13843/4 "2025-07-12T23:58:16Z")

</div>

I have a question about this. If tgt’s INCLUDE\_DIRECTORIES has `$<BUILD_INTERFACE:...>` and `$<INSTALL_INTERFACE:...>` generator expressions as suggested [here](https://cmake.org/cmake/help/latest/command/target_include_directories.html), then

```auto
"$<LIST:TRANSFORM,$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,PREPEND,-I>"

```

expands to something like

```auto
-Idir1 -Idir2 -I -Idir3

```

with one empty `-I` flag for each `$<INSTALL_INTERFACE:...>`. The empty `-I` flags cause gcc to complain it can’t find headers! Is there a way to filter these out?

Edit: the form with `$<JOIN>:` doesn’t produce the empty `-I` flags and works as expected! It seems these two solutions are not equivalent. It would be a good idea to update the documentation accordingly (or fix the bug, if it’s a bug).

```auto
set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
add_custom_target(run_some_tool
  COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
  COMMAND_EXPAND_LISTS
  VERBATIM
)

```
