This is an emacs extension for building projects using cmake. It uses projectile for a few basic features. Main features:
cmake
rather than relying on specific build systems, so anything
should work (e.g., GNU make
, ninja
, etc)Menu:
Build window:
Basically, see the feature list. Projectile has some basic support for "build"
but no comprehension of more complex project builds. I almost always have
numerous build configurations with multiple compilers (clang, gcc for each of
Release
, Debug
, etc.). My projects often have numerous targets and
sometimes multiple configurations I switch between regularly... for instance, a
viewer might be configured to run with multiple different test files.
This comes with a very tiny example project, in example/
. You should be able
to load mytest.c
and use the commands, hotkeys (if you bind them), or menu
(likewise) to invoke cmake-build and compile/run.
First, need a project root. This uses projectile.
I highly recommend creating the file .projectile-root
in the root of your
project, and using the following configuration:
(setq projectile-project-root-files-top-down-recurring
'(".projectile-root"))
(setq projectile-project-root-files-bottom-up nil)
This causes projectile to base the root directory off one thing: the existence
of the file .projectile-root
.
Next, you need a .cmake-build.el
in the project root. This describes a
number of things:
For example, suppose we have a simple setup that builds mytest
. We might set
up the following .cmake-build.el
:
((cmake-build-cmake-profiles
(release "-DCMAKE_BUILD_TYPE=Release")
(debug "-DCMAKE_BUILD_TYPE=Debug"))
(cmake-build-run-configs
(mytest
(:build "mytest")
(:run "" "./mytest" ""))))
First, you should do M-x cmake-build-set-cmake-profile
, and type or select
the profile you want (release
or debug
).
Now you can run M-x cmake-build-clear-cache-and-configure
. Since this is a
mouthful to type (fingerful?), I generally bind it to C-S-F7
. This will
create build.release
(or build.debug
if you selected that), if it doesn't
exist, remove the cmake cache, and run cmake with your configuration.
If you don't want to fully reconfigure, M-x cmake-build-run-cmake
, which I
bind to S-F7
, will just run cmake with the current profile. This requires
the directory etc exist.
Note: Unlike emacs's "project-local variables," nothing is evaluated
from .cmake-build.el
. This is READ
only (in the lisp sense). Emacs's
reader does not appear to allow arbitrary evaulation during read (e.g. Common
Lisp's #.(form)
).
Before you build, you need to select a target. Target management is done
through run configurations, as set up above. cmake-build.el
does not parse
your CMakeLists.txt.
M-x cmake-build-set-config
M-x cmake-build-current
M-x cmake-build-run
I bind build to F7
and run to F5
. By default, with
cmake-build-before-run
set to t
, running will first invoke build, so if you
want to run you can skip the build step.
Either of these commands will open a small shell process window below the
current one (size configurable via cmake-build-run-window-size
) showing the
output.
Most of the commands are available via the graphical menu. This is available
by using M-x cmake-build-menu
, which I bind to C-c b
. This will let you
graphically select profiles, run configurations, other targets, and a few basic
"tools" (such as the clean
target).
A simple option has been added to call the emacs M-x gdb
with the current target and default/basic options. One can run this by M-x cmake-build-debug
or via the cmake-build menu.
There are no options for this right now; perhaps in the future.
Run configurations pair a target and a command invocation. Target configuration is straightforward enough:
(:build "targetname")
Where, of course, "targetname"
should correspond to a target cmake
understands.
Run configurations are slightly more complex:
(:run "path" "command" "parameters")
The "path"
parameter will be the current working directory. This should be
relative to the build root. (Mechanically, it will be bound to
default-directory
during the invocation, i.e., it is the actual cwd, and not
prepended to the command).
The "command"
parameter is what is passed to the shell, along with
"parameters"
. For instance, we could have multiple configurations for
mytest
:
(( .. )
(cmake-build-run-configs
(mytest
(:build "mytest")
(:run "" "./mytest" ""))
(mytest-with-data
(:build "mytest")
(:run "" "./mytest" "data.txt"))
(mytest-output
(:build "mytest")
(:run "" "./mytest" "data.txt -o output.txt"))
: .. and so on ..
)
Additionally, one can specify (:env ...)
to set various environment variables:
(mytest
(:build "mytest")
(:run "" "./mytest" "")
(:env "LSAN_OPTIONS=suppressions=..." "SOMEVAR=...")
This applies only while running (or debugging).
It is often useful to build "other" targets with cmake; for instance, you may
create a target with cmake's add_custom_target(TARGET-NAME ..)
. You can
specify this in .cmake-build.el
:
;;; Order doesn't matter here; context for illustration
((cmake-build-cmake-profiles ...)
:
(cmake-build-other-targets "some-target" "another-target" ...)
: etc
)
This will populate the "Other targets" menu.
You may wish to have a project root that is not the source root, and does not have a CMakeLists.txt. You can configure this in the .cmake-build.el
using cmake-build-source-root
:
(...
(cmake-build-source-root "src")
...)
This will append src/
to the project root path, and search for your root CMakeLists.txt there.
Note: If you merely wish to build out of the project tree, see the next option.
You may wish to build in another location. By default, builds happen in a profile-specific build directory in the root of the project. You may set a new root for builds by using M-x cmake-build-set-project-build-root
and specifying a path. This is also available under the "Tools" menu with "Set project build root".
If you want to show the current run configuration in the modeline, you could use projectile's modeline function:
(defun projectile-custom-mode-line-function ()
(if-let ((name (cmake-build-get-run-config-name)))
(format "[%s:%s]"
(projectile-project-name)
(cmake-build-get-run-config-name))
(projectile-default-mode-line)))
(setq projectile-mode-line-function 'projectile-custom-mode-line-function)
The critical call here is (cmake-build-get-run-config-name)
.
By default, the build directory is named in the form build.<profile>
. For instance, if your profile is gcc-debug
, the build directory is build.gcc-debug
.
If you wish to alter this, you may write a new elisp function in the following form:
;;; This will make the build directory "gcc-debug.build" instead
(defun my-dir-name-function (project-root profile)
(concat profile ".build"))
Note that this should be a single filename without /
or other path. The project root is given for convenience in case one wishes to do anything interesting based on the source (e.g., look up a VCS tag or revision).
A number of variables are available for customization:
cmake-build-local-options-file
: This is the file where "local" options are stored in your ~/.emacs.d/
.cmake-build-run-window-autoswitch
: (Default: set) If set, this will automatically switch between compile and run output.cmake-build-before-run
: (Default: set) If set, this will try to build before running. If build fails, it will not run.cmake-build-display-type
: (Default: split) How to display cmake-build output; 'split' will split the window (using cmake-build window splitting options), 'frame' will create a new frame. In all cases, the buffers will be reused if they are visible, regardless of current display type.cmake-build-run-window-size
: (Default: 20) This is the size in lines of the split build/run windows.cmake-build-split-threshold
: (Default: 40%) Percentage after which the window will not be split; e.g. if the build window is set to 20, and the current window is 25, this is 80% of the current window. By default, it would simply use the other window in this case.cmake-build-never-split
: (Default: nil) If set, this will never split the window, and just use the default.cmake-build-switch-to-build
: (Default: nil) If set, this will also make the build window current. By default, it leaves the current window active.cmake-build-export-compile-commands
: (Default: nil) If set, this will ask cmake to export the compile commands during configuration, and create a symbolic link from project-root to the compile_commands.json
file created in the build directory. __This will erase any previously created compile_commands.json
file in project-root directory__.A number of local settings are stored by default in your
~/.emacs.d/cmake-build-options.el
. These are separate from custom variables
(which are stored in whatever custom
file you've configured). This is to
support "shared" custom variables (i.e., you check them into a repository), but
"local" cmake-build.el settings. You can exclude this file from VCS, and not
have a dirty tree everytime you switch configurations and profiles.
Note this file is similar to custom
data and is not intended to be directly edited. It is likely to be overwritten if you make changes.
The variables are as follows:
cmake-build-profile
: The current profilecmake-build-options
: Additional options passed to cmake
, e.g. -j 4
.
You can set this via the menu or M-x cmake-build-set-options
.cmake-build-run-config
: The current run configuration.cmake-build-project-root
: This, if set, will force a project root, ignoring
projectile. This may be useful if you're working in multiple directories but
only want to build in one specific root. You can set this by M-x cmake-build-set-project-root
. Note, this does not override projectile
itself, just cmake-build.el.