Skip to main content

One weird trick that will give you makefile X-ray vision

Sometimes when you are running a make you'd like to see what commands get executed (even if they've been muted by prefixing them with @) and where in the makefile those commands reside. But you can't. There's no way to override @ and make -n doesn't actually run the make.

But here's 'one weird trick' that makes it possible to see inside a make as its running. Just add this to the makefile:

_SHELL := $(SHELL)
SHELL = $(warning [[email protected]])$(_SHELL) -x

Before digging into how that gives you makefile X-ray vision, let's take a look at it in action. Here's an example makefile that builds an executable from foo.o and bar.o (which are built from corresponding foo.c and bar.c files).

.PHONY: all
all: runme

runme: foo.o bar.o ; @$(LINK.o) $^ -o [email protected]

foo.o: foo.c
bar.o: bar.c

%.o: %.c ; @$(COMPILE.C) -o [email protected] $<

Running simply make on this performs the compiles and link but produces no output because output has been suppressed by the @ signs on the compile and link commands. Running a make -n gives this output:

% make -n
g++    -c -o foo.o foo.c
g++    -c -o bar.o bar.c
cc   foo.o bar.o -o runme

That's handy, but doesn't tell the whole story. For example, which of those lines correspond to which targets? And where are the actual commands found in the makefile?

But add the two lines above to the makefile and do a normal make and everything becomes clear:

% make
Makefile:9: [foo.o]
+ g++ -c -o foo.o foo.c
Makefile:9: [bar.o]
+ g++ -c -o bar.o bar.c
Makefile:4: [runme]
+ cc foo.o bar.o -o runme

It's easy to see that foo.o is built by the rule on line 9 of a makefile called Makefile (the %.o: %.c pattern rule) and that the link is on line 4. As each rule runs the location of the rule (with the corresponding target) is output followed by the actual commands.

How that works

The first line of the trick defines a variable called _SHELL and captures the value of the built-in SHELL variable using :=. SHELL contains the path (and parameters) for the shell that will be used to execute commands.

Then SHELL itself is redefined (this time using = and not :=) to contains a $(warning) and the original shell command (from _SHELL) with -x added. The -x causes the shell to print out commands being executed.

Since SHELL gets expanded for every recipe in the makefile, as it runs the $(warning) gets expanded and outputs the specific makefile line where the recipe can be found and [email protected] will be valid and contain the name of the target being built.

Caveat: doing this will slow down a build as GNU make doesn't use the shell if it can avoid it. If SHELL is untouched in a makefile the GNU make short-circuits the shell and execs commands directly if it can.

More?

If that sort of thing interests you, you might enjoy my book: The GNU Make Book.

Comments

Etan said…
The accepted Stack Overflow answer to this question discusses some other approaches to doing this same sort of thing.
Etan said…
The answers on this Stack Overflow question discuss some other methods of getting similar results.

Popular posts from this blog

Your last name contains invalid characters

My last name is "Graham-Cumming". But here's a typical form response when I enter it:


Does the web site have any idea how rude it is to claim that my last name contains invalid characters? Clearly not. What they actually meant is: our web site will not accept that hyphen in your last name. But do they say that? No, of course not. They decide to shove in my face the claim that there's something wrong with my name.

There's nothing wrong with my name, just as there's nothing wrong with someone whose first name is Jean-Marie, or someone whose last name is O'Reilly.

What is wrong is that way this is being handled. If the system can't cope with non-letters and spaces it needs to say that. How about the following error message:

Our system is unable to process last names that contain non-letters, please replace them with spaces.

Don't blame me for having a last name that your system doesn't like, whose fault is that? Saying "Your last name …

All the symmetrical watch faces (and code to generate them)

If you ever look at pictures of clocks and watches in advertising they are set to roughly 10:10 which is meant to be the most attractive (smiling!) position for the hands. They are actually set to 10:09.14 if the hands are truly symmetrical. CC BY 2.0image by Shinji
I wanted to know what all the possible symmetrical watch faces are and so I wrote some code using Processing. Here's the output (there's one watch face missing, 00:00 or 12:00, because it's very boring):



The key to writing this is to figure out the relationship between the hour and minute hands when the watch face is symmetrical. In an hour the minute hand moves through 360° and the hour hand moves through 30° (12 hours are shown on the watch face and 360/12 = 30).
The core loop inside the program is this:   for (int h = 0; h <= 12; h++) {
    float m = (360-30*float(h))*2/13;
    int s = round(60*(m-floor(m)));
    int col = h%6;
    int row = floor(h/6);
    draw_clock((r+f)*(2*col+1), (r+f)*(row*2+1), r, h, floor(m…

The Elevator Button Problem

User interface design is hard. It's hard because people perceive apparently simple things very differently. For example, take a look at this interface to an elevator:


From flickr

Now imagine the following situation. You are on the third floor of this building and you wish to go to the tenth. The elevator is on the fifth floor and there's an indicator that tells you where it is. Which button do you press?

Most people probably say: "press up" since they want to go up. Not long ago I watched someone do the opposite and questioned them about their behavior. They said: "well the elevator is on the fifth floor and I am on the third, so I want it to come down to me".

Much can be learnt about the design of user interfaces by considering this, apparently, simple interface. If you think about the elevator button problem you'll find that something so simple has hidden depths. How do people learn about elevator calling? What's the right amount of informati…