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)
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.
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.
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
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
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.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With