我使用过一些rake(一个Ruby make程序),它有一个选项,可以获得所有可用目标的列表,例如

> rake --tasks
rake db:charset      # retrieve the charset for your data...
rake db:collation    # retrieve the collation for your da...
rake db:create       # Creates the databases defined in y...
rake db:drop         # Drops the database for your curren...
...

但是在GNU make中似乎没有这样做的选项。

显然,代码几乎已经有了,截至2007年- http://www.mail-archive.com/help-make@gnu.org/msg06434.html。

不管怎样,我做了一个小hack来从makefile中提取目标,你可以将它包含在makefile中。

list:
    @grep '^[^#[:space:]].*:' Makefile

它会给你一个已定义目标的列表。这只是一个开始——例如,它并没有过滤掉依赖关系。

> make list
list:
copy:
run:
plot:
turnin:

当前回答

对于讨厌AWK的人来说,为了简单起见,这个精巧的设计适合我:

help:
  make -qpRr $(lastword $(MAKEFILE_LIST)) | egrep -v '(^(\.|:|#|\s|$)|=)' | cut -d: -f1

(对于在Makefile外部使用,只需删除$(最后一个词…)或将其替换为Makefile路径)。

This solution will not work if you have "interesting" rule names but will work well for most simple setups. The main downside of a make -qp based solution is (as in other answers here) that if the Makefile defines variable values using functions - they will still be executed regardless of -q, and if using $(shell ...) then the shell command will still be called and its side effects will happen. In my setup often the side effects of running shell functions is unwanted output to standard error, so I add 2>/dev/null after the make command.

其他回答

这是对jsp非常有用的回答(https://stackoverflow.com/a/45843594/814145)的修改。我喜欢这个想法,不仅要得到目标的列表,还要得到他们的描述。jsp的Makefile将描述作为注释,我发现在目标的描述echo命令中经常会重复。因此,我从每个目标的echo命令中提取描述。

Makefile示例:

.PHONY: all
all: build
    : "same as 'make build'"

.PHONY: build
build:
    @echo "Build the project"

.PHONY: clean
clean:
    @echo "Clean the project"

.PHONY: help
help:
    @echo -n "Common make targets"
    @echo ":"
    @cat Makefile | sed -n '/^\.PHONY: / h; /\(^\t@*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/    make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20

make help输出:

$ make help
Common make targets:
    make all        same as 'make build'
    make build      Build the project
    make clean      Clean the project
    make help       Common make targets

注:

与jsp的答案相同,只能列出PHONY目标,这可能适用于您的情况,也可能不适用 此外,它只列出那些有echo或:命令作为recipe的第一个命令的PHONY目标。:表示“什么都不做”。我在这里将它用于那些不需要回声的目标,比如上面所有的目标。 帮助目标还有一个额外的技巧,就是在make帮助输出中添加“:”。

注意:这个答案已经更新到GNU make v4.3仍然可以工作——如果你遇到什么问题,请告诉我们。

本文试图改进Brent Bradburn的伟大方法,如下所示:

使用更健壮的命令来提取目标名称,这有望防止任何误报(还消除了不必要的sh -c) 并不总是以当前目录中的makefile为目标;尊重使用-f <file>显式指定的makefile 不包括隐藏目标——按照惯例,这些目标的名称既不是以字母开头,也不是以数字开头 只对付一个假目标 使用@作为命令的前缀,防止命令在执行前被回显


奇怪的是,GNU make没有列出makefile中定义的目标名称的特性。虽然-p选项生成包含所有目标的输出,但它将这些目标隐藏在许多其他信息中,并执行默认目标(可以使用-f/dev/null来抑制)。

将下面的规则放在一个makefile中,让GNU make实现一个目标命名列表,简单地按字母顺序列出所有目标名称-即:调用为make列表:

.PHONY: list
list:
    @LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

重要提示:在粘贴此文件时,确保最后一行缩进了恰好1个实际的制表符字符。(空格无效)。

Note that sorting the resulting list of targets is the best option, since not sorting doesn't produce a helpful ordering in that the order in which the targets appear in the makefile is not preserved. Also, the sub-targets of a rule comprising multiple targets are invariably output separately and will therefore, due to sorting, usually not appear next to one another; e.g., a rule starting with a z: will not have targets a and z listed next to each other in the output, if there are additional targets.

规则解释:

.PHONY: list declares target list a phony target, i.e., one not referring to a file, which should therefore have its recipe invoked unconditionally LC_ALL=C makes sure that make's output in in English, as parsing of the output relies on that.Tip of the hat to Bastian Bittorf $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null Invokes make again in order to print and parse the database derived from the makefile: -p prints the database -Rr suppresses inclusion of built-in rules and variables -q only tests the up-to-date-status of a target (without remaking anything), but that by itself doesn't prevent execution of recipe commands in all cases; hence: -f $(lastword $(MAKEFILE_LIST)) ensures that the same makefile is targeted as in the original invocation, regardless of whether it was targeted implicitly or explicitly with -f .... Caveat: This will break if your makefile contains include directives; to address this, define variable THIS_FILE := $(lastword $(MAKEFILE_LIST)) before any include directives and use -f $(THIS_FILE) instead. : is a deliberately invalid target that is meant to ensure that no commands are executed; 2>/dev/null suppresses the resulting error message. Note: This relies on -p printing the database nonetheless, which is the case as of GNU make 3.82. Sadly, GNU make offers no direct option to just print the database, without also executing the default (or given) task; if you don't need to target a specific Makefile, you may use make -p -f/dev/null, as recommended in the man page. -v RS= This is an awk idiom that breaks the input into blocks of contiguous non-empty lines. /(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ Matches the range of lines in the output that contains all targets, across paragraphs - by limiting parsing to this range, there is no need to deal with false positives from other output sections. Note: Between make versions 3.x and 4.3, paragraph structuring in make's output changed, so (^|\n) / (\n|$$) ensures that the lines that identify the start and the end of the cross-paragraph range of lines of interest are detected irrespective of whether they occur at the start or inside / at the end of a paragraph. if ($$1 !~ "^[#.]") Selectively ignores blocks: # ... ignores non-targets, whose blocks start with # Not a target: . ... ignores special targets All other blocks should each start with a line containing only the name of an explicitly defined target followed by : egrep -v -e '^[^[:alnum:]]' -e '^$@$$' removes unwanted targets from the output: '^[^[:alnum:]]' ... excludes hidden targets, which - by convention - are targets that start neither with a letter nor a digit. '^$@$$' ... excludes the list target itself

然后运行make list,打印所有目标,每个目标在自己的行上;您可以通过管道连接到xargs来创建一个以空格分隔的列表。

这个对我很有帮助,因为我想看到make目标所需的构建目标(以及它们的依赖关系)。我知道make目标不能以“。”字符开头。我不知道支持什么语言,所以我使用了egrep的括号表达式。

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

我把这两个答案结合起来:https://stackoverflow.com/a/9524878/86967和https://stackoverflow.com/a/7390874/86967 并做了一些转义,以便可以从makefile中使用。

.PHONY: no_targets__ list
no_targets__:
list:
    sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"

.

$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run

正如mklement0所指出的,GNU-make中缺少列出所有Makefile目标的功能,他的回答和其他回答提供了实现这一点的方法。

然而,最初的帖子也提到了rake,它的任务开关做的事情与仅仅在rakefile中列出所有任务略有不同。Rake只会给您一个有相关描述的任务列表。没有描述的任务将不会被列出。这使得作者既可以提供定制的帮助描述,也可以省略某些目标的帮助。

如果您想模拟rake的行为,为每个目标提供描述,有一个简单的技术可以做到这一点:在注释中嵌入您想列出的每个目标的描述。

你可以把描述放在目标旁边,或者像我经常做的那样,放在目标上面的PHONY规范旁边,就像这样:

.PHONY: target1 # Target 1 help text
target1: deps
    [... target 1 build commands]

.PHONY: target2 # Target 2 help text
target2:
    [... target 2 build commands]

...                                                                                                         

.PHONY: help # Generate list of targets with descriptions                                                                
help:                                                                                                                    
    @grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20

它会屈服

$ make help
target1             Target 1 help text
target2             Target 2 help text

...
help                Generate list of targets with descriptions

你也可以在这里找到一个简短的代码示例。

同样,这不能解决在Makefile中列出所有目标的问题。例如,如果您有一个大的Makefile,它可能是生成的或由其他人编写的,并且您想要一种快速的方法来列出它的目标,而不需要深入研究它,那么这将没有帮助。

但是,如果您正在编写Makefile,并且希望以一致的、自记录的方式生成帮助文本,则此技术可能会有用。