#+TITLE: CMake layer

#+TAGS: layer|tool

[[file:img/cmake.png]]

* Table of Contents                     :TOC_5_gh:noexport:
- [[#description][Description]]
  - [[#features][Features:]]
- [[#install][Install]]
- [[#configuration][Configuration]]
  - [[#choosing-a-backend][Choosing a backend]]
    - [[#company-cmake][Company-cmake]]
    - [[#lsp][LSP]]
  - [[#cmake-ide][CMake-ide]]
- [[#key-bindings][Key bindings]]

* Description
This layer adds support [[https://cmake.org/][CMake]] scripts.

** Features:
- Syntax highlighting
- Auto-completion
- Support for CMake configure/build (with limited support for other build systems) and
  automatic generation of =compile_commands.json= (compile flags).
- Run selected test using =Helm= interface via =helm-ctest=.
- Extraction of compile parameters from =compile_commands.json= with [[https://github.com/atilaneves/cmake-ide][cmake-ide]]

* Install
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
add =cmake= to the existing =dotspacemacs-configuration-layers= list in this
file.

* Configuration
All layer configurations can be done by setting layer variables in your dotfile.
No custom user config lines are necessary

** Choosing a backend
This layer provides two alternative backends to choose from.

*** Company-cmake
This is the default choice if nothing is set and no lsp layer
is loaded in your dotfile. This mode only provides very
limited IDE capabilities. Used best if only small scripts
are edited. To set explicitly set the following in your
dotfile:

#+BEGIN_SRC emacs-lisp
  (cmake :variables cmake-backend 'company-cmake)
#+END_SRC

*** LSP
For proper IDE support this backend should be used. It is
based on an external server which will be started automatically
by emacs, once a cmake file is opened. The key bindings are
the same for all lsp modes so if you are already familiar with
one you should be able to work the same in all modes.

To set explicitly do the following in your dotfile:

#+BEGIN_SRC emacs-lisp
  (cmake :variables
          cmake-backend 'lsp)
#+END_SRC

For this to work you will also need to obtain
the latest version of the lsp server from [[https://github.com/regen100/cmake-language-server][here]].

You can also simply install it with pip:

#+BEGIN_SRC sh
  pip install cmake-language-server
#+END_SRC

NOTE: Key bindings for LSP are defined in the
LSP layer. Also it is advisable to have a look
at the autocomplete layer for an optimal
intellisense config for LSP.

** CMake-ide
To enable CMake projects support set the layer variable =cmake-enable-cmake-ide-support=
to =t= in your dotfile:

#+BEGIN_SRC emacs-lisp
  (setq-default dotspacemacs-configuration-layers
    '((cmake :variables cmake-enable-cmake-ide-support t)))
#+END_SRC

=cmake-ide= plugin has several useful configuration options.
Normally all should just work well as long as there is a standard
cmake compilation database available. If not some manual configuration
may be necessary. Details can be found below.

To configure a project you need to create =.dir-locals.el= file. In case of using
make as CMake backend you can use =helm-make= to select required build target.

Here is a sample configuration. This configuration forces =cmake-ide= to use the
local directory and pass that directory to =helm-make=. Such config allows to
build your project with ~SPC c c~ key binding.

Additionally it's possible to configure =helm-ctest= in the same way via defining ~helm-ctest-dir~.
Trailing slash is required.

#+BEGIN_SRC emacs-lisp
  ((nil .
        ((cmake-ide-project-dir . "~/Project")
         (cmake-ide-build-dir . "~/Project/build")
         (cmake-ide-cmake-opts . "-DCMAKE_BUILD_TYPE=Debug")
         (helm-make-build-dir . "build")
         (helm-make-arguments . "-j7")
         (helm-ctest-dir . "~/Project/build/")
         )))
#+END_SRC

In case of projectile it's possible to configure project like:

#+BEGIN_SRC emacs-lisp
  ((nil . ((eval . (setq
                    projectile-project-test-cmd #'helm-ctest
                    projectile-project-compilation-cmd #'helm-make-projectile
                    projectile-project-compilation-dir "build"
                    helm-make-build-dir (projectile-compilation-dir)
                    helm-ctest-dir (projectile-compilation-dir)
                    ))
           (projectile-project-name . "My Cool Project")
           (projectile-project-run-cmd . "./run.sh")
           (projectile-project-configure-cmd . "cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..")
           (helm-make-arguments . "-j7"))))
#+END_SRC

* Key bindings

| Key binding | Description                                                             |
|-------------+-------------------------------------------------------------------------|
| ~SPC m p c~ | Run CMake and set compiler flags for auto-completion and flycheck       |
| ~SPC m p C~ | Run CMake if compilation database JSON file is not found                |
| ~SPC m p d~ | Remove file connected to current buffer and kill buffer, then run CMake |
| ~SPC m p t~ | Run CTest                                                               |
