gpt4 book ai didi

linux - makefile 中的循环问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:19 26 4
gpt4 key购买 nike

我正在尝试实现在 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

最佳答案

正如您在评论中指出的那样,问题在于 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 中导出 N 并设计 PRINT_PROGRESS 命令,以便始终更新 N作为环境变量。不过,我找不到使这项工作正常进行的方法,因为它需要某种方法将更新的 N 值返回到 Make after命令已写入,因此单独的命令仍然有效。


编辑:运行上述脚本时的输出(使用更正的制表符缩进),加上使用的版本:

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

关于linux - makefile 中的循环问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4979426/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com