# How to structure include()-s

**URL:** <https://discourse.cmake.org/t/how-to-structure-include-s/13071>\
**Category:** Code\
**Created:** [November 27, 2024, 11:15am UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071 "2024-11-27T11:15:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![silverqx](https://discourse.cmake.org/user_avatar/discourse.cmake.org/silverqx/32/2353_2.png) [@silverqx](https://discourse.cmake.org/u/silverqx)\
**Post date:** [November 27, 2024, 11:15am UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/1 "2024-11-27T11:15:45Z")

</div>

I’m using include()-s all around even for **the same** module or file, eg. `include(TinyHelpers)`, I’m including it in the main `CMakeLists.txt` file at the top as it’s needed there, but I’m also including it in deeper modules or `add_subtirectory()`-ies.

One example for all, I have `include(TinyTestCommon)` in every test project ~46, I can remove all of them and instead use one include in the `tests/CMakeLists.txt` or a little deeper in my case like:

```cmake
include(TinyTestCommon)
add_subdirectory(functional)
add_subdirectory(unit)

```

In C++ you can `#include` in a deeper header file and then you can omit this `#include` in the parent file (this works in CMake too).

But in CMake, you can` include()` in top-level CMakeLists.txt and you don’t have to `include()` anywhere else then (this doesn’t work eg. in C++).

Now I’m wondering if it’s a good idea to remove include()-s I described in the paragraph above.

I suppose that CMake simply includes everywhere and doesn’t track whether the include is already in the scope, which means it can also increase performance? (No performance gain, I tried to remove ~56 include()-s and no performance gain).

But anyway should I look at it like they are duplicate includes or like every project should be self-contained and should be able to configure standalone?

Even when I removed all includes and they are only in the parent files I’m still able to rebuild sub-projects which doesn’t contain these includes like:

```cmake
cmake.exe --build <buildPath> --target mysql_querybuilder

```

This only supports the claim they are duplicate includes as I’m still able to build these sub-projects without these includes.

I searched in Scott book, docs, and also forum and found nothing about this problem.

How do you manage your includes?

---

<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:** [November 27, 2024, 8:17pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/2 "2024-11-27T20:17:52Z")

</div>

There won’t be a “one approach to rule them all” here. The best approach will depend on the project. Speaking of project…

> But anyway should I look at it like they are duplicate includes or like every project should be self-contained and should be able to configure standalone?

What do you mean by “project” here? I ask because I often see folks pepper calls to `project()` throughout their build, where really there should just be one `project()` call at the top level. But some repositories allow sub-parts to be built standalone, in which case the top of each standalone sub-tree will need a `CMakeLists.txt` with its own call to `project()`. The top of the repo might still allow all sub-parts to be pulled together in a single build, in which case you’ll have many `project()` calls. That’s fine, I’m just trying to clarify what you mean by “project”. Here, whether you want the ability to build such sub-directories standalone is directly relevant to where you need to put your `include()` calls.

A key thing to be careful of is to ensure that something in the current or parent scope has included whatever the thing is you need to use. Don’t rely on it having been included in some other sibling scope that isn’t an ancestor. Some things in CMake have global visibility (e.g. functions, macros, non-imported targets), but some are only visible if defined in the current or parent scope (e.g. variables, directory properties). Depending on what an included file defines, it might matter whether it is included in a parent scope or not.

It generally isn’t a problem if a file is included multiple times, unless it is specifically designed to do something when it is included and it only expects to be included once. Modules like `CPack` are designed to do something when it is included, rather than defining functions the project can call later. Such modules might be more problematic if included multiple times, but they are less common.

FWIW, I tend to find collecting together includes in the top level `CMakeLists.txt` can simplify some things, but it can also pull conditional logic away from the lower levels where it might otherwise be more relevant. An alternative would be to include files unconditionally even if not needed, which might be an acceptable strategy for some projects, but might break things for others (e.g. an included file doesn’t support a particular toolchain or target platform).

So the rather unsatisfactory answer I’d give is “it depends”.

---

<div class="post-metadata">

**Author:** ![silverqx](https://discourse.cmake.org/user_avatar/discourse.cmake.org/silverqx/32/2353_2.png) [@silverqx](https://discourse.cmake.org/u/silverqx)\
**Post date:** [November 27, 2024, 9:07pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/3 "2024-11-27T21:07:30Z")

</div>

> What do you mean by “project” here?

CMakeLists.txt file with the `project()` call. I have 4 libraries, 2 exe-s, and ~40 test cases (executables) in my repo/project, so there is ~46 projects in my CMake build (every project in its own sub-folder of course). I have 47 `project()` calls in this repo exactly. ( **OT:** is this a problem? that every exe, library has its own project() call?)

I don’t have any conditional includes(), virtually all of the includes that I have only include .cmake files, which contain functions (abstracted logic) **without** any state.

> Don’t rely on it having been included in some other sibling scope that isn’t an ancestor.

This is clear.

> Depending on what an included file defines, it might matter whether it is included in a parent scope or not.

I didn’t realize this, maybe some included files define some variable outside of a function, thx for clarifying this. (I will have to check this). Especially macro()-s can cause this problem, there are some macros() inside these includes (I think this will be the biggest problem if there will be any).

> it can also pull conditional logic away from the lower levels where it might otherwise be more relevant

Thx, need to check also.

I will have to check variables outside functions and macros(), but it looks like defining these includes in the top-level CMakeLists.txt might be a good idea in my case, it shouldn’t harm anything. Especially that `include(TinyTestCommon)` as it is included in 40 test cases (projects) and it only contains one function inside.

Thx for the detailed reply, I think is much more clear now for me.

---

<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:** [November 27, 2024, 9:16pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/4 "2024-11-27T21:16:04Z")

</div>

> [@silverqx](#):
>
> **OT:** is this a problem? that every exe, library has its own project() call?

Projects are not targets. A project is often closely associated with a package, and a package might provide multiple targets, CMake functions, etc.

Something you will commonly see in online tutorials and examples is to use `${PROJECT_NAME}` as the name of a target. Don’t do that, they are separate, distinct things. It may happen to be the case that a project has only one target, and it might be that the project name and that one target name are the same, but projects and targets are separate concepts.

---

<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:** [November 27, 2024, 9:18pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/5 "2024-11-27T21:18:45Z")

</div>

If you look at the `boost` project, it is the worst case scenario.

Every `boost submodule` is buildable standalone, but the price is high, if it depends on other boost library. And that is very common! In worst case, there are hundreds of include paths needed.

In contrast, if you setup a build from the source tar file distribution, only one include path is needed.

The build is very fast and simple.

With `Ninja`, you may build a single big project with many subdirectories and libraries.  
But even if you want to build only one unit test for a single library, it is possible and fast.

---

<div class="post-metadata">

**Author:** ![silverqx](https://discourse.cmake.org/user_avatar/discourse.cmake.org/silverqx/32/2353_2.png) [@silverqx](https://discourse.cmake.org/u/silverqx)\
**Post date:** [November 27, 2024, 9:55pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/6 "2024-11-27T21:55:16Z")

</div>

I have defined all my test cases virtually identically like this, should there be this `project()`? You can also see that include there I would like to get rid of 😁:

```cmake
project(mysql_querybuilder
    LANGUAGES CXX
)

add_executable(mysql_querybuilder
    tst_mysql_querybuilder.cpp
)

add_test(NAME mysql_querybuilder COMMAND mysql_querybuilder)

include(TinyTestCommon)
tiny_configure_test(mysql_querybuilder)

```

---

<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:** [November 28, 2024, 9:07pm UTC](https://discourse.cmake.org/t/how-to-structure-include-s/13071/7 "2024-11-28T21:07:31Z")

</div>

If you want to be able to build with that as a standalone project (i.e. that `CMakeLists.txt` file would be the top level of the build), then yes you need `project()` there. You would also need a call to `cmake_minimum_required()` before it. If you don’t need to be able to build it as a standalone project, then remove the `project()` call.
