如何将Makefile中所有变量及其值写入文件?
Makefile变量输出到文件的问题与解决
原需求与工作代码
我需要用Makefile获取所有变量及其值并写入文件,目前有一段代码可以在终端打印出变量,但无法将输出重定向到文件:
.PHONY: test test: $(foreach v, \ $(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), \ $(info $(v) = $($(v))))
无效的尝试
我试了几种方法都无法将输出写入文件:
- 直接在
info后加重定向:...$(info $(v) = $($(v)))) > myfile.txt - 追加模式重定向:
...$(info $(v) = $($(v))) >> myfile.txt) - 尝试用变量存储所有输出后写入:
ALL_MAKEFILE_VARS:; $(foreach v, $(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), $(info $(v)=$($(v)))) .PHONY: test test: $(file > myfile.txt,$(ALL_MAKEFILE_VARS))
- 用echo包裹输出重定向:
echo -e $(foreach v, $(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), $(info $(v)=$($(v)))) > derp.txt
使用file函数遇到的新问题
问题1:提示"Nothing to be done for 'test'"
尝试用file函数写入文件时,执行make test会提示该信息,对应的代码:
VARS_OLD:= $(.VARIABLES) .PHONY: test test: $(foreach v, \ $(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), \ $(file >myfile.txt,$(v) = $($(v))))
问题2:移除VARS_OLD后报错且文件内容不完整
去掉VARS_OLD:= $(.VARIABLES)后,执行报错:
*** Undefined required by target `test`. Stop
虽然生成了myfile.txt,但文件里只有一行内容:
.LIBPATTERNS = lib%.dylib lib%.a
解决方案
核心问题分析
$(file >myfile.txt,...)每次调用都会清空文件再写入,循环结束后只会保留最后一个变量的内容,需要改用追加模式$(file >>myfile.txt,...)。VARS_OLD:= $(.VARIABLES)用立即展开赋值时,会在Makefile解析阶段就把.VARIABLES的内容赋值给VARS_OLD,导致后续filter-out把所有变量都过滤掉,foreach没有生成任何执行命令,因此make认为test目标无操作。- 移除
VARS_OLD后,filter-out $(VARS_OLD) VARS_OLD变成空参数加VARS_OLD,导致filter-out行为异常,生成无效变量名引发报错。
正确写法1:通过Shell重定向输出
直接在目标命令中用foreach生成echo语句,整体重定向到文件:
.PHONY: test test: @$(foreach v, $(filter-out VARS_OLD,$(.VARIABLES)), echo "$(v) = $($(v))";) > myfile.txt
@用于隐藏命令本身的输出- 用
echo输出每个变量,整体重定向避免循环中多次打开文件 - 如果变量包含特殊字符,
"$(v) = $($(v))"的引号可以保证输出格式正确
正确写法2:使用file函数追加并延迟变量展开
改用递归展开变量定义VARS_OLD,确保foreach在执行阶段才展开变量,同时先清空文件再追加:
.PHONY: test test: $(file >myfile.txt,) # 先清空文件 $(foreach v, $(filter-out VARS_OLD,$(.VARIABLES)), \ $(file >>myfile.txt,$(v) = $($(v)))) VARS_OLD = $(.VARIABLES)
VARS_OLD = $(.VARIABLES)是递归展开,会在foreach执行时才获取当前的.VARIABLES内容$(file >myfile.txt,)清空文件,避免多次运行时内容累加>>模式保证每个变量内容都追加到文件中
内容的提问来源于stack exchange,提问作者red888
相关产品推荐
相关产品推荐

