小编典典

你如何获得生成文件中的目标列表?

all

我使用了一点 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。

无论如何,我做了一些小技巧来从 makefile 中提取目标,您可以将其包含在 makefile 中。

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

它将为您提供已定义目标的列表。这只是一个开始——例如,它不会过滤掉依赖项。

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

阅读 69

收藏
2022-05-06

共1个答案

小编典典

如下所示:

  • 使用更强大的命令来提取目标名称,这有望防止任何误报(并且也消除了不必要的sh -c
  • 并不总是以 当前 目录中的 makefile 为目标;尊重明确指定的makefile-f <file>
  • 排除隐藏目标 - 按照惯例,这些目标的名称既不以字母也不以数字开头
  • 只用一个 虚假 的目标
  • 为命令添加前缀@以防止在执行前对其进行回显

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

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

.PHONY: list
list:
    @LC_ALL=C $(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 个实际的制表符字符。 (空格 不起作用

请注意,对生成的目标列表进行 排序 是最好的选择,因为 排序不会产生有用的排序,因为 不会 保留目标在 makefile 中出现的顺序。
此外,包含多个目标的规则的子目标总是 单独 输出,因此由于排序,通常 不会 彼此相邻出现;例如,如果有其他目标,则以 开头的规则a z:
没有 目标a并在输出 中彼此相邻z列出。 __

规则解释

  • .PHONY: list

    • 将目标列表声明为虚假目标,即 引用 文件 的目标,因此应 无条件调用其配方
    • LC_ALL=C确保make‘ 以 English 输出,因为输出的解析依赖于此。
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • 再次调用make以打印和解析从 makefile 派生的数据库:
    • -p打印数据库
    • -Rr禁止包含内置规则和变量
    • -q仅测试目标的最新状态(不重新制作任何东西),但这本身并不能阻止在所有情况下执行配方命令;因此:
    • -f $(lastword $(MAKEFILE_LIST))确保与原始调用中相同的 makefile 被定位,无论它是使用-f ....
      警告如果您的 makefile 包含include指令,这将中断;为了解决这个问题,在任何指令THIS_FILE := $(lastword $(MAKEFILE_LIST)) 之前 定义变量并使用。include``-f $(THIS_FILE)

    • :故意无效的目标 ,旨在 确保不执行任何命令2>/dev/null抑制生成的错误消息。注意:这仍然依赖于-p打印数据库,GNU make 3.82 就是这种情况。 遗憾的是,GNU make 没有提供 直接打印数据库的选项,而不 执行 默认(或给定)任务;如果您不需要针对特定​​的 Makefile,您可以按照页面中的建议使用。 __make -p -f/dev/null``man

    • -v RS=

    • 这是一个 awk 习惯用法,它将输入分成连续的非空行块。

    • /^# File/,/^# Finished Make data base/

    • 匹配包含所有目标的输出中的行范围(从 GNU make 3.82 开始为真) - 通过将解析限制在此范围内,无需处理来自其他输出部分的误报。

    • if ($$1 !~ "^[#.]")

    • 选择性地忽略块:

    • #…忽略非目标,其块以# Not a target:
    • .…忽略特殊目标
    • 所有其他块都应以仅包含显式定义目标名称的行开头,后跟:
    • egrep -v -e '^[^[:alnum:]]' -e '^$@$$'从输出中删除不需要的目标:

    • '^[^[:alnum:]]'… 不包括 隐藏 目标,按照惯例,隐藏目标是既不以字母也不以数字开头的目标。

    • '^$@$$'…不包括list目标本身

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

2022-05-06