Skip to content

A makefile to facilitate checking Emacs packages

Notifications You must be signed in to change notification settings

DamienCassou/makel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

makel

pipeline status

Summary

makel is a project consisting of a Makefile (makel.mk) that Emacs package authors can use to facilitate quality checking (linting and tests). The Makefile can be used both locally on the developer machine and remotely on a continuous integration machine. These are the rules provided by makel.mk:

test-ert
run your ERT (the Emacs Lisp Regression Testing tool) tests.
test-buttercup
run your buttercup tests.
lint-checkdoc
collect and report checkdoc (the Emacs coding convention tool) errors.
lint-package-lint
collect and report package-lint (a linting library for package definitions) errors.
lint-compile
collect and report errors and warnings from the Emacs Lisp compiler.
lint
starts all linting-related rules.
test
starts all test-related rules (both ert and buttercup tests).
check
starts all lint and test rules.
makel-version
displays makel’s version

What distinguishes makel from similar tools (see below) is its simplicity: simplicity to use it in your Emacs package (there are just a handful of variables to define) and simplicity to understand what it does (it’s just a Makefile).

Installation

Alongside your package, create a Makefile file containing the following code:

makel.mk:
        # Download makel
        @if [ -f ../makel/makel.mk ]; then \
                ln -s ../makel/makel.mk .; \
        else \
                curl \
                --fail --silent --show-error --insecure --location \
                --retry 9 --retry-delay 9 \
                -O https://github.com/DamienCassou/makel/raw/v0.8.0/makel.mk; \
        fi

# Include makel.mk if present
-include makel.mk

The lines above indicate that you want to use makel.mk if present in the current directory. If not, you want to use the one from a sibling directory (../makel/makel.mk) or from Internet.

You decide which version of makel you want to use by changing the URL (here v0.8.0 is the latest version).

Usage

You have to tell makel which files you want each rule to look at. This is a bit verbose but easy to understand (and easy to copy/paste :-)). This can be done by setting a few variables at the beginning of your Makefile:

# Space-separated list of the dependencies of your project (include
# package-lint and/or buttercup if you want makel to use these tools):
ELPA_DEPENDENCIES=package-lint

# List of package archives to download above dependencies
# from. Available archives are: gnu (aka elpa), elpa-devel, nongnu,
# melpa, melpa-stable and org:
ELPA_ARCHIVES=melpa

# List of ERT test files:
TEST_ERT_FILES=$(wildcard test/*.el)

# List of buttercup test directories:
TEST_BUTTERCUP_OPTIONS=specs

# List of files to check for Emacs conventions:
LINT_CHECKDOC_FILES=$(wildcard *.el) ${TEST_ERT_FILES}

# List of files to check for packaging guidelines:
LINT_PACKAGE_LINT_FILES=$(wildcard *.el)

# List of files to check for compilation errors and warnings:
LINT_COMPILE_FILES=${LINT_CHECKDOC_FILES}

The variable ELPA_DEPENDENCIES list Emacs packages that you want makel to download if not already present. This is especially useful on a continuous integration environment where no external package is usually installed. If some of the dependencies you need are not available on a package archive (or not in a recent-enough version), you can add URLs to DOWNLOAD_DEPENDENCIES and they will be downloaded to the project’s main directory.

Above code uses the wildcard Make function to list Emacs Lisp files in the current directory as well as the test/ sub-directory. makel makes sure to remove any *-autoloads.el file from such a list before doing anything.

Running the rules

Now that you have configured makel, you just need to use it. A design choice I made is that makel should only print important information: this is to avoid making you spend time searching for potential problems in a log that doesn’t contain any. If everything is fine, makel will only print the tasks it runs:

$ make check
# Run ert tests from test/libmpdel-test.el…
# Run checkdoc on libmpdel.el, test/libmpdel-test.el…
# Run package-lint on libmpdel.el…
# Run byte compilation on libmpdel.el, test/libmpdel-test.el…

makel is only noisy if there actually is a problem to report:

$ make check
# Run ert tests from test/libmpdel-test.el…
Loading /home/cassou/.emacs.d/lib/libmpdel/test/libmpdel-test.el (source)...
Running 29 tests (2018-10-03 20:49:23+0200)
   passed   1/29  libmpdel-test--message-filter-activates-saved-buffer
   passed   2/29  libmpdel-test--message-filter-keeps-current-buffer-if-saved-one-died
   passed   3/29  libmpdel-test--msghandler-status-updates-volume
   passed   4/29  libmpdel-test--raw-send-command-with-handler-add-ignore-handler
   […]
Test libmpdel-test-artist-name condition:
    (ert-test-failed
     ((should
       (equal "The Artist"
	      (libmpdel-artist-name artist)))
      :form
      (equal "The Artist" "The Artists")
      :value nil :explanation
      (arrays-of-different-length 10 11 "The Artist" "The Artists" first-mismatch-at 10)))
   FAILED  12/29  libmpdel-test-artist-name
   passed  13/29  libmpdel-test-create-song-from-data
   passed  14/29  libmpdel-test-current-playlist-p

Ran 29 tests, 28 results as expected, 1 unexpected (2018-10-03 20:49:23+0200)

1 unexpected results:
   FAILED  libmpdel-test-artist-name

make: *** [makel.mk:55: test-ert] Error 1

Emacs packages using makel

The following Emacs packages (all from me :-)) are already using makel and could act as examples:

Package nameDescription
libmpdelLibrary to communicate with Music Player Daemon (MPD), server-side application for playing music
mpdelUser interface for Music Player Daemon (MPD), server-side application for playing music
libelcouchLibrary to communicate with CouchDB databases
elcouchUser interface to view and manipulate CouchDB databases
khardelUser interface to integrate khard, a console cardav client

Alternatives

If you are looking for something similar to makel, you might be interested in these projects:

I designed and implemented makel after having used both Cask and EMake for some time. My opinion is that makel is simpler to use and maintain (it’s only a Makefile and it has many unit tests) but may lack some features you might need.

Regarding makem.sh, I suggest you try it if you like makel. It seems like it’s a better version of it: more features, more documentation, easier to setup. I haven’t used it yet but I will probably try it soon.

Regarding Cask, I was frustrated by the complexity (I mean understanding how things work and play together) and warnings/errors I and others would regularly get.

Regarding EMake, I opened a few PRs and issues to make it do what I need but the maintainer and I disagreed on several core decisions. I made sure I agree with all decisions I took for makel :-).

Eldev is a new alternative that seems to be worth keeping an eye on. For now, it doesn’t support running buttercup or checking the quality of the code.

License

See COPYING. Copyright (c) 2018-2023 Damien Cassou.