列出GNU make中包含variables的目标/目标

我有一个相当大的makefile,通过从variables中计算名称,即时创build大量目标。 (例如foo $(VAR):$(PREREQS))。 有没有什么办法可以使gnu make在扩展这些variables之后吐出一个目标列表?

我希望能够得到一个任意makefile的目标。 我正在尝试为我的shell编写一个完成函数。

你可以parsingmake -pn的输出(即make --print-data-base --dry-run )吗? 它打印出所有的variables,规则,隐含的规则,以及哪些命令将在辛苦的细节中运行。

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

采取从arg完成,其作品像一个魅力。

我不确定这是否只是一个牛咀作品,但是这个效果很好:

make help

有几位响应者build议使用make -pn ,它将打印规则数据库,但不会执行任何操作 – 或多或less。 这种方法的问题在于-n仍然会调用所有的recursion方法,而且它仍然会执行更多的工作,因为它会打印出在常规的构build中调用的每个命令。 更有效的解决scheme是创build一个简单的makefile,dummy.mk,其中包含以下内容:

 __all_targets__: ; #no-op 

现在调用make make make -p -f Makefile -f dummy.mk __all_targets__ 。 在任何实质的构build上,制造产生的产量差异是显着的。 例如:

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

执行时间也明显更好 – 第一版2.063s,第二版0.059s。

在GitHub上检查bash的完成 。

编辑:仅供参考在另一个答案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脚本)还不够用。

这不是我链接到的原始脚本,但它更简单,更快。

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

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

这会给出一个很好的结果:

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

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

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

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

这主要起作用,尽pipe它可能还包括一些非目标的东西,如vpath指令。 如果您不依赖make的内置规则,则可以使用make -qpR作为pipe道中的第一个命令。

Ruby解决scheme:

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

我在solaris 10和一个turbo C shell上工作。 给定的解决scheme不适用于我的生成文件项目。 即使在将上面的命令行更改为tcsh语法之后。 不过,我发现你可以使用一个简单的解决scheme

 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 

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

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

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

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

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

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

 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 ... 

编辑:
你想要一种方式来显示任意makefile的所有可能的目标,我想这意味着非侵入性的。 好…

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

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

  1. 使用sed从makefile获取所有目标名称。
  2. 包含makefile以便使用它扩展variables。
  3. 使用`show_%:; echo $$ *`打印所有的目标

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

 grep ^[az].*\:$ Makefile | sed s,:,,g