
On Mon, Aug 28, 2006 at 11:15:32PM +0200, Wolfgang Denk wrote:
Yes, and IMHO you can easily show more problems with make. To me it's really frightening to see so many issues with a tool in so wide use like GNU make.
Well, make is powerful, so expect it to be complex :-)
-> cat Makefile all: hello_world.tgt
%.tgt: % cp $< $@
%: %.src cp $< $@
%.src: FORCE touch $@
.PHONY: FORCE FORCE: -> make -n touch Makefile.src cp Makefile.src Makefile rm Makefile.src make: *** No targets. Stop. -> ls -l total 0 -rw-r--r-- 1 wd users 0 Aug 28 23:08 Makefile -rw-r--r-- 1 wd users 0 Aug 28 23:08 Makefile.src -> make --version GNU Make 3.80 ...
So yes, your Makefile is dangerous.
But wait. I used "-n" on the command line. And the man page says:
-n Print the commands that would be executed, but do not execute them.
Do not execute them? So who did execute the "touch" and the "cp", but skip the "rm"? I'm frightened.
I don't have a solution, but some remarks:
from 'info make':
----------8<----------
3.7 How Makefiles Are Remade ============================
[...]
To this end, after reading in all makefiles, `make' will consider each as a goal target and attempt to update it. If a makefile has a rule which says how to update it (found either in that very makefile or in another one) or if an implicit rule applies to it (*note Using Implicit Rules: Implicit Rules.), it will be updated if necessary.
[...]
When you use the `-t' or `--touch' option (*note Instead of Executing the Commands: Instead of Execution.), you would not want to use an out-of-date makefile to decide which targets to touch. So the `-t' option has no effect on updating makefiles; they are really updated even if `-t' is specified. Likewise, `-q' (or `--question') and `-n' (or `--just-print') do not prevent updating of makefiles, because an out-of-date makefile would result in the wrong output for other targets.
----------8<----------
So -n is being ignored for Makefile-remaking, and the "%: %.src" rule is found as a goal target to update the Makefile from Makefile.src, which is not there and thus being touched by using the "%.src: FORCE" rule.
Actually: where is the "rm" coming from?
The file you refer to with "%" is an intermediate file, as it is part of a chain. So it is being deleted automatically. If you don't want to do that, declare it .INTERMEDIATE.
Here's a modified version which doens't work as well, but does if you 'make hello_world.src' manually (not the intended behaviour, but it shows some things):
----------8<---------- all: hello_world.tgt
%.tgt: % cp $< $@
% :: %.src cp $< $@
%.src: FORCE touch $@
.INTERMEDIATE: hello_world
.PHONY: FORCE FORCE: ----------8<----------
Note that I've declared % to be terminal, so Makefile is not rebuilt, because there is no Makefile.src.
rsc@isonoe:~/wd$ ll total 4 -rw-r--r-- 1 rsc ptx 138 Aug 29 01:52 Makefile -rw-r--r-- 1 rsc ptx 0 Aug 29 01:56 hello_world.src rsc@isonoe:~/wd$ make cp hello_world.src hello_world cp hello_world hello_world.tgt rsc@isonoe:~/wd$ ls -l total 4 -rw-r--r-- 1 rsc ptx 138 Aug 29 01:52 Makefile -rw-r--r-- 1 rsc ptx 0 Aug 29 01:56 hello_world -rw-r--r-- 1 rsc ptx 0 Aug 29 01:56 hello_world.src -rw-r--r-- 1 rsc ptx 0 Aug 29 01:56 hello_world.tgt
Anyway, can't you avoid the match-anything rule somehow?
Robert