makefile 图灵完整吗?

发布于 2024-09-14 10:41:07 字数 176 浏览 9 评论 0原文

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

无论如何,这让我思考:Makefile 语言(具体来说是最新的 GNU make)图灵完整吗?

Lately at work, I've been doing some translation from Makefiles to an alternative build system. I've seen some pretty hairy Make code in some places using functional map, filter, and foreach constructs. This surprised me since I think build scripts ought to be as declarative as possible.

Anyway, this got me thinking: is the Makefile language (say the latest GNU make to be specific) Turing complete?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冰之心 2024-09-21 10:41:07

是的,请参阅。一旦有了 lambda,一切就开始走下坡路了。

这是一个 剽窃 斐波那契示例

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

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 位限制。真糟糕。

Yes, see this. Once you have lambda, it's all downhill from there.

Here is a plagiarized Fibonacci example

This should be enough to build a foundation for more generality (I've got to get back to work, or I'd play more.)

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,)

This prints out squares, fibonacci numbers and factorials. There appears to be a 16 bit limit on number sizes. Bummer.

愁以何悠 2024-09-21 10:41:07

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

1) 递归扩展变量

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

Actually make detects the infinite loop and reports an error.

顺便说一句,我不知道允许它们在实践中如何有用。)

2)规则链

也不能是递归的:

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 难以维护的事情之外。)

PS 对于我最近编写的一个项目 GNU make 3.82 的补丁,它使用新的 -M 选项消除了此限制(请参阅讨论)。它对我来说效果很好。

Now for a negative answer:
GNU make actively blocks some mechanisms to create recursion:

1) Recursively expanded variables

aren't recursive in the "recursive function" sense: they can't be defined in terms of themselves:

Actually make detects the infinite loop and reports an error.

(I don't see how allowing them could be useful in practice, by the way.)

2) Rule chaining

can't be recursive, either:

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.

(I lost quite a lot of time over this while debugging my Makefiles - in addition to all the other things that make makefiles hard to maintain.)

P.S. for a recent project I wrote a patch to GNU make 3.82 which removes this limitation with a new -M option (see discussion). It works fine for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文