How I currently (2025) set up Emacs for C++ and CMake

This is how I currently set up Emacs for C++, as an update to Trying to set up Emacs for C++ (2022).

Goals

I'm using Emacs to code for KDE projects, mostly written in C++/Qt.

Dependencies

Clangd as the language server, and lsp-mode as the LSP implementation in Emacs. I don't use Eglot because last time I used it it didn't support multiple language servers in one buffer, which is a thing I need.

Unlike in 2022 I'm not using Bear because I finally understand how to set up compile_commands.json. I finally understand now thanks to joshtronic - How to generate a JSON compile commands database with CMake.

Emacs setup

I'm just using Doom Emacs's module for this here without extra config. In other words, it's just

(doom!
 ;; ...
 :lang
 (cc +lsp))

The core of the module in this configuration is basically just running lsp-deferred in c++-mode.

CMake

Set up the build directory and make sure compile_commands.json is generated so that Clangd can make use of it:

cmake -B build -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=1
// Note that this isn't obvious (is it done when making the build directory or when doing a build?)

I use Ninja because it has parallel build by default.

This will put compile_commands.json in ./build, the build directory, but Clangd is able to make use of it when editing the source files.

I prefer to write this in the build command because I don't want to modify CMakeLists in projects that I don't maintain.

After setting up the build directory, spurious errors about missing stuff that are actually present should already be gone in the editor.

To build and run:

cmake --build ./build
./build/bin/[executable]