如何获取 makefile 中的目标列表?
我用过一点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/[电子邮件受保护]/msg06434.html。
不管怎样,我做了一些小技巧来从 makefile 中提取目标,您可以将其包含在 makefile 中。
list:
@grep '^[^#[:space:]].*:' Makefile
它将为您提供已定义目标的列表。这只是一个开始 - 例如,它不会过滤掉依赖项。
> make list
list:
copy:
run:
plot:
turnin:
I've used rake a bit (a Ruby make program), and it has an option to get a list of all the available targets, eg
> 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...
...
but there seems to be no option to do this in GNU make.
Apparently the code is almost there for it, as of 2007 - http://www.mail-archive.com/[email protected]/msg06434.html.
Anyway, I made little hack to extract the targets from a makefile, which you can include in a makefile.
list:
@grep '^[^#[:space:]].*:' Makefile
It will give you a list of the defined targets. It's just a start - it doesn't filter out the dependencies, for instance.
> make list
list:
copy:
run:
plot:
turnin:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(29)
这远非干净,但对我来说已经完成了工作。
我使用 make -p 转储内部数据库,放弃 stderr,使用快速而肮脏的 grep -A 100000 来保留输出的底部。然后,我使用几个
grep -v
清理输出,最后使用cut
获取冒号之前的内容,即目标。这对于我的大多数 Makefile 上的帮助程序脚本来说已经足够了。
编辑:添加了
grep -v Makefile
这是一个内部规则This is far from clean, but did the job, for me.
I use
make -p
that dumps the internal database, ditch stderr, use a quick and dirtygrep -A 100000
to keep the bottom of the output. Then I clean the output with a couple ofgrep -v
, and finally usecut
to get what's before the colon, namely, the targets.This is enough for my helper scripts on most of my Makefiles.
EDIT: added
grep -v Makefile
that is an internal rule要扩展 @jsp 给出的答案,您甚至可以使用
$( 评估帮助文本中的变量eval)
函数。下面建议的版本具有以下增强的属性:
# TARGETDOC:
)添加 要记录,请使用以下形式:
然后,在 makefile 中的某个位置:
To expand on the answer given by @jsp, you can even evaluate variables in your help text with the
$(eval)
function.The proposed version below has these enhanced properties:
# TARGETDOC:
)So to document, use this form:
Then, somewhere in your makefile:
默认情况下,
make
不支持此功能,其他答案已经显示了如何自动提取可能目标的列表。但是,如果您希望对列表进行更多控制而不产生任何副作用(例如使用
.PHONY
目标来标记文档,这会阻止将目标名称用作实际文件的逻辑使用来决定哪些目标需要重建),您可以仅为文档发明自己的语法。我更喜欢像这样使用###
:(像往常一样,缩进的文件必须以一个制表符开头,但 stackoverflow 无法正确重现该详细信息。)
输出将如下所示:
这有效,因为只有行以
###
开头并具有:
字符被视为要输出的文档。请注意,这故意不提取实际的目标名称,而仅完全信任文档行。这也允许始终为非常复杂的 Makefile 技巧发出正确的输出。另请注意,这避免了需要将文档行放在相对于实际规则的任何特定位置。我还故意避免对输出进行排序,因为只需按首选顺序列出文档行,就可以从 Makefile 本身完全控制输出的顺序。显然,您可以发明任何您喜欢的其他语法,甚至可以执行类似的操作
,并且仅打印与当前语言环境匹配的行以支持多种语言,并使用别名来本地化目标名称:
最重要的问题是为什么要列出目标?您想要实际的文档或某种调试信息吗?
make
doesn't support this by default and other answers have shown how to extract the list of possible targets automatically.However, in case you want to have more control with the listing without any side-effects (such as using the
.PHONY
target to mark the documentation which prevents the logic of using the target names as actual files which Make uses to decide which targets needs to be rebuilt), you can invent your own syntax just for the documentation. I prefer to use###
like this:(as usual, the indented files must start with exactly one tabulator but stackoverflow cannot reproduce that detail correctly.)
Output will look like this:
This works because only lines starting with
###
and having a:
character are considered as the documentation to output. Note that this intentionally does not extract the actual target name but fully trusts the documentation lines only. This allows always emitting correct output for very complex Makefile tricks, too. Also note that this avoids needing to put the documentation line on any specific position relative to actual rule. I also intentionally avoid sorting the output because the order of output can be fully controlled from the Makefile itself simply by listing the documentation lines in preferred order.You could obviously invent any other syntax you like and even do something like
and only print lines that match the current locale to support multiple languages and having aliases to localize the target names, too:
The most important question is why do you want to list the targets? Do you want actual documentation or some kind of debugging information?
这是对 jsp 非常有用的答案的修改(https://stackoverflow.com/a/45843594/814145)。我喜欢不仅获得目标列表而且还获得其描述的想法。 jsp 的 Makefile 将描述作为注释,我发现它经常会在目标的描述 echo 命令中重复。因此,我从每个目标的 echo 命令中提取描述。
示例 Makefile:
make help
的输出:注意:
echo
或:
命令作为第一个命令的 PHONY 目标。食谱。:
表示“不执行任何操作”。我在这里将它用于那些不需要 echo 的目标,例如上面的all
目标。help
目标还有一个额外的技巧,可以在make help
输出中添加“:”。This is a modification to jsp's very helpful answer (https://stackoverflow.com/a/45843594/814145). I like the idea of getting not only a list of targets but also their descriptions. jsp's Makefile puts the description as the comment, which I found often will be repeated in the target's description echo command. So instead, I extract the description from the echo command for each target.
Example Makefile:
Output of
make help
:Notes:
echo
or:
command as the first command of the recipe.:
means "do nothing". I use it here for those targets that no echo is needed, such asall
target above.help
target to add the ":" in themake help
output.这里有很多可行的解决方案,但正如我喜欢说的,“如果值得做一次,那就值得再做一次。”
我确实赞成使用 (tab)(tab) 的建议,但正如一些人指出的那样,您可能没有完成支持,或者,如果您有许多包含文件,您可能需要一种更简单的方法来了解目标的定义位置。
我还没有用子品牌测试过以下内容......我认为它不起作用。众所周知,递归被认为是有害的。
我喜欢它,因为:
说明:
示例输出:
Plenty of workable solutions here, but as I like saying, "if it's worth doing once, it's worth doing again."
I did upvote the sugestion to use (tab)(tab), but as some have noted, you may not have completion support, or, if you have many include files, you may want an easier way to know where a target is defined.
I have not tested the below with sub-makes...I think it wouldn't work. As we know, recursive makes considered harmful.
Which I like because:
Explanation:
Sample Output:
这是
bash-completion
脚本功能的非常简化版本。说明:
make -npq
:打印数据库而不执行任何操作-v RS=
:按整个段落分隔记录-F:
:按:
(因此规则名称为$1
)$1 ~ /^[^#%]+$/
:匹配不包含的规则#
或%
(注释或模式规则){ print $1 }
:打印规则名称这比 mklement0 的方法(我自己修复了),效果更好。
This is a very simplified version of what the
bash-completion
script does.Explanation:
make -npq
: Print the database without executing anything-v RS=
: Separate records by whole paragraphs-F:
: Separate fields by:
(so the rule name is$1
)$1 ~ /^[^#%]+$/
: Match rules that don't contain#
or%
(comments or pattern rules){ print $1 }
: Print the rule nameThis is much simpler than mklement0's approach (which I fixed myself), and works better.
这对我很有帮助,因为我想查看 make 目标所需的构建目标(及其依赖项)。我知道 make 目标不能以“.”开头。特点。我不知道支持哪些语言,所以我使用了egrep的括号表达式。
This one was helpful to me because I wanted to see the build targets required (and their dependencies) by the make target. I know that make targets cannot begin with a "." character. I don't know what languages are supported, so I went with egrep's bracket expressions.
对上面的另一个补充答案。
在 MacOSX 上仅使用 cat 和 awk 在终端上进行测试
将输出如下所示的 make 文件:
应该是相同的语句,确保使用 $$variable 而不是 $variable 对变量进行转义。
解释
cat - 吐出内容
| - 管道将输出解析到下一个 awk
awk - 运行正则表达式,不包括“shell” ”并仅接受“Az”行,然后打印出 $1 第一列
awk - 再次从列表中删除最后一个字符“:”,
这是一个粗略的输出,您可以用以下命令做更多时髦的事情AWK。尽量避免使用 sed,因为它在 BSD 变体中不一致,即某些在 *nix 上可以工作,但在 MacOSX 等 BSD 上却失败。
更多
您应该能够将其(经过修改)添加到 make 的文件中,默认的 bash-completion 文件夹 /usr/local/等/bash-completion.d/
意思是当您“制作选项卡选项卡”时。它将根据单行脚本完成目标。
Yet another additional answer to above.
tested on MacOSX using only cat and awk on terminal
will output of the make file like below:
in the Makefile, it should be the same statement, ensure that you escape the variables using $$variable rather than $variable.
Explanation
cat - spits out the contents
| - pipe parses output to next awk
awk - runs regex excluding "shell" and accepting only "A-z" lines then prints out the $1 first column
awk - yet again removes the last character ":" from the list
this is a rough output and you can do more funky stuff with just AWK. Try to avoid sed as its not as consistent in BSDs variants i.e. some works on *nix but fails on BSDs like MacOSX.
More
You should be able add this (with modifications) to a file for make, to the default bash-completion folder /usr/local/etc/bash-completion.d/
meaning when you "make tab tab" .. it will complete the targets based on the one liner script.
对于 AWK 讨厌者来说,为了简单起见,这个装置对我有用:(
要在 Makefile 之外使用,只需删除
$(lastword ...)
或将其替换为 Makefile 路径)。如果您有“有趣”的规则名称,则此解决方案将不起作用,但对于大多数简单的设置都适用。基于
make -qp
的解决方案的主要缺点是(如此处的其他答案),如果 Makefile 使用函数定义变量值 - 无论-q
如何,它们仍然会被执行>,如果使用$(shell ...)
那么 shell 命令仍然会被调用并且它的副作用将会发生。在我的设置中,运行 shell 函数的副作用通常是输出到标准错误,因此我在 make 命令后添加2>/dev/null
。For AWK haters, and for simplicity, this contraption works for me:
(for use outside a Makefile, just remove
$(lastword ...)
or replace it with the Makefile path).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 add2>/dev/null
after the make command.我受到 @jsp 的 answer 适应了他的文件解析技术,这个版本有以下好处。
.PHONY
放置在每个节标题下方,并将注释放在目标后面,以便看起来更清晰。给定这样的 makefile,
您将得到如下输出
正则表达式解释:
's|^#=(.*)|\n\1:|p'
捕获节声明#=
后括号中的所有内容并打印\1
前面有一个换行符,后面有一个冒号。's|^([a-zA-Z-]*):((.*?)# (.*))?| \1 \4|p'
捕获目标名称并包含用于描述的可选捕获组()?
。可选组包围另外两个捕获组,第一个捕获:
和#
之间的所有内容,第二个捕获帮助文本(旁白:正则表达式有点复杂,但它让我们输出带注释和不带注释的目标(开放更好的方法)。最后,它输出目标名称\1
和描述\4
缩进 2 个空格以将其塞到节标题下。I was inspired by @jsp's answer to adapt his file parsing technique and this version has the following benefits.
.PHONY
below each section header for all targets within that section and places comments after the target so it's a little cleaner to look at.Given a makefile like this
You'll get output like this
Regex explanations:
's|^#=(.*)|\n\1:|p'
Captures everything in parens after section declaration#=
and prints it\1
with a newline before and colon after it.'s|^([a-zA-Z-]*):((.*?)# (.*))?| \1 \4|p'
Captures target name and includes an optional capture group()?
for the description. The optional group surrounds two more capture groups, the first one capturing everything between:
and#
and the second capturing the help text (aside: the regex is a bit complicated but it lets us output targets with and without comments. Open to better methods). Finally it outputs the target name\1
and description\4
indented 2 spaces to tuck it under the section header.这是使用 cat、grep 和 cut 的版本。
Here is a version using cat, grep and cut.
tl;dr 我个人为我构建的每个 Makefile 复制粘贴相同的
help
目标。我还在这个 Github gist 中保留了它的副本:
https://gist.github.com/Olshansk/689fc2dee28a44397c6e31a0776ede30
tl;dr I personally copy-paste the same
help
target for every Makefile I build.I also maintain a copy of it in this Github gist:
https://gist.github.com/Olshansk/689fc2dee28a44397c6e31a0776ede30
非常简单的 AWK 解决方案:(
注意:这并不涵盖 接受的答案 中的所有极端情况,如 此处解释。)
Very simple AWK solution:
(Note: This doesn't cover all the corner-cases as the accepted answer, as explained here.)
试试这个:
Try this one:
我通常这样做:
它会返回类似以下内容:
我希望这有帮助
I usually do:
It would come back with something like:
I hope this helps
不知道为什么之前的答案如此复杂:
not sure why the previous answer was so complicated:
在 Bash 下(至少),这可以通过制表符补全自动完成:
make
spacetabtab如果您正在使用一个简单的发行版(可能是一个容器),您可能需要安装一个软件包。
Under Bash (at least), this can be done automatically with tab completion:
make
spacetabtabIf you're using a bare-bones distribution (maybe a container) you might need to install a package.
前言:
根据这个答案,
制作
版本< em>post-4.4.1 将原生支持新的--print-targets
选项,这使得下面的解决方案变得不必要。此处的另一个答案基于下面的解决方案,并添加了对打印描述的支持描述以及目标名称,假设您已在目标中嵌入了
@#
前缀注释。注意:此答案已更新,自 GNU
make
v4.3 起仍然有效 - 如果您遇到问题,请告诉我们。这是对 Brent Bradburn 的伟大方法的尝试,如下所示:
sh -c
),-f
显式指定的 makefile奇怪的是,GNU make 没有仅列出目标名称的功能在 makefile 中定义。虽然
-p
选项生成包含所有目标的输出,但它将它们隐藏在许多其他信息中,并且还执行默认目标(可以使用-f/dev/null< /代码>)。
将以下规则放入 GNU
make
的 makefile 中,以实现名为list
的目标,该目标仅按字母顺序列出所有目标名称 - 即:调用为make list
:重要:粘贴此内容时,确保最后一行缩进正好 1 个实际制表符。(空格不起作用)。
请注意,对生成的目标列表进行排序是最佳选择,因为不进行排序不会产生有用的排序,因为目标在 makefile 中出现的顺序是未保留。
此外,包含多个目标的规则的子目标总是单独输出,因此,由于排序,通常不会彼此相邻出现;例如,以
az:
开头的规则不会在每个目标旁边列出a
和z
输出中的 other(如果有其他目标)。规则说明:
.
PHONY:列表
LC_ALL=C
确保make
的输出为英语,因为输出的解析依赖于向 Bastian Bittorf致敬
$(MAKE) -pRrq -f $(第一个字 $(MAKEFILE_LIST)) : 2>/dev/null
make
以打印和解析从 makefile 派生的数据库:-p
打印数据库-Rr
禁止包含内置规则和变量-q
仅测试目标的最新状态(不重新制作任何内容),但这本身并不会阻止在所有情况下执行配方命令;因此:-f $(firstword $(MAKEFILE_LIST))
确保与原始调用中的目标相同的 makefile,无论它是使用隐式还是显式定位的 - f...
。(由于
MAKEFILE_LIST
还包含include
d Makefile 的列表,因此firstword
用于仅提取原始目标文件;这意味着目标文件文件名/路径不得包含空格,但实际情况不太可能如此)。:
是一个故意无效的目标,旨在确保不执行任何命令;2>/dev/null
抑制生成的错误消息。注意:这仍然依赖于-p
打印数据库,从 GNU make 3.82 开始就是这种情况。遗憾的是,GNU make 没有提供直接选项来仅打印数据库,而不也执行默认(或给定)任务;如果您不需要针对特定的 Makefile,则可以按照man
页面中的建议使用make -p -f/dev/null
。<代码>-v RS=
/(^|\n)# 文件(\n|$$)/,/(^|\n)# 数据库制作完成/
make
版本 3.x 和 4.3 之间,make
输出中的段落结构发生了变化,因此(^|\n)
/(\n|$$)
确保识别感兴趣行的跨段落范围的开始和结束的行被检测到,无论它们出现在开始还是内部 /在段落末尾。if ($$1 !~ "^[#.]")
#
... 忽略非目标,其块以# Not a target:
开头
.
...忽略特殊目标:
grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'
从输出中删除不需要的目标:'^[^[:alnum:]]'
...排除隐藏目标,按照惯例,这些目标既不以字母也不以字母开头数字。'^$@$$'
...排除list
目标本身运行
make list
然后打印所有目标,每个目标都在其上自己的线路;您可以通过管道传输到 xargs 来创建一个以空格分隔的列表。Preface:
Per this answer,
make
versions post-4.4.1 will natively support a new--print-targets
option, which makes the solution below unnecessary.This other answer here builds on the solution below, and adds support for printing descriptions along with target names, assuming you've embedded
@#
-prefixed comments in your targets.Note: This answer has been updated to still work as of GNU
make
v4.3 - let us know if you come across something that breaks.This is an attempt to improve on Brent Bradburn's great approach as follows:
sh -c
)-f <file>
@
to prevent it from being echoed before executionCuriously, GNU
make
has no feature for listing just the names of targets defined in a makefile. While the-p
option produces output that includes all targets, it buries them in a lot of other information and also executes the default target (which could be suppressed with-f/dev/null
).Place the following rule in a makefile for GNU
make
to implement a target namedlist
that simply lists all target names in alphabetical order - i.e.: invoke asmake list
:Important: On pasting this, make sure that the last line is indented by exactly 1 actual tab char. (spaces do not work).
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 targetsa
andz
listed next to each other in the output, if there are additional targets.Explanation of the rule:
.
PHONY: list
LC_ALL=C
makes sure thatmake
's output in in English, as parsing of the output relies on that.Tip of the hat to Bastian Bittorf$(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null
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 $(firstword $(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 ...
.(Since
MAKEFILE_LIST
also contains the list ofinclude
d Makefiles,firstword
is used to extract only the originally targeted file; the implication is that the targeted file name / path must not contain spaces, but that is unlikely to be the case in practice).:
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 usemake -p -f/dev/null
, as recommended in theman
page.-v RS=
/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/
make
versions 3.x and 4.3, paragraph structuring inmake
'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 !~ "^[#.]")
#
... ignores non-targets, whose blocks start with# Not a target:
.
... ignores special targets:
grep -E -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 thelist
target itselfRunning
make list
then prints all targets, each on its own line; you can pipe toxargs
to create a space-separated list instead.更新!
自 1 月 8 日起, 2024,Make 有一个
--print-targets
选项,应该可以在不使用 hacky 正则表达式的情况下正确执行此操作。当前版本是 Make 4.4.1,因此之后的下一个版本将具有此功能。如果您的
Makefile
是由 CMake 创建的,您也许能够运行make help
。如果没有,我编写了一个补丁来为Make添加对这个明显有用的功能的适当支持。这比这里的所有其他答案都要好得多,这些答案都涉及 grep Makefiles 的可怕黑客行为。如果您包含其他 Makefile、使用计算的目标名称等,这显然不起作用。
补丁尚未合并,因此您必须从源代码构建。这还不错,但您确实需要一些与 autoconf 相关的旧的构建工具:
在 Linux 上,您可以使用 我已经构建了这个二进制文件。
然后您可以使用
-l
标志来列出目标:Update!
As of Jan 8th, 2024, Make has a
--print-targets
option that should do this properly without hacky regexes. The current version is Make 4.4.1 so the next release after that will have this feature.If your
Makefile
was created by CMake you might be able to runmake help
.If not, I wrote a patch to add proper support for this obviously useful feature to Make. This is way better than all the other answers here which all involve horrible hacks to grep the Makefiles. That obviously doesn't work if you include other Makefiles, use computed target names, etc.
The patch hasn't been merged so you have to build from source. It's not too bad but you do need some crusty old autoconf-related build tools:
On Linux you can use this binary I built already.
Then you can use the
-l
flag to list targets:我结合了这两个答案: https://stackoverflow.com/a/9524878/86967 和 https://stackoverflow.com/a/7390874/86967
并进行了一些转义,以便可以在 makefile 中使用它。
。
I combined these two answers: https://stackoverflow.com/a/9524878/86967 and https://stackoverflow.com/a/7390874/86967
and did some escaping so that this could be used from inside a makefile.
.
正如 mklement0 指出的,GNU-make 中缺少列出所有 Makefile 目标的功能,他的答案和其他人提供了方法来做到这一点。
然而,原始帖子还提到了 rake,其 tasks 开关的作用略有不同而不仅仅是列出 rakefile 中的所有任务。 Rake 只会为您提供具有相关描述的任务列表。没有描述的任务不会列出。这使作者能够提供定制的帮助描述,并省略某些目标的帮助。
如果您想模拟 rake 的行为,请提供每个目标的描述,有一个简单的技术可以做到这一点:在您想要列出的每个目标的注释中嵌入描述。
您可以将描述放在目标旁边,或者像我经常做的那样,放在目标上方的 PHONY 规范旁边,如下所示:
这将产生
您还可以在 此要点和此处 也是。
同样,这并不能解决在 Makefile 中列出所有目标的问题。例如,如果您有一个可能是生成的或其他人编写的大 Makefile,并且您想要一种快速的方法来列出其目标而不深入挖掘它,那么这将无济于事。
但是,如果您正在编写 Makefile,并且想要一种以一致、自记录的方式生成帮助文本的方法,则此技术可能很有用。
As mklement0 points out, a feature for listing all Makefile targets is missing from GNU-make, and his answer and others provides ways to do this.
However, the original post also mentions rake, whose tasks switch does something slightly different than just listing all tasks in the rakefile. Rake will only give you a list of tasks that have associated descriptions. Tasks without descriptions will not be listed. This gives the author the ability to both provide customized help descriptions and also omit help for certain targets.
If you want to emulate rake's behavior, where you provide descriptions for each target, there is a simple technique for doing this: embed descriptions in comments for each target you want listed.
You can either put the description next to the target or, as I often do, next to a PHONY specification above the target, like this:
Which will yield
You can also find a short code example in this gist and here too.
Again, this does not solve the problem of listing all the targets in a Makefile. For example, if you have a big Makefile that was maybe generated or that someone else wrote, and you want a quick way to list its targets without digging through it, this won't help.
However, if you are writing a Makefile, and you want a way to generate help text in a consistent, self-documenting way, this technique may be useful.
我最喜欢的答案是 Chris Down 在 Unix & 上发布的。 Linux 堆栈交换。我会引用。
用户Brainstone建议通过管道
sort -u
删除重复条目:来源:如何列出 make 中的所有目标? (Unix&Linux SE)
My favorite answer to this was posted by Chris Down at Unix & Linux Stack Exchange. I'll quote.
User Brainstone suggests piping to
sort -u
to remove duplicate entries:Source: How to list all targets in make? (Unix&Linux SE)
如果您安装了
make
的 bash 补全,则补全脚本将定义一个函数_make_target_extract_script
。此函数旨在创建一个 sed 脚本,该脚本可用于获取目标列表。像这样使用它:
If you have bash completion for
make
installed, the completion script will define a function_make_target_extract_script
. This function is meant to create ased
script which can be used to obtain the targets as a list.Use it like this:
专注于描述 make 目标的简单语法,并具有干净的输出,我选择了这种方法:
因此,将上述内容视为 Makefile 并运行它会给您类似
命令链的解释:
Focusing on an easy syntax for describing a make target, and having a clean output, I chose this approach:
So treating the above as a Makefile and running it gives you something like
Explanation for the chain of commands:
我采用了上面提到的一些答案并编译了这个答案,它还可以为每个目标生成一个很好的描述,并且它也适用于带有变量的目标。
示例 Makefile:
示例输出:
它是如何工作的:
make help
目标的顶部部分与 mklement0 在此发布的完全一样 - 如何获取 makefile 中的目标列表?。获取目标列表后,它运行
make; -nB
作为每个目标的试运行,并解析以@# Help:
开头的最后一行以获取目标的描述。并且该字符串或空字符串会打印在格式良好的表格中。正如您所看到的,变量甚至在描述中也得到了扩展,这对我的书中来说是一个巨大的好处:)。
I took a few answers mentioned above and compiled this one, which can also generate a nice description for each target and it works for targets with variables too.
Example Makefile:
Example output:
How does it work:
The top part of the
make help
target works exactly as posted by mklement0 here - How do you get the list of targets in a makefile?.After getting the list of targets, it runs
make <target> -nB
as a dry run for each target and parses the last line that starts with@# Help:
for the description of the target. And that or an empty string is printed in a nicely formatted table.As you can see, the variables are even expanded within the description as well, which is a huge bonus in my book :).
对于 Bash 脚本
这是在 bash 中执行此操作的一种非常简单的方法 - 基于 @cibercitizen1 的评论上面:
另请参阅@Marc.2377的更权威的答案,它说明了Bash如何完成
make
的模块可以做到这一点。For a Bash Script
Here's a very simple way to do this in
bash
-- based on the comment by @cibercitizen1 above:See also the more authoritative answer by @Marc.2377, too, which says how the Bash completion module for
make
does it.将此目标添加到您的 Makefile 中:
make -qpRr
=make --question --print-data-base --no-builtin-variables --no- builtin-rules
egrep -e '^[az].*:$$'
:搜索以小写字母开头并以“:”结尾的行sed -e 's ~:~~g'
:删除“:”然后运行:
这对我有用
Add this target to your Makefile:
make -qpRr
=make --question --print-data-base --no-builtin-variables --no-builtin-rules
egrep -e '^[a-z].*:$$'
: searches for lines which start with lowercase and ends with ":"sed -e 's~:~~g'
: deletes the ":"Then just run:
This works for me ????
PD: more info at...
@nobar 的回答有助于展示如何使用制表符完成来列出 makefile 的目标。
这非常适合默认提供此功能的平台(例如Debian、Fedora)。
在其他平台(例如Ubuntu)上,您必须显式加载此功能,如@hek2mgl 的回答:
make
的功能
make
的选项卡完成功能:以不同的 makefile 为目标>-f <文件>
。@nobar's answer helpfully shows how to use tab completion to list a makefile's targets.
This works great for platforms that provide this functionality by default (e.g., Debian, Fedora).
On other platforms (e.g., Ubuntu) you must explicitly load this functionality, as implied by @hek2mgl's answer:
. /etc/bash_completion
installs several tab-completion functions, including the one formake
make
:. /usr/share/bash-completion/completions/make
-f <file>
.此
help
目标将仅打印带有##
后跟说明的目标。这允许记录公共和私人目标。使用.DEFAULT_GOAL
可以使帮助更容易被发现。仅使用
sed
、xargs
和printf
,这些都是非常常见的。使用
< $(MAKEFILE_LIST)
允许调用除Makefile
之外的其他内容,例如Makefile.github
您可以在
Makefile.github
中自定义输出以满足您的偏好。代码> printf 。此示例的设置是为了匹配 OP 对rake
样式输出的请求。剪切并粘贴下面的 make 文件时,不要忘记将 4 个空格缩进更改为制表符。
这是上面
Makefile
的输出。请注意,private
目标不会获得输出,因为它只有一个#
作为注释。This
help
target will only print targets which have##
followed by a description. This allows for documenting both public and private targets. Using the.DEFAULT_GOAL
makes the help more discoverable.Only
sed
,xargs
andprintf
used which are pretty common.Using the
< $(MAKEFILE_LIST)
allows for the makefile to be called something other thanMakefile
for instanceMakefile.github
You can customize the output to suit your preference in the
printf
. This example is set up to match the OP's request forrake
style outputWhen cutting and pasting the below make file, don't forget to change the 4 spaces indentation to tabs.
Here is the output from the
Makefile
above. Notice theprivate
target doesn't get output because it only has a single#
for it's comment.