Makefile中$(eval $(call))结合foreach使用报missing separator错误求解
报错原因
missing separator 报错的核心原因是 eval 函数的执行逻辑不符合你当前的预期:
- 直接使用
$(call fun())能正常运行时,call会把函数展开后的@echo this is function作为all规则下的命令内容,你在命令前加了 Tab 符,完全符合 Makefile 规则的语法要求。 - 当你在命令行使用
$(foreach objdir, $(OBJECTDIRS), $(eval $(call fun)))时,eval会把展开得到的@echo this is function当做独立的 Makefile 语法片段直接解析,而不是作为当前all规则的命令处理。这行展开后的内容既没有关联的规则声明,开头也没有 Tab 符,Make 无法识别其格式,就会抛出分隔符缺失的错误。
另外你当前的 fun 定义没有用到入参,即便修复语法问题,循环执行也只会重复输出相同内容,不会用到遍历到的 objdir 变量。
解决方法
根据你的使用场景选择对应方案即可:
方案1:仅需要循环执行命令(绝大多数场景)
删掉 eval 即可,foreach 本身可以展开为多段命令文本,直接作为规则的命令执行:
define fun @echo 当前处理目录: $(1) endef # 示例变量,替换为你自己的定义 OBJECTDIRS := src obj bin all: $(foreach objdir,$(OBJECTDIRS),$(call fun,$(objdir));)
如果需要每条命令单独占一行,可以在函数定义里加空行包裹命令:
define fun @echo 当前处理目录: $(1) endef OBJECTDIRS := src obj bin all: $(foreach objdir,$(OBJECTDIRS),$(call fun,$(objdir)))
方案2:确实需要用 eval 动态生成规则
如果你的需求是循环生成多条独立规则、或者给规则动态追加配置,就把 foreach + eval 逻辑放到规则外面,同时明确生成内容的规则格式:
define fun all: @echo 为 $(1) 生成命令 endef OBJECTDIRS := src obj bin # 放在规则外层解析,动态给all规则追加多条命令 $(foreach objdir,$(OBJECTDIRS),$(eval $(call fun,$(objdir))))
注意事项
所有规则的命令行开头必须是原生Tab字符,不要用多个空格代替,大部分编辑器默认的Tab转空格功能会触发这个报错,编写Makefile时需要临时关闭该配置。
内容的提问来源于stack exchange,提问作者SleepyCat
相关产品推荐
相关产品推荐

