为什么 GNU make 删除文件

发布于 2024-07-13 19:13:06 字数 535 浏览 3 评论 0原文

我有一个稍微有点hackish的makefile来运行测试:

### Run the tests

tests := tests/test1 tests/test2 ...

test: $(tests)

$(tests): %: %.c
    gcc -o $@ $(testflags) $<
    $@

它可以工作,但它使Make做一些我以前从未见过它做的事情。 我的测试当前已损坏,并导致总线错误。 Make 给出以下输出:

gcc -o tests/test1 [flags blah blah] tests/test1.c
tests/test1
make: *** [tests/test1] Bus error
make: *** Deleting file `tests/test1'

我对最后一行感到好奇。 我以前从未见过Make这样做过。 为什么Make会删除已编译的测试?

注意:我对这个示例进行了大量编辑以使其更简单。 我可能引入了一些错误。

I've got a slightly hackish makefile for running tests:

### Run the tests

tests := tests/test1 tests/test2 ...

test: $(tests)

$(tests): %: %.c
    gcc -o $@ $(testflags) 
lt;
    $@

It works, but it makes Make do something I've never seen it do before. My test is currently broken, and causes a bus error. Make gives the following output:

gcc -o tests/test1 [flags blah blah] tests/test1.c
tests/test1
make: *** [tests/test1] Bus error
make: *** Deleting file `tests/test1'

I'm curious about the last line. I've never seen Make do that before. Why does Make delete the compiled test?

Note: I edited this example pretty heavily to make it simpler. I might have introduced some mistakes.

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

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

发布评论

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

评论(3

め可乐爱微笑 2024-07-20 19:13:06

因为目标可能没有正确构建。 下次您make该项目时,它将尝试重建目标。 如果该文件没有被删除,make 将无法知道出了什么问题。 make 无法知道失败是来自测试而不是构建目标的过程。


您的情况是否需要这种行为取决于测试的性质。 如果您计划修复测试以使其不会导致总线错误,那么删除目标并不是什么大问题。 如果您想稍后使用目标进行调试,则需要对 make 过程进行更改。

不删除目标的一种方法是使用 .PRECIOUS 目标。


另一种可能是:

$(tests): %: %.c
    gcc -o $@ $(testflags) 
lt;
    -$@

未测试,但 文档 指示目标不会被删除:

当发生 make 未被告知忽略的错误时,这意味着当前目标无法正确地重新制作,并且任何其他直接或间接依赖于它的目标也无法正确地重新制作。 由于尚未实现这些目标的先决条件,因此不会对这些目标执行进一步的命令。

和:

通常,当命令失败时,如果它根本更改了目标文件,则该文件已损坏并且无法使用,或者至少没有完全更新。 然而该文件的时间戳表明它现在是最新的,因此下次 make 运行时,它不会尝试更新该文件。 这种情况和命令被信号杀死的情况一样; 请参阅中断。 因此,如果开始更改文件后命令失败,通常正确的做法是删除目标文件。 如果 .DELETE_ON_ERROR 作为目标出现,make 将执行此操作。 这几乎总是你想要做的,但这不是历史实践; 因此为了兼容性,您必须明确请求它。

Because the target might not have been built correctly. The next time you make the project, it will attempt to rebuild the target. If the file had not been removed, make would have no way of knowing something went wrong. make can't know that the failure was coming from a test rather than the process that builds the target.


Whether or not this behavior is desirable in your case depends on the nature of the tests. If you plan on fixing the test so that it does not cause a Bus error, removing the target isn't a big deal. If you want to use the target for debugging later, you'll need to make a change to your make process.

One way to not delete targets is to use the .PRECIOUS target.


Another might be:

$(tests): %: %.c
    gcc -o $@ $(testflags) 
lt;
    -$@

Not tested, but the documentation indicates the target will not be removed:

When an error happens that make has not been told to ignore, it implies that the current target cannot be correctly remade, and neither can any other that depends on it either directly or indirectly. No further commands will be executed for these targets, since their preconditions have not been achieved.

and:

Usually when a command fails, if it has changed the target file at all, the file is corrupted and cannot be used—or at least it is not completely updated. Yet the file's time stamp says that it is now up to date, so the next time make runs, it will not try to update that file. The situation is just the same as when the command is killed by a signal; see Interrupts. So generally the right thing to do is to delete the target file if the command fails after beginning to change the file. make will do this if .DELETE_ON_ERROR appears as a target. This is almost always what you want make to do, but it is not historical practice; so for compatibility, you must explicitly request it.

不忘初心 2024-07-20 19:13:06

避免这种行为的一种方法是将构建和测试执行分为两个步骤:(

tests := tests/test1 tests/test2 ...

test: $(tests) runtests

$(tests): %: %.c
    gcc -o $@ $(testflags) 
lt;

runtests: %.out: %
    
lt; | tee $@

我的 make 语法中可能有错误,任何人都可以随意更正它。)总体思路是让测试运行生成一个输出文件,该文件使 make 更容易单独运行每个测试。

One way to avoid this behaviour is to split the build and test execution into two steps:

tests := tests/test1 tests/test2 ...

test: $(tests) runtests

$(tests): %: %.c
    gcc -o $@ $(testflags) 
lt;

runtests: %.out: %
    
lt; | tee $@

(There's probably errors in my make syntax, anybody feel free to correct it.) The general idea is to have the test run generate an output file, which makes it easier for make to run each test individually.

千年*琉璃梦 2024-07-20 19:13:06

这是 make 的默认行为。
当命令返回错误代码(例如非零返回)时,make 目标将被删除。 .PRECIOUS 和 .IGNORE makefile 指令可以更改此行为。

This is the default behaviour of make.
When a command returns an error code (e.g. non-zero return) then the make target is deleted. The .PRECIOUS and .IGNORE makefile directives can change this behaviour.

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