Scripting 制作/制作文件进度指示!

Scripting 制作/制作文件进度指示!,scripting,makefile,build-automation,progress-bar,Scripting,Makefile,Build Automation,Progress Bar,看看这个makefile,它有一些原始的进度指示(可能是一个进度条)。 请给我一些建议/意见 #构建最初是未定义的 ifndef构建 #最大值等于256 x 十六:=x x x x x 最大值:=$(外汇兑换x,$(十六),$(十六)) #T通过用特殊字符串替换BUILD来估计我们正在构建的目标数量 T:=$(shell$(MAKE)-nrRf$(firstword$(MAKEFILE_LIST))$(MAKECMDGOALS)\ BUILD=“COUNTTHIS”| grep-c“COUNT

看看这个makefile,它有一些原始的进度指示(可能是一个进度条)。

请给我一些建议/意见


#构建最初是未定义的 ifndef构建 #最大值等于256 x 十六:=x x x x x 最大值:=$(外汇兑换x,$(十六),$(十六)) #T通过用特殊字符串替换BUILD来估计我们正在构建的目标数量 T:=$(shell$(MAKE)-nrRf$(firstword$(MAKEFILE_LIST))$(MAKECMDGOALS)\ BUILD=“COUNTTHIS”| grep-c“COUNTTHIS”) #N是基数1中待处理目标的数量,实际上,基数x:-) N:=$(单词表1,$T,$(最大值)) #自动递减计数器,返回基数为10的挂起目标数 计数器=$(单词$N)$(评估N:=$(单词表2,$(单词$N),$N)) #BUILD现在定义为显示进度,这也避免了在循环中重新定义T BUILD=@echo$(计数器)共$(T) 恩迪夫 #假目标 .骗子:都是干净的 全部:目标 @回音完成 清洁: @rm-f目标*.c #虚拟构建规则 目标:a.c.b.c.c.d.c.e.c.f.c.g.c @触碰$@ $(构建) %.c: @触碰$@ $(构建)
欢迎所有建议

好把戏!(-):

但对于分布在多个目录和大量makefile中的不断增长的项目来说,这并不是真正可伸缩的

我更倾向于在项目中的[Mm]akefiles*中添加日志记录,并用它来跟踪进度

只是一个想法。顺便说一句,谢谢分享

编辑:刚刚有了一个想法。在修改后的表单中,这可能很有用,可以在长时间任务进行时显示一个跳动器以显示进度,例如,解包一个大型分发tarball,而不仅仅是为tar命令指定-v选项。仍然有点糖衣,但也有点乐趣。(-:

干杯


罗伯

这部电影不那么打扰人,更令人敬畏

ifneq ($(words $(MAKECMDGOALS)),1)
.DEFAULT_GOAL = all
%:
        @$(MAKE) $@ --no-print-directory -rRf $(firstword $(MAKEFILE_LIST))
else
ifndef ECHO
T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
      -nrRf $(firstword $(MAKEFILE_LIST)) \
      ECHO="COUNTTHIS" | grep -c "COUNTTHIS")

N := x
C = $(words $N)$(eval N := x $N)
ECHO = echo "`expr " [\`expr $C '*' 100 / $T\`" : '.*\(....\)$$'`%]"
endif

.PHONY: all clean

all: target
        @$(ECHO) All done

clean:
        @rm -f target *.c
#       @$(ECHO) Clean done

target: a.c b.c c.c d.c e.c
        @$(ECHO) Linking $@
        @sleep 0.1
        @touch $@

%.c:
        @$(ECHO) Compiling $@
        @sleep 0.1
        @touch $@

endif

这是对@GiovanniFunchal的优秀设计的轻微修改

因此,我想更好地理解这一点,并使其在<10%的范围内发挥作用,因此我深入研究并了解了更多

我去掉了
:“.*\(..)$$”
部分。它将返回内部
expr
命令的最后4个字符,但如果小于4,则将失败。现在它的工作效率低于10%

以下是免评论版本:

ifneq ($(words $(MAKECMDGOALS)),1) # if no argument was given to make...
.DEFAULT_GOAL = all # set the default goal to all
%:                   # define a last resort default rule
      @$(MAKE) $@ --no-print-directory -rRf $(firstword $(MAKEFILE_LIST)) # recursive make call, 
else
ifndef ECHO
T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
      -nrRf $(firstword $(MAKEFILE_LIST)) \
      ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
N := x
C = $(words $N)$(eval N := x $N)
ECHO = echo -ne "\r [`expr $C '*' 100 / $T`%]"
endif

# ...

endif

希望这会有所帮助。

这不是一个真正的问题,所以这不是一个独立的答案,而是对Giovanni Funchai的答案的扩展。这个问题是“GNU取得进展”的第一个谷歌结果,所以我在这里寻找如何做到这一点


正如Rob Wells所指出的,这个解决方案不适用于,这多亏了
@Giovanni Funchal
@phyatt
的问答

我只是为了更好的理解而简化了它

ifndef ECHO
HIT_TOTAL != ${MAKE} ${MAKECMDGOALS} --dry-run ECHO="HIT_MARK" | grep -c "HIT_MARK"
HIT_COUNT = $(eval HIT_N != expr ${HIT_N} + 1)${HIT_N}
ECHO = echo "[`expr ${HIT_COUNT} '*' 100 / ${HIT_TOTAL}`%]"
endif
  • !=
    从shell命令分配
  • =
    每次使用变量时都对其求值
  • eval
    在没有任何输出的情况下执行其参数
  • expr
    允许进行算术计算
(不确定哪种方法更快:使用expr调用shell或使用make计算“x'-e”。)

用法相同:

target:
    @$(ECHO) $@

可爱的把戏,但我看不出我想要它。我可以。在Gentoo上这会很好。
cmake
有一个内置计数器[文件x/n文件]。但是,如果有一个进度条而不让每个命令行充斥屏幕,那就太好了。谢谢你的评论,你能解释一下为什么你认为它不能缩放吗?好的,代码只是一个草图,但是如果需要的话,MAX可以容纳64k x,并且T变量的计算速度非常快。它不能缩放,因为如果你使用“转换多个目录”,每个子目录都有自己的生成文件。@ScottieT812,干杯,这是我发表评论的主要原因!(:另一个是随着项目的扩展不断计算和更新所需的x的数量。尽管如此。这是一个很好的技巧。Rob你不理解我的脚本。如果你有多个目录上的makefiles(尽管我不建议递归make),并且x不是目标的数量,它只是一个上限,那么它是有效的(256个,可以更多)。将自动发现目标的确切数量(请参见代码$T)以使其重新写入上一行。将其用于回显行:
ECHO=ECHO-ne“\r``expr”[\`expr$C'*'100/$T\`':'.\(..)$$'``%]”
它在bash中工作,可能在其他*磁盘上也不工作。这取决于
echo
是否支持
-e
-n
。注意在前面的注释中,双反勾应该是单反勾,就像在文章中一样。唯一添加的是echo后面的
-ne
和引号后面的
\r
。这很好,但是使用-j选项时百分比会中断。例如[28%]编译b.c[14%]编译a.c…我在Linux内核makefile上使用了它,它抑制了输出!构建仍然在后台运行,但我在标准输出中看不到任何东西。可能是echo中的
\r
使它每次都保持在同一行,或者是echo中的
-ne
部分。即使删除了它们,问题仍然存在内核KBUILD脚本正在做一些特殊的事情,这段代码没有涉及到?很高兴看到在我最初的帖子发表10年后,这仍然受到关注;)不错!应该在顶部。但我认为您的第二个python代码有一个缺陷。它使用非ASCII字符,但没有任何编码声明。您必须在脚本顶部添加例如
#coding:utf-8
。请参阅。但是非常感谢:)
"""
Print makefile progress
"""

import argparse
import math
import sys

def main():
  parser = argparse.ArgumentParser(description=__doc__)
  parser.add_argument("--stepno", type=int, required=True)
  parser.add_argument("--nsteps", type=int, required=True)
  parser.add_argument("remainder", nargs=argparse.REMAINDER)
  args = parser.parse_args()

  nchars = int(math.log(args.nsteps, 10)) + 1
  fmt_str = "[{:Xd}/{:Xd}]({:6.2f}%)".replace("X", str(nchars))
  progress = 100 * args.stepno / args.nsteps
  sys.stdout.write(fmt_str.format(args.stepno, args.nsteps, progress))
  for item in args.remainder:
    sys.stdout.write(" ")
    sys.stdout.write(item)
  sys.stdout.write("\n")

if __name__ == "__main__":
  main()
_mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
I := $(patsubst %/,%,$(dir $(_mkfile_path)))

ifneq ($(words $(MAKECMDGOALS)),1)
.DEFAULT_GOAL = all
%:
    @$(MAKE) $@ --no-print-directory -rRf $(firstword $(MAKEFILE_LIST))
else
ifndef ECHO
T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
      -nrRf $(firstword $(MAKEFILE_LIST)) \
      ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
N := x
C = $(words $N)$(eval N := x $N)
ECHO = python $(I)/echo_progress.py --stepno=$C --nsteps=$T
endif

.PHONY: all clean

all: target
    @$(ECHO) All done

clean:
    @rm -f target *.c
#       @$(ECHO) Clean done

target: a.c b.c c.c d.c e.c f.c g.c h.c i.c j.c k.c l.c m.c n.c o.c p.c q.c \
        r.c s.c t.c u.c v.c w.c x.c y.c z.c
    @$(ECHO) Linking $@
    @sleep 0.01
    @touch $@

%.c:
    @$(ECHO) Compiling $@
    @sleep 0.01
    @touch $@

endif
$ make
[ 1/28](  3.57%) Compiling a.c
[ 2/28](  7.14%) Compiling b.c
[ 3/28]( 10.71%) Compiling c.c
[ 4/28]( 14.29%) Compiling d.c
[ 5/28]( 17.86%) Compiling e.c
[ 6/28]( 21.43%) Compiling f.c
[ 7/28]( 25.00%) Compiling g.c
[ 8/28]( 28.57%) Compiling h.c
[ 9/28]( 32.14%) Compiling i.c
[10/28]( 35.71%) Compiling j.c
[11/28]( 39.29%) Compiling k.c
[12/28]( 42.86%) Compiling l.c
[13/28]( 46.43%) Compiling m.c
[14/28]( 50.00%) Compiling n.c
[15/28]( 53.57%) Compiling o.c
[16/28]( 57.14%) Compiling p.c
[17/28]( 60.71%) Compiling q.c
[18/28]( 64.29%) Compiling r.c
[19/28]( 67.86%) Compiling s.c
[20/28]( 71.43%) Compiling t.c
[21/28]( 75.00%) Compiling u.c
[22/28]( 78.57%) Compiling v.c
[23/28]( 82.14%) Compiling w.c
[24/28]( 85.71%) Compiling x.c
[25/28]( 89.29%) Compiling y.c
[26/28]( 92.86%) Compiling z.c
[27/28]( 96.43%) Linking target
[28/28](100.00%) All done
"""
Print makefile progress
"""

import argparse
import math
import sys

def get_progress_bar(numchars, fraction=None, percent=None):
  """
  Return a high resolution unicode progress bar
  """
  if percent is not None:
    fraction = percent / 100.0

  if fraction >= 1.0:
    return "█" * numchars

  blocks = [" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█"]
  length_in_chars = fraction * numchars
  n_full = int(length_in_chars)
  i_partial = int(8 * (length_in_chars - n_full))
  n_empty = max(numchars - n_full - 1, 0)
  return ("█" * n_full) + blocks[i_partial] + (" " * n_empty)

def main():
  parser = argparse.ArgumentParser(description=__doc__)
  parser.add_argument("--stepno", type=int, required=True)
  parser.add_argument("--nsteps", type=int, required=True)
  parser.add_argument("remainder", nargs=argparse.REMAINDER)
  args = parser.parse_args()

  nchars = int(math.log(args.nsteps, 10)) + 1
  fmt_str = "\r[{:Xd}/{:Xd}]({:6.2f}%) ".replace("X", str(nchars))
  progress = 100 * args.stepno / args.nsteps
  sys.stdout.write(fmt_str.format(args.stepno, args.nsteps, progress))
  sys.stdout.write(get_progress_bar(20, percent=progress))
  remainder_str = " ".join(args.remainder)
  sys.stdout.write(" {:20s}".format(remainder_str[:20]))
  if args.stepno == args.nsteps:
    sys.stdout.write("\n")

if __name__ == "__main__":
  main()
$ make clean && make
[12/28]( 42.86%) ███████▊             Compiling k.c
$ make clean && make
[28/28](100.00%) ████████████████████ All done 
ifndef ECHO
HIT_TOTAL != ${MAKE} ${MAKECMDGOALS} --dry-run ECHO="HIT_MARK" | grep -c "HIT_MARK"
HIT_COUNT = $(eval HIT_N != expr ${HIT_N} + 1)${HIT_N}
ECHO = echo "[`expr ${HIT_COUNT} '*' 100 / ${HIT_TOTAL}`%]"
endif
target:
    @$(ECHO) $@