Emacs mode for full offline project builds (whole project flymake)
Emacs Lisp Makefile
Latest commit a897701 Oct 31, 2016 @ericbmerritt committed on GitHub Merge pull request #13 from tarsius/patch-1
Sorry I missed this. Major failure on my part.


Projmake Mode For Emacs

What is It?


This mode builds runs the build system for your projects every time you save and based on the errors and warnings generated by that system highlights them in your open buffers.

Long version

This mode uses your project's build system to build your project and highlight errors in your open source buffers each time you save a file under the project directory. If you are familiar with Flymake Mode, then this is a project oriented version of flymake mode that correctly handles complex projects, includes, etc and highlights every time you save. If you are not familiar with Flymake Mode then read on.

Your project already has a well designed build system where one command builds the entire thing, correctly managing all the includes, dependencies, etc. If it does not have it already then fix that problem right now. I will wait here ..... OK, continuing. This mode takes that build system and leverages it to do syntax and error checking. Basically, it builds your project every time you save and highlights errors and warnings generated in your open buffers.

Functionality and Features

  • Each time a file is saved a build is started silently in the background.

  • When the build is finished error lines are highlighted in your open buffers with the details of the error messages.

  • When starting a build of a particular project, either a possible previous live build of the same project is interrupted first or a new build is queued to start after the current one finishes. That is behaviour is configurable by you, the user.

  • A project configuration file specifies the commands required to build a project.

  • Multiple projects can be loaded into projmake mode and can be built as changes in the project occur.


You can get this mode in its current form from github or, even easier, from Marmalade.


The easiest way to set things up is to get this package from Marmalade. However, if you are setting it up manually just add the elisp directory to your build path.

(add-to-list 'load-path (file-truename "path-to-the-el-files"))

to your ~/.emacs. You’ll probably also want to start the mode automatically by adding

(require 'projmake-mode)

to you .emacs configuration and then doing:

(defun my-mode-hook ()

(add-hook '<mode>-mode-hook 'my-mode-hook)

to your Emacs init file for mode/file-type file type for which you want to enable projmake. Once the mode is activated, you should see the Projmake indicator on the mode line.

Using the Mode

Typically projects are built (or compiled) using a tool like make, but the details vary. Projmake natively supports make and rebar based build systems. You can trivially add addition build systems by modifying the 'projmake-project-descs' customization. To automatically search for and load a project do the following in to load on your major mode load hooks.


Manually describing a project

For those projects that are not automatically discoverable you can add a manual mode. The projmake mode will need a project configuration file to know how to build your project. A project configuration file basically contains an Emacs Lisp expression calling a function named projmake that returns a project object. A simple example of a project configuration file would be the (projmake) file used with smlbot:

 :name  "SML-Bot"
 :shell "nice -n5 make all")

The projmake function takes a number of keyword arguments:

name : specifies the name of the project. This can be any expression that evaluates to a string or to a nullary function that returns a string.

shell : specifies a shell command to execute. This can be any expression that evaluates to a string, a list of strings, or to a nullary function returning a list of strings.

All of the keyword arguments, except :shell, are optional and can be left out.

Note the use of the nice command above. It means that background build process is given a lower priority by the system process scheduler. Assuming your machine has enough memory, using nice ensures that your computer remains responsive. (You probably won’t even notice when a build is started.)

Manually Adding The projmake file

Once you have written a project file for projmake mode. Use the projmake-add-project command to load the project file for projmake mode.

Automatically Adding the projmake file

Its also possible to load the mode automatically. By calling projmake-add-project. This will load up the project manually into the system.

After the project file has been loaded and projmake mode activated, each time you save a file in Emacs, the projmake mode tries to build your project.

Seeing The Build Output

Projmake only puts markers on buffers when build errors happen. However, sometimes the build process itself fails, or on parsable error information for files in open buffers are presented. When this happens you sometimes what to see the build output. You can do that by toggling the build output on (there will be one buffer per project) with:

M-x projmake-toggle-kill-build-buffer

This will allow the output from the lastest build to be always available in a buffer. However, it does not bring that buffer to the front.

Changing the Error Parse Engine

Projmake-mode supports both multi-line and single-line error output parsing. The single line error parser is the default and should provide the ability to parse any of the common error output types. The only multi-line parse engine available is designed for the Ocaml language compiler. It may work for other compilers as well. You can use it by adding a :parse-engine line to your projmake file. An example projmake file with the Ocaml parse engine enabled follows.

  :name  "Voteraise"
  :shell "build-support/bin/remote-build"
  :parse-engine (projmake-ocaml-parse-engine-make))

You can also write your own parse engine for error output that is currently not supported. Its quite simple. You can use the Ocaml parse engine and the default parse engines as examples. If you do this please consider contributing it back so that others may benefit.

Fixing Filenames

Sometimes the file path that the compiler outputs does not map directly to the file path of the source file. This happens when you are automatically building on a remote box or in a docker image, etc. Projmake mode provides a way to fix that, by specifying a function in your .projmake file to do conversion in the file-name-rectifier property.

 :name  "Voteraise"
 :shell "build-support/bin/remote-build libs test run-dev"
 :parse-engine (projmake-ocaml-parse-engine-make)
 :file-name-rectifier (lambda (filename)
                       (mapconcat 'identity
                           (cdr (split-string filename "/")) "/")))

The above project builds on a remote box and the output has an extra directory in the name. The file-name-rectifier simply removes that name to make the file path relative to the project on the local box. You should not have to do this the vast majority of the time. However, when you do its nice to have the option to fix it.