Last month I wrote about creating user-defined functions in GNU Make. This month I'm going to look inside the GNU Make source code to show how you can enhance GNU Make with your own built-in functions by writing some C code.
The Source
First, we need to get the source code of GNU Make which is available from the Free Software Foundation. For this aritcle I'm going to be working with the very latest GNU Make: 3.81.
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






