代码之家  ›  专栏  ›  技术社区  ›  BitShifter

在GNU make中列出定义中包含变量的目标

  •  98
  • BitShifter  · 技术社区  · 16 年前

    我有一个相当大的makefile,它通过从变量中计算名称来动态创建许多目标。(例如foo$(var):$(先决条件))。GNU在扩展了这些变量之后,有没有任何方法可以说服GNU给出目标列表?

    我想能找到一个很少见的makefile的目标。我正在尝试为shell编写一个完成函数。

    16 回复  |  直到 8 年前
        1
  •  78
  •   Jack Kelly    15 年前

    你能分析输出吗 make -pn (即 make --print-data-base --dry-run )?它打印出所有的变量、规则、隐式规则以及哪些命令将在费力的细节中运行。

        2
  •  112
  •   Tim Cooper    14 年前
    make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     
    

    取自make arg completion,这就像一个魅力。

        3
  •  13
  •   Zdenik    13 年前

    我不确定这是否只是一个GNU制造的东西,但这很好地工作:

    make help

        4
  •  10
  •   Eric Melski    14 年前

    一些响应者建议使用 make -pn ,它将打印规则数据库,但不执行任何操作——或多或少。这种方法的问题在于 -n 仍然会调用所有递归生成,并且它仍然会做比需要更多的工作,因为它会打印出在常规构建中调用的每个命令。更有效的解决方案是创建一个简单的makefile dummy.mk,其中包含以下内容:

    __all_targets__: ; #no-op
    

    现在调用make as make -p -f Makefile -f dummy.mk __all_targets__ . 在任何实质性的构建中,make生成的输出量差异都是显著的。例如:

    $ gmake -pn | wc
     138985 2632330 69612711
    $ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
      21673   93437  878985
    

    执行时间也明显更好——第一个版本为2.063秒,第二个版本为0.059秒。

        5
  •  9
  •   js.    9 年前

    退房狂欢 completion for make 在吉瑟布上。

        6
  •  7
  •   codeshot    13 年前

    编辑:仅供参考,另一个答案中的debian bash completion git存储库现在包含了针对bash completion用例定制的该脚本的增强版本。

    #!/bin/bash
    
    SCRIPT='
      /^# Make data base/,/^# Files/d             # skip until files section
      /^# Not a target/,+1          d             # following target isnt
      /^\.PHONY:/                   d             # special target
      /^\.SUFFIXES:/                d             # special target
      /^\.DEFAULT:/                 d             # special target
      /^\.PRECIOUS:/                d             # special target
      /^\.INTERMEDIATE:/            d             # special target
      /^\.SECONDARY:/               d             # special target
      /^\.SECONDEXPANSION/          d             # special target
      /^\.DELETE_ON_ERROR:/         d             # special target
      /^\.IGNORE:/                  d             # special target
      /^\.LOW_RESOLUTION_TIME:/     d             # special target
      /^\.SILENT:/                  d             # special target
      /^\.EXPORT_ALL_VARIABLES:/    d             # special target
      /^\.NOTPARALLEL:/             d             # special target
      /^\.ONESHELL:/                d             # special target
      /^\.POSIX:/                   d             # special target
      /^\.NOEXPORT:/                d             # special target
      /^\.MAKE:/                    d             # special target
    
    # The stuff above here describes lines that are not
    #  explicit targets or not targets other than special ones
    # The stuff below here decides whether an explicit target
    #  should be output.
    
      /^[^#\t:=%]+:([^=]|$)/ {                    # found target block
        h                                         # hold target
        d                                         # delete line
      }
      /^# File is an intermediate prerequisite/ { # nope
        s/^.*$//;x                                # unhold target
        d                                         # delete line
      }
      /^([^#]|$)/ {                               # end of target block
        s/^.*$//;x                                # unhold target
        s/:.*$//p                                 # write current target
        d                                         # hide any bugs
      }
    '
    
    make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
      | sort | uniq
    

    这是一个比DebianBash完成脚本更完整的脚本,因为它为生成的规则提供了结果,而这个问题所要求的和最热门的答案(DebianBash完成脚本在DebianGit服务器上)都不够。

    这不是我链接到的原始脚本,但它简单得多,而且触摸速度更快。

        7
  •  4
  •   Nguyễn Minh VÅ©    11 年前

    这是基于todd-hodes解决方案的别名代码

    alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
    
        8
  •  3
  •   Andor    15 年前

    这将提供一个很好的输出:

    make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort
    
        9
  •  3
  •   Atilla Filiz    13 年前

    这里有一个非常好的解决方案,具有一些SED和Egrep魔力: https://gist.github.com/pvdb/777954

        10
  •  2
  •   DGrady    15 年前

    我想我参加这个聚会有点晚了,但是如果你要找一个具体的命令,你可以试试

    make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
    

    虽然它可能仍然包含一些非目标的东西,比如 vpath 指令。如果你不依赖 make 的内置规则,您可以使用 make -qpR 作为管道中的第一个命令。

        11
  •  1
  •   gdub    13 年前

    红宝石溶液:

    `make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
    
        12
  •  1
  •   Aviv    10 年前

    我正在开发Solaris 10和Turbo C Shell。 给定的解决方案不适用于我的makefile项目。甚至在将上面的命令行更改为tcsh语法之后。 不过,我发现你可以用

    remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´
    

    重新制作版本:

    remake --version
    

    GNU Make 3.82+dbg0.8
    Built for sparc-sun-sparc2-9
    

    以及其他一些不重要的版本数据

        13
  •  0
  •   dwj    9 年前

    我找了同样的问题,想出了这个问题:

    make -pn | sed -rn '/^[^# \t\.%].*:/p'
    

    这将删除所有注释行、模式规则(以制表符开头的行)、所有内部函数(示例 .c.o %.o: %.c 图案)。

        14
  •  0
  •   thisismydesign    8 年前

    在另一个线程中找到此解决方案:

    sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""
    

    您也可以将其添加到 Makefile :

    list:
        sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""
    

    并执行 make list .

        15
  •  -1
  •   Beta    16 年前

    当然,但你想什么时候把它们吐出来?

    要在目标运行规则时报告其名称,请在规则中放置一行:

    foo$(VAR): $(PREREQS)
        @echo now making the foo target: $@
        do_other_stuff...
    

    为了一次把它们吐出来,你可以做一个单独的假目标:

    .PHONY: show_vars
    show_vars:
        @echo foo$(VAR)
        @echo bar$(PARAM) blah$(FLAG)
        # and so on
    

    这可以成为默认目标的先决条件:

    all: show_vars
        ...
    

    编辑:
    您需要一种方法来显示任意生成文件的所有可能目标,我想这意味着非侵入性。好。。。

    准确地执行,并能够处理复杂的生成文件,例如涉及由 eval 语句,您必须在make模拟器附近编写一些内容。不切实际的

    要查看简单规则的目标,可以编写一个makefile,它将充当makefile scanner,在任意makefile上操作:

    1. 使用sed从makefile中获取所有目标名称。
    2. ` include`the makefile以便使用它展开变量。
    3. 使用'show_%:;echo$*'打印所有目标

    这将是一项令人印象深刻的工作。你确定目标值得努力吗?

        16
  •  -4
  •   animuson    14 年前
    grep ^[a-z].*\:$ Makefile | sed s,:,,g