我使用过一些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:
我个人为我构建的每个Makefile复制粘贴相同的帮助目标。
.SILENT:
.PHONY: help
## This help screen
help:
printf "Available targets\n\n"
awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")-1); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf "%-30s %s\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
我也在这个Github要点中保留了它的副本:
https://gist.github.com/Olshansk/689fc2dee28a44397c6e31a0776ede30
我把上面提到的几个答案编译成这个,它也可以为每个目标生成一个很好的描述,它也适用于有变量的目标。
Makefile示例:
APPS?=app1 app2
bin: $(APPS:%=%.bin)
@# Help: A composite target that relies only on other targets
$(APPS:%=%.bin): %.bin:
@# Help: A target with variable name, value = $*
test:
@# Help: A normal target without variables
# A target without any help description
clean:
# A hidden target
.hidden:
help:
@printf "%-20s %s\n" "Target" "Description"
@printf "%-20s %s\n" "------" "-----------"
@make -pqR : 2>/dev/null \
| awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \
| sort \
| egrep -v -e '^[^[:alnum:]]' -e '^$@$$' \
| xargs -I _ sh -c 'printf "%-20s " _; make _ -nB | (grep -i "^# Help:" || echo "") | tail -1 | sed "s/^# Help: //g"'
示例输出:
$ make help
Target Description
------ -----------
app1.bin A target with variable name, value = app1
app2.bin A target with variable name, value = app2
bin A composite target that relies only on other targets
clean
test A normal target without variables
它是如何工作的:
make help目标的顶部部分与mklement0在这里发布的工作完全相同——如何在makefile中获得目标列表?
在获得目标列表之后,它运行make <target> -nB作为每个目标的演练,并解析以@# Help:开头的最后一行,用于目标的描述。或者一个空字符串被打印在一个格式化好的表格中。
正如你所看到的,变量甚至在描述中进行了扩展,这在我的书中是一个巨大的奖励:)。
这里有很多可行的解决方案,但正如我喜欢说的,“如果值得做一次,就值得再做一次。”
我确实赞成使用(tab)(tab)的建议,但正如一些人指出的那样,您可能没有补全支持,或者,如果您有许多包含文件,您可能想要一种更简单的方法来知道目标定义在哪里。
我还没有测试下面的子制作…我认为这行不通。我们知道,递归是有害的。
.PHONY: list ls
ls list :
@# search all include files for targets.
@# ... excluding special targets, and output dynamic rule definitions unresolved.
@for inc in $(MAKEFILE_LIST); do \
echo ' =' $$inc '= '; \
grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
cut -f 1 | sort | sed 's/.*/ &/' | sed -n 's/:.*$$//p' | \
tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done
# to get around escaping limitations:
open_paren := \(
close_paren := \)
我喜欢它是因为:
通过包含文件列出目标。
输出原始动态目标定义(用模替换变量分隔符)
在新行上输出每个目标
似乎更清楚了(主观意见)
解释:
MAKEFILE_LIST中的foreach文件
输出文件的名称
包含冒号的Grep行,不缩进,没有注释,也不以句号开头
排除立即赋值表达式(:=)
切、排序、缩进和切规则依赖项(冒号后)
蒙格变量分隔符以防止扩展
样例输出:
= Makefile =
includes
ls list
= util/kiss/snapshots.mk =
rotate-db-snapshots
rotate-file-snapshots
snap-db
snap-files
snapshot
= util/kiss/main.mk =
dirs
install
%MK_DIR_PREFIX%env-config.php
%MK_DIR_PREFIX%../srdb
这个帮助目标只打印带有##后跟描述的目标。这允许同时记录公共目标和私有目标。使用. default_goal使帮助更容易被发现。
只使用sed, xargs和printf,这是非常常见的。
使用< $(MAKEFILE_LIST)允许将makefile命名为makefile以外的名称,例如makefile .github
您可以在printf中定制输出以满足您的偏好。这个示例的设置是为了匹配OP对rake样式输出的请求
在剪切和粘贴下面的make文件时,不要忘记将4个空格缩进改为制表符。
# vim:ft=make
# Makefile
.DEFAULT_GOAL := help
.PHONY: test help
help: ## these help instructions
@sed -rn 's/^([a-zA-Z_-]+):.*?## (.*)$$/"\1" "\2"/p' < $(MAKEFILE_LIST) | xargs printf "make %-20s# %s\n"
lint: ## style, bug and quality checker
pylint src test
private: # for internal usage only
@true
test: private ## run pytest with coverage
pytest --cov test
下面是上面Makefile的输出。注意,私有目标没有得到输出,因为它的注释只有一个#。
$ make
make help # these help instructions
make lint # style, bug and quality checker
make test # run pytest with coverage
我最喜欢的答案是Chris Down在Unix & Linux Stack Exchange上发布的。我将引用。
这是make的bash完成模块获取列表的方式:
使得qp | awk - f ': ' ' / ^ [a-zA-Z0-9] [^ $ # \ / \ t =]*:([^=]|$)/ { 分(1美元,/ /);(我的)打印一个[我]}’
它输出以换行符分隔的目标列表,不进行分页。
用户Brainstone建议使用sort -u来删除重复的条目:
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' | sort -u
来源:如何列出所有的目标在使?(unix和linux SE)