# How does add\_subdirectory(... SYSTEM) work?

**URL:** <https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198>\
**Category:** Code\
**Created:** [January 4, 2023, 7:10pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198 "2023-01-04T19:10:30Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 4, 2023, 7:10pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/1 "2023-01-04T19:10:30Z")

</div>

Hi all, fairly new to cmake.

I have a library that I want to use in my project but want its files to be treated as system header files when included in my own code.

Here’s my directory structure:

```auto
top
 src1
 src2
 src3
 include
 libs
  blah
    some_lib

```

In directory _libs_ I have a CMakeLists.txt that has

`add_subdirectory(blah/some_lib SYSTEM)`

_some\_lib_ itself uses its own cmake setup to build. I expected all the include directories from some\_lib to be using -isystem but they still use -I. I even tried adding

`add_subdirectory(libs SYSTEM)`

to my top level CMakeLists.txt but still no go.

Is this the right way to do what I want to do? Looking at the cmake documentation it’s not clear if the SYSTEM property will propagate to all subdirectories.

[https://cmake.org/cmake/help/latest/command/add\_subdirectory.html?highlight=add\_subdirectory](https://cmake.org/cmake/help/latest/command/add_subdirectory.html?highlight=add_subdirectory)

Thanks,  
Nick

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [January 4, 2023, 7:12pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/2 "2023-01-04T19:12:22Z")

</div>

I don’t see the docs mentioning that it is recursive, so I’d assume that it is not.

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 4, 2023, 7:13pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/3 "2023-01-04T19:13:37Z")

</div>

But in that case I’d be forced to edit the third-party library’s CMakeList.txt files, which is rather undesirable.

Nick

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [January 4, 2023, 7:52pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/4 "2023-01-04T19:52:08Z")

</div>

Yeah. Maybe there’s another way around this though. @craig.scott ?

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 4, 2023, 8:03pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/5 "2023-01-04T20:03:33Z")

</div>

I was trying to follow discussions like this [https://gitlab.kitware.com/cmake/cmake/-/issues/18040#note\_1197146](https://gitlab.kitware.com/cmake/cmake/-/issues/18040#note_1197146) but they did not make it clearer what to do.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [January 4, 2023, 9:56pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/6 "2023-01-04T21:56:06Z")

</div>

If I recall correctly, when you set the `SYSTEM` directory property to true, it propagates into any subdirectories that directory creates too. In other words, it should be acting recursively. It wouldn’t really make sense for it to work any other way, as already highlighted in comments above.

The behavior probably relates to details of the project not provided. You mentioned that the subdirectory uses its own cmake setup, but what does that mean? It is most likely related to that, but without any details about precisely how that is done and how you’re adding things from there into the main build, it’s hard to offer any further insight.

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 4, 2023, 10:11pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/7 "2023-01-04T22:11:27Z")

</div>

Could be. Is there a way to debug how the -I/-isystem paths are added to consumers?

I tried --debug-output/–log-level/–trace-source but it did not seem to have any info about that.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [January 5, 2023, 11:30am UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/8 "2023-01-05T11:30:13Z")

</div>

Depends what you mean by “how the -I/-isystem paths are added to consumers”. If you just want to see the compiler command lines so you can tell what flags are used, the method for that depends on what CMake generator you’re using. If you’re using Ninja, add `--verbose` to the `ninja` command line. If using Makefiles, add `VERBOSE=1` to the `make` command line (I think this works, it’s been so long since I had to do that with Makefiles). If you’re using something else, you can probably find the details in the IDE settings somewhere.

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 5, 2023, 7:14pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/9 "2023-01-05T19:14:46Z")

</div>

I can see that the command lines don’t have the -isystem that I expected.

What I meant is to find where those command lines are created. Perhaps checking the SYSTEM property at that point can shed some light and I can somehow trace it back.

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [January 7, 2023, 2:30am UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/10 "2023-01-07T02:30:09Z")

</div>

Can you show the contents of the file at `libs/blah/some_lib/CMakeLists.txt`? The details of that will probably shed some light on what’s really going on.

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 9, 2023, 3:45am UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/11 "2023-01-09T03:45:04Z")

</div>

It’s

[or-tools/CMakeLists.txt at stable · google/or-tools · GitHub](https://github.com/google/or-tools/blob/stable/CMakeLists.txt)

but when compilation lines for the consumers are created I see

`-I/home/nick/code/build/_deps/zlib-src`

instead of the expected

`-isystem/home/nick/code/build/_deps/zlib-src`

---

<div class="post-metadata">

**Author:** ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)\
**Post date:** [January 14, 2023, 8:02am UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/12 "2023-01-14T08:02:01Z")

</div>

I’ll be honest, that’s a lot more detail than I have time to go through. I suggest you reduce your real world case down to a minimal project which demonstrates the problem. That exercise very often uncovers the underlying cause. If you can still reproduce the problem with a very minimal example, that will be more likely to be investigated further.

---

<div class="post-metadata">

**Author:** ![nicks](https://discourse.cmake.org/user_avatar/discourse.cmake.org/nicks/32/3056_2.png) [@nicks](https://discourse.cmake.org/u/nicks)\
**Post date:** [January 15, 2023, 2:08am UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/13 "2023-01-15T02:08:58Z")

</div>

I can definitely understand 🙂 I have a decent workaround. As I get more comfortable with cmake, if I find the time, I’ll try to distill it and report it here.

Cheers!

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)\
**Post date:** [September 30, 2023, 6:30pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/14 "2023-09-30T18:30:18Z")

</div>

> [@craig.scott](#):
>
> If you can still reproduce the problem with a very minimal example, that will be more likely to be investigated further.

If I remember right, it may be caused by an open cmake [issue/23393](https://gitlab.kitware.com/cmake/cmake/-/issues/23393)

from installed **stagedir/lib/cmake/greeter/greeterTargets.cmake**

```cmake
# Create imported target greeter::greeter
add_library(greeter::greeter STATIC IMPORTED)

set_target_properties(greeter::greeter PROPERTIES
  INTERFACE_COMPILE_FEATURES "cxx_std_20;cxx_std_20"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include/greeter"
  INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:>"
  INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "include" # <<<<<<<<<<<<
)

```

created from [CMakeLists.txt](https://github.com/ClausKlein/ModernCmakeStarter/blob/3a816c49bb2286db05d257410946c7ec2999bce0/CMakeLists.txt)

```cmake
# target_include_directories with the SYSTEM modifier will request the compiler to omit warnings
# from the provided paths, if the compiler supports that
target_include_directories(
  ${PROJECT_NAME} SYSTEM PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
                                $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

```

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)\
**Post date:** [September 30, 2023, 6:59pm UTC](https://discourse.cmake.org/t/how-does-add-subdirectory-system-work/7198/15 "2023-09-30T18:59:15Z")

</div>

### But a local build works right:

```bash
bash-5.2$ ninja -nv GreeterStandalone 
[1/2] /usr/local/bin/ccache /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ \
 -I/Users/clausklein/Workspace/cpp/ModernCmakeStarter/build/standalone/_deps/greeter-build/PackageProjectInclude \
 -isystem /Users/clausklein/Workspace/cpp/ModernCmakeStarter/include -isystem /usr/local/include \
 -O3 -DNDEBUG -std=gnu++20 -isysroot \
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk \
-mmacosx-version-min=13.6 -MD -MT CMakeFiles/GreeterStandalone.dir/Unity/unity_0_cxx.cxx.o \
-MF CMakeFiles/GreeterStandalone.dir/Unity/unity_0_cxx.cxx.o.d -o CMakeFiles/GreeterStandalone.dir/Unity/unity_0_cxx.cxx.o \
-c /Users/clausklein/Workspace/cpp/ModernCmakeStarter/build/standalone/CMakeFiles/GreeterStandalone.dir/Unity/unity_0_cxx.cxx

```

see [standalone/CMakeLists.txt](https://github.com/ClausKlein/ModernCmakeStarter/blob/3a816c49bb2286db05d257410946c7ec2999bce0/standalone/CMakeLists.txt)
