首页 文章

列出GNU中的目标/目标,使其在定义中包含变量

提问于
浏览
98

我有一个相当大的makefile,它通过计算变量中的名称来动态创建多个目标 . (例如foo $(VAR):$(PREREQS)) . 有没有什么方法可以让gnu make在扩展这些变量之后吐出一系列目标?

我希望能够获得aribitrary makefile的目标 . 我正在尝试为我的shell编写一个完成函数 .

16 回答

  • 1

    我猜这个派对有点晚了,但是如果你正在寻找一个特定的命令,你可以试试

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

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

  • 2

    Ruby解决方案:

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

    你能解析 make -pn 的输出(即 make --print-data-base --dry-run )吗?它打印出所有变量,规则,隐式规则以及哪些命令将以繁重的细节运行 .

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

    取自make arg完成,其作品就像一个魅力 .

  • 111

    我不确定这只是一个gnu make的东西,但这很有效:

    make help

  • 1

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

    __all_targets__: ; #no-op
    

    现在调用make作为 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秒 .

  • -4

    在GitHub上查看bash completion for make .

  • 0

    编辑:仅供参考,在另一个答案中,debian bash完成git存储库现在包含了为bash完成用例量身定制的此脚本的增强版本 .

    #!/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
    

    这是一个比debian bash完成脚本更完整的脚本,因为它提供了生成规则的结果,问题要求和最高投票答案(debian git服务器上的debian bash完成脚本)还不够 .

    这不是我链接到的原始脚本,但它更简单,触摸速度更快 .

  • 0

    这是基于Todd Hodes解决方案的别名代码

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

    这将给出一个很好的输出:

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

    这里有一个非常好的解决方案,有一些sed和egrep魔法:https://gist.github.com/pvdb/777954

  • 9

    我正在使用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
    

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

  • 4

    我去寻找同样的问题并提出了这个问题:

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

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

  • 3

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

    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 .

  • 10

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

    要在运行规则时报告目标的名称,请在规则中添加一行:

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

    要立即全部吐出,你可以制作一个单独的PHONY目标:

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

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

    all: show_vars
        ...
    

    EDIT:
    你想要一种方法来显示任意makefile的所有可能目标,我想这意味着非侵入性 . 好...

    要做到这一点,并能够应对复杂的makefile,例如涉及由 eval 语句构造的规则,你必须写一些接近Make模拟器的东西 . 不切实际的 .

    要查看简单规则的目标,您可以编写一个makefile作为makefile扫描程序,在任意makefile上运行:

    • 使用sed从makefile获取所有目标名称 .

    • “include”makefile以便用它来扩展变量 .

    • 使用show_%:; echo $$ *打印所有目标

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

  • 7
    grep ^[a-z].*\:$ Makefile | sed s,:,,g
    

相关问题