How to use CMAKE_EXPORT_COMPILE_COMMANDS?
Asked Answered
C

6

86

I've been trying to use clang-modernize with CMAKE_EXPORT_COMPILE_COMMANDS as recommended in the help of this tool.

With this option cmake generates a JSON file containing compile info like include paths (see also).

This variable is accepted on the command line of cmake, but cmake --help-variable CMAKE_EXPORT_COMPILE_COMMANDS doesn't work (which is coherent with this mailing list posting).

Has someone any idea on how to use it?

I could also use it with cppcheck.

Some more info

I've discovered on a clang developer forum that this cmake feature is not available on all generators. This might change in the future, in the mean time my question remains and I will try too see what happen if I use other generators than Visual Studio.

Cerate answered 18/11, 2013 at 22:51 Comment(0)
G
96

I suggest setting

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

in the CMakeList.txt

Grouper answered 20/8, 2017 at 10:53 Comment(5)
late to the show but for those also googling this, that would never have worked - it has to be set prior to the invocation of cmake. A 2nd cmake invocation would see it work however.Edition
@HörmannHH Thanks for mentioning this. I had exactly this issue where compile_commands.json was never generated the first time, but only after the second configure.Diocese
Continuing my search I found this issue gitlab.kitware.com/cmake/cmake/issues/16588. I was able to make it happen in CMakeLists.txt if I put it right after my project() specification.Diocese
In the (now closed) issue linked by @Marnix, there was another cause for this issue that came from CMake overwriting the variable, even if project() was called before the variable was set. This was resolved for CMake 3.18+; for older versions, a workaround can be implemented by modifying the set() command to set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "").Steelworks
I had trouble with the generated file not working correctly (clang-d complaining about strange things) until I put this command directly under the project(...) command e.g) second line of the file.Grantgranta
C
39

As of CMake 3.5 the CMAKE_EXPORT_COMPILE_COMMANDS option is supported by the Ninja and Makefiles generators.

That means to generate a JSON compile database one has to select a generator that supports it.

For example on UNIX just:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src

(as it uses the makefile generator there, by default)

Otherwise you can explicitly specify a generator like this:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src -G Ninja

Or:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 /path/to/src -G 'Unix Makefiles'

Or another makefiles variant that your cmake supports - a list of supported generators is included in the output of cmake --help.

Note that the compile database JSON file is generated at cmake execution time - not at compile time. Also, with recent clang versions (e.g. clang >= 3.8), clang-modernize was merged into clang-tidy.

Cervine answered 26/6, 2016 at 16:0 Comment(0)
V
5

I too was not able to get to work on the Visual Studio generator. It did, however, work using the "NMake Makefiles" generator.

C:\work\build>cmake -G "NMake Makefiles"  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON  ..
Verlinevermeer answered 3/2, 2014 at 22:7 Comment(1)
M
2

The first one you use CMAKE_EXPORT_COMPILE_COMMANDS ON in your CMakelists.txt Or run CMake with following parameters:

cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..

1.Option:

Here is a simple source and build tree to make it clear.

.
├── build
├── cars
│   ├── car.cpp
│   ├── car.h
│   └── CMakeLists.txt
├── CMakeLists.txt
└── main.cpp

main.cpp

#include <iostream>

#include "car.h"

int main (int argc, char *argv[])
{
    std::cout << "car - main function" << std::endl;
    showCarName();
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.20)
project(Cars
    VERSION 0.1
    HOMEPAGE_URL "github/alitokur"
    LANGUAGES CXX
    )

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

    add_executable(carApp main.cpp)
    add_subdirectory(cars)
    target_link_libraries(carApp PRIVATE cars)

cars/CMakeLists.txt

add_library(cars OBJECT
    car.cpp
    )
target_include_directories(cars PUBLIC .)

And that's all, target link directories allow main.cpp to include the cars.h file without providing a relative path. You should use set(CMAKE_EXPORT_COMPILE_COMMANDS ON) after the project() definition because sometimes other tools override this setting and that's why you can't see compile_commands.json.

enter image description here

Miscue answered 10/1, 2023 at 9:11 Comment(0)
F
2

CMake 3.17

As of CMake 3.17 you can now set CMAKE_EXPORT_COMPILE_COMMANDS as an environment variable.

The default value for CMAKE_EXPORT_COMPILE_COMMANDS when there is no explicit configuration given on the first run while creating a new build tree. On later runs in an existing build tree the value persists in the cache as CMAKE_EXPORT_COMPILE_COMMANDS.

This is the best approach since you don't have to pollute project code or remember to set it individually for each project.

# Set this in your .bashrc or whatever environment you choose to set env variables
export CMAKE_EXPORT_COMPILE_COMMANDS=1

CMake 3.5

The second best approach is to pass CMAKE_EXPORT_COMPILE_COMMANDS as a cache variable when configuring the project.

cmake -S . -B build -D CMAKE_EXPORT_COMPILE_COMMANDS=1

I prefer the new CMake 3.17 approach, since the 3.5 approach is easy to forget.

Flashboard answered 9/2, 2023 at 17:42 Comment(2)
should compile_command.json be re-generated on incremental builds or is it an initial build thing?Leporine
It will be updated as needed. If you change a compiler option or file name. Then compile_commands.json will be updated by CMake.Flashboard

© 2022 - 2024 — McMap. All rights reserved.