【问题标题】:Are makefiles Turing complete?makefile 图灵完整吗?
【发布时间】:2011-03-29 16:47:33
【问题描述】:

最近在工作中,我一直在做一些从 Makefile 到替代构建系统的翻译。我在某些地方看到了一些使用功能映射、过滤器和 foreach 构造的非常复杂的 Make 代码。这让我很惊讶,因为我认为构建脚本应该尽可能地具有声明性。

无论如何,这让我想到:Makefile 语言(具体来说就是最新的 GNU make)图灵完备了吗?

【问题讨论】:

  • 如果没有你的描述,我会问你是否解决了赌注:)
  • 它在 Unix 中,语法复杂,而且非常强大。大多数类似的事情都是图灵完备的。 20 年前,当有人向我展示 vi 宏图灵机时,我并不感到惊讶。
  • 在构建字符串的过程中,您可以使用任何您喜欢的东西,包括图灵机。从技术上讲,你在这一点上已经输了。 (我们的 Makefile 中有 Perl 调用。叹息)。

标签: makefile turing-complete


【解决方案1】:

是的,请参阅this。一旦你有了 lambda,一切都会从那里走下坡路。

这是一个plagiarized 斐波那契示例

这应该足以为更通用性奠定基础(我必须回去工作,否则我会玩更多。)

dec = $(patsubst .%,%,$1)

not = $(if $1,,.)

lteq = $(if $1,$(if $(findstring $1,$2),.,),.)
gteq = $(if $2,$(if $(findstring $2,$1),.,),.)
eq = $(and $(call lteq,$1,$2),$(call gteq,$1,$2))
lt = $(and $(call lteq,$1,$2),$(call not,$(call gteq,$1,$2)))

add = $1$2
sub = $(if $(call not,$2),$1,$(call sub,$(call dec,$1),$(call dec,$2)))
mul = $(if $(call not,$2),$2,$(call add,$1,$(call mul,$1,$(call dec,$2))))
fibo = $(if $(call lt,$1,..),$1,$(call add,$(call fibo,$(call dec,$1)),$(call fibo,$(call sub,$1,..))))
fact = $(if $(call lt,$1,..),.,$(call mul,$1,$(call fact,$(call dec,$1))))

numeral = $(words $(subst .,. ,$1))

go = $(or $(info $(call numeral,$(call mul,$1,$1)) $(call numeral,$(call fibo,$1)) $(call numeral,$(call fact,$1)) ),$(call go,.$1))

_ := $(call go,)

这会打印出正方形、斐波那契数和阶乘。数字大小似乎有 16 位限制。真可惜。

【讨论】:

  • 一旦你有了 lambda,那么我想你可以创建一个 Y 组合器来给你递归。正如你所说,从那里开始下坡。
  • 太棒了。而且很吓人。主要是可怕的。
  • @Jorg Oleg 是一个很棒但很可怕的人。主要是吓人。阅读他拥有的其他资料。
  • 我现在才意识到这是谁的网站。我同意。奥列格·基谢廖夫很棒。他用 60 行代码编写的纯功能性 OO 系统是纯粹的天才。
  • @deinst:答案并不那么容易。 Kiselyov 使用的构造(字符串连接,=$(call)$(foreach) 不是必需的)不提供图灵完备性:他们确实给你递归(但只是因为这些“函数”可能包含 $(call)*s 给自己)但没有办法停止它(没有条件执行);但是,*$(if) 和 *$(subst) 提供了这一点,因此理论上达到了图灵完备性。但是,例如,我无法实际编写带有原语的斐波那契数的递归定义。
【解决方案2】:

现在给出否定答案: GNU make 主动阻止了一些创建递归的机制:

1) Recursively expanded variables

在“递归函数”的意义上不是递归的:它们不能根据自身来定义:

Actually make detects the infinite loop and reports an error.

(顺便说一句,我看不出允许它们在实践中有何用处。)

2) Rule chaining

也不能递归:

No single implicit rule can appear more than once in a chain. (...)
This constraint has the added benefit of preventing any infinite loop
in the search for an implicit rule chain.

(在调试我的 Makefile 时,我为此浪费了很多时间 - 除了所有其他使 makefile 难以维护的事情之外。)

附:对于最近的一个项目,我写了a patch to GNU make 3.82 ,它通过一个新的-M 选项消除了这个限制(参见discussion)。对我来说效果很好。

【讨论】:

  • 这很有趣,但如果 make 总能在 $(eval) 之类的东西存在的情况下检测递归宏,我会感到非常惊讶。
猜你喜欢
  • 2014-12-26
  • 2015-08-23
  • 2011-05-22
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
相关资源
最近更新 更多