CMake:如何分辨传递依赖从何而来?


10

我正在重写旧的CMake设置以使用自动依赖项传播等现代功能。(即使用target_include_directories(<target> PUBLIC <dir>)代替include_directories(<dir>)。)当前,我们通过设置一堆全局目录属性来手动处理所有项目依赖项信息。

在测试中,我找到了一些示例,其中新版本中的目标将链接到旧版本中不会的库。我没有明确地链接到它,所以我知道这是来自目标的依赖关系,但是为了找到哪个(一个或多个)我必须递归地浏览项目的所有CMakeLists.txt依赖关系,跟踪依赖关系层次结构,直到找到一个引入相关库的库。我们有数十个库,因此这不是一个简单的过程。

CMake是否提供任何方式查看每个目标的显式添加了哪些依赖关系,以及通过传递性依赖关系传播了哪些依赖关系?

看起来--graphviz输出确实显示了这种区别,因此很明显CMake内部知道上下文。但是,我想编写一个类似tree脚本来在命令行上显示依赖项信息,而解析Graphviz文件听起来既像噩梦,也像黑客一样。

据我所知,cmake-file-api没有包含此信息。我认为该codemodel/target/dependencies字段可能有效,但是它列出了混合在一起的本地和可传递依赖项。并且backtrace每个依赖项的字段仅关系到当前目标的add_executable/ add_library调用。


1
--graphiz选项如何不回答您的问题?为什么解析点文件感觉就像一场噩梦?点文件是人类可读的表示连接点的最简单,通用和灵活的方式。使用gvpr实用程序,您可以以奇怪的方式对它们执行任何操作,也可以使用其他语言导入它们。为什么是一个点文件,从字面上表示目标之间依赖关系的树状结构,而不是您所要求的“观察方式”?
KamilCuk

@KamilCuk足够公平。我想我希望能获得一种更标准化的格式,如JSON,无需安装其他程序包也无需编写自己的解析器就可以读取它。我假设依赖关系图将以多种格式提供(例如,我仍然需要尝试CMake服务器API)。但是,如果点文件是获取该信息的最简单(或唯一)方法,那就很好。
0x5453

1
我不会在Graphviz上以不同的方式押注太多赌注。告诉它区别的代码在这里链接,不是很复杂。
kert

Answers:


4

您可以解析dot由生成的文件graphviz并提取所需的详细信息。以下是执行此操作的示例python脚本。

import pydot
import sys

graph = pydot.graph_from_dot_file(sys.argv[1])
result = {}

for g in graph:
    # print(g)
    for node in g.get_node_list():
        if node.get("label") != None:
            result[node.get("label")] = []

    for edge in g.get_edges():
        result[g.get_node(edge.get_source())[0].get("label")].append(g.get_node(edge.get_destination())[0].get("label"))

for r in result:
    print(r+":"+",".join(result[r]))

您还可以添加该脚本以从cmake运行作为自定义目标,因此可以从构建系统中调用它。您可以在此处找到示例cmake项目


感谢您的示例,我将不得不研究pydot
0x5453
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.