【问题标题】:gnu make: list the values of all variables (or "macros") in a particular rungnu make:列出特定运行中所有变量(或“宏”)的值
【发布时间】:2011-10-30 09:14:56
【问题描述】:

如何在运行 make 时列出 Makefile 中所有变量(也称为宏)的当前值?

例如如果这是在 Makefile 中:

CUR-DIR := $(shell /bin/pwd)
LOG-DIR := $(CUR-DIR)/make-logs

那我想让它告诉我:

CUR-DIR = /home/johv/src/test
LOG-DIR = /home/johv/src/test/make-logs

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    GNU make 提供.VARIABLES 它包含所有全局变量的名称。 但是,这包括内置变量(如MAKEFLAGS)。 如果你必须排除内置变量,一些过滤如下 可能需要。 下面的 makefile 打印用户定义的变量(CUR-DIR, LOG-DIR) 使用info:

    VARS_OLD := $(.VARIABLES)
    CUR-DIR := $(shell pwd)
    LOG-DIR := $(CUR-DIR)/make-logs
    $(foreach v,                                        \
      $(filter-out $(VARS_OLD) VARS_OLD,$(.VARIABLES)), \
      $(info $(v) = $($(v))))
    

    (我将CURDIR重命名为CUR-DIR,因为CURDIR似乎是内置的 我系统中的变量)

    【讨论】:

    • 如何运行它?将其放入Makefile 并运行“make”我得到“make: *** No targets. Stop.
    • 对不起,我忘了说,如果你的 GNU make 的版本是 3.80 或更低,这个答案不起作用。
    • 啊,是的,我用的是 3.80。在 3.81 中它起作用了。另外,我在问题中改为 CUR-DIR。
    • 如何将其写入文件而不是打印出来?
    • @JasonS,让你的外壳处理它。 make > variables.txt
    【解决方案2】:

    我最终这样做了:

    gmake -pn | grep -A1 "^# makefile"| grep -v "^#\|^--" | sort | uniq > makevars.txt
    

    给出:

    CUR-DIR := /home/johv/src/test
    LOG-DIR := /home/johv/src/test/make-logs
    MAKEFILE_LIST :=  Makefile
    MAKEFLAGS = pn
    SHELL = /bin/sh
    VARS_OLD := [...]
    

    gmake -pn 真的很冗长,看起来有点像这样:

    # environment
    GNOME2_PATH = /usr/local:/opt/gnome:/usr:/usr/local:/opt/gnome:/usr
    # automatic
    @F = $(notdir $@)
    # makefile
    SHELL = /bin/sh
    # default
    RM = rm -f
    

    【讨论】:

    • 并非所有系统都有gmake
    【解决方案3】:

    感谢@Ise Wisteria,精简后显示了所有变量,对于具有多个makefile (Buildroot) 的大型项目很有用。

    $(foreach v, $(.VARIABLES), $(info $(v) = $($(v))))
    

    输出:BR2_GCC_TARGET_TUNE = "cortex-a8" ...

    如果您收到如下错误消息:insufficient number of arguments (1) to function 'addprefix' 这个项目有一些损坏的变量...我修剪了要显示的变量列表,仅带有前缀 BR2_

    $(foreach v, $(filter BR2_%,$(.VARIABLES)), $(info $(v) = $($(v))))
    

    【讨论】:

    • 非常感谢!这正是我迫切寻求的答案:)
    【解决方案4】:

    不保存所有.VARIABLES 并过滤掉它们也是可行的。

    此外,如果在您的 makefile 中修改了原始 .VARIABLES 之一,则投票最多的两个答案将无法捕捉到它。

    查看$(origin) 函数。此目标过滤并打印在 makefile 中定义的所有变量:

    print_file_vars:
        $(foreach v, $(.VARIABLES), $(if $(filter file,$(origin $(v))), $(info $(v)=$($(v)))))
    

    这样我只得到了一些多余的变量:CURDIR SHELL MAKEFILE_LIST .DEFAULT_GOAL MAKEFLAGS

    可以将file 替换为environmentcommand line 以打印相应类型的变量。

    【讨论】:

    • 效果很好!天才!
    【解决方案5】:

    感谢@kevinf 的好主意。我建议做一个小改动,以防止 .VARIABLE 本身在变量列表中打印出来:

    $(foreach v, $(filter-out .VARIABLES,$(.VARIABLES)), $(info $(v) = $($(v))))

    【讨论】:

      【解决方案6】:

      感谢@kevinf 的 foreach 解决方案——如果想将此列表导出为某种机器可读的文件,那么在使用 echo 或 printf 时会遇到不均匀的引号或换行符,因为 Make 不是能够正确引用数据——需要使用 $(file ...) 函数来写入数据以避免 sh/bash 抱怨语法无效。例如,在您的规则中使用它——它会打印变量名称、定义和扩展值:

      $(file > $(MAKEFILE_ENV_FILE),)
      $(foreach v, $(.VARIABLES), \
          $(file >> $(MAKEFILE_ENV_FILE),$(v)) \
          $(file >> $(MAKEFILE_ENV_FILE),    := $(value $(v))) \
          $(file >> $(MAKEFILE_ENV_FILE),    == $($(v))) \
          $(file >> $(MAKEFILE_ENV_FILE),) \
      )
      

      (这仍然不允许始终将带有双换行符的恶意变量与两个变量区分开来,因为这个现在在每个 Makefile 生成的换行符前面添加一个足够唯一的分隔符,就在 $(file >> NAME,TEXT) 内的每个逗号之后)

      将 MAKEFILE_ENV_FILE 设置为某个文件名,例如:

      MAKEFILE_ENV_FILE := $(abspath $(lastword $(MAKEFILE_LIST))).env
      

      【讨论】:

        【解决方案7】:

        这里有很多好的答案,但是如果您的某些变量属于递归 flavor,那么使用 $($(v)) 就会遇到问题。这就是为什么你应该使用$(value $(v))

        这个变体稍微清理了一下,按名称对变量进行排序并使输出更具可读性。

        dump:
            $(foreach v, \
                $(shell echo "$(filter-out .VARIABLES,$(.VARIABLES))" | tr ' ' '\n' | sort), \
                $(info $(shell printf "%-20s" "$(v)")= $(value $(v))) \
            )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-04-11
          • 1970-01-01
          • 2011-03-05
          • 1970-01-01
          • 1970-01-01
          • 2014-04-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多