make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
取自 make arg 完成,它就像一个魅力。
您能解析 make -pn
(即 make --print-data-base --dry-run
)的输出吗?它打印出所有变量、规则、隐式规则以及哪些命令将被详细运行。
make -pn | sed -rn '/^[^# \t\.%].*:[^=]?/p'
make -pnr
。 -r
删除隐式规则。
我不确定这是否只是一个 gnu 制作的东西,但这很好用:
make help
一些响应者建议使用 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 秒。
time make -pn | wc -l
”:1338738 real 0m47.754s.
“time make -f Makefile -f dummy.mk -pn __all_targets__ | wc -l
”:938621 real 0m40.219s
。
make
的手册页似乎暗示了类似但友好的内容,即 make -p -f/dev/null
-f /dev/null
将阻止 make
解析常规生成文件,因此您将仅获得内置规则的打印输出。这就是我的解决方案指定 -f Makefile -f dummy.mk
的原因。但这还不够,因为使用 -n
,make
将继续执行并实际开始执行 makefile 中的规则。不幸的是,我不知道有任何修改可以简化最初提出的解决方案。
-n
...”
编辑:仅供参考,另一个答案中的 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 解决方案的别名代码
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
猜猜我参加这个聚会有点晚了,但如果你正在寻找一个特定的命令,你可以试试
make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
这主要是有效的,尽管它可能仍然包含一些非目标内容,如 vpath
指令。如果您不依赖 make
的内置规则,您可以使用 make -qpR
作为管道中的第一个命令。
红宝石解决方案:
`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
我正在研究solaris 10 anda 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
和其他一些不重要的版本数据
我去寻找同样的问题并想出了这个旋转:
make -pn | sed -rn '/^[^# \t\.%].*:/p'
这将删除所有注释行、模式规则(以制表符开头的行)、所有内在函数(例如 .c.o
和 %.o: %.c
模式)。
在另一个线程中找到了这个解决方案:
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
。
当然可以,但是你希望它什么时候吐出来?
要在运行规则时报告目标的名称,请在规则中添加一行:
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,例如涉及由 eval
语句构造的规则,您必须编写一些接近 Make 模拟器的东西。不切实际的。
要查看简单规则的目标,您可以编写一个充当生成文件扫描器的生成文件,对任意生成文件进行操作:
使用 sed 从 makefile 中获取所有目标名称。 `include` 生成文件以便使用它来扩展变量。使用`show_%: ; echo $$*` 打印所有目标
这将是一件令人印象深刻的作品。你确定目标值得付出努力吗?
grep ^[a-z].*\:$ Makefile | sed s,:,,g
:=
),这种方法也会产生误报。
~/bin
中的 shell 脚本中,而不是使用别名。效果很好;谢谢!alias mkl="make -qp | awk -F':' '/^[a-zA-Z0-9][^\$#\/\t=]*:([^=]|\$)/ {split(\$1,A,/ /);for(i in A)print A[i]}' | sort"
将为您节省 2 分钟的引用游戏时间 :-)| sort -u
看起来更有用 :)