[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

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
        @echo $@

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

  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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]