Skip to content

emacsmirror/project-cmake

 
 

Repository files navigation

project-cmake.el - A cmake backend for project.el

Description

This package adds a cmake backend for Emacs’ project.el framework.

The added value comes from cmake’s reliance on external build directories which breaks `project-compile` when using the default project.el backend. This also adds some convenience functions for configuring projects and running unit tests.

Installation

The package can now be installed from MELPA or MELPA stable.

Usage

You should add project-cmake-find-root to project-find-functions which then autoloads the package:

(add-hook 'project-find-functions #'project-cmake-find-root -1)

The DEPTH parameter to add-hook is important here, because it prioritizes the cmake backend over the vc backend. If your project is in version control, project-cmake function will still get information like ignored files from the vc backend.

Build directories

By default project-cmake will build in a build subdirectory under your project’s source directory. This can be changed by setting project-cmake-build-directory to point to a different build path. Relative paths will be interpreted relative to the source directory. Absolute paths mostly make sense when set per project via .dir-locals.el (See Directory Variables).

This variable can also be set to a function that gets passed the path to the source directory and returns a path to the desired build directory. For example:

(setopt project-cmake-build-directory
        (lambda (source)
          (expand-file-name (file-name-nondirectory source)
                            "~/Projects/Build")))

This uses the directory name of the source and places a build directory with the same name under ~/Projects/Build/. Note that this function can not make use of any defmethod project-* functions that require the project object, i.e. project-name in this case.

Functions are not considered safe values in .dir-locals.el by default.

Running CMake

You can define some global defaults for your cmake variables in project-cmake-default-cmake-options which get applied when a build directory is first created. If you need to set options on an already existing build directory, you can use the interactive command M-x project-cmake-set-option which also has completion, or change the defaults and rerun cmake with the prefix arg, i.e. C-u M-x project-cmake-run-cmake, which will cause cmake to reconfigure the build directory from scratch.

On any fresh or initial run, if your project has presets defined in a CMakePresets.json file, project-cmake-run-cmake will prompt you for a selection.

Note that some options do not take effect when changed interactively after a build directory has been created, CMAKE_GENERATOR being one example. If you’re unsure, consult the CMake documentation.

Compiling Projects

This project adds an advice to project-compile to call compile-command in the build directory instead of the source directory. If the build directory doesn’t exist or doesn’t contain a CMakeCache.txt file, an initial cmake run is performed first.

Testing

You can run tests with M-x project-cmake-test and the results will display in a *ctest* compilation buffer. When you run the command with the prefix argument (i.e. C-u M-x project-cmake-test) you can select a test using completing-read. Instead of selecting/completing a given test you can also enter a regex pattern as unterstood by ctest -R and all matching tests will be run. Depending on your completion framework you may get a nice preview of what tests match this pattern before running it.

Scope of the Package

Some things are determined to be out of scope for this backend. Mostly this concerns convenience functions that are already easily achievable with on-board mechanisms in emacs or that would take away too much choice from the user:

Convenient testing

Currently, the testing part of this package is relatively bare-bones compared to full IDEs. I’ve considered to add a nice frontend with its own major mode, giving the user an interactive display of passing and failing tests, with filters for what to display. However, it doesn’t make sense to develop something like this in the scope of a backend for a single build system of a single language. If Emacs adds a proper unit test framework or a language-agnostic package gains enough traction, I will be happy to add support for it (if necessary).

Eglot

Due to the limitation of how eglot chooses to configure server programs and options in a monolithic list. I see no easy way to incorporate a one-size-fits-all setup function in this package. If I provide a setup-function to changes the defaults, this would affect non-cmake projects as well. If I define a second function given to eglot as the CONTACT part in eglot-server-programs that distinguishes between project backends on the fly (see below), then users would have to change this function to change the options of the server program. If I then also add a custom variable so users can override the options, project-cmake would be the central point of configuration for all c-mode server stuff.

So instead this package touches none of that and I’ll just share a simplified version of my personal config:

(with-eval-after-load 'eglot
  (setf (cdr (seq-find (lambda (server)
                         (and (listp (car server))
                              (memq 'c-mode (car server))))
                       eglot-server-programs))
        (lambda (_int project)
          (list "clangd" "--background-index"
                (concat "--compile-commands-dir=" (if (eq (car project) 'cmake)
                                                      (cdr (assq 'build project))
                                                    (project-root project)))))))

This gets the entry that contains c-mode from eglot-server-programs and sets the CONTACT to a lambda function that looks at the current project and sets the --compile-commands-dir option for clangd to the build dir if it’s a cmake project or the project root if its not. You should be able to easily extend this for ccls if necessary.

About

A cmake backend for project.el

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Emacs Lisp 99.5%
  • Other 0.5%