The most recent change (taking GMD from v1.0.0 to v1.0.1) is the addition of dynamic target breakpoints. At the GMD prompt it's now possible to set and remove breakpoints on the name of a file (in GNU Make language a target) that the Makefile will build.
It's no longer necessary to insert the $(__BREAKPOINT) string in a Makefile. Typing a simple set breakpoint command has the same effect. And another keystroke list all breakpoints currently in effect.
Adding this functionality wasn't easy. In this article I'll show their use of the new breakpoints, but also how they are coded. The new code is entirely written in GNU Make's macro language and uses the new GMSL set functions (detailed in my December 2005 article to maintain the list of current breakpoints.
Getting the breakpoints to activate required a little bit of GNU Make magic, but first here's an example.
Dynamic Breakpoints In Action
Before showing you how the debugger works, let's take a look at how to use it. The debugger and these examples all assume that you are using GNU Make 3.80 or above.
Here's an example Makefile that builds all from prerequisites foo and bar.
To illustrate the use of the debugger I've set a breakpoint in the Makefile by inserting a line at the end of the Makefile that consists of just the variable $(__BREAKPOINT). $(__BREAKPOINT) will get expanded when the Makefile is parsed and this will cause the debugger to break execution before any rules are run and prompt for input. (The debugger is included here with the include gmd command at the start; you can get the GMD files from the GMD web site ; it's all open source code).
include gmd MYVAR1 = hello MYVAR2 = $(MYVAR1) everyone all: MYVAR3 = $(MYVAR2) all: foo bar @echo Finally making $@ foo bar: @echo Building $@ $(__BREAKPOINT)
Here's what happens when this Makefile is executed with no existing files called all, foo or bar. The debugger immediately breaks and waits for input. The first thing to do is type h to see the help text and the three new commands: b (to set a breakpoint), r (to remove a breakpoint) and l (to list current breakpoints).
Makefile:11: GNU Make Debugger Break 1> h Makefile:11: c: continue Makefile:11: q: quit Makefile:11: v VAR: print value of $(VAR) Makefile:11: o VAR: print origin of $(VAR) Makefile:11: d VAR: print definition of $(VAR) Makefile:11: b TAR: set a breakpoint on target TAR Makefile:11: r TAR: unset breakpoint on target TAR Makefile:11: l: list all target breakpoints 2>
We'll set two breakpoints in the Makefile: one when foo gets built and one for all. (If you look back in the previous article on GMD you'll see that this can also be achieved by modifying the Makefile, but these new breakpoints can be set dynamically at run time).
After setting the breakpoints we'll verify with the l command that they are set.
2> b foo Makefile:11: Breakpoint set on `foo' 3> b all Makefile:11: Breakpoint set on `all' 4> l Makefile:11: Current target breakpoints: `all' `foo' 5>
Continuing execution by typing c causes the foo breakpoint to be hit immediately. foo is the first target that the Makefile will build (followed by bar and finally all). The breakpoint indicates that the rule for foo is at line 9.
5> c Makefile:9: GNU Make Debugger Break Makefile:9: - Building 'foo' 1>
Continuing on we first see the output generated when bar is created and then hit the all breakpoint which prints out much more information than foo because all has prerequisites. (Once gain,