不在规则中保存命令的输出

make not saving output of a command inside a rule

我有一个项目,我必须 运行 多个随机生成的不同长度的字符串,以通过实验获得其复杂性。

我已经编写了一个脚本来生成这些序列并将它们全部放在一个文件夹中。它们都有后缀“.in”。我正在尝试在此文件夹中生成一个 makefile,它调用:

{ time ../proj1 < gen.in 1> /dev/null 2>&1; } 2> gen.time

对于每个生成的文件。 到目前为止,我已经尝试过这样的事情:

MAKEFLAGS += --no-print-directory # No entering and leaving messages

all:: clean # run tests
    @$(MAKE) $(MFLAGS) `ls *.in | sed -e "s/in/time/"`

%.time: %.in
    { time ../proj1 < $< 2> /dev/null 2>&1; } 2> $@

clean::
    rm -f *.time

makefile 开始执行,但它没有给出正确的结果,而是创建了空文件。如果我尝试执行 make 打印到终端上的命令,它们会按预期工作......我无法理解我做错了什么......

在您的示例命令行中:

{ time ../proj1 < gen.in 1> /dev/null 2>&1; } 2> gen.time

在您的 makefile 中:

{ time ../proj1 < $< 2> /dev/null 2>&1; } 2> $@

请注意 1>2>,这显然是错误的:如果您向我们展示了 运行 的输出,我们将能够看到输出。但这并不是导致您的文件为空的原因。

原因是,当您 运行 在 shell 中使用此命令时,它正在使用您的 shell,这很可能 bash,并且 bash time 的内置版本。但是当你 运行 make 时,它​​使用 make SHELL 变量的值,默认情况下它总是 /bin/sh :在许多不是 bash 的系统上它是一个快速 POSIX-compliant shell like dash,它没有 time 的内置版本,所以你 运行ning /usr/bin/time 相反:那个版本只是写像任何其他程序一样到 stderr:

$ /usr/bin/time sleep 2 2>/dev/null
$

您需要重写您的规则,或者添加:

SHELL = /bin/bash

到您的 makefile 以强制它使用 bash(当然,它不会在任何没有安装 bash 的系统上运行)。