ifndef include guard in Gnu Make 嵌套条件中断

ifndef include guard in Gnu Make breaks on nested conditional

我正在尝试在 Gnu Make 中实现 include guards。在这个 Makefile 中,第一次包含 OK,而第二次包含错误。

ifndef INCLUDED
INCLUDED = 1
$(info Including)

define macro
ifneq ($(1),)
define inner_macro
macro content...
endef
else
define inner_macro
endef
endif
endef

endif

可以通过在包含之前明确给出 INCLUDED = 1 来模拟相同的效果,例如在命令行上。

Gentoo 下的 Gnu Make 4.1 表示 Makefile:14: *** missing separator. Stop.,而 Debian Wheezy 下的 Gnu Make 3.81 表示 Makefile:14: *** extraneous `endef'. Stop.。在第一次包含时,他们都说:

Including
make: *** No targets.  Stop.

如果我在第一次包含后尝试 $(eval $(call macro,whatever)),它会按预期定义 inner_macro

我分别使用了 make INCLUDED=1make 命令来获得所描述的行为。

当我清除环境并禁用内置规则和变量时,也会发生同样的情况:env -i make -rR INCLUDE=1。当我使用 -p 转储数据库时,没有 INCLUDED=1macro 被定义为它应该的,但是 INCLUDED=1,空 inner_macro 被定义。这在 Make 的两个版本中都是一致的。这暗示我,当条件为假时,Make 以不同的方式解析 Makefile,并认为 macro 定义中的 else 属于 ifndef。其他条件类型的行为完全相同。

如果我删除 inner_macro 的两个定义,问题就会消失。

我阅读了手册页 info make conditional\ syntax and info make multi-line(以前的 defining),但我没有发现任何警告,我仍然认为我没有做错任何事。

  1. 我的结论正确吗?
  2. 这是 Make 中的错误,还是我调用了未定义的行为?
  3. 我应该如何在 Gnu Make 中实现 include guards?

这是一个错误。在 Savannah.

上报告

在未采取 ifdef/ifndef 条件下跟踪嵌套 define/endef 有问题。如果你不使用嵌套 define/endef 那么它就可以工作;例如(显然您可能无法在您的环境中执行此操作):

ifndef INCLUDED
INCLUDED = 1
$(info Including)

define macro
ifneq ($(1),)
inner_macro = macro content...
else
inner_macro =
endif
endef

endif