【问题标题】:Make 3.82 - Backward incompatibility issue?Make 3.82 - 向后不兼容问题?
【发布时间】:2015-06-08 17:22:11
【问题描述】:

我在尝试使用 make 3.82 运行一些小型 Makefile 后遇到了一些问题。

错误:

[me@localhost make]$ make
 Makefile:3: *** empty variable name.  Stop.

这适用于 make 3.81,但不适用于新版本。我知道旧版本有一些向后兼容性。

我有两个 Makefile,一个基本文件和一个主要文件。

这是我的 Makebase

define TestFile
ifeq ($$(shell test $(1) $(2) || echo 1),1)
    $$(error $(2) mmm, not found)
endif
endef

define CheckIt
$(eval $(call TestFile,-d,$(1)))
endef

define CheckDir
p := $(foreach d,$1,$(call CheckIt,$d))
endef


define SomeCheck
$(call CheckDir,$(1))
endef

这是我的 Makefile

include Makebase

$(call SomeCheck, ~/test/make)

正如我所说,它在 make 3.81 中运行良好。

任何帮助将不胜感激。 谢谢

BR

【问题讨论】:

  • 你确定它的工作方式和你认为的 3.81 一样吗?这看起来像将p 设置为目标,= 作为先决条件。 (您没有在调用SomeCheck 的结果上使用eval。添加eval 也会使3.82 在makefile 上工作,无论我可以称之为混乱的工作定义。)这似乎是一种相当可怕的做法事情(您在 make 解析时间期间反复强行炮击,这将是昂贵的)。这一切的目标是什么?
  • 嗨 Etan,这是我正在处理的大混乱的摘录,不是我做的。问题是,在更新到 3.82 之后,有很多空变量名错误,这只是该问题的概念证明。看起来像 eval 做的工作,但不知道为什么 eval 在 3.82 中做不同的事情?非常感谢
  • 现在想一想,eval 应该扭曲 SomeChek 的调用还是可以在 SomeCheck 的定义中完成?谢谢
  • 老实说,我建议要么根本不升级 make,要么放弃任何可以执行此类操作的 make 系统,然后从头开始。因为我根本不相信上述方法可以正常工作,而且设计也很糟糕。
  • 我完全同意你的看法,但现在退出系统不是一种选择。保持 3.81 也不是一种选择。会看到...谢谢伊坦。

标签: makefile gnu-make


【解决方案1】:

所以,我不知道这在 GNU make 3.81 中打算做什么。正如 Etan 指出的那样,当我使用 GNU make 3.81 运行你的 makefile 时,我得到了这个错误:

make: *** No rule to make target `=', needed by `p'.  Stop.

这是因为 call 函数不能扩展为变量赋值,所以 make 将 p := 解释为好像它是 p: = (即目标 p 具有 = 的先决条件)。我不明白这实际上是你想要的。如果你没有看到这个错误,我只能假设在你的 makefile 中的某个地方,有人声明了一个带有目标 = 的配方(啊!!)

在 GNU make 3.82 中,我看到了 empty variable name 消息。原因是 GNU make 3.82 引入了解析器增强功能,这导致了一些向后不兼容。 NEWS 文件给出了这个警告:

由于解析器增强,三个向后兼容性问题 存在:首先,包含“=”的先决条件不能用 反斜杠不再。您必须创建一个包含“=”和 在先决条件中使用该变量。

这样做的一个不为人知的副作用是,在先决条件列表中之前没有值的等号现在被视为特定于目标的变量,其中变量名称为空,而在此之前它被假定为目标,因为它不符合变量赋值的要求。我不确定这是一个错误......一般来说,我不喜欢用奇怪的极端情况“欺骗”解析器,所以我实际上更喜欢更新的行为。

这整个定义是相当虚假的:

define CheckDir
p := $(foreach d,$1,$(call CheckIt,$d))
endef

为什么?因为CheckIt 用户定义函数只包含eval 语句。但是eval 语句被扩展并且结果由 make 解析,所以它们总是扩展为空字符串。因此,整个foreach 循环扩展为空字符串。因此,即使这被 make 解释为(显然)你想要的,它总是会简单地扩展为:

p :=

这似乎不是很有用。如果你把上面的定义改成简单的:

define CheckDir
$(foreach d,$1,$(call CheckIt,$d))
endef

那么它就会一直有效,而且你不会看到这些奇怪的问题。

我不会评论这个 makefile 是多么的虚假...... :)

【讨论】:

    猜你喜欢
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 2010-09-05
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多