Autotools for humans (part 2)
Ohai. Last time around we saw how to use Autotools to build a very simple C program. This time around, I’m going to show how you might go about testing your C code using Autotools and check, a unit testing framework for C.
Before we start, ensure you’ve got check installed. On Debian/Ubuntu/Mint, this is easy:
$ sudo apt-get install check
Alright. Let’s do this.
AM_PATH_CHECK and configure.ac
First, recall our configure.ac from Part 1:
AC_INIT([my-project],[0.0.1],[firstname.lastname@example.org]) AM_INIT_AUTOMAKE([1.9 foreign]) AC_PROG_CC AC_CONFIG_FILES([Makefile]) AC_OUTPUT
Let’s add a feature test to configure.ac to test for the presence of the check testing framework. If you look through the check documentation, you’ll find a reference to AM_PATH_CHECK, which will test for the presence of the check suite on the build host. The documentation tells you exactly what tests are performed, so I won’t repeat it here.
Here’s the updated configure.ac:
AC_INIT([my-project],[0.0.1],[email@example.com]) AM_INIT_AUTOMAKE([1.9 foreign]) AM_PATH_CHECK([0.9.0],,[AC_MSG_ERROR([check is missing])]) AC_PROG_CC AC_CONFIG_FILES([Makefile]) AC_OUTPUT
If you refer to the documentation for AM_PATH_CHECK, you’ll see that it expects a version number, followed by an action to perform if check is present, and then an action to perform if check is *not* present. This is a pretty common pattern within configure.ac scripts, so it’s best you try to grok the syntax here.
You can see we’re wrapping all the arguments between square brackets, as discussed in Part 1. Now might be a good time to have a quick read of the m4 quotation documentation. Just try to get the gist of it, no great need to understand every nitty gritty detail at this point.
You can see we pass in the minimum version number of check we can operate with, the action to take if the check framework is found and last of all the action to take when the check framework is not found. Note that although we take no action if the check framework is found, we invoke the code generated by an AC_MSG_ERROR macro if it is not found. AC_MSG_ERROR print an error message (which we pass as an argument to the macro) and halt execution of the configure script.
Note that it’s not at all unreasonable for you to simply ignore the fact that check wasn’t found & to let the user continue at their own peril if you’re not too fussed about your users running tests. We’re just being serious about our testing here. ;)
aclocal and m4 macros
You’ll notice the documentation for AM_PATH_CHECK makes reference to a file called check.m4, which is actually picked up by our friend aclocal when it sees that you’re using the AM_PATH_CHECK macro. aclocal does this by first scanning the contents of your system aclocal directory — typically /usr/share/aclocal — and associating macro definitions with the files in which they were defined, then scanning configure.ac. If it finds any macros in configure.ac that it discovered in /usr/share/aclocal, it knows that you’re going to need those macros and ultimately writes them to aclocal.m4 on your behalf. Note that this is true even of the AM_INIT_AUTOMAKE macro — you’ll find this macro defined in your project’s aclocal.m4 after running autogen.sh.
The automake documentation actually does a pretty great job of describing [how aclocal works] and how third party libraries (like check) can