我想计算一个make规则的执行时间,但是无法获得有效的开始和停止时间以及让简单的算术(减法)工作。
$ make money
sleep 2
echo "money: 1453412887" > logfile
echo "money: 1453412887" >> logfile
echo "money: 1453412887" >> logfile
在Makefile
:
money:
$(eval start := $(shell date +%s))
sleep 2
$(eval end := $(shell date +%s))
echo "$@: ${start}" > logfile
echo "$@: ${end}" >> logfile
echo "$@: $(shell date +%s)" >> logfile
答案 0 :(得分:2)
请尝试以下示例,
test:
@start=$$(date +%s); \
echo $@: $$start > test.log
@sleep 2
@end=$$(date +%s); \
echo $@: $$end >> test.log
,一个关键项是,shell变量赋值应与echo命令在同一行。
答案 1 :(得分:2)
$(...)
格式的shell命令,则可能更容易在makefile配方中读取:
test:
echo $@: `date +%s` > test.log
@sleep 2
echo $@: `date +%s` >> test.log
您的尝试不起作用的原因是make会在开始第一行之前评估配方的所有行。因此,在配方的任何部分开始之前,整个配方中的所有make变量和函数(如eval
,shell
等)都是预先扩展的。因此,多次运行date
命令的结果将始终相同。
如果您正在尝试计算所有命令并且不想更改所有配方以保留日志,则另一个选项是编写一个特殊的脚本或程序,将命令行作为参数,然后在shell中运行该命令。然后设置make SHELL
变量以使用该脚本/程序而不是真正的shell。如果你有复杂的配方(你必须保留所有的引用等),让这个工作正常将会有点棘手。实际编写一个小程序并使用fork / exec最简单:那里没有引用问题。但是,这是最可靠和最少侵入性的方式。
答案 2 :(得分:1)
这是我用来定时执行makefile构建项目(配方及其各自的项目,甚至项目的输出)的一种解决方案。
原理上,make
命令的输出通过管道
while read line; do date +'%s%N'; echo "$line"; done`
所有在make调用中发出的所有输出行都加上了一个时间戳记行,从而可以查看用于各个配方及其元素/项目的时间。
一个例子说明了这一点。假设这个简单的Makefile
如果这是我们的Makefile
all: part1 part2
cat part1 part2 > all
part1:
sleep 1
echo "part1 content" > part1
part2:
sleep 2
echo "part2 content" > part2
然后运行它会导致以下输出:
$> make | while read line; do date +'%s%N'; echo "$line"; done
1561566560276946890
sleep 1
1561566561280995480
echo "part1 content" > part1
1561566561290389273
sleep 2
1561566563292382045
echo "part2 content" > part2
1561566563298681800
cat part1 part2 > all
毫不意外地显示,part1
配方步骤sleep 1
的规则采用了1561566561280995480 - 1561566560276946890 = 1 004 048 640
毫微秒,
到预期的1秒持续时间。
unix epoc纳秒产生的时间戳,如本答案所示 提供一种简单的方法来快速检查输出的时间长度,并 从而获得表彰。
注意。通过-j
命令行参数使用多个make作业时,时间戳仅反映-Onone
的时间,即不使用输出同步。
答案 3 :(得分:0)
这里是如何做到这一点,而无需在整个 makefile 上乱涂乱画。
基本上,
您可以用自己设计的 shell 脚本替换 make 通常用来执行命令 (/bin/sh
) 的 shell。
一个班轮就可以了。类似的东西:
$ cat ~/TIMING
#!/bin/bash
command time -ao ~/LOG -f "%E [$*]" bash "$@"
command
因为我们想使用 /bin/time
(YMMV) 而不是 bash 内置的 time。-ao
将消息附加到日志文件中。我们使用绝对路径,以便 sub-make 更改文件夹继续记录到文件。-f
指定时间格式:我选择经过时间,然后是 make 给 shell 的参数。"$@"
扩展为 make 传递给 shell 的参数。 make 使用的第一个参数应该是 -c
,这会导致 bash 将以下参数作为命令执行。$ cat Makefile
.PHONY: atest
atest:
sleep 1.5
echo testing non-zero exit code
exit 22
echo done
然后正常运行:
$ make
sleep 1.5
echo testing non-zero exit code
testing non-zero exit code
exit 22
make: *** [atest] Error 22
然后是定时跑步。看起来都一样:
$ rm -f ~/LOG
$ chmod a+x ~/TIMING
$ make SHELL=~/TIMING
sleep 1.5
echo testing non-zero exit code
testing non-zero exit code
exit 22
make: *** [atest] Error 22
但是这次我们有一个不错的日志文件:
$ cat ~/LOG
0:01.50 [-c sleep 1.5]
0:00.00 [-c echo testing non-zero exit code]
0:00.00 [-c exit 22]
不错。并行安全也。你的 makefile 是并行安全的,对吧?