[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [bug #13877] Error parsing define/endef when both are indente d usin
reid . madsen
RE: [bug #13877] Error parsing define/endef when both are indente d using tabs
Tue, 2 Aug 2005 12:54:21 -0700
I can see your points. I may not agree with them ;-), but I understand
In the case where someone wants to put 'endef', or any of the others as
the first word of a command, one could always remove the specialness of
the keyword by escaping, or quoting, it. Example:
This would work for any of GNUmake's keywords. All would be handled the
IMO, this is a much better solution that standing on our heads to
support the rare case where 'endef', et. al, might be used as the first
word of a command.
And, I tried to define a target within a define/endef -- it doesn't
make: *** No rule to make target '
', needed by all. Stop.
I would think it should work, but it doesn't. Effectively removing one
of your arguments.
So, IMO, all these reserved words (ifndef, ..., endif, define, endef)
should always be recognized - regardless of leading blanks/tabs, and if
you want to use one of these reserved words as the first word of a
command, then you need to escape, or quote it.
Consistency is a good thing. Consistency across make versions is even
From: Paul Smith [mailto:address@hidden On Behalf Of Paul D. Smith
Sent: Tuesday, August 02, 2005 11:25 AM
To: Madsen, Reid; Reid Madsen
Subject: Re: [bug #13877] Error parsing define/endef when both are
indented using tabs
Hi Reid; I'm posting this to bug-make for a wider audience.
%% Reid Madsen <address@hidden> writes:
rm> Now regarding #2 -- the '<tab>endef' issue. GNUmake supports
rm> conditional structures implemented with 'ifdef', 'ifndef', 'ifeq',
rm> 'ifneq', 'else', 'endif'. In addition it supports macro definition
rm> using 'define' and 'endef'. All of these are considered to be
rm> reserved words in GNUmake. With the notable exeception of 'endef'
rm> all of the above can be indented using tabs. I've attached a
rm> Makefile to #13877 that illustrates this. It looks like:
rm> <tab>ifdef FOO
rm> <tab>ifndef BAR
rm> <tab>ifeq ($(FOO),)
rm> <tab>ifneq ($(BAR),)
rm> <tab>define macro
rm> <tab><tab>@echo macro text
rm> all: ; $(macro)
Your makefile is not constructed properly to see the problem. Try
this: instead of putting the "all" target at the bottom of the file,
move it to the top of the file (or even put it into the middle).
NOW you see the issue. Try removing the syntax error by either
indenting the endef with a TAB or removing that line... now you'll see
without question that all those supposed "make keywords" are not being
treated specially by make at all: they're considered to be shell script
This was true in GNU make 3.76 as well, AFAIK.
rm> All you can see, everything but 'endef' can be indented with
That's not quite true. As you'll see with the experiment above, EVERY
SINGLE (logical) LINE in a makefile follows the same rule: if it begins
with a TAB, and it's in a context where it COULD be part of a command
script, then it IS considered part of a command script--regardless of
the contents. That goes for ALL the special keywords, like ifdef,
endif, etc. etc. This is true even for comment lines!
Remember that blank lines and (non-TAB indented) comment lines (and even
conditionals) do NOT end a command script: only another target line or a
variable definition can end a command script.
rm> Thus, the requirement that the 'endef' must appear at start
rm> of line makes absolutely no sense. It also makes no sense that
rm> the 'define' is allowed to be indented using a tab, but that the
rm> matching 'endef' cannot be indented similarly with a tab.
"define" (etc.) is NOT allowed to be indented by a TAB _if_ it comes in
the context of a command script.
You'll get other kinds of errors if you, for example, use <TAB>ifdef in
a command script context, then use spaces to indent the endif... in that
case the ifdef will not be seen by make (it will be considered part of
the command script) and you'll get an error saying that you have an
Play around with changing various TABs to spaces in your example above,
with the "all" target first, and see what I mean.
rm> Once, you've entered the 'do_define()' function, the only purpose
rm> is to find the matching 'endef'. You are known to be in a
rm> 'define' statement and the 'define' statement could not be a part
rm> of a rule.
Unfortunately endef presents a special problem. You're correct that the
define statement itself cannot be part of a rule, but the define
statement can unquestionably CONTAIN a rule, like this:
Now, if the endef is indented by a TAB, the meaning is ambiguous: does
it mean that the next line in the command script for the "target" should
be the command "endef", or does it mean that the define statement is
EVERYWHERE else in GNU make, as I said above, if a line could be
considered part of a command script it IS considered part of a command
script, even if it looks a whole lot like a make conditional etc.
Further complicating matters, GNU make does not parse the contents of
the define to determine whether or not the endef actually DOES appear in
a command context. So, make is simply assuming that any character
indented with a TAB inside the define is meant to be part of a command
rm> The documentation states: "The 'define' directive is followed on
rm> the same line by the name of the variable and nothing more.
rm> ... The end of the value is marked by a line containing just
rm> containing the work 'endef'." It is unclear from the
rm> documentation whether the 'define' or 'endef' may be indented, but
rm> since 'define' may be indented, it follows that 'endef' could be
rm> indented as well.
As I've said above, the 'define' cannot be indented either, _IF_ it
appears on a command script context.
I've not made a decision on this yet, and I'm still thinking about ways
we might be able to make this work without breaking make's general rule.
I will say that in my opinion in this case adherence to the general rule
(TAB introduces a command script line) is more important than
backward-compatibility to version 3.76.
However, I want to point out that in make it is a *very* bad idea to
EVER use a TAB as the first character on any line that is not intended
to be a command script. Doing so causes your makefile to be brittle and
easy to break in confusing and often difficult to find ways. For
example, if someone were to add a target in the middle of any of the
ifdef/define/export/variable setting/whatever statements in your
makefile, all of a sudden those lines become part of that target's
command script instead of being recognized by make.
I realize you have a very large existing system but if I were you I
would consider it a good idea, for the sake of reliability and
robustness, to bite the bullet and make the change from TAB to 8 spaces
Paul D. Smith <address@hidden> Find some GNU make tips at:
"Please remain calm...I may be mad, but I am a professional." --Mad
- RE: [bug #13877] Error parsing define/endef when both are indente d using tabs,
reid . madsen <=