You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU Makefile遍历列表异常:首项为空且末项被跳过

Makefile foreach循环首次迭代传空值、最后一个元素未处理的问题解决

问题现象

编写的Makefile通过foreach遍历列表元素并传递给函数时,首次迭代出现空值,最后一个元素从未被处理。执行make -f loop.mak后输出显示:

  • 第一次$(info)打印空的BENCHMARK和COMPILER
  • 仅处理了前3个元素,bench_4从未出现在---- BENCHMARK:的输出中

问题原因

核心问题在于变量展开时机和延迟赋值的副作用:

  1. GENERATE_TARGET中使用BENCHMARK=$(1)这种延迟赋值(=),变量不会立即展开,而是在后续被引用时才会解析。
  2. foreach循环中,$(eval)执行时,$(info)会先尝试展开$(BENCHMARK)和$(COMPILER),但此时这些变量的赋值还未生效,或者被循环的下一次迭代覆盖,导致输出错位。
  3. 循环最后一次迭代的$(eval)生成的目标,因为没有后续迭代触发$(info)输出,所以看不到对应的打印。

修复方案

修改GENERATE_TARGET的变量赋值方式为立即展开(:=),并调整$(info)的位置,确保在变量赋值后立即展开:

ALL_BENCHMARKS=bench_1 bench_2 bench_3 bench_4

define GENERATE_TARGET
BENCHMARK:=$(1)
COMPILER:=$(2)
$(info ---- BENCHMARK: $(BENCHMARK) COMPILER: $(COMPILER))
./$(BENCHMARK)$(COMPILER).file:
	@echo "Building $$@"
endef

$(foreach benchmark, $(ALL_BENCHMARKS), \
    $(info loop: $(benchmark)) \
    $(eval $(call GENERATE_TARGET,$(benchmark),.llvm)) \
)

default:
	@echo "default"

执行验证

运行make -f loop.mak后,输出将符合预期:

$ make -f loop.mak
loop: bench_1
---- BENCHMARK: bench_1 COMPILER: .llvm
loop: bench_2
---- BENCHMARK: bench_2 COMPILER: .llvm
loop: bench_3
---- BENCHMARK: bench_3 COMPILER: .llvm
loop: bench_4
---- BENCHMARK: bench_4 COMPILER: .llvm
default

关键说明

  • 使用:=(立即赋值)替代=(延迟赋值),确保BENCHMARK和COMPILER在GENERATE_TARGET被调用时就完成赋值,避免后续展开时的变量覆盖问题。
  • 将$(info)放在目标定义之前,确保在eval执行时立即打印当前迭代的正确变量值,不会被下一次迭代干扰。

内容的提问来源于stack exchange,提问作者CONts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:33:13