I’m trying to implement include guards in Gnu Make. In this Makefile, the first inclusion is OK, while the second one fails with an error.
ifndef INCLUDED
INCLUDED = 1
$(info Including)
define macro
ifneq ($(1),)
define inner_macro
macro content...
endef
else
define inner_macro
endef
endif
endef
endif
The same effect can be simulated by explicitly giving INCLUDED = 1
before the inclusion, e.g. on command line.
Gnu Make 4.1 under Gentoo says Makefile:14: *** missing separator. Stop.
, while Gnu Make 3.81 under Debian Wheezy says Makefile:14: *** extraneous `endef'. Stop.
. On the first inclusion, they both say:
Including
make: *** No targets. Stop.
If I try $(eval $(call macro,whatever))
after the first inclusion, it defines inner_macro
as expected.
I used make INCLUDED=1
and make
commands respectively to get the described behavior.
The same happens when I clear the environment and disable built-in rules and variables: env -i make -rR INCLUDE=1
. When I use -p
to dump the database, without INCLUDED=1
, the macro
is defined as it should be, but with INCLUDED=1
, empty inner_macro
is defined. This is consistent across both the versions of Make. This hints me that when the condition is false, Make parses the Makefile differently and thinks the else
inside macro
’s definition belongs to the ifndef
. Other condition types behave all the same.
If I remove both the definitions of inner_macro
, the problem goes away.
I read the manual pages info make conditional\ syntax
and info make multi-line
(formerly defining
), but I found no caveat there and I still think I am doing nothing wrong.
That's a bug. Report it on Savannah.
There's something wrong with the tracking of nested define/endef inside a not-taken ifdef/ifndef condition. If you don't use nested define/endef then it works; for example (obviously you may not be able to do this in your environment):
ifndef INCLUDED
INCLUDED = 1
$(info Including)
define macro
ifneq ($(1),)
inner_macro = macro content...
else
inner_macro =
endif
endef
endif