如何获得makefile中的目标列表? [英] How do you get the list of targets in a makefile?

查看:73
本文介绍了如何获得makefile中的目标列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经用过rake(一个Ruby make程序),它可以选择获取所有可用目标的列表,例如

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...
...

,但是在GNU make中似乎没有选择这样做.

but there seems to be no option to do this in GNU make.

显然,自2007年以来,几乎已经有了相应的代码- http://www.mail-archive.com/help-make@gnu.org/msg06434.html .

Apparently the code is almost there for it, as of 2007 - http://www.mail-archive.com/help-make@gnu.org/msg06434.html.

无论如何,我几乎没有办法从makefile中提取目标,您可以将其包含在makefile中.

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:

推荐答案

这是对 @nobar的绝佳方法的改进 a>如下:

  • 使用更强大的命令来提取目标名称,从而有望防止出现任何误报(并且还消除了不必要的sh -c)
  • 始终不会将目标文件定位在 current 目录中;遵守用-f <file>
  • 明确指定的makefile
  • 排除隐藏目标-按照惯例,这些目标的名称均不以字母或数字开头
  • 使单个伪造目标
  • 为命令加上@前缀,以防止在执行前被回显
  • uses a more robust command to extract the target names, which hopefully prevents any false positives (and also does away with the unnecessary sh -c)
  • does not invariably target the makefile in the current directory; respects makefiles explicitly specified with -f <file>
  • excludes hidden targets - by convention, these are targets whose name starts neither with a letter nor a digit
  • makes do with a single phony target
  • prefixes the command with @ to prevent it from being echoed before execution

奇怪的是,GNU make没有仅列出在makefile中定义的目标名称的功能. -p选项产生的输出包括所有目标,但是将它们包含在许多其他信息中.

Curiously, GNU make has no feature for listing just the names of targets defined in a makefile. The -p option produces output that includes all targets, but buries them in a lot of other information.

在GNU make的makefile中放置以下规则,以实现名为list的目标,该目标仅按字母顺序列出所有目标名称-即:以make list 的身份调用:

Place the following rule in a makefile for GNU make to implement a target named list that simply lists all target names in alphabetical order - i.e.: invoke as make list:

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

重要:粘贴此代码时,确保最后一行由精确地1个实际制表符缩进.(空格不是 工作).

Important: On pasting this, make sure that the last line is indented by exactly 1 actual tab char. (spaces do not work).

请注意,排序目标结果列表是最佳选择,因为 not 排序不会产生有用的排序,因为目标出现在其中的顺序生成文件未保存 .
同样,包含多个目标的规则的子目标始终不变地分别输出 ,因此,由于排序,通常 not 会彼此相邻出现;例如,如果有其他目标,则以a z:开头的规则将 not 的目标az彼此相邻列出的 .

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
    • 将目标列表声明为假目标,即一个 not 引用一个文件,因此应无条件调用
    • ). li>
    • .PHONY: list
      • declares target list a phony target, i.e., one not referring to a file, which should therefore have its recipe invoked unconditionally

      $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

      • 再次调用make以便打印和解析从makefile派生的数据库:
        • -p打印数据库
        • -Rr禁止包含内置规则和变量
        • -q仅测试目标的最新状态(不进行任何修改),但是它本身并不能在所有情况下都阻止执行配方命令;因此:
        • -f $(lastword $(MAKEFILE_LIST))确保与原始调用相同的makefile成为目标文件,无论它是通过-f ...隐式还是显式目标文件.
          注意事项 :如果您的makefile包含include指令,则此操作会中断;要解决此问题,请在任何include指令之前在变量THIS_FILE := $(lastword $(MAKEFILE_LIST)) 之前定义,并改用-f $(THIS_FILE).
        • :是一个故意无效的目标,旨在确保不执行任何命令2>/dev/null禁止显示结果错误消息.注意:尽管如此,这仍然依赖于-p打印数据库,从GNU make 3.82开始就是这种情况.可悲的是,GNU make没有提供直接选择来只是打印数据库,而没有执行默认(或给定)任务.如果不需要定位特定的Makefile,则可以按照man页中的建议使用make -p -f/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=

          • 这是一个awk惯用法,它将输入分成连续的非空行块.
          • 匹配包含所有目标的输出中的行范围(从GNU make 3.82开始为true)-通过将解析限制为该范围,无需处理来自其他输出节的误报.
          • 选择性地忽略块:
            • # ...忽略非目标,其目标块以# Not a target:
            • 开头
            • . ...忽略特殊目标
            • Selectively ignores blocks:
              • # ... ignores non-targets, whose blocks start with # Not a target:
              • . ... ignores special targets
              • '^[^[:alnum:]]' ...不包括隐藏的目标,按照惯例,这些目标既不是字母也不是数字.
              • '^$@$$' ...排除了list目标本身
              • '^[^[: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来创建以空格分隔的列表.

              Running make list then prints all targets, each on its own line; you can pipe to xargs to create a space-separated list instead.

              这篇关于如何获得makefile中的目标列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆