Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prefixing make output with target name - like ant does

Tags:

makefile

build

Assuming I have the following Makefile:

.PHONY: mytarget
mytarget:
    echo "Hello World!"

running make mytarget gives the following output:

echo "Hello World!"
Hello World!

what I would like to see is something like the below

[mytarget] echo "Hello World!"
[mytarget] Hello World!

Is this possible?

I've been searching http://www.gnu.org/software/make/manual/make.html but haven't yet found a solution (granted, I haven't yet read the whole manual)

like image 866
zsepi Avatar asked Jul 18 '14 08:07

zsepi


3 Answers

I'm not sure that there is something readily available for what you want in GNUmake (based on your link, I assume that we are speaking about this flavor). You can emulate it somehow, but I'm afraid no solution will be perfect.

use debug flags

make --debug=j mytarget will let make output information about each command it is about to launch, including the target that triggers it. In your case, the result will be:

Live child 0x021d2360 (mytarget) PID 10747 
echo Hello World!
Hello World!
Reaping winning child 0x021d2360 PID 10747 
Removing child 0x021d2360 PID 10747 from chain.

You have the information, but it's not really pretty, and I guess that parallel runs (-j options) won't produce a correct output.

Change SHELL

You can set the SHELL variable to tell make which interpreter is supposed to be used for launching the command. This can be (ab)used to perform an echo before actually launching the command. with the following line in the Makefile

SHELL=/bin/sh -c 'echo -n "[$@]: " && $$@'

we obtain

echo "Hello World!"
[mytarget]: "Hello World!"

This is not perfect, as the echoing of the whole line is done directly by make and thus not impacted by SHELL

change the command itself

If you can modify the commands themselves, it is possible to let make expand them so that the final output is what you want:

echo_target=@echo -n '[$@]: ' && echo $(1) && echo -n '[$@]: ' && $(1)

.PHONY: all bla

mytarget:
    $(call echo_target, echo "Hello World!")

will result in

[mytarget]: echo Hello World!
[mytarget]: Hello World!

but this requires adding the call to each command of your Makefile

Update: stitching it together

As mentioned by Natan Reisner, the SHELL command proposed above is not correct for arguments that contain spaces. As a matter of fact, it also occured to me that you can use SHELL to do the echoing before launching the command: Here is a new proposal that work with arguments containing spaces, and echoes the command with $@ prepended:

 SHELL=/bin/sh -c 'echo -n "[$@] " && echo "$$@" && echo -n "[$@] " && eval "$$@"'

on the following target

mytarget:
    echo 'Hello World!'
    @touch foo\ bar
    @ls -l "foo bar"

we obtain this result

echo 'Hello World!'
[mytarget] echo 'Hello World!'
[mytarget] Hello World!
[mytarget] echo foo\ bar
[mytarget] foo bar
[mytarget] touch foo\ bar
[mytarget] [mytarget] ls -l "foo bar"
[mytarget] -rw-rw-r-- 1 virgile virgile 0 juil. 23 08:44 foo bar

Note that there is still an issue for commands that do not produce any output, such as touch. This could probably be mitigated by redirecting the output of the command in a variable, and echoing only if the resulting length is non-zero.

like image 56
Virgile Avatar answered Oct 02 '22 13:10

Virgile


As a complement to the Change SHELL option from @Virgile (which has issues, see my comment on his answer).

You can get the prefix on the executed shell lines by adjusting PS4.

SHELL=/bin/bash -x
export PS4=[$@]

all: mytarget blah

.PHONY: mytarget blah

mytarget:
        @echo 'Hello World!'

blah:
        @echo '$@: output'

$ make
[mytarget] echo 'Hello World!'
Hello World!
[blah] echo 'blah: output'
blah: output

In theory this means that if you can get the Change SHELL option to work in a safe manner (I couldn't but I feel like I'm missing something here) you should be able to get what you want.

like image 27
Etan Reisner Avatar answered Oct 02 '22 15:10

Etan Reisner


Here is the output using remake (a fork of GNU make) when run on the file Makefile you gave:

$ remake -x 
Reading makefiles...
Updating goal targets....
File 'mytarget' does not exist.
Must remake target 'mytarget'.
Makefile:3: target 'mytarget' does not exist
##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
echo "Hello World!"
##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Hello World!
Successfully remade target file 'mytarget'.

The number after the colon in Makefile gives the line number inside Makefile of the target. The chevrons separate the command that is invoked from the output it produces. If a target fails, you'll get a target stack trace similar to what you'd get in a programming language.

Although this is already a bit more than you asked, in the unlikely event you need more there is a debugger available if you use -X instead of -x.

like image 34
rocky Avatar answered Oct 02 '22 13:10

rocky