0
点赞
收藏
分享

微信扫一扫

Yocto生成组件依赖图

1. 引言

本文介绍如何通过解析Yocto系统中的组件包依赖关系,了解各组件的物理结构和工程结构。这对于理解某个组件的构建流程和依赖关系非常重要。

2. Dot文件基础知识

2.1 Dot文件基本结构

一个有效的DOT文件应具有以下基本结构:

digraph G {
    "node1" [label="Node 1"];
    "node2" -> "node1";
}

语法规则
  • 图的声明: 使用 digraph 声明有向图。
  • 节点定义: 格式为 "node_name" [label="Node Label"];
  • 边的定义: 格式为 "node1" -> "node2";
  • 分号: 每一行定义后必须以分号 ; 结束。

2.2 语法检查工具

  • Graphviz

dot -Tpng yourfile.dot -o output.png

  • 在线验证工具
  • Graphviz Online
  • Graphviz Visual Editor

2.3 Dot示例

以下是一个有效的 DOT 文件示例:

digraph G {
    "A" [label="Node A"];
    "B" [label="Node B"];
    "C" [label="Node C"];
    
    "A" -> "B";
    "B" -> "C";
    "C" -> "A";  // 循环依赖
}

总结

通过遵循 DOT 文件的语法规则和使用 Graphviz 等工具进行检查,你可以确保 DOT 文件的正确性并避免常见错误。

3. 生成依赖图

首先,使用 bitbake -g <recipe> 命令生成依赖关系文件,这会生成 pn-buildlisttask-depends.dot 文件。这里以lib32-curl为例讲解整个过程。

此时在build下生成2个文件

文件名

内容

pn-buildlist

包列表

task-depends.dot

yocto执行的task(如xxx.do_fetch)的依赖关系

task-depends.dot 文件通常采用 DOT 格式,用于描述图形结构,特别是节点和边之间的关系。对于 Yocto 项目中的依赖关系,文件的内容格式大致如下:

  1. 基本结构


digraph G {
    "task1" [label="task1\n:version\n:path"]
    "task1" -> "task2"
    "task2" [label="task2\n:version\n:path"]
    "task2" -> "task3"
    ...
}

  1. 具体组件
  • digraph G { ... }:
  • 指定这是一个有向图(directed graph),G 是图的名称。
  • 节点定义:
  • 格式为

"task_name" [label="task_name\n:version\n:path"]

,其中:

  • "task_name": 任务的名称,例如 acl-native.do_compile
  • label: 描述性标签,通常包括任务名称、版本和路径信息。使用换行符 \n 分隔不同信息。
  • 依赖关系:
  • 格式为 "task1" -> "task2",表示 task1 依赖于 task2。每个箭头表示一个任务对另一个任务的依赖。
  1. 示例内容

以下是一个具体的示例:


digraph G {
    "acl-native.do_compile" [label="acl-native do_compile\n:2.3.1-r0\nvirtual:native:/path/to/acl_2.3.1.bb"]
    "acl-native.do_compile" -> "acl-native.do_configure"
    "acl-native.do_configure" [label="acl-native do_configure\n:2.3.1-r0\nvirtual:native:/path/to/acl_2.3.1.bb"]
    "acl-native.do_configure" -> "acl-native.do_patch"
    "acl-native.do_patch" [label="acl-native do_patch\n:2.3.1-r0\nvirtual:native:/path/to/acl_2.3.1.bb"]
    "acl-native.do_patch" -> "acl-native.do_fetch"
}

  1. 总结

task-depends.dot 文件通过 DOT 格式清晰地表示了任务之间的依赖关系,便于可视化工具(如 Graphviz)进行解析和展示。理解该格式有助于更好地分析 Yocto 构建过程中的各个任务及其依赖。

通过解析task-depends.dot文件,既可以知道我依赖谁以及谁依赖我的问题。

4.我有哪些依赖

这个问题已经有解决方案,可以使用https://github.com/openembedded/openembedded-core/blob/master/scripts/oe-depends-dot 脚本来实现。

First generate the .dot file:
    bitbake -g core-image-minimal

To find out why a package is being built:
    %(prog)s -k <package> -w ./task-depends.dot

To find out what a package depends on:
    %(prog)s -k <package> -d ./task-depends.dot

Reduce the .dot file packages only, no tasks:
    %(prog)s -r ./task-depends.do

该脚本支持的如下功能:

  1. 查找某个package为什么会被编译
  2. 查找某个package依赖了什么
  3. 从dot文件中移除task

python3 oe-depends-dot.py -r ./task-depends.dot

执行之后,会生成一个精简版本的dot文件task-depends-reduced.dot,将原始的task依赖转变为package依赖,且将有些复杂的依赖关系进行了简化,比如 如果A->B, B->C, A->C, 那么 A->C 可以直接移除。这样大大减小了dot文件的大小,加速了后续dot转化为png的过程。

如下是简化后的文件的部分内容

digraph depends {
 ...
"acl-native" -> "attr-native"
"gtk-doc-native" -> "pkgconfig-native"
"lib32-binutils-cross-arm" -> "zlib-native"
"lib32-binutils-cross-arm" -> "bison-native"
"lib32-binutils-cross-arm" -> "pkgconfig-native"
"lib32-ca-certificates" -> "openssl-native"
"lib32-ca-certificates" -> "opkg-utils-native"
"lib32-ca-certificates" -> "lib32-openssl"
"lib32-ca-certificates" -> "debianutils-native"
"lib32-curl" -> "lib32-ca-certificates"
"lib32-curl" -> "lib32-libidn2"
"lib32-curl" -> "lib32-zlib"
"lib32-gcc-cross-arm" -> "zstd-native"
"lib32-gcc-cross-arm" -> "libmpc-native"
 ...
}

精简后的dot文件生成图片的效果。

dot -Tpng task-depends-reduced.dot  -o task-depends-reduced-output.png

Yocto生成组件依赖图_ide

这里生成的图形依赖比较复杂,包含了诸多我们不需要关注的部分,比如一些native组件。移除dot文件中的native的行,结果:

sed  '/native/d' task-depends-reduced.dot > task-depends-reduced1.dot

Yocto生成组件依赖图_python_02

对于一个较小的组件,通过这种方式,可以得到清晰准确的package依赖链,但是对于依赖复杂的组件,通常生成的dot复杂,以至于不能渲染成图片。因此开发了一个新的工具,在以上的基础上做了一些精简:

  1. 使用package黑名单,移除不需要关注的package
  2. 改变链表渲染方向,改为从左到右
  3. 使用一个集合来记录已添加的依赖,确保每个 package 只被添加一次。构建依赖关系时,优先添加靠近根节点的依赖。

使用脚本

python3 pn-depends.py

自动生成lib32-curldependency_chain.png

最终效果为

Yocto生成组件依赖图_ide_03

5. 我被谁依赖

经常在项目中,遇到有些非期望的目标,我们想知道它是因为怎样的依赖关系,才被添加到编译系统的。此时可以通过这种方式

%(prog)s -k <package> -w ./task-depends.dot

但是需要注意的是,这里的task-depends.dot需要编译最终的目标来生成

# python3 oe-depends-dot.py -k lib32-curl -w ./task-depends.dot
Because: lib32-socl-system-server lib32-dtvkit-release-prebuilt lib32-gstreamer1 lib32-packagegroup-amlogic-baserootfs lib32-playready lib32-oem-generic-mediaclient-image lib32-socl-platformserver lib32-cobalt-browser lib32-gst-agmplayer lib32-gst-socl-drm-plugins lib32-gst-socl-drmbufferpool-plugins lib32-gst-plugin-socl-asink lib32-gst-plugin-socl-demux lib32-gst-plugin-socl-subtitlesink lib32-gst-plugin-socl-v4l2dec lib32-gst-plugin-video-sink lib32-socl-player-service lib32-socl-appmanager lib32-socl-dial lib32-socl-system-app lib32-libvideorender
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-socl-system-app -> lib32-socl-system-server -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-dtvkit-release-prebuilt -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-socl-dial -> lib32-socl-appmanager -> lib32-socl-platformserver -> lib32-gst-plugin-socl-asink -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-cobalt-browser -> lib32-socl-appmanager -> lib32-socl-platformserver -> lib32-gst-plugin-socl-asink -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-libvideorender -> lib32-socl-appmanager -> lib32-socl-platformserver -> lib32-gst-plugin-socl-asink -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-socl-player-service -> lib32-gst-agmplayer -> lib32-gst-socl-drm-plugins -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-gst-plugin-socl-demux -> lib32-gst-socl-drm-plugins -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-gst-plugin-socl-v4l2dec -> lib32-gst-socl-drmbufferpool-plugins -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-gst-plugin-video-sink -> lib32-gst-socl-drmbufferpool-plugins -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-gst-plugin-socl-subtitlesink -> lib32-gstreamer1 -> lib32-curl
lib32-oem-generic-mediaclient-image -> lib32-packagegroup-amlogic-baserootfs -> lib32-playready -> lib32-curl

生成图片

dot -Tpng dependency_graph.dot  -o dependency_graph-output.png

Yocto生成组件依赖图_依赖关系_04


举报

相关推荐

0 条评论