# CMake

### Generate a compilation database with CMake

CMake can generate a compilation database at configuration. When using a CMake project you have two ways of generating it:

* Using the CMAKE\_EXPORT\_COMPILE\_COMMANDS variable globally (from CMake 3.5): <https://cmake.org/cmake/help/latest/variable/CMAKE\\_EXPORT\\_COMPILE\\_COMMANDS.html>
* Using the EXPORT\_COMPILE\_COMMANDS target property for the specific target you want to analyze (from CMake 3.20): <https://cmake.org/cmake/help/latest/prop\\_tgt/EXPORT\\_COMPILE\\_COMMANDS.html#prop\\_tgt:EXPORT\\_COMPILE\\_COMMANDS>

Compilation database generation with CMake is only available with Makefiles and Ninja generators. Any other generator will ignore these variables and the compilation database will not be generated.

{% hint style="warning" %}
If your CMake configuration has multiple targets, it is strongly recommended to activate compile commands generation only for the target you want to analyze. Generating compile commands globally in multi-target projects may lead to undefined behaviour if some sources are compiled multiple times with different commands.
{% endhint %}

{% stepper %}
{% step %}

### Enable compile commands globally

You can enable global generation either from the CMake command line:

{% code title="Command" %}

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
```

{% endcode %}

or by setting it in the root `CMakeLists.txt`:

{% code title="CMakeLists.txt" %}

```cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
```

{% endcode %}
{% endstep %}

{% step %}

### Prefer enabling per-target (recommended for multi-target projects)

First, force the global generation off:

{% code title="CMakeLists.txt" %}

```cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)
```

{% endcode %}

Then, enable it for the specific target:

{% code title="CMakeLists.txt" %}

```cmake
set_target_properties(mytarget PROPERTIES EXPORT_COMPILE_COMMANDS ON)
```

{% endcode %}
{% endstep %}
{% endstepper %}

When running CMake, `compile_commands.json` is generated in the build directory. For example, running:

{% code title="Command" %}

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release .
```

{% endcode %}

will produce `./build/compile_commands.json`.

In beLow, enter the CMake command as the "Configure script" when asked; beLow will find the `compile_commands.json` file by name.

Try not to leave any stale `compile_commands.json` files in your project root if you can generate them at configuration or build time. A leftover file may be used in priority and cause issues if it is out of date or uses absolute paths (in copy mode).

### Windows specificities

On Windows, CMake's compile-commands generation can produce commands with unexpected escaping of backslashes and quotes. A common problematic case is when injecting include file names via preprocessor definitions.

Example C/C++ usage you might try:

{% code title="source.c / source.cpp" %}

```c
#include LIB_HEADER_FILE
```

{% endcode %}

And in `CMakeLists.txt`:

{% code title="CMakeLists.txt (problematic)" %}

```cmake
add_definitions(-DLIB_HEADER_FILE="lib.h")
```

{% endcode %}

CMake may generate an over-escaped entry in `compile_commands.json` like `-DLIB_HEADER_FILE=\"lib.h\"`, which breaks the intended injection.

There are two ways to address this:

* Modify the compilation database after generation with a script (not recommended).
* Prefer rewriting the macro so the compiler adds the quotes. This is the recommended approach.

Recommended fix in source:

{% code title="source.c / source.cpp" %}

```c
#define INCLUDE_FILE(x) #x
#include INCLUDE_FILE(LIB_HEADER_FILE)
```

{% endcode %}

Then, in your `CMakeLists.txt`, define the macro without quotes:

```cmake
add_definitions(-DLIB_HEADER_FILE=lib.h)
```

or for a target:

```cmake
target_compile_definitions(<your-target> PUBLIC LIB_HEADER_FILE=lib.h)
```

With this approach, after running CMake configuration the generated compilation database will be correct.

Last updated 1 month ago


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wedolow.com/documentation/ressources/compatibility-guide/cmake.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
