Makefile中export命令致变量从简单展开变为递归展开的问题
GNU Make export后子Make中简单展开变量变为递归展开的原因及解决方法
问题原因
GNU Make 的export是通过系统环境变量传递变量的,但环境变量只能存储纯字符串,没法携带 Make 内部的变量类型(简单展开/递归展开)元数据。当子 Make 进程启动时,会把环境中的所有变量默认导入为递归展开变量——这是 Make 处理环境变量的固定规则,和父 Make 里原变量的类型无关。
你遇到的情况里,父 Make 中ARGS是用:=定义的简单展开变量,导出到环境后只剩字符串-a -b;子 Make 拿到这个字符串后,自动把ARGS初始化为递归展开变量。后续子 Make 执行ARGS += ../$(DIR)/lib.a时,因为ARGS是递归展开类型,这个操作会把../$(DIR)/lib.a作为表达式附加进去,而非展开后的静态值。所以当DIR从foo改成bar时,ARGS的表达式重新展开就会得到更新后的结果。
解决方法
方法一:在子 Makefile 中显式转换变量类型
在子 Makefile 的最开头,把导入的ARGS重新定义为简单展开变量:
ARGS := $(ARGS)
这一步会把原来的递归展开变量转换成简单展开类型,后续的+=操作会直接追加静态值,不再受DIR变化的影响。
方法二:通过命令行参数传递变量(替代 export)
父 Make 里放弃用export,改为在递归调用子 Make 时,通过命令行直接传递带类型的变量:
default: $(MAKE) -C child/ ARGS:=$(ARGS)
命令行中用VAR:=VALUE的形式传递变量时,子 Make 会直接将其创建为简单展开变量,完全保留父 Make 里的变量类型和静态值。
内容的提问来源于stack exchange,提问作者geometrian
相关产品推荐
相关产品推荐

