列出GNU中的目标/目标,使其在定义中包含变量

Bit*_*ter 99 makefile gnu-make

我有一个相当大的makefile,它通过计算变量中的名称来动态创建多个目标.(例如foo $(VAR):$(PREREQS)).有没有什么方法可以让gnu make在扩展这些变量之后吐出一系列目标?

我希望能够获得aribitrary makefile的目标.我正在尝试为我的shell编写一个完成函数.

小智 113

make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     
Run Code Online (Sandbox Code Playgroud)

取自make arg完成,其作品就像一个魅力.

  • 我认为它与定义的地方有关.我认为如果将其定义为别名,其工作目录将成为其定义的目录,并且显然awk部分不喜欢隐藏目录中的点.定义函数有效. (3认同)
  • 别名`alias mkl ="make -qp | awk -F':''/ ^ [a-zA-Z0-9] [^\$#\ /\t =]*:([^ =] |\$ )/ {split(\ $ 1,A,/ /); for(i in A)print A [i]}'| sort"`这将节省你2分钟的引用游戏:-) (3认同)
  • 我试图为它做一个别名,把它放在双引号中,但它只是导致awk在第一个逗号上有语法错误...有关如何正确地逃避这个shell(bash)别名的任何想法? (2认同)

Jac*_*lly 78

你能解析make -pn(即make --print-data-base --dry-run)的输出吗?它打印出所有变量,规则,隐式规则以及哪些命令将以繁重的细节运行.

  • 请注意,如果Makefile动态生成目标,则输出可能取决于您指定的目标.输出还可能取决于环境变量的值或使用make命令指定变量. (6认同)
  • 我喜欢简洁.+1添加了我自己的旋转(在下面的答案中描述):`make -pn | sed -rn'/ ^ [^#\ t \.%].*:[^ =]?/ p'` (6认同)

Zde*_*nik 13

我不确定这只是一个gnu make的东西,但这很有效:

make help

  • 没有真正使用GNU Make 3.81,可能是你makefile中的一个目标:"make:***没有规则来制作目标`帮助'.停止" (8认同)
  • 这只是在Makefile中调用"help"目标.如果它存在,它将打印一些东西(不是*完整*目标列表),如果它不存在(典型情况),它将拯救. (8认同)
  • 好消息是cmake似乎产生了一个很好的易读"帮助"目标. (2认同)

Eri*_*ski 10

一些响应者建议使用make -pn,它将打印规则数据库但不执行任何操作 - 或多或少.这种方法的问题在于-n仍然会调用所有递归的make,并且它仍然会执行比必要更多的工作,因为它会打印出它在常规构建中调用的每个命令.更有效的解决方案是使用以下内容创建一个简单的makefile,dummy.mk:

__all_targets__: ; #no-op
Run Code Online (Sandbox Code Playgroud)

现在调用make as make -p -f Makefile -f dummy.mk __all_targets__.在任何实质性构建中,make产生的输出量的差异是显着的.例如:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985
Run Code Online (Sandbox Code Playgroud)

执行时间也明显更好 - 第一个版本为2.063秒,第二个版本为0.059秒.


cod*_*hot 7

编辑:仅供参考,在另一个答案中,debian bash完成git存储库现在包含了为bash完成用例量身定制的此脚本的增强版本.

#!/bin/bash

SCRIPT='
  /^# Make data base/,/^# Files/d             # skip until files section
  /^# Not a target/,+1          d             # following target isnt
  /^\.PHONY:/                   d             # special target
  /^\.SUFFIXES:/                d             # special target
  /^\.DEFAULT:/                 d             # special target
  /^\.PRECIOUS:/                d             # special target
  /^\.INTERMEDIATE:/            d             # special target
  /^\.SECONDARY:/               d             # special target
  /^\.SECONDEXPANSION/          d             # special target
  /^\.DELETE_ON_ERROR:/         d             # special target
  /^\.IGNORE:/                  d             # special target
  /^\.LOW_RESOLUTION_TIME:/     d             # special target
  /^\.SILENT:/                  d             # special target
  /^\.EXPORT_ALL_VARIABLES:/    d             # special target
  /^\.NOTPARALLEL:/             d             # special target
  /^\.ONESHELL:/                d             # special target
  /^\.POSIX:/                   d             # special target
  /^\.NOEXPORT:/                d             # special target
  /^\.MAKE:/                    d             # special target

# The stuff above here describes lines that are not
#  explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
#  should be output.

  /^[^#\t:=%]+:([^=]|$)/ {                    # found target block
    h                                         # hold target
    d                                         # delete line
  }
  /^# File is an intermediate prerequisite/ { # nope
    s/^.*$//;x                                # unhold target
    d                                         # delete line
  }
  /^([^#]|$)/ {                               # end of target block
    s/^.*$//;x                                # unhold target
    s/:.*$//p                                 # write current target
    d                                         # hide any bugs
  }
'

make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
  | sort | uniq
Run Code Online (Sandbox Code Playgroud)

这是一个比debian bash完成脚本更完整的脚本,因为它提供了生成规则的结果,问题要求和最高投票答案(debian git服务器上的debian bash完成脚本)还不够.

这不是我链接到的原始脚本,但它更简单,触摸速度更快.