Clangd based Emacs C++ IDE
Saturday, July 7, 2018
This is now very out of date! Updated method here: click.
I've seen a lot of posts on the Emacs and C++ subreddits over the last few months related to Emacs as a C/C++ IDE. If one gives the topic a quick googling a lot of tutorials pop up that will walk through using cquery, lsp-mode, rtags, ggtags, irony, company, ycmd, etc. (obviously there are a number of options out there and multiple blog posts and tutorials for each). I've personally tried using cquery and rtags (both libclang based) in combination with company-mode. Playing with those packages produced a hacked up Emacs init file and I didn't really know what I was doing at the time. I was never comfortable with the black box I created for myself -- so I decided to clean it up and start over after some research.
I've recently landed on a new setup using a combination of lsp-mode, company, and lsp-clangd. As is clear from the package name and post title, this method takes advantage of the LLVM/Clang tool clangd (which is very much in development).
Here's a quick rundown of the new configuration:
company-lsp is installed and enable company-mode (I
choose a global configuration):
(use-package company-lsp :ensure t :config (push 'company-lsp company-backends) (add-hook 'after-init-hook 'global-company-mode))
lsp-ui are installed and required:
(use-package lsp-mode :ensure t :commands lsp) (use-package lsp-ui :ensure t)
lsp-clangd isn't in melpa yet, so I cloned it to my
.emacs.d directory and make sure to point to it (while writing this
post there is an open GitHub
PR to add lsp-clangd to
melpa). Be sure to set the proper clangd executable path and add a
hook to C++ mode to enable it:
(use-package lsp-clangd :load-path "~/.emacs.d/lsp-clangd" :init ;; for macOS (when (equal system-type 'darwin) (setq lsp-clangd-executable "/usr/local/opt/llvm/bin/clangd")) ;; for linux machine with hostname "proton" (when (string= (system-name) "proton") (setq lsp-clangd-executable "/home/ddavis/software/llvm/head/bin/clangd")) (add-hook 'c++-mode-hook 'lsp-clangd-c++-enable))
Like I said, Clangd is under heavy development, so expect some
imperfections. For example, using the version shipped with the LLVM
6.0.0 release wasn't working with header files. I went ahead and built
a bleeding edge installation (using
brew install --HEAD llvm on
macOS and building from the trunk of their svn repositories on a
Fedora machine; read how to do that
here and that fixed the
I use this setup in combination with
that are produced by
This file must be kept at the project root (using
projectile with a
.projectile file at the project root helps when using git
repositories with submodules; lsp-mode appears to handle that nicely).
I'm still by no means an expert, but it was a good learning experience and I no longer have a black box from copying and pasting from other's Emacs init files. I have code completion and inter/intra-project file and definition jumping -- the two big features I like to add to my C++ development setup in Emacs.