This note is a guide to setup auto completion for C and C++ modes in Emacs on Windows with minimal manual work. We need Clang, Irony and some Company; we additionally require CMake and MinGW for building something small. Although there are many methods of getting this working, this was the most performant and least time-taking solution for me, so I’m documenting it here.
The general installation instructions provided in Irony’s
README works but it asks you to build the complete Clang compiler from source for a single DLL (
libclang.dll). I don’t know about you but this isn’t exactly my idea of fun. This article skips that and uses Clang’s binary directly; this method has some quirks captured below to help others and myself.
This article assumes that you are on Emacs 24.5 or later and have the following packages installed:
I think mine are from Melpa. Irony’s homepage is a straight-forward installation guide.
Company (Complete anything) is a text completion “UI” for Emacs. It has support for a variety of backends; Company only shows the choices, while the choices itself come from a backend.
company-irony is one of the supported backends that in turn depends on
company-irony the first in the list of backends for it to be picked up. Enable
company modes in the
c-mode-common-hook function (that is called for both
c++-mode). Effectively, my
.emacs looks thus:
(eval-after-load 'company '(add-to-list 'company-backends 'company-irony)) (defun my-c-common-setup () ;; function called by c-mode-common-hook (irony-mode 1) (company-mode))
Also fix key bindings to use Irony:
;; replace the `completion-at-point' and `complete-symbol' bindings in ;; irony-mode's buffers by irony-mode's function (defun my-irony-mode-hook () (define-key irony-mode-map [remap completion-at-point] 'irony-completion-at-point-async) (define-key irony-mode-map [remap complete-symbol] 'irony-completion-at-point-async)) (add-hook 'irony-mode-hook 'my-irony-mode-hook) (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
This snippet was lifted from the project’s homepage. Make sure you do the Windows performance tweaks; there are good reasons to do this.
(when (boundp 'w32-pipe-read-delay) (setq w32-pipe-read-delay 0)) ;; Set the buffer size to 64K on Windows (from the original 4K) (when (boundp 'w32-pipe-buffer-size) (setq irony-server-w32-pipe-buffer-size (* 64 1024)))
- Make sure CMake and MinGW are installed
- Install LLVM from a pre-built binary package
- It should match the bit-ness of the MinGW toolchain installed
- Verify that the installed directory has
- The LLVM binaries (specifically
clang.dll) should have been built with MinGW
- The ones built with MSVC didn’t seem to work for me
- I chose
While you type out code in a buffer with
irony-mode will get enabled and that would run a
irony-server.exe in the background. This program will talk to Clang as you type code into the buffer to get completion suggestions in real-time. But this program doesn’t come pre-built; it has to be built manually. This is the only manual building in our entire procedure:
- On a Command Prompt,
cdto Irony’s package site
mkdir build && cd build
cmake -DLIBCLANG_LIBRARY=C:\PROGRA~2\LLVM\bin\libclang.dll -G "MinGW Makefiles" ..
LIBCLANG_LIBRARYis set manually to make sure the right DLL is picked up
- Same may be needed for the
INCLUDEdirectory as well
- Notice that I have made sure there’re no spaces in the path, even when
Program Files (x86)is part of it. I have used its short name
dir /xto get a directory’s short name
- Open a
.cppfile and run
M-x irony-install-server; don’t press
- Copy the command shown and cancel it (
C-g). Run it on
- Before running on
cmdun-escape what Emacs escaped
:and path separator would be
- Before running on
- CMake should place
cpp -xc++ -Wp,-v < NUL
- Save just the (search) list of directories in a file named
- Change it into compiler flags that
clang++understands (see sample below)
- Put this file in the project root or your home directory
- Restart Emacs
- A buffer with
company-modeshould display suggestions
- Save it to a persistent file if it’s not backed by one
-std=c++14 -target i686-w64-windows-gnu -Wall -pedantic -DDEBUG -IF:/Apps/mingw32/lib/gcc/i686-w64-mingw32/6.3.0/include/c++ -IF:/Apps/mingw32/lib/gcc/i686-w64-mingw32/6.3.0/include/c++/i686-w64-mingw32 -IF:/Apps/mingw32/lib/gcc/i686-w64-mingw32/6.3.0/include/c++/backward -IF:/Apps/mingw32/lib/gcc/i686-w64-mingw32/6.3.0/include -IF:/Apps/mingw32/lib/gcc/i686-w64-mingw32/6.3.0/include-fixed -IF:/Apps/mingw32/i686-w64-mingw32/include -IF:/Libs/boost_1_57_0
Note: each argument gets its own line
-std=c++14 ate hours of my time investigating why C++14 syntax and tokens aren’t suggested by Clang. I then realized that I had installed Clang 3.4 and the documentation clearly states that
-std=c++1y is to be used for versions 3.4 or earlier.
As a verification of things working fine, check if a process of
irony-server.exe is running smoothly.
As a bonus of using Irony, we can do on-the-fly syntax checking using Clang and know of errors as the code is typed out without actually compiling the file separately. This quickens the development cycle by avoiding slow compilations; when you have an error-free buffer, you’ll only be left with linker errors, if at all, when you do a proper compilation. Install
flycheck-pos-tip. Enable it with
(eval-after-load 'flycheck '(add-hook 'flycheck-mode-hook #'flycheck-irony-setup))
flycheck-irony-setup is a function you get with the
flycheck-irony package. Make sure you enable Flycheck when needed
(defun my-c-common-setup () (flycheck-mode) (flycheck-pos-tip-mode))
Flycheck shows the errors in a separate buffer which keeps getting update as you type. But you can see the error in a particular statement without having to open this buffer with
flycheck-pos-tip-mode. It will show error tooltips as the cursor is moved to an erroneous token.
Without having a bloated IDE, you get to have both auto-complete (a.k.a. intellisense) and on-the-fly syntax checking. They are valuable tools when writing code in a project with large code bases, taking lot of time to build. Also, most IDEs require you to create a project for some single-file, toy, sample code you want to scribble; in our setup you just need to create a new buffer backed by a file on disk i.e. the usual drill for any new file. Make sure you have the right
.clang_complete saved in your Home directory (where you have your code lab of dirty files) with the required
include paths and compiler flags.
The advantage of Irony is that it uses a proper compiler (Clang) to do this job and hence the results are very reliable.
Finally, you can have a look at my
.emacs file if you’ve doubts.