我正在尝试实现逻辑以在makefile中显示构建的进度。
我可以成功地将其打印为与此处级联的makefile中的目标“simple”。然而,当涉及makefile中的另一个目标“for”时,出现了问题,我无法弄清楚它是什么。
任何帮助都会非常感激。
## BUILD is initially undefined
ifndef BUILD
# T estimates how many targets we are building by replacing BUILD with a special string
T := $(shell $(MAKE) progress --no-print-directory \
-nrRf $(firstword $(MAKEFILE_LIST)) \
BUILD="COUNTTHIS" | grep -c "COUNTTHIS")
## N is the target number
N := x
## incrementing counter
C = $(words $N)$(eval N := x $N)$(shell export $N)
## BUILD is now defined to show the progress, this also avoids redefining T in loop
BUILD = echo "`expr " [\`expr $C '*' 100 / $T\`" : '.*\(....\)$$'`%]"
endif
MODULE_LIST = module1
MODULE_LIST := $(MODULE_LIST) module2
MODULE_LIST := $(MODULE_LIST) module3
MODULE_LIST := $(MODULE_LIST) module4
MODULE_LIST := $(MODULE_LIST) module5
progress:
@$(BUILD)
@$(BUILD)
@$(BUILD)
@$(BUILD)
@$(BUILD)
simple:
# T=5 and C increases for every access
@$(BUILD) "Cleaning Module \"module1\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module2\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module3\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module4\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module5\""
@sleep 0.1
for:
# T=1 and C increases for every access but not inside the for loop
@for MODULE in $(MODULE_LIST); do \
$(BUILD) "Cleaning Module \"$$MODULE\"" ; \
sleep 0.1 ; \
done
答案 0 :(得分:4)
正如您在评论中指出的那样,问题是for循环在shell中执行,因此不会更新Makefile的变量(或者当Make通过评估变量引用来构建命令字符串时至少不会超过一次在里面)。
我能看到的唯一可行解决方案是将循环结构移动到Makefile中。试试这个:
## PRINT_PROGRESS is initially undefined
ifndef PRINT_PROGRESS
# T estimates how many targets we are building by replacing PRINT_PROGRESS with a special string
T := $(shell $(MAKE) $(MAKECMDGOALS) --no-print-directory \
-rRf $(firstword $(MAKEFILE_LIST)) \
PRINT_PROGRESS="echo COUNTTHIS" BUILD="test x ||" | grep -c "COUNTTHIS")
N := 1
## PRINT_PROGRESS is now defined to show the progress and update N
PRINT_PROGRESS = echo "`expr " [\`expr $N '*' 100 / $T\`" : '.*\(....\)$$'`%]"$(eval N := $(shell expr $N + 1))
endif
ifndef BUILD
BUILD := #blank
endif
MODULE_LIST = module1
MODULE_LIST += module2
MODULE_LIST += module3
MODULE_LIST += module4
MODULE_LIST += module5
simple:
# T=5 and C increases for every access
@$(PRINT_PROGRESS) "Cleaning Module \"module1\""
@$(BUILD) { sleep 0.1 ; echo "doing some work" ; }
@$(PRINT_PROGRESS) "Cleaning Module \"module2\""
@$(BUILD) { sleep 0.1 ; echo "doing some work" ; }
@$(PRINT_PROGRESS) "Cleaning Module \"module3\""
@$(BUILD) { sleep 0.1 ; echo "doing some work" ; }
@$(PRINT_PROGRESS) "Cleaning Module \"module4\""
@$(BUILD) { sleep 0.1 ; echo "doing some work" ; }
@$(PRINT_PROGRESS) "Cleaning Module \"module5\""
@$(BUILD) { sleep 0.1 ; echo "doing some work" ; }
for:
@$(foreach MODULE,$(MODULE_LIST),\
$(PRINT_PROGRESS) "Cleaning Module \"$(MODULE)\"" ; \
$(BUILD) { \
sleep 0.1 ; \
echo "doing some work" ; \
} ; \
)
这也包括其他一些变化。
乍一看似乎合理的解决方案是从makefile中export N
并设计PRINT_PROGRESS
命令,以便N
始终更新为环境变量。我找不到一种方法来完成这项工作,因为它需要一些方法将更新的 N值返回到之后的命令已被写入,因此单独的命令仍然有效。
编辑:运行上面的确切脚本时输出(带有更正的选项卡缩进),以及使用的版本:
jpab@oberon : /memtmp
$ make --version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-pc-linux-gnu
jpab@oberon : /memtmp
$ bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
jpab@oberon : /memtmp
$ make
# T=5 and C increases for every access
[20%] Cleaning Module "module1"
doing some work
[40%] Cleaning Module "module2"
doing some work
[60%] Cleaning Module "module3"
doing some work
[80%] Cleaning Module "module4"
doing some work
[100%] Cleaning Module "module5"
doing some work
jpab@oberon : /memtmp
$ make for
[20%] Cleaning Module "module1"
doing some work
[40%] Cleaning Module "module2"
doing some work
[60%] Cleaning Module "module3"
doing some work
[80%] Cleaning Module "module4"
doing some work
[100%] Cleaning Module "module5"
doing some work