被包含Makefile目标中变量展开异常问题及实现方案咨询
根因解释
该问题来自GNU Make不同语法位置的变量展开时机差异,和递归变量(=定义的变量)的全局延迟展开特性并不矛盾:
- Make逐行解析Makefile时,规则行(即
target: prerequisites格式的行)中的目标名、依赖列表里的变量,会在该行被读入的瞬间立即展开求值 - 只有规则下tab缩进的shell命令段中的变量,才会在对应目标被实际执行时延迟展开
对应最初的写法:执行include ../targets.mk时,FF_LIST、DESIGN_NAME等变量还未赋值,全部为空值。此时Make解析通用规则,实际得到的是一组目标名为空、get_ff_list无依赖的无效规则。等include执行完成再给变量赋值,已经不会改变已经解析完成的规则结构——只有后面命令段里的变量因为是执行时才展开,所以echo输出的值正确,最终就出现了命令能正常打印、但依赖目标完全不触发的现象。
临时方案的缺陷
将include移到配置变量后的写法,仅能解决基础配置传参的问题,扩展性很差:
- 如果用户需要覆写通用规则的命令、追加依赖,include放太早就会出现前述展开时机问题
- 如果include放太晚,通用逻辑里的默认变量、默认规则又会覆盖用户的自定义配置
- 没有强制约束的情况下,其他用户很容易随意调整include位置,触发各种难以排查的诡异问题。
可落地的框架优化方案
不需要推翻现有设计,只要给通用Makefile加固定分层和防呆设计,就能彻底规避这类问题:
- 固定用户侧Makefile模板,强制include位置
直接给所有用户提供可直接复制的设计Makefile模板,明确要求所有基础配置写在include之前,所有扩展、覆写逻辑写在include之后,不允许随意移动include行,模板示例:# --------------- 以下为必填配置区,不要改动顺序 --------------- DESIGN_NAME = design1 FF_LIST = ./misc/ff_list.csv SRC_FILES = ./src/*.v # --------------- 固定引入通用框架,不要移动这行 --------------- include ../targets.mk # --------------- 以下为自定义扩展区,可覆写规则/追加逻辑 --------------- # 示例:给get_ff_list追加额外校验步骤 get_ff_list: @echo "Run extra format check for generated ff list" # 示例:覆写ff_list的默认生成逻辑 $(FF_LIST): @echo "Use custom extraction flow for $(DESIGN_NAME)" - 重构通用Makefile为三段式结构,适配上述模板
把targets.mk按「默认配置-防呆校验-核心规则-扩展挂载点」的结构重写,示例:# 1. 可选参数默认值,用?=允许用户提前覆写 GEN_FF_LOG_LEVEL ?= info # 2. 必填参数防呆校验,用户漏填/写错include位置直接抛出明确错误 ifeq ($(strip $(DESIGN_NAME)),) $(error Fatal: Please define DESIGN_NAME in config section before including targets.mk) endif ifeq ($(strip $(FF_LIST)),) $(error Fatal: Please define FF_LIST in config section before including targets.mk) endif # 3. 核心通用规则,此时所有配置变量已经完成赋值,展开完全正常 $(FF_LIST): $(SRC_FILES) @echo "[$(GEN_FF_LOG_LEVEL)] Extract FF List for $(DESIGN_NAME)" .PHONY: get_ff_list get_ff_list: $(FF_LIST) @echo "[$(GEN_FF_LOG_LEVEL)] Get FF list for $(DESIGN_NAME) from $(FF_LIST)" - 对高频覆写逻辑做变量抽象
把通用规则里容易被用户修改的命令片段抽成带默认值的变量(比如前述示例里的GEN_FF_LOG_LEVEL,甚至可以把整个生成ff_list的命令抽成GEN_FF_CMD变量),用户不需要重写整个规则,只要重新给变量赋值就能修改逻辑,进一步降低出错概率。
内容的提问来源于stack exchange,提问作者Starvin Marvin
相关产品推荐
相关产品推荐

