An Interactive GNU Make Debugger

[article]
 Makefile:55: MYVAR3 is defined as '$(MYVAR2)' 
 6> 

which shows that MYVAR3 is defined as $(MYVAR2). And so the obvious next step is to find out how MYVAR2 is defined (and also MYVAR1):

6> d MYVAR2 
 Makefile:55: MYVAR2 is defined as '$(MYVAR1) everyone' 
 7> d MYVAR1 
 Makefile:55: MYVAR1 is defined as 'hello' 
 8> 

And if it wasn't clear where MYVAR1 got its value from the o command will show its origin:

8> o MYVAR1 
 Makefile:55: MYVAR1 came from file 
 9> 

which means that MYVAR1 is defined in a Makefile. In contrast, if the user has overriden the value of MYVAR1 on the command line of Make (by running say make MYVAR1=Hello) the o command would reflect that:

1> v MYVAR1 
 Makefile:55: MYVAR1 has value 'Hello' 
 2> o MYVAR1 
 Makefile:55: MYVAR1 came from command line 
 3> 

Breakpoints In PatternsAs well as setting breakpoints in normal rules, you can also set them in patterns. Every time that pattern rule is used the breakpoint is hit. For example,

all: foo.x bar.x 
  
 %.x: FOO = foo 
 %.x: %.y 
     $(__BREAKPOINT) 
     @echo Building $@ from $<... 
  
 foo.y: 
 bar.y: 

Here all is built from foo.x and bar.x which requires building them from foo.y and bar.y using the %.x : %.y rule. I've inserted a breakpoint in the pattern rule and the debugger breaks twice: once for foo.x and once for bar.x:

Makefile:66: GNU Make Debugger Break 
 Makefile:66: - Building 'foo.x' from 'foo.y' 
 Makefile:66: - First prerequisite is 'foo.y' 
 Makefile:66: - Prerequisites 'foo.y' are newer than 'foo.x' 
 1> c 
 Building foo.x from foo.y... 
 Makefile:66: GNU Make Debugger Break 
 Makefile:66: - Building 'bar.x' from 'bar.y' 
 Makefile:66: - First prerequisite is 'bar.y' 
 Makefile:66: - Prerequisites 'bar.y' are newer than 'bar.x' 
 1> c 
 Building bar.x from bar.y... 

Even pattern-specific variables work. %.x has a pattern-specific variable FOO with value foo the debugger v command can access it during a breakpoint on the pattern rule:

Makefile:67: GNU Make Debugger Break 
 Makefile:67: - Building 'foo.x' from 'foo.y' 
 Makefile:67: - First prerequisite is 'foo.y' 
 Makefile:67: - Prerequisites 'foo.y' are newer than 'foo.x' 
 1> v FOO 
 Makefile:67: FOO has value 'foo' 
 2> 

Breakpoints In MakefilesFinally, you can simply stick a breakpoint in a Makefile if needed. Parsing of Makefiles will pause at the breakpoint and the current state of variables in the Makefile can be examined. For example with a breakpoint after each definition of FOO in this Makefile it's possible to see its value change:

FOO = foo 
 $(__BREAKPOINT) 
 FOO = bar 
 $(__BREAKPOINT) 
  
 Makefile:76: GNU Make Debugger Break 
 1> v FOO 
 Makefile:76: FOO has value 'foo' 
 2> c 
 Makefile:78: GNU Make Debugger Break 
 1> v FOO 
 Makefile:78: FOO has value 'bar' 
 2> 

The DebuggerThe debugger itself draws on functions defined in the GNU Make Standard Library (you can read more about the GMSL in this article ). The first line of the debugger includes the GMSL functions:

include gmsl 
  
 __LOOP := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 

The __PROMPT variable is used by the debugger to output the n> and read in a command followed by a single argument. __PROMPT uses the read command to get the command and argument into shell variables $CMD and $ARG and then returns a list of two elements: the first element is the command and the second the argument. Expanding __PROMPT prompts for an returns a single command and argument pair.

__PROMPT = $(shell read -p "$(__HISTORY)> " CMD ARG ; echo $$CMD $$ARG) 

The __BREAK variable is used to get and handle

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!