[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: possible make bug
Re: possible make bug
Sun, 28 Nov 2010 11:19:52 -0500
On Sun, 2010-11-28 at 13:14 +0100, Sergio Villone wrote:
> you ill find in the allegate a directory containg a possible guilty
> makefile (prova), a text file f the result of running this makefile
> and a text file (comment) explaining the misleading results
Hi Sergio; in the future we prefer if the problem description, etc. are
included in the message itself rather than in an attached file; it's
much simpler to just read the message rather than having to break open a
separate tar file first.
However, the behavior you're seeing is not a bug. Please check the GNU
make manual section on how make reads a makefile, as well as discussions
of the preprocessor statements like ifeq.
Make works by completely parsing all makefiles first, and only as a
second step does it start to run recipes after deciding which targets to
build. Make does not evaluate the recipes of targets until and unless
it decides to build those targets.
Preprocessor statements like ifeq, etc. are all evaluated during the
first step, the read-in of the makefiles. So, your test for the
variable nlist3 is done during this first phase, before make starts to
build targets. Here, nlist3 has not been set yet.
Then when make decides to build the all: target it evaluates the recipe
and at that time it sets the value of nlist3, so when the echo command
runs it appears to have the right value.
When writing makefiles the single most important thing to understand is
the phases that make goes through, and when variables are evaluated.
If you want to see what the value of nlist3 is when the ifeq is run, you
can use $(warning nlist3 = $(nlist3)) BUT it must be on a line without a
TAB; any line starting with TAB is part of the recipe and won't be
evaluated until the second phase.
If you want to have your recipe behavior depending on values that exist
only when the recipe is run you have to use shell-based if statements,
not make ifeq. Rewrite your rule as:
$(eval nlist3 := $$(words $$(list3)))
echo "list1 ($(list1)) has $(nlist1) words"
echo "list2 ($(list2)) has $(nlist2) words"
if [ $(nlist1) -eq $(nlist2) ]; then \
echo "list1 & list2 have the same # of words"; \
echo "list1 & list2 do not have the same # of words"; \
echo "list3 ($(list3)) has $(nlist3) words"
if [ $(nlist1) -eq $(nlist3) ]; then \
echo "list1 & list3 have the same # of words"; \
echo "list1 & list3 do not have the same # of words"; \
echo " but nlist1:$(nlist1) and nlist3:$(nlist3) -- so what??"; \
Also, is the output of "make -v" you quote in the "comment" file
correct? It's very odd because the single most important line, the one
telling us what version of GNU make you have, is missing from your
output. When I run this I get:
~$ make -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
This program built for x86_64-pc-linux-gnu
Note the first line of the output describing the version.
Paul D. Smith <address@hidden> Find some GNU make tips at:
"Please remain calm...I may be mad, but I am a professional." --Mad Scientist