GNU Make 4.0发布

On 2014年05月15日, in soft, by netoearth

The new upload of GNU Make 4.0 recently reached Debian’s unstable distribution, and has also migrated to the testing distribution, currently codenamed “jessie”. GNU Make 4.0 brings in several new features, perhaps the most interesting of which is support for the use of plugins.

A full changelog for the package is perhaps out of our scope, but significant highlights include:

  • Support for Guile inside Makefiles.
  • Support for plugins, written in C.

In addition to this there are several bug-fixes, and similar minor updates. There is a nice writeup of the features in this whats new in GNU Make 4.0 blog entry.

The ultimate goal of enabling plugins in Make is to allow more complex operations to be carried out, but this is just a preview with the ability to support adding dynamic functions to your Makefile – supported by shared libraries.

In the future it might be possible to make more extensive plugins, which would use SHA1 hashes instead of timestamps, etc. For the moment though adding simple fuctions to Makefiles is both powerful and interesting.

To get started we’re going to look at writing a simple extension which will generate a temporary file, and allow the name of that file to be returned to your Makefile.

Here is the plugin code:

#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <gnumake.h>

int plugin_is_GPL_compatible;

char *
gen_tmpfile(const char *nm, unsigned int argc, char **argv)
{
    int fd;

    /* Compute the size of the filename and allocate space for it.  */
    int len = strlen (argv[0]) + 6 + 1;
    char *buf = gmk_alloc (len);

    strcpy (buf, argv[0]);
    strcat (buf, "XXXXXX");

    fd = mkstemp(buf);
    if (fd >= 0)
    {
        /* Don't leak the file descriptor.  */
        close (fd);
        return buf;
    }

    /* Failure.  */
    fprintf (stderr, "mkstemp(%s) failed: %s\n", buf, strerror (errno));
    gmk_free (buf);
    return NULL;
}

int
mk_temp_gmk_setup ()
{
    /* Register the function with make name "mk-temp".  */
    gmk_add_function ("mk-temp", gen_tmpfile, 1, 1, 1);
    return 1;
}

To build and use this plugin we’re going to need a Makefile, and this is the one we’ll use:

#
#  Build the shared library
#
mk_temp.so: mk_temp.c
	$(CC) -I. -shared -fPIC -o mk_temp.so mk_temp.c


#
#  Use the shared library in a trivial test fasion
#
test: mk_temp.so
	@echo Temporary file: $(mk-temp tmpfile.)

#
#  If we're running `make test` load the plugin.
#
ifeq ($(MAKECMDGOALS),test)
load mk_temp.so
endif

With these two files we can run the following to build the plugin, and then invoke it:

$ make
cc -I. -shared -fPIC -o mk_temp.so mk_temp.c

$ make test
Temporary file: tmpfile.vMUZVv

This is just the bare minimum, but you could easily imagine a plugin which would get the git-tag from a source tree, or allow you to invoke some code written in Perl, Lua, or some similar embedded code.

(As an example of invoking Perl you can consult gmk-perl, on github.)

In short many new options are available, and the official GNU Make documentation contains a chapter on the plugin API, along with a brief introduction to the general plugin overview.

Tagged with:  

Comments are closed.