从本质上讲,以下是我正在寻找的东西 - 或者是一个相当干净的黑客将它拉下来:
GET_TIMESTAMP = $(shell perl -e 'print time()')
START_TIME := ${GET_TIMESTAMP}
all: T1 T2 ... TN
T1:
T2:
...:
TN:
#...
timer:
@perl -e 'printf( "Loaded makefiles in %ds, build completed in %ds\n", $ARGV[1] - $ARGV[0], $ARGV[2] - $ARGV[1] );' ${START_TIME} ${LOAD_COMPLETE} ${GET_TIMESTAMP}
.ATEND: timer
LOAD_COMPLETE := ${GET_TIMESTAMP}
......可以通过多种方式启动:
~ gmake all
(...)
Loaded makefiles in 8s, build completed in 93s
~ gmake T2 T3 T4
(...)
Loaded makefiles in 8s, build completed in 13s
其核心是.ATEND
特殊目标的这一想法会导致在所有CMDGOALS
或DEFAULTGOALS
完成后发生某些事情。
答案 0 :(得分:3)
如果您只想为构建计时,并且您在UNIXy平台上运行,为什么不只使用time
本身?
如:
pax$ time sleep 1
real 0m1.004s
user 0m0.000s
sys 0m0.000s
(虽然,在你的情况下,它当然是time gmake all
)。
这似乎是一个更优雅的解决方案,而不是尝试在make
中编写代码并使用正确的工具来完成工作。
或者,您可以将规则本身修改为:
all: T1 T2 ... TN
@perl -e blah blah blah
这将确保Perl在所有目标完成后执行 - 你必须摆弄makefile
所以它不是一个自动解决方案(你最好将自己局限于某些高级目标),但我不认为这是一个巨大的负担,因为一旦正确设置,makefile往往相对无变化。
答案 1 :(得分:1)
好吧,我一直想知道同样的事,并尝试了一些事情。 我猜一个递归的make可能会这样做,但我到目前为止还没有。 遗憾的是,确实没有。确实!
注意:显然你只会显示重新制作的食谱需要多长时间,除非是干净的。
因为paxdiablo建议unix时间命令是最简单的(以及我过去所做的)。
% time make
基于为每个食谱添加一个计时器会给你一个累积的运行时间,但不知道每个食谱花了多长时间(不是它在问题中)。 但是对于特定的配方,您可以在配方中再次使用时间,甚至将输出传送到日志文件(在bash中使用pipefail)。例如
# SHELL = /bin/bash -o pipefail
# @bash -o pipefail -c ' ( time /home/matt/bin/example_stdouterr.bash ) |& tee z.log'
# @bash -o pipefail -c ' ( time /home/matt/bin/example_stdouterr.bash ) 2>&1 | tee z.log '
所以我认为将它添加到大多数食谱中是最好的。 那你不需要特别的电话。 请参阅下面的示例,该示例应显示与以下内容的区别:
time -p make
time -p make -j 2
给出累积时间和时间戳。
TIME_START := $(shell date +%s)
define TIME-END
@time_end=`date +%s` ; time_exec=`awk -v "TS=${TIME_START}" -v "TE=$$time_end" 'BEGIN{TD=TE-TS;printf "%02dd:%02dh:%02dm:%02ds\n",TD/(60*60*24),TD/(60*60)%24,TD/(60)%60,TD%60}'` ; echo "##DATE end `date '+%Y-%m-%d %H:%M:%S %Z'` cumulative $${time_exec} $@"
endef
PHONY_GOALS := all
all: toprule1
$(TIME-END)
PHONY_GOALS += toprule1
toprule1: subrule1 subrule2
@echo toprule 1 start
@sleep 1
@echo toprule 1 done
$(TIME-END)
PHONY_GOALS += subrule1
subrule1: botrule1
@echo subrule 1 start
@sleep 1
@echo subrule 1 done
$(TIME-END)
PHONY_GOALS += subrule2
subrule2: botrule1
@echo subrule 2 start
@time -p sleep 2
@echo subrule 2 done
$(TIME-END)
PHONY_GOALS += botrule1
botrule1:
@echo botrule 1 start
@sleep 1
@echo "botrule 1 done"
$(TIME-END)
PHONY_GOALS += help
help:
@echo "$(info All the goals are: ${PHONY_GOALS})"
########### end bit
.PHONY :${PHONY_GOALS}
OTHER_GOALS := ${filter-out ${PHONY_GOALS}, ${MAKECMDGOALS}}
${OTHER_GOALS}:
答案 2 :(得分:0)
我刚刚想到了一个解决方案:
GET_TIMESTAMP = $(shell perl -e 'print time()')
START_TIME := ${GET_TIMESTAMP}
all: T1 T2 ... TN
T1:
T2:
...:
TN:
timer_target : ${TIMER_DEPENDENCY}
@echo do whatever to print out timing info
这将在命令行中用作:
gmake timer_target TIMER_DEPENDENCY='T3 T4 T5'
......或类似的东西。
它不能无缝地对每个目标起作用,但它可以使用。
答案 3 :(得分:0)
好的,只是想了一下,然后编码了。 您可以拥有一个计时器目标,该目标具有任何其他命令目标的先决条件,或者全部为空。那就是:
make -j 2 subrule1 timer
下面的示例(哦,只要它在相同的配方行上,它也会经过计时器。)
# gnu make file
TIME_START := $(shell date +%s)
define TIME-END
@time_end=`date +%s` ; \
time_exec=`awk -v "TS=${TIME_START}" -v "TE=$$time_end" 'BEGIN{TD=TE-TS;printf "%02dd:%02dh:%02dm:%02ds\n",TD/(60*60*24),TD/(60*60)%24,TD/(60)%60,TD%60}'` ; \
echo "##DATE end `date '+%Y-%m-%d %H:%M:%S %Z'` cumulative $${time_exec} $@"
endef
define ELAPSED-START
@elapsed_start=`date +%s`
endef
define ELAPSED-END
elapsed_end=`date +%s` ; \
elapsed_exec=`awk -v "TS=$$elapsed_start" -v "TE=$$elapsed_end" 'BEGIN{TD=TE-TS;printf "%02dd:%02dh:%02dm:%02ds\n",TD/(60*60*24),TD/(60*60)%24,TD/(60)%60,TD%60}'` ; \
echo "##DATE end `date '+%Y-%m-%d %H:%M:%S %Z'` elapsed $${elapsed_exec} $@"
endef
PHONY_GOALS := all
all: subrule1 subrule2
@$(TIME-END)
PHONY_GOALS += subrule1
subrule1:
$(ELAPSED-START) ; \
echo subrule 1 start ; \
sleep 1 ; \
echo subrule 1 done ; \
$(ELAPSED-END)
@sleep 1
@$(TIME-END)
PHONY_GOALS += subrule2
subrule2:
@echo subrule 2 start
@$(ELAPSED-START) ; time -p sleep 2 ; $(ELAPSED-END)
@echo subrule 2 done
@$(TIME-END)
# create a prereq for timer to any CMDGOAL if empty add all
TIMERPREREQ := ${filter-out timer, ${MAKECMDGOALS}}
ifeq ($(strip $(TIMERPREREQ)),)
TIMERPREREQ := all
endif
#$(info TIMERPREREQ := ${TIMERPREREQ})
PHONY_GOALS += timer
timer: ${TIMERPREREQ}
@$(TIME-END)
PHONY_GOALS += help
help:
@echo "$(info All the goals are: ${PHONY_GOALS})"
########### end bit
.PHONY :${PHONY_GOALS}
结果是:
subrule 1 start
subrule 1 done
##DATE end 2016-03-18 13:41:56 GMT elapsed 00d:00h:00m:01s subrule1
##DATE end 2016-03-18 13:41:57 GMT cumulative 00d:00h:00m:02s subrule1
##DATE end 2016-03-18 13:41:58 GMT cumulative 00d:00h:00m:02s timer
答案 4 :(得分:0)
我希望你喜欢这个Makefile性能测量工具。 此脚本适用于make的所有版本和品牌。
为了我自己的使用,我编写了这个Python帮助程序脚本,以便在外部维护Makefile过去的时间。它运作良好,并且有很好的文档记录。
使用此脚本从'make'实用程序卸载复杂而微妙的任务,并使Makefile编写器能够对make性能的报告进行细粒度控制。
#!/usr/bin/env python
"""
MakeTime.py(support)
NAME
MakeTime.py - Maintain storage for Makefile rule elapsed times.
SYNOPSIS
MakeTime.py [OPTION]
MakeTime.py [label] [title text]
DESCRIPTION
Hold timing data in the external file 'MakeTime.json'.
OPTIONS
-c, --clean, --clear, --initialize
Delete the external file.
-s, --summary, --summarize, --report
Generate summary of stored timing data.
-h, --help, (anything else beginning with '-')
Show this help
EXAMPLES
./MakeTime.py
./MakeTime.py -h
./MakeTime.py --help
Show help
./MakeTime.py -c
./MakeTime.py --clean
./MakeTime.py --clear
./MakeTime.py --initialize
Delete JSON file 'MakeTime.json' to prepare for new timings.
./MakeTime.py START How much time does the make execution take?
Associate title and t0 for START rule
./MakeTime.py START
Associate t1 to JSON for START rule
./MakeTime.py -r
./MakeTime.py -s
./MakeTime.py --report
./MakeTime.py --summary
./MakeTime.py --summarize
Perform calculations for execution times then
summarize collected timings with labels to help.
EXAMPLE MAKEFILE
###############################################################################
all: START rule1 rule2 END
.PHONY:
START:
@./MakeTime.py --clear
@./MakeTime.py $@ Elapsed during the entire make process.
.PHONY:
rule1:
@./MakeTime.py $@ Elapsed during rule1.
sleep 3
@./MakeTime.py $@
.PHONY:
rule2:
@./MakeTime.py $@ Elapsed during rule2.
sleep 5
@./MakeTime.py $@
.PHONY:
END:
@./MakeTime.py START
@./MakeTime.py --summary
###############################################################################
COPYRIGHT
Copyright(c)2016 Jonathan D. Lettvin, All Rights Reserved
"""
from time import time
from sys import argv
from pprint import pprint
from os import remove
from os.path import exists
store = "MakeTime.json"
result = {}
marked = time()
if len(argv) == 1:
"When no args are given, display the help text."
print __doc__
elif len(argv) == 2:
arg1 = argv[1]
if arg1 in ["-c", "--clean", "--clear", "--initialize"]:
"Clear the backstore."
if exists(store):
remove(store)
elif arg1 in ["-r", "-s", "--summary", "--summarize", "--report"]:
"Calculate elapsed times and print summary"
with open(store, "r") as source:
names = []
seen = set()
for n, line in enumerate(source):
data = eval(line)
for k,v in data.iteritems():
result[k] = result.get(k, {})
result[k].update(v)
if not k in seen:
seen.add(k)
names.append(k)
for k in names:
v = result[k]
timing = "unknown MakeTime"
if v.has_key('t1') and v.has_key('t0'):
timing = "%4.3f seconds" % (float(v['t1']) - float(v['t0']))
print("\t\t%s [%s] %s" % (timing, k, v['title']))
elif arg1[0] == '-': # -, -h, --help, or anything beginning with '-'
print __doc__
else:
"Per rule delta"
result = {arg1: {'t1': marked}}
with open(store, "a") as target:
print>>target, str(result)
else:
"Per rule t0"
result = {argv[1]: {'t0': marked, 'title': " ".join(argv[2:])}}
with open(store, "a") as target:
print>>target, str(result)
答案 5 :(得分:0)
我在一个无法修改的制作系统中处理这个微小的解决方案(Makefiles只读)。
将此文件另存为" timebash"并为其设置执行权限:
var PRODUCTS = []
fetch('https://api.myjson.com/bins/10scuq')
.then(res => res.json())
.then(data => { PRODUCTS = data; renderMe() })
const container = document.getElementById('root')
const renderMe = () => {
render(
<FilterableProductTable products={PRODUCTS} />,
document.getElementById('root')
);
}
renderMe();
然后你可以在不改变任何Makefile的情况下调用make这样的
#!/bin/bash
# shell replacement to time make recipes, invoke with:
# make SHELL='/path/to/timebash "$(@)"' . . .
# timing data (start, elapsed) appears in the make output, along
# with a "make stack" tracked in the MKSTACK variable like
# "target[0].subtarg[1].subtarg2[2]..."
target="$1"
shift
export MKSTACK
MKSTACK="${MKSTACK}${MKSTACK:+.}${target}[$MAKELEVEL]"
# compose your timing data format here
# on multiple lines here for readability
now=$(date "+%Y%m%d_%H%M%S")
fmt="timebash:$$" ## each line starts with 'timebash'+pid
fmt="${fmt}:mkstack=${MKSTACK}" ## add the MKSTACK
fmt="${fmt}:start=${now}" ## wall clock at start
fmt="${fmt}:elapsed=%e" ## time() fills this in
fmt="${fmt}:cmd='%C'" ## time() fills this too
# now invoke time and the original make command
/usr/bin/time -f "$fmt" -- /bin/bash "${@}"
我编写了一个python脚本,用于在ascii甘特图中渲染时序数据,并能够非常清晰地显示制作时间。