GNU make:计时构建,是否可以有一个目标,其配方在所有目标完成后执行

发布于 2024-12-21 00:39:56 字数 974 浏览 1 评论 0原文

我的问题类似于这个这个

本质上,我正在寻找类似以下的东西——或者一个相当干净的黑客来实现它:

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 特殊目标,当所有 CMDGOALSDEFAULTGOALS 完成时,会导致发生某些事情。

My question is similar to this one and this one.

In essence, something like the following is what I'm looking for -- or a fairly clean hack for pulling it off:

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}

... which could be kicked off in a number of ways:

~ gmake all
(...)
  Loaded makefiles in 8s, build completed in 93s
~ gmake T2 T3 T4
(...)
  Loaded makefiles in 8s, build completed in 13s

At the heart of it is this idea of an .ATEND special target that causes something to happen when all CMDGOALS or DEFAULTGOALS are finished.

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

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

发布评论

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

评论(6

马蹄踏│碎落叶 2024-12-28 00:39:57

我希望您喜欢这个 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)

I hope you like this Makefile performance measuring tool.
This script works with ALL versions and brands of make.

For my own use I wrote this Python helper script to maintain Makefile elapsed timings externally. It works very well and is fairly well documented.

Using this script unloads a complex and subtle task from the 'make' utility and enables the Makefile writer to exercise fine-grained control over reporting of make performance.

#!/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)
泪眸﹌ 2024-12-28 00:39:56

如果您只想为构建计时,并且您在 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 往往相对不会发生变化。

If you just want to time your build, and you're running on a UNIXy platform, why not just use time itself?

As in:

pax$ time sleep 1
    real    0m1.004s
    user    0m0.000s
    sys     0m0.000s

(although, in your case, it would of course be time gmake all).

This seems a much more elegant solution than trying to code something up in make and uses the right tools for the job.


Alternatively, you could modify the rule itself to be something like:

all: T1 T2 ... TN
    @perl -e blah blah blah

This will ensure the Perl is executed once all targets are complete - you'll have to fiddle with the makefile so it's not an automatic solution (you'll be best off limiting yourself to certain high-level targets), but I don't think that's a huge burden since makefiles tend to be relatively changeless once set up correctly.

愿与i 2024-12-28 00:39:56

好吧,我也想知道同样的事情有一段时间了,并尝试了一些事情。
我想递归 make 可能会做到这一点,但到目前为止我避免使用这些。
遗憾的是确实没有 .ATEND!

注意:显然,您只会显示重新制作的食谱需要多长时间,除非是干净的。

time

因此,正如 paxdiablo 建议的那样,unix time 命令是最简单的(也是我过去所做的)。

% time make

基于配方

向每个配方添加一个计时器将为您提供累计运行时间,但不知道每个配方花费了多长时间(不是问题中的时间)。
然而,对于特定的配方,您可以在配方中再次利用时间,甚至将输出发送到日志文件(在 bash 中使用 pipelinefail)。例如

# 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}:

Well I have been wondering the same for a while, and tried a few things.
I guess a recursive make might do it, but I avoid those so far.
Pity there isn't a .ATEND indeed!

Note: Obviously you will only show how long re-made recipes take, unless from a clean.

time

So as paxdiablo suggested unix time commmand is the easiest (and what I have done in the past).

% time make

recipe based

Adding a timer to each recipe will give you a cumulative run time, but not an idea of how long each recipe took (not that it was in the question).
However for specific recipes you could make use of time again within the recipe and even tee the output to a logfile (using pipefail in bash). eg

# 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 '

summary

So I think just adding it to most of the recipes would be the best.
You don't need a special call then.
See below for an example, which should show differences with:

time -p make 
time -p make -j 2

Example

Gives cumulative time, as well as timestamp.

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}:
紫﹏色ふ单纯 2024-12-28 00:39:56

好吧,只是想到了一点,就编码了。
您可以拥有一个计时器目标,该目标具有任何其他命令目标的先决条件,或者全部为空。那么它就是:

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

Ok, just had a thought, and coded it.
You can have a timer goal that has prerequisites for any other command goals or all if empty. Then it would just be:

make -j 2 subrule1 timer

Example below (oh it also does elapsed timer as long as it is on same recipe line).

# 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}

Result is:

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
木森分化 2024-12-28 00:39:56

我在一个无法修改的 make 系统中研究了这个微小的解决方案(Makefile 是只读的)。

将此文件另存为“timebash”并为其设置执行权限:

#!/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 "${@}"

然后您可以像这样调用 make 而无需更改任何 Makefile

make SHELL='/path/to/timebash "$(@)"' . . .

我编写了一个 python 脚本来在 ascii 甘特图中呈现计时数据,并且能够非常清楚地可视化 make 计时。

I worked on this tiny solution in a make system that couldn't be modified (Makefiles were read only).

Save this file as "timebash" and set execute permissions on it:

#!/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 "${@}"

Then you can invoke make like this without changing any Makefiles

make SHELL='/path/to/timebash "$(@)"' . . .

I wrote a python script to render the timing data in an ascii gantt chart and was able to visualize the make timing quite clearly.

哥,最终变帅啦 2024-12-28 00:39:56

我刚刚想到了一个解决方案:

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'

...或类似的东西。

它不会无缝地适用于每个目标,但它是可用的。

A solution just occurred to me for this:

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

This would be used from the command line as:

gmake timer_target TIMER_DEPENDENCY='T3 T4 T5'

... or something similar.

It won't work for every target seamlessly, but it's usable.

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