Makefile 和 .ONESHELL

Makefile 和 .ONESHELL

不使用时.ONESHELLMakefile 在单独的 shell 中执行每个 shell 命令。这样做有什么好处呢?为什么 makefile 不使用相同的 shell?

答案1

不在单个 shell 实例中运行与收据关联的所有命令的原因之一是 无法检测到其中一个命令的失败make。仅将 shell 的最终退出状态提供给make.必须另外设置.SHELLFLAGS-e使 shell 在出现错误时尽早终止(这是多命令 shell 调用所必需的,即使.ONESHELL它们不存在)需要在第一个错误时失败)。

SHELL对于POSIX shell来说,这一切都很好。 Makefile 还可以设置SHELL为例如/usr/bin/perl/usr/bin/python或其他一些命令解释器。那么使用 可能合适,也可能不合适.ONESHELL

进行.ONESHELL默认行为make也可能会破坏旧的 Makefile。

尽管这不是与 POSIX 标准或 GNU 对该标准的遵守情况相关的问题makePOSIX 规范make关于当前的问题有这样的说法:

某些高级版本中的默认设置make是将目标的所有命令行分组并使用单个 shell 调用来执行它们;System V 方法是将每一行单独传递到一个单独的 shell。单壳方法具有性能上的优势并且不需要许多连续线。然而,转换到这种较新的方法导致了许多历史 makefile 的可移植性问题,因此 POSIX makefile 的行为被指定为与 System V 相同。建议将特殊目标.ONESHELL用作实现扩展,以实现一个目标或一组目标的单 shell 分组。

GNUmake在这方面符合 POSIX,因为它实现了 System V 行为如果需要,提供.ONESHELL启用替代行为的目标。 ...这是 GNUmake保持当前行为的另一个原因。

答案2

.ONESHELL是 GNU 供应商特定的扩展,不可移植,也不属于 POSIX 标准的一部分。

POSIX 标准中没有这一点的原因很可能是迄今为止只有一种实现支持它。

这不是标准默认值的原因更容易解释:

POSIX 试图标准化现有的行为,并且 POSIX 不喜欢使现有的原始 UNIX 实现与标准发生冲突 - 除非特定行为可以被视为明显的设计错误。

Stuart Feldman 在 1977 年的最初make实现在单独的 shell 中调用操作列表中的每一行sh -ce cmdline,这已成为所有后来实现的主要实现make

.ONESHELL但即使是 GNU 实现(单独参见)在生效时也并非没有问题。原因是GNU make-e在调用命令时没有设置shell的标志。这会导致多行 shell 脚本在.ONESHELL发生错误时无法终止。

除此之外,我认为没有什么好处.ONESHELL

  • make多行 shell 脚本可以通过 make 文件中的反斜杠换行序列在内部使用。

  • 性能参数不适用于现代make实现,因为现代实现尝试避免在命令行不包含 shell 特定元字符的情况下调用 shell。

  • 我的smake实现甚至实现了对该echo命令的内联支持,以防它是一行中的第一个命令,echo后面仅跟一个分号和一个简单的其他命令。这避免了 90% 以上的情况下都不需要调用 shell。

相关内容