Using Emacs as a C++ IDE
By on July 17, 2016
An updated version of this post is available
Last year I wrote a post about using Flymake with Emacs to get on-the-fly syntax checking. Recently I watched a cppcon lightning talk by Atila Neves on his setup for using Emacs as a C++ IDE and was inspired to adapt this to my own needs. In this post I will guide you through the setup process, which will carry over to Aquamacs for the most part too. I’ll try to note any differences as they come up. This guide will also use Homebrew for installing some additional software, but on Ubuntu you should be able to get it from apt. Please note that I take no credit for this setup at all. It is all thanks to the many developers and blog authors whose content I was able to use and piece together. I will do my best to cite any resources as I go. I apologize in advance for anything I missed.
Additional Software Installation
First we will install the necessary backends using brew and then
move on to the actual Emacs setup. All of the packages listed here should
be installed by running
brew install package. I recommend that at this
stage you run
brew update to make sure you are getting the latest version
of all the packages. Let us first install the package Bear (Build
EAR) for recording how your project is
compiled. It won’t be necessary for all projects, but definitely for some.
To install it, run
brew install bear. If you use LaTeX I recommend you
install the package
chktex using brew as well.
In order to be able to use RTags to navigate your project
you should install LLVM using
brew install llvm --with-libcxx --with-clang --without-assertions --with-rtti.
I suggest you follow the RTags website for the most up-to-date
installation instructions. It may look long, but it is rather straight forward
to do. You can actually install RTags from brew by running
brew install rtags,
but note that you still need LLVM. Note that we will be changing the
way we launch
rdm later (if you don’t know what
rdm is, see here).
One really cool thing about RTags is that it is not specific to Emacs.
You can use it with vim, sublime, Atom, and possibly other editors too.
The last package I suggest you install is
clang-format, which allows you to
format parts or the entirety of your code to a a certain style. This is
extremely useful for ensuring uniform style across a project and for
maintaining readability. ClangFormat also is not tied to Emacs and can be used
stand alone or in other editors.
As a side note, if you want to try the clang-complete part of the IDE (I use
Flycheck’s clang-mode), you will probably have to install the
emacs-clang-complete-async package from brew or from the project’s
Below I’ll go over my Emacs init file (
~/.emacs) in a sort of section by section
What often annoys me in Emacs is that I have to type “yes” or “no”. I’d much prefer
to just type “y” and “n”. This can be done (thanks to the post here)
by adding the following to your init (
I also find the
#...# auto-save files annoying, so let’s disable that by adding
On OSX you will have to set additional paths in Emacs so that it can find the packages you install from brew. Add the following to the start of your init file:
Now, the easiest way to install all the packages we will use is to add the following to your init file:
This will automatically install any packages listed in the
package-list variable if it is not already installed.
If you are using a recent version of Emacs (24.3 or newer)
then everything should install without any issues.
If you are using Aquamacs on OSX then you may need to comment
out the lines below
;; install the missing packages and install
the packages yourself manually.
On The Fly Syntax Checking: Flycheck
Compiling code or running through an interpreter takes time. Time is probably
our most valuable personal resource. I’ve recently made the change from
Flymake to Flycheck. One of the reasons is that
it can be integrated with
compile_commands.json file that is generated by Bear. I also
have to write some python code on occasion, and there too I don’t want to
spend time running the code to check for errors. Flycheck offers an extension,
flycheck-pyflakes that does python syntax checking really well. Combining
these, I get a short section for my init file, but you will want to
cmake-ide to get the most out of it. Here is the relevant code:
Now there are sometimes some annoying things with Flycheck. While working on a large (and quickly growing) project I found that I sometimes got bizarre errors such as not being able to find a certain type, specifically a class we wrote, or even that there were errors in one of the included STL headers. This seemed really strange to me, especially because RTags syntax checking did not find these errors (I use RTags and Flycheck for syntax checking of larger projects). To make things even stranger, the code compiles fine. So after much stumbling around I think I finally understand what the issue is. Flycheck seems to parse the code local to the buffer, and so if that code does not compile stand-alone then you get strange errors. This could be seen as a good thing since it will force developers to explicitly include headers they use rather than using functions or classes because they are included in a header file that’s being included. So the lesson here is that if you get strange errors, don’t look at the first error, look at all of them and see if it could be related to missing headers preventing Flycheck from analyzing the code locally.
cmake-ide and RTags
Flycheck integrates nicely with the
cmake-ide package. The nice thing
cmake-ide is that it also sets up RTags for your project. To enable
RTags and cmake-ide, add the following to your init file:
You might notice that I set a keyboard shortcut,
C-c m, for compiling
Now let me discuss RTags and what I had to do to get cmake-ide to behave the
way I wanted it to. I’ll start with RTags. RTags needs the r-daemon (rdm) to
be running to handle generating and finding the tags. This is reasonable and
you can customize the behavior of the daemon a lot. Just look at the manual
entry and you’ll see that it really allows for a lot of customization. One
thing that troubled me was that by default when it re-indexes a project it
runs the process
rp on 8 threads and with a nice of
-1. Now my notebook only
has 4 physical cores, so with hyperthreading that means it’s running at full
capacity for a thread that really should be a background thing I hardly notice.
The reason this is annoying is because if you are working on a file that is
a dependency of a large portion of your project RTags re-indexes a large portion
of the project, or at least does a lot of work. Since cmake-ide starts the rdm
on its own, I had to change the way it behaves. The other problems I encountered
were that cmake-ide does not use multiple threads for building and also doesn’t
seem to have an option for Build EAR. Because my changes to cmake-ide are
currently hard-coded I have not contributed them back to the project, but let
me tell you the way you can recompile cmake-ide to behave better.
The first thing I changed was to have cmake-ide call make using Build EAR and
to build using 8 threads so that I don’t have to wait very long for the build
to finish. To do this you must find the
cmake-ide.el file. It could be
~/.emacs.d/elpa/cmake-ide... or if you’re using Aquamacs it will be
I changed the line in the function
cmake-ide--get-compile-command that says
((file-exists-p (expand-file-name "Makefile" dir)) (concat ... to say
((file-exists-p (expand-file-name "Makefile" dir)) (concat "bear --append make -j8 -C " dir))
You can specify however many threads you want to build with and if you don’t
want to build with Bear then simply remove
bear --append . Next, to get
rdm to run on only 2 cores and have a larger nice value I changed the function
cmake-ide-maybe-start-rdm by adding
"-j 2" "-i 40" "-a 10" after
cmake-ide-rdm-executable in the
start-process call. Here the
the niceness and
-i the number of translation units to cache. Now you have
recompile cmake-ide by doing
M-x and then running
selecting the directory that
cmake-ide.el is in. Do not specify the file
itself, just the directory.
The last piece of advice for using RTags is that you shouldn’t save very often. Every time you save a file it gets re-indexed so if you change something small and start thinking about the next line don’t immediately save, unless you want RTags to be re-indexing continually and using up your computing resources.
RTags allows you to quickly navigate around your code. Here is an example
of jumping straight to the header file where the class is declared that
is actually intentionally performed a bit slower than you can do in practice:
Since I consider legible code part of having correct code I’ll mention
ClangFormat here. ClangFormat automatically formats your code
to conform to a specific style. There are several built-in presets but you
can also add your own. ClangFormat will search up directories until it reaches
.clang-format file and then uses that. This means you can specify
formatting for each project individually by placing a
in the root directory of your project. Since it’s a text file you can even
track it with git. One nice things is that we can actually call ClangFormat
to format the selected line or region. For this to work add the following
to your init file:
I use the keyboard shortcut
C-M-tab but you may change this if you wish.
Helm is a framework for incremental completions that allows fuzzy matching and a variety of other powerful features. For example, integrating helm with git allows you to search your project for files no matter which directory you are currently in. Helm’s search is also case-insensitive meaning you don’t have to deal with pesky CamelCase spelling of filenames. Helm also offers similar features for the command-prefix (Meta-x), the buffer list, mini buffer list, finding files, ctest (which you are using, right?) and many others that I have not yet explored. You can also integrate it with Flycheck and Flyspell to get nicer windowing and navigation with them. I’ll discuss Flyspell in more detail below, but for now, here is my helm configuration:
To activate helm-flycheck use the keyboard shortcut
C-c ! h and
to use helm-ctest
C-c t. When in helm-ctest you can type the name
or partial name of a test to limit the tests disabled. To run a test
press enter (I use
C-m) and to select several tests to run use
C-space on each test you want to execute, then press enter.
The tests will run and you will get immediate feedback on whether
or not they passed.
Code Completion: Company, Irony and Semantic
Note: This part of the post is still somewhat in progress. I’m happy with the current behavior but may find bugs and improvements as time goes on. If there are any, I’ll post updates here.
company stands for “Complete Anything” and so you can
probably guess we will leverage it as our backend for code completion.
It is also useful for all around completion. The other nice thing is
we can use
company to get STL and C library header completion,
query RTags for completions, ask clang to give completions for the
entire STL, and still use Yasnippet for custom completions to save
us typing out mundane things like for loops.
Let’s start with getting Yasnippet set up. Yasnippet comes with several useful snippets for code completion, but to really get the most out of it you will want to use the snippets from here
I’ve found that there are some missing that I will add and also that some seem to add incorrect code or don’t work.
Now let’s load up company and the backends we will want to use.
I’ve generally found that semantic completion is quite slow
and gives irrelevant results. However, semantic is really nice
for navigating around a file using helm. The shortcut I’ve set
C-c h i. For navigating between files I still recommend RTags.
I also provide functions
to enable and disable semantic completion so you can easily change
it if you wish. The code in my init file is:
To start company completion just press tab. I’ve found that sometimes
it will timeout and not offer any completions. When this happens
I find that most of the time pressing tab again gives the completions.
Sometimes it may appear to hang for a brief period of time. This I
believe occurs when RTags is being queried for completions. You can
navigate the completions menu using
M-p then pressing
enter to select the desired completion. Note that return types
in C++ are denoted using the postfix syntax
Directory local variables can be very useful for setting behaviors for
individual projects. For example, setting the build path, CMake flags,
or compiler flags is best done by using directory local
variables. These are set in a file called
.dir-locals.el and Emacs
searches up the directory tree until it finds one so you only need to
add it to the root directory of your project. Here is an example of
how to set the directory local variables for a project
Without setting directory local variables the code completion and
syntax checking tools may not know how to properly compile your code,
which means they also cannot function properly since they compile your
code to see if what you are changing is functional. What I have
noticed is that sometimes you need to restart Emacs (Aquamacs) in
order for the directory local variables to properly take effect. This
seems to be true if you open a source file of your project before
Before moving on I want to show you some of the useful things that
you can auto-complete using this infrastructure.
If you know the first few letters of a function you can quickly complete
the entire member function name with the correct arguments:
If you cannot remember the member functions then you can get a full list too. This is a bit finicky sometimes, but here is an example of what the list looks like:
Finally, you can use the snippets from Yasnippet to get an entire class template complete with move and copy constructors and assignment operators.
This is just an example. You can add any snippets and shortcuts you want, which is what makes Yasnippet so great.
Spell Check: Flyspell
Something that I find to be quite useful is on-the-fly spell checking. Flyspell offers this for all your buffers and restricts itself to comments when checking your code. Nobody wants an embarrassing spelling mistake in their comment and this fixes that. The code I use to set up Flyspell is:
For a list of corrections I again use helm (
To pull up the options move the cursor over the word you
want to correct and then type
F8 (on a Mac you must use the
fn key). Here is an example of what this setup looks like
In order to keep this post to a somewhat reasonable length I’ll end here with Magit and cmake-mode. My Magit configuration is
and to load cmake-mode I use
I have customized my Emacs configuration a great deal more. My current
init file is ~650 lines long, whatever that’s worth. I have a header
that shows the current function and the path to the current file,
but this required customizing the font a great deal to make it
legible and nice. I’ve uploaded a complete version of my Emacs file
here and will eventually make a public copy on
either GitHub or BitBucket. If you want you can simply copy the
entire contents of
init.el into your
~/.emacs file and you should
automatically have the entire configuration set the way I do.
I hope you found this guide useful and please email me with any questions, feedback and/or suggestions.