Makefile 为什么GNU要删除一个文件

Makefile 为什么GNU要删除一个文件,makefile,gnu-make,Makefile,Gnu Make,我有一个用于运行测试的略显粗糙的makefile: ### Run the tests tests := tests/test1 tests/test2 ... test: $(tests) $(tests): %: %.c gcc -o $@ $(testflags) $< $@ 我对最后一行很好奇。我以前从未见过这样的人。为什么要删除已编译的测试 注意:我对这个示例进行了大量编辑,以使其更简单。我可能引入了一些错误。因为目标可能没有正确构建。下次您创建项目时,它

我有一个用于运行测试的略显粗糙的makefile:

### Run the tests

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

test: $(tests)

$(tests): %: %.c
    gcc -o $@ $(testflags) $<
    $@
我对最后一行很好奇。我以前从未见过这样的人。为什么要删除已编译的测试


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

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


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

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


另一个可能是:

$(tests): %: %.c
    gcc -o $@ $(testflags) $<
    -$@
$(测试):%:%.c
gcc-o$@$(测试标志)$<
-$@
未测试,但指示不会移除目标:

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

以及:

通常,当命令失败时,如果它更改了目标文件,则该文件已损坏,无法使用,或者至少没有完全更新。但是文件的时间戳显示它现在是最新的,所以下次运行时,它不会尝试更新该文件。情况与命令被信号杀死时一样;参见中断。因此,通常正确的做法是,如果在开始更改文件后命令失败,则删除目标文件。make将在以下情况下执行此操作。删除\u ON\u错误显示为目标。这几乎总是你想要做的,但它不是历史的实践;因此,为了兼容性,您必须显式地请求它


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

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

test: $(tests) runtests

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

runtests: %.out: %
    $< | tee $@
tests:=tests/test1测试/test2。。。
测试:$(测试)运行测试
$(测试):%:%
gcc-o$@$(测试标志)$<
运行测试:%。输出:%
$<| T形三通$@

(我的make语法可能有错误,任何人都可以随意更正。)一般的想法是让测试运行生成一个输出文件,这使得
make
更容易单独运行每个测试。

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

+1是指出此行为是由错误的makefile导致的,该错误的makefile将生成测试程序并将其运行到单个规则中。IMO这是更好的解决方案:更干净,更“像make”。不过,细节可以处理得更干净。首先,makefile作者必须决定:您是希望始终运行测试,还是仅在重新生成测试文件时运行测试(后者是原始示例所做的)。
tests := tests/test1 tests/test2 ...

test: $(tests) runtests

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

runtests: %.out: %
    $< | tee $@