Индикация прогресса Make / Makefile! - PullRequest
24 голосов
/ 16 января 2009

Посмотрите на этот make-файл, у него есть какой-то примитивный индикатор прогресса (это мог быть индикатор выполнения).

Пожалуйста, дайте мне предложения / комментарии к нему!



# BUILD is initially undefined
ifndef BUILD

# max equals 256 x's
sixteen := x x x x x x x x x x x x x x x x
MAX := $(foreach x,$(sixteen),$(sixteen))

# T estimates how many targets we are building by replacing BUILD with a special string
T := $(shell $(MAKE) -nrRf $(firstword $(MAKEFILE_LIST)) $(MAKECMDGOALS) \
            BUILD="COUNTTHIS" | grep -c "COUNTTHIS")

# N is the number of pending targets in base 1, well in fact, base x :-)
N := $(wordlist 1,$T,$(MAX))

# auto-decrementing counter that returns the number of pending targets in base 10
counter = $(words $N)$(eval N := $(wordlist 2,$(words $N),$N))

# BUILD is now defined to show the progress, this also avoids redefining T in loop
BUILD = @echo $(counter) of $(T)
endif

# dummy phony targets

.PHONY: all clean

all: target
    @echo done

clean:
    @rm -f target *.c

# dummy build rules

target: a.c b.c c.c d.c e.c f.c g.c
    @touch $@
    $(BUILD)

%.c:
    @touch $@
    $(BUILD)


Все предложения приветствуются!

Ответы [ 3 ]

7 голосов
/ 18 января 2009

Это менее навязчиво и более круто.

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
3 голосов
/ 10 февраля 2016

Это небольшая модификация превосходного ответа @ GiovanniFunchal .

Итак, я хотел лучше понять это и заставить его работать на <10%, поэтому я углубился в документацию <a href="http://www.gnu.org/software/make/manual/make.html" rel="nofollow noreferrer"> и узнал больше о expr .

# PLACE AT THE TOP OF YOUR MAKEFILE
#---------------------------------
# Progress bar defs
#--------------------------------
#  words = count the number of words
ifneq ($(words $(MAKECMDGOALS)),1) # if no argument was given to make...
.DEFAULT_GOAL = all # set the default goal to all
#  http://www.gnu.org/software/make/manual/make.html
#  $@ = target name
#  %: = last resort recipe
#  --no-print-directory = don't print enter/leave messages for each output grouping
#  MAKEFILE_LIST = has a list of all the parsed Makefiles that can be found *.mk, Makefile, etc
#  -n = dry run, just print the recipes
#  -r = no builtin rules, disables implicit rules
#  -R = no builtin variables, disables implicit variables
#  -f = specify the name of the Makefile
%:                   # define a last resort default rule
      @$(MAKE) $@ --no-print-directory -rRf $(firstword $(MAKEFILE_LIST)) # recursive make call, 
else
ifndef ECHO
#  execute a dry run of make, defining echo beforehand, and count all the instances of "COUNTTHIS"
T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
      -nrRf $(firstword $(MAKEFILE_LIST)) \
      ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
#  eval = evaluate the text and read the results as makefile commands
N := x
#  Recursively expand C for each instance of ECHO to count more x's
C = $(words $N)$(eval N := x $N)
#  Multipy the count of x's by 100, and divide by the count of "COUNTTHIS"
#  Followed by a percent sign
#  And wrap it all in square brackets
ECHO = echo -ne "\r [`expr $C '*' 100 / $T`%]"
endif
#------------------
# end progress bar
#------------------

# REST OF YOUR MAKEFILE HERE

#----- Progressbar endif at end Makefile
endif

Я избавился от части : '.*\(....\)$$'. Он вернет последние 4 символа внутренней команды expr, но потерпит неудачу, если он будет меньше 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

Надеюсь, это поможет.

2 голосов
/ 16 января 2009

Хороший трюк! (-:

Но не очень масштабируемый для растущих проектов, которые распределены по многим каталогам с большим количеством make-файлов.

Я был бы более склонен к тому, чтобы протоколирование проходило через [Mm] akefiles * в вашем проекте и использовало это для отслеживания прогресса.

Просто мысль. Кстати, спасибо, что поделились этим.

Редактировать: Просто подумал. Это может быть полезно в измененной форме для отображения пульсатора, чтобы показать прогресс во время выполнения длинной задачи, например, распаковка большого архива дистрибутива вместо простого указания опции -v для команды tar. Все еще немного сахарного покрытия, но немного веселья. (-:

ура

Rob

...