让 make 在出错时删除其他文件
我们最近正在讨论如何在基于 make 的构建过程中处理依赖项的 .d 文件。 有人提出的问题是,当构建中断时,.d 文件有时可能会损坏。
我们使用 .DELETE_ON_ERROR 目标来确保如果构建中断或失败,则正在生成的目标文件将被删除。 然而,我们还使用 GCC 在编译时生成 .d 文件,该文件也需要删除。 似乎没有一种直接的方法可以告诉 make 这件事。
所以问题是,有没有一种方法可以让 make 在发生错误时删除我们的对象和依赖文件? 我们是否可以通过某种方式设置规则,以便它知道 .d 和 .o 文件是同时生成的,并且在出现错误时需要将其删除?
或者,我们还可以采取其他措施来解决损坏的 .d 文件问题吗? 沿着这些思路的一个建议是生成具有临时名称的 .d 文件,并为每个文件提供单独的后编译步骤,将其复制到正确的名称。
We're having some discussion lately about the way we handle .d files for dependencies in our make-based build process. The issue has been raised that sometimes the .d files can become corrupted when builds are interrupted.
We're using the .DELETE_ON_ERROR target to ensure that if a build is interrupted or fails, the object files that it was in the process of generating are deleted. However we're also using GCC to generate .d files at compile time which would need to be deleted as well. There doesn't appear to be a straightforward way to tell make about this.
So the question is, is there a way we can coax make to delete both our object and our dependency files in the case of an error? Is there some way we can set up the rules so that it knows that both the .d and .o files are generated at the same time and need to be deleted if there's an error?
Alternately, is there something else we can do to fix the problem of corrupt .d files? One suggestion along these lines is to generate the .d files with a temporary name and have a separate post-compile step per file that copies it to the correct name.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一般来说,GNU make 不支持具有多个输出的目标。 然而,该规则有一个例外:模式规则。 如果您可以构建 makefile,使其使用模式规则来生成目标文件,那么您也许能够实现您的目标。 例如:
您将看到,使用此 makefile,当在规则中检测到“错误”时,.d 和 .o 文件都会被删除。 这种方法的优点是,它通过描述如何生成 .d 文件以及生成它的规则来更准确地表达依赖关系图。
或者,这种情况下的常见范例正如您所建议的那样:让 GCC 将 .d 文件生成为临时文件名,并且仅在 GCC 命令成功完成后才将其移动到位。 通常这是通过 shell 的技巧来完成的:
这里的“神奇”技巧是使用 GCC 标志
-MMD
,它会生成依赖文件作为编译的副作用,并且-MF
,允许您指定依赖文件的输出名称; 以及 shellcmd1 && 的使用 cmd2
语法,这会导致 shell 仅在cmd1
成功退出时才执行cmd2
。Generally speaking, GNU make doesn't support targets with multiple outputs. However, there is an exception to that rule: pattern rules. If you can structure your makefile such that it uses pattern rules to generate the object files, you may be able to achieve your goals. For example:
You'll see that with this makefile when the "error" is detected in the rule, both the .d and the .o file are deleted. The advantage to this approach is that it more accurately expresses the dependency graph by describing how the .d file is to be generated and what rule will produce it.
Alternatively, a common paradigm in this case is just as you suggested: have GCC generate the .d file into a temporary file name and only move it into place after the GCC command has completed successfully. Usually this is accomplished with a trick of the shell:
Here the "magic" trick is the use of the GCC flags
-MMD
, which generates the dependency file as a side-effect of compilation, and-MF
, which lets you specify the output name for the dependency file; and the use of the shellcmd1 && cmd2
syntax, which causes the shell to only executecmd2
ifcmd1
exits successfully.我没有让埃里克的例子正常工作。 当您传入 -MM 开关时,GCC(版本 4.4)不会编译任何内容,因此看起来您无法一次性编译和写入 .d。 这就是我所做的:
它首先删除现有的 .d 文件,只有当第二个命令(实际的编译步骤)成功时才会执行生成新文件的第三行(埃里克的 && 技巧不是必需的, make 自动执行此操作)。
由于某种我不明白的原因,如果编译失败,现有的 .o 文件不会自动删除,但是通过将
$@
添加到第一个rm
。I got neither of Eric's examples to work properly. GCC (version 4.4) doesn't compile anything when you pass in the -MM switch so it doesn't look like you can compile and write the .d in one go. Here's what I did:
It starts out by deleting an existing .d file, the third line which generates the new one is only executed if the second command, the actual compilation step, succeeds (Eric's && trick isn't necessary, make does this automatically).
For some reason I don't understand, an existing .o file isn't automatically deleted if the compilation fails, but that was easily solved by adding
$@
to the firstrm
.