[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug #13877] Error parsing define/endef when both are indented using
From: |
Paul D. Smith |
Subject: |
Re: [bug #13877] Error parsing define/endef when both are indented using tabs |
Date: |
Tue, 2 Aug 2005 12:25:20 -0400 |
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>endif
rm> <tab>ifndef BAR
rm> <tab>endif
rm> <tab>ifeq ($(FOO),)
rm> <tab>endif
rm> <tab>ifneq ($(BAR),)
rm> <tab>endif
rm> <tab>define macro
rm> <tab><tab>@echo macro text
rm> endef
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
commands.
This was true in GNU make 3.76 as well, AFAIK.
rm> All you can see, everything but 'endef' can be indented with
rm> tabs.
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
extraneous endif.
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:
define DO_TARGET
target:
@echo $@
endef
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
being ended?
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
script.
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
(or whatever).
--
-------------------------------------------------------------------------------
Paul D. Smith <address@hidden> Find some GNU make tips at:
http://www.gnu.org http://make.paulandlesley.org
"Please remain calm...I may be mad, but I am a professional." --Mad Scientist
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [bug #13877] Error parsing define/endef when both are indented using tabs,
Paul D. Smith <=