如何将makefile中给定的依赖关系显示为树?


18

问题

我想查看makefile的一个或多个目标的依赖关系。因此,我正在寻找一个程序,该程序可以解析makefile,然后以树状格式(缩进,ascii-art,...)或图形(点,...)表示依赖项。

类似

有一些程序可以在其他情况下执行此操作:

  • pactreebtreeree可以树状格式(例如ascii格式)或dot图形形式显示相应格式软件包的依赖关系,
  • gcc -M source_file.c 将C源文件的依赖性显示为生成规则,
  • pstree显示进程树的ascii表示。

进展

在网上搜索时,我发现没有什么帮助。那导致我尝试

make --always-make --silent --dry-run some_target | \
  grep --extended-regexp 'Considering target file|Trying rule prerequisite'

但看起来我必须在perl或python中破解一些其他解析代码,才能将其表示为漂亮的树/图。而且我还不知道我是否真的会以这种方式获得完整正确的图表。

要求

最好以某种方式限制图形(没有内置规则,只有给定的目标,只有一定的深度),但是在大多数情况下,我只是在寻找一种工具,该工具将给我一些“合理的”,人类的依赖关系。 -可见格式(例如“相似”下的程序)。

问题

  • 是否有任何程序可以做到这一点?
  • 我会从中获得完整和正确的信息make -dnq ...吗?
  • 有没有更好的方法来获取此信息?
  • 是否已经存在用于解析此信息的脚本/尝试?

1
这里要理解的关键是:依赖关系不会形成一棵树。 它们形成有向(希望是!)无环图,也称为DAG。尝试为以下内容绘制依赖关系图,您将看到:A依赖于B; A依赖于B; B依赖于B。A也取决于C;B取决于D;,c取决于D.
通配符

我知道@Wildcard,但就我的目的而言,足以将依赖关系表示为树。我可以将子图复制(并切成圆形)做成一棵树。抱歉,我没有明确。以您为例,我的输出会很好printf 'A\n B\n D\n C\n D\n'。(谁说我不能在评论中添加换行符?:)
卢卡斯

与“ A取决于B; B取决于D; D取决于C; A取决于D”有什么区别?您可以对任何DAG施加总排序(因为任何DAG都表示部分排序),但是您不能将DAG变成树。这是基本的图论。我希望看到您用于创建DAG的树表示形式的算法,然后将其显示出来。没有这样的基础算法,任何试图将依赖关系显示为树的工具都将极度容易破解且容易出错。
通配符

也许我还不够明确,但是我认为我在“ 相似”下给出的示例很清楚。我对图论不感兴趣(至少在这个问题上)。我想要的是一个看起来像树的视觉表示(特别是如果它应该显示在终端上,因为dot顺序图显然很好。)我将稍作更新以使问题更清楚(我希望)。
卢卡斯

2
兰特:老实说,我有点沮丧,因为make不能提供像这样的现成的东西。Make是世界上使用最广泛的构建系统之一,该功能非常有用,以至于很难掌握,在神知道有几十年的历史中,没有人添加这种功能。以明确定义的文本格式输出此信息就足够了。我知道make是开源的,我总是可以自己添加此功能。并且相信我,如果make基本上不是我的黑匣子,我会的!乱跑。
antant

Answers:


10

尝试makefile2graph同一作者有AA类似的工具MakeGraphDependencies写成java代替c

make -Bnd | make2graph | dot -Tsvg -o out.svg

然后使用某些矢量图形编辑器突出显示所需的连接。


1
我已经尝试过该工具。甚至都没有开始工作(至少对于我尝试过的任何化身都没有)。大多数情况下,它只是由于一些内存访问冲突而出现。
antant

3

我发现了一种破解方法,至少可以输出结构清晰的信息,以了解哪些目标取决于哪些先决条件。不利的一面是,这是很麻烦的。换句话说,您需要更改makefile以将所有目标的构建配方包装到一个小的条件函数中。我将发布一个简短的示例:

getRecipe = $(if $(DEPENDENCY_GRAPH),@echo Target $@ depends on prerequisites "$^",$(1))


VARIABLE_TARGET_NAME = foobar.txt

all : TopLevelTarget

TopLevelTarget : Target_A Target_D
    $(call getRecipe,\
        @echo Building target $@)

Target_A : Target_B
    $(call getRecipe,\
        @echo Building target $@)

Target_D : Target_C
    $(call getRecipe,\
        @echo Building target $@)

Target_B : $(VARIABLE_TARGET_NAME)
    $(call getRecipe,\
        @echo Building target $@)

Target_C :
    $(call getRecipe,\
        @echo Building target $@)

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@)

在此示例中,我使用了手动滚动的getRecipe函数来包装每个目标的配方,然后决定是实际运行该配方还是仅输出正在构建的目标及其依赖的先决条件。后者仅在DEPENDENCY_GRAPH设置了变量(例如,作为环境变量)时才发生。在该示例中,构建配方仅是一个回声,表明正在构建目标,但是显然可以用您选择的命令替换它。

随着DEPENDENCY_GRAPH设置为1,这导致输出:

Target foobar.txt depends on prerequisites ""
Target Target_B depends on prerequisites "foobar.txt"
Target Target_A depends on prerequisites "Target_B"
Target Target_C depends on prerequisites ""
Target Target_D depends on prerequisites "Target_C"
Target TopLevelTarget depends on prerequisites "Target_A Target_D"

它应该足够容易解析然后转换为点图。

如果DEPENDENCY_GRAPH完全不设置或设置为0,则输出为:

Building target foobar.txt
Building target Target_B
Building target Target_A
Building target Target_C
Building target Target_D
Building target TopLevelTarget

或者换句话说,使用常规构建配方。我尚未测试过这种方法是否可以可靠地用于复杂的配方。我已经遇到的一个问题是,它对于多行配方根本不起作用。

例如,在最后一个目标的构建配方中,如果除了说正在构建目标之外,我实际上还想要touch该文件:

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@\
        touch $@)

make似乎认为该touch $@部分只是上一行中回显的一部分:

Building target foobar.txt touch foobar.txt

如果我在上一行中省略了结尾的反斜杠,则make抱怨*** unterminated call to function呼叫“:丢失” )'. Stop.如果有人知道如何获取make打出好球,我将不知所措。:)

编辑:这种方法的另一个问题是,这只有在不存在构建结果的情况下才有效,因为make显然不会执行它认为是最新的目标的构建配方。


;target $@touch命令之后添加即可工作
mug896

对于第二个问题,请使用make -B无条件地确定所有目标的选项。
mug896

2

我使用了remake --profile(的替代品make),它以callgrind格式生成了一个依赖关系树。

然后,gprof2dot可以生成目标树的图像。


我是否理解文档错误或remake --profile仅输出其执行目标的依赖关系图?还是可以以某种方式输出所有目标的图形?
卢卡斯

恐怕只有它运行了。但是你可以用所有-dry运行运行它们
维克多Sergienko

哦,是的,remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -B看起来很有希望。
卢卡斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.