GNU Make user-defined functions, part 2

[article]
Summary:

Creating GNU Make built-in functions is easy, but it does create a maintenance problem: the next time GNU Make is updated we'll need to port our changes to the new version.

If we download make-3.81.tar.gz and ungzip and untar it we'll end up with a directory structure that looks something like this:

$ ls -F

ABOUT-NLS doc/

AUTHORS
dosbuild.bat

COPYING expand.c

ChangeLog file.c

INSTALL
filedef.h

Makefile function.c

Makefile.DOS getloadavg.c

Makefile.am
getopt.c

Makefile.ami getopt.h

Makefile.in getopt1.c

NEWS
gettext.h

NMakefile glob/

README hash.c

README.Amiga
hash.h

README.DOS implicit.c

README.OS2 job.c

README.W32
job.h

README.customs main.c

SCOPTIONS make.1

SMakefile
make.dot

acinclude.m4 make.h

aclocal.m4 make.lnk

alloca.c
make2.dot

amiga.c make_msvc_net2003.sln

amiga.h
make_msvc_net2003.vcproj

ansi2knr.1 makefile.com

ansi2knr.c
makefile.vms

ar.c misc.c

arscan.c po/

build.sh* read.c

build.sh.in*
readme.vms

build_w32.bat remake.c

commands.c remote-cstms.c

commands.h
remote-stub.c

config/ rule.c

config.ami rule.h

config.h
signame.c

config.h-vms stamp-h1

config.h.W32 strcache.c

config.h.in
subproc.bat

config.log tests/

config.status* variable.c

configh.dos
variable.h

configure* version.c

configure.bat vmsdir.h

configure.in
vmsfunctions.c

debug.h vmsify.c

default.c vmsjobs.c

dep.h
vpath.c

dir.c w32/

The first step is to build GNU Make using the standard configure then make:

$ ./configure

$
make

Once we've done that successfully we are left with a working GNU Make in the same directory.   Since I find it handy to be able to tell which GNU Make I'm running the first modification will be to change the message printed out when we ask for the version information.  Here's the default:

$ ./make -v

GNU Make 3.81

Copyright (C) 2006  Free
Software Foundation, Inc.

This is free software; see the source for copying
conditions.

There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
A

PARTICULAR PURPOSE.

This program built for
i386-apple-darwin9.2.0

As you can see I'm working on a Mac (that final string will change depending upon the machine you are working with), and it's version 3.81.

~  I'm going to change that message so that it prints "(with jgc's modifications)" after the version number.   To do that we need to open

the file main.c in a text editor and find the function called print_version (it's at line 2,922) which looks like this:

/* Print version information.  */

static
void

print_version (void)

{

~  static int printed_version =
0;

~  char *precede = print_data_base_flag ? "# " : "";

~  if
(printed_version)

~    /* Do it only once.  */

~    return;

~  /*
Print this untranslated.  The coding standards recommend

translating
the

~     (C) to the copyright symbol, but this string is going to change
every

~     year, and none of the rest of it should be translated (including
the

~     word "Copyright", so it hardly seems worth it.  */

~  printf
("%sGNU Make %s\n\

%sCopyright (C) 2006  Free Software Foundation,
Inc.\n",

~          precede, version_string, precede);

~  printf
(_("%sThis is free software; see the source for
copying

conditions.\n\

%sThere is NO warranty; not even for
MERCHANTABILITY or FITNESS FOR A\n\

%sPARTICULAR
PURPOSE.\n"),

~            precede, precede, precede);

~  if
(!remote_description || *remote_description == '\0')

~    printf (_("\n%sThis
program built for %s\n"), precede, make_host);

~  else

~    printf
(_("\n%sThis program built for %s (%s)\n"),

~            precede, make_host,
remote_description);

~  printed_version = 1;

~  /* Flush stdout so
the user doesn't have to wait to see the

~     version information while
things are thought about.  */

~  fflush (stdout);

}

The first printf  in that function is where the version number if printed and we can modify it like this:

~  printf ("%sGNU Make %s (with jgc's
modifications)\n\

%sCopyright (C) 2006  Free Software Foundation,
Inc.\n",

~          precede, version_string, precede);

Save the file and then rerun make.  Now when we type make - -v we know which version we are working with:

$ ./make -v

GNU Make 3.81
(with jgc's modifications)

Copyright (C) 2006  Free Software Foundation,
Inc.

This is free software; see the source for copying conditions.

There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A

PARTICULAR
PURPOSE.

This program built for
i386-apple-darwin9.2.0

Anatomy of a built-in function

GNU Make's

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Sep 22
Sep 24
Oct 12
Nov 09