Emacs LSP for C

Updated: Apr 22, 2023

LSP (Language Server Protocol)

Language Server Protocol [1] is a standard way of assisting programmers by providing set of features (like on the fly compilation, symbol resolution, references resolution, providing help or documentation etc). This is a client/server model, implementation of this protocol consist of a server process (eg: clangd [2]) parsing the code which is currently written (or already written) and listening for any client to connect with it and ask for details. The client (eg: lsp-mode [3] in emacs [4]) will communicate with the server on the fly and ask for details based on the current context of the code currently written.

clangd

This LSP server is provided by llvm [5] project for C/C++. Also, there are other LSP servers for C/C++ available like ccls [6]. This ccls depend on libclang [7] which is also used by clangd, basically libclang is the one which parses the source code. Both ccls and clangd utilize the libclang library for code parsing.

lsp-mode

This is a emacs package. This acts as a LSP client communicating with different LSP servers based on the current source file. There are additional packages like lsp-ui [8] to provide visual response.

../../_images/lsp-mode.png

Installation

LSP consist of two parts, the LSP server and the LSP client. For different languages, we need to install different LSP servers based on our requirement. On the client side, as we are going to use emacs, we only need to install lsp-mode (additionally lsp-ui) once, this same client can be used with multiple LSP servers for different languages.

Installing LSP Server for C/C++ (clangd)

For the C/C++ Language, we need to install clangd LSP server. This clangd is available on all major distros. You have to install based on your distro. Following command will install clangd in Arch [9].

$ sudo pacman -S clang

Installing bear [10]

Merely installing clangd will not going to provide all the LSP server functionality. You need to tell clangd about how-to parse each source file in your project so that clangd will be able to parse the source code same like the compiler will parse. To know how-to compile a source file, clangd uses compilation database [11]. This compilation database is nothing but a file called compile_commands.json which contains compilation command lines to compile each source code in the project. The cmake [12] can generate this compile_commands.json automatically when -DCMAKE_EXPORT_COMPILE_COMMANDS=ON added to cmake. The meson [16] can generate compile_commands.json automatically. But for non cmake or meson projects, bear tool is needed to produce compile_commands.json. This bear tool is available on all major distros. You have to install based on your distro. For Arch, bear is available in AUR [13].

Installing LSP Client for emacs (lsp-mode and lsp-ui)

Following emacs packages needed and can be installed through ELPA [20]/MELPA [21] (M-x list-packages).

  • lsp-mode (core LSP client)

  • lsp-ui (adds UI to lsp-mode)

  • company [14] (text completion Framework for emacs)

Configuration

Configuring clangd

For clangd, we need to generate compile_commands.json file in project root directory. If you are using autotools [15] based projects, instead of running make [17], you have to run make with bear like this,

$ bear -- make

This will run make along with bear and records all the compilation commands from make, finally bear saves all the recorded compilation commands in compile_commands.json.

Configuring emacs LSP packages

We need to add the following lines to .emacs [18] to configure the LSP packages,

;; company
(add-hook 'after-init-hook 'global-company-mode)

;; lsp (language server)
(require 'lsp-mode)
(add-hook 'prog-mode-hook #'lsp-deferred)

Running emacs with lsp-mode

Just open a C/C++ source file or header file, lsp-mode will be automatically become active, emacs will also start clangd process. Following keybindings will be helpful once lsp-mode is active.

  • M-. (to go to definition of the symbol at point)

  • M-, (to traverse back in call stack)

  • M-? (to list all references of the symbol at point)

  • s-l G r (peek all references of the symbol at point)

../../_images/lsp-peek-references.png

More lsp keybindings [19] are available for lsp-mode.