列出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上运行:
- 使用sed从makefile获取所有目标名称。
- 包含makefile以便使用它扩展variables。
- 使用`show_%:; echo $$ *`打印所有的目标
这将是一个令人印象深刻的工作。 你确定这个目标是值得的吗?
grep ^[az].*\:$ Makefile | sed s,:,,g