GNU Make 递归调用与 -j 参数陷阱
Recursive `make` and `-j`
今天我在研究 GNU Make 的递归调用时,发现了一个令人头疼的并行陷阱。当 Makefile 中的 recipe 再次调用 make 时,如果直接写死 make 命令,即使你在命令行指定了 -j4,子进程也会因为无法获取 jobserver 而退化到单线程运行,导致并行效率大打折扣。更糟糕的是,不同版本的 GNU Make(从 3.81 到 4.3)对此的处理逻辑和警告信息各不相同。虽然可以通过在 recipe 行首加 '+' 或使用 $(MAKE) 变量来修复 jobserver 传递问题,但在处理显式指定的 -j 参数时,依然会触发 'disabling jobserver mode' 的警告。这篇文章详细对比了各版本的行为差异,并指出了目前尚未完美的解决方案。
我更喜欢在 recipe 行末尾加上 '|| true',而不是在行首使用那个像魔法一样的 '-' 前缀。
- stabbles
`-j` 参数仅应用于顶层调用,而 `$(MAKE)` 模式是标准做法。
在 gmake 4.4(2022 年发布)中,不再需要 `+` 或 `$(MAKE)` 这类“技巧”来确保子 make 和其他子进程继承 jobserver,因为它默认使用 FIFO 而非管道。作者应该直接升级 gmake 就好了 :)。
- fragmede
千万别这么做!
https://accu.org/journals/overload/14/71/miller_2004/
Recursive Make Considered Harmful
作者:Peter Miller