从绝望到成功:我在Ubuntu上构建Yocto Dunfell的完整心路历程

261 阅读10分钟

引言

1. 前言:由于近期项目需要,我被安排负责开发基于Yocto的Qt桌面应用程序。在Yocto项目下构建嵌入式Linux的过程中,我遇到了诸多挑战,从环境配置到编译错误,每一步都充满了不确定性。在历经各种艰难终于成功构建后,我深知对于初学者来说这个过程有多么不易。为此,我决定将整个构建过程记录下来,分享遇到的问题和解决方案,希望能让初次接触Yocto的开发者少走弯路,构建过程更加顺利。

0b1367895fcc77917e6866d0ad641df7.gif
  • Yocto项目简介及其在嵌入式领域的重要性

    Yocto Project是一个开源的嵌入式Linux构建系统,它不是一个现成的Linux发行版,而是一个让你自己制作Linux发行版的工具集。
    Yocto解决了嵌入式开发的根本矛盾:标准化生产与个性化定制。它让开发者能够在统一的框架下,为特定硬件和特定应用构建最合适的Linux系统。

  • 个人学习Yocto的动机
      最初接手Yocto确实是出于项目安排的客观原因,但随着深入了解,我不仅被它强大的定制能力所折服,更被它在嵌入式领域的巨大价值深深震撼。

  • 本文能为读者解决什么问题
      对于刚接触Yocto的开发者,本文将从环境搭建、配方(Recipe)编写到常见构建错误的排查,手把手带你完成第一个镜像的构建。你将获得一条清晰的入门路径,彻底弄清BitBake的工作流程,掌握解决依赖缺失和配方解析失败这些典型难题的方法。

编译环境说明

2.软硬件环境

2.1 硬件环境

  • Yocto项目构建嵌入式Linux镜像是在Ubuntu Linux系统下进行的,建议你使用Ubuntu 16.04以上的版本,我这里是使用的Ubuntu 20.04 LTS版本。
  • 16GB内存及以上,使Ubuntu Linux系统有足够的内存用于构建镜像。
  • 80G的磁盘空间。

2.2 软件环境

  • 宿主机完整的构建包清单
核心编译工具集:gcc, make, build-essential,
构建系统工具:make, gawk, diffstat, chrpath,
Python运行时环境:python3, python3-pip, python3-pexpect, python3-jinja2, python3-subunit, python3-git,
源码获取工具:git, wget,
压缩解压工具集:xz-utils, unzip, zstd, liblz4-tool,
文档生成工具:texinfo,
网络测试工具:iputils-ping,
图形界面支持:libegl1-mesa, libsdl1.2-dev, mesa-common-dev, xterm,
系统工具:socat, cpio, debianutils,
代码质量工具:pylint3

提示:我在后面正式的构建中会用到上面的所有工具,新手不用担心,这里展示出来只是让大家有个初步的了解

  • Yocto分支版本
      这里我们选择Dunfell分支版本,这是一个长期支持(LTS)的稳定版本。对新手来说,它拥有最成熟稳定的生态,能最大可能的少踩坑。唯一的不足是它的官方支持已于2024年4月结束。
      如果你希望使用仍处于官方支持周期内的稳定版本,可以选择Kirkstone。它作为更新的LTS版本,功能更丰富,但软件包体积也更大,这会导致构建所需的时间和磁盘空间显著增加。

构建过程全记录

3.Yocto构建实战

3.1 准备构建环境

  • 安装工具集
      我们打开系统中的Terminal,然后输入如下这一行指令来安装构建所必须的工具集。
sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat 
cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git 
python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm python3-subunit 
mesa-common-dev zstd liblz4-tool -y
  • 输入密码

59e0bc86-d2a2-4ace-8acd-c70b313581bc.jpg

提示:这里需要输入自己的用户登录密码,也就是开机后登录Ubuntu桌面时输入的密码。输入密码时,屏幕上不会有任何显示,这是正常的安全设计。

  • 回车,开始安装工具集

885e38ef-bd2a-4038-a482-81857e1597a0.jpg

这里,我们构建所必须的工具集就已经安装准备好了!

3.2 下载Yocto的Poky

提示:获取Poky,这是Yocto的核心框架。Poky包含了构建自定义Linux镜像所需的所有组件。

  逐行输入如下三行指令来下载Poky。

$ git clone git://git.yoctoproject.org/poky

$ cd poky

$ git fetch --tags

168e68a1-d1ec-4529-bc78-de58cc9865a1.png

这里,我们的Poky就已经成功下载好了。你也可以到文件目录中去查看验证。因为Git代码文件很多是隐藏的,需要点击右上角"☰"菜单来显示隐藏的文件。

579b63ce-d0bb-42ad-b478-ceee1f655fa8.jpg

3.3 选择对应的Yocto分支版本

  如我们上面所说的,我们选择Dunfell版本。输入如下指令来进行指向。

git checkout -t  origin/dunfell -b my-dunfell

9f60ebc0-2370-4ead-b0b4-494828378f20.jpg

3.4 初始化构建环境

  输入如下指令来初始化编译环境。

source oe-init-build-env

edcdfda7-90b9-4d71-bd39-7b2c57137ea4.jpg 这里,我们构建环境的初始化就已经完成了!

3.5 开始正式构建

提示:构建过程中,如果出现报错,我们需要立马停止构建,先解决完问题后,再继续构建。停止指令:Ctrl+C

  输入如下指令开始进行构建。

bitbake core-image-sato

  在构建过程中,你可能会在终端看到如下黄色警告信息,这是系统正在自动切换和配置可用的镜像源,不用担心。 dae10092-1305-434e-a61b-491571ab7e22.png

提示:构建的过程肯定会出现不同的错误,如你在过程中出现错误,首先停止构建,然后看一看我下面的问题解决实录这一章节所写的,相信一定能帮到你。

3.6 构建完成

86a0e5b0-d862-45a0-a9bb-c54b52ca55e1.jpg

  这时,我们可以在如下文件目录中看到已经构建完成的镜像文件了。 1414d248-a1fe-4354-a345-fc1ee4d7adff.png

3.7 结果验证

  执行如下指令,输入用户密码,该密码依然为之前安装工具集时所输入的自己的用户登录密码,启动 QEMU 虚拟机来运行你刚刚构建的 Yocto 系统镜像。

提示:在终端主机或者 ~/poky/build 层级输入这条指令均可。

runqemu qemux86-64

3400dca9-7b60-4550-bb28-8393be8ba71f.png

6efbac23-59d1-483d-ba1d-1e46040774b0.png

这里,我们的Yocto系统镜像就已经成功构建完成了!

问题解决实录

4. 踩坑记录与解决方案

:有趣的是,当我为了准备本文而重新构建镜像时,却只遇到了"gcc内存不足"问题。之前困扰我的qemu-nativegcc-runtime问题并未复现。这正说明了Yocto构建的环境敏感性——你可能遇到不同的问题,但解决思路是相通的。我将在本章结尾附上构建过程中解决问题的方法论。

4.1 gcc编译内存不足

  • 错误现象:g++: fatal error: Killed signal terminated program cc1plus

08c09189-1c81-4dfd-b519-bdc775e57ab8.png   然后,我们顺着错误提示的文件目录,找到记录错误信息的日志。一般在日志的最后50行左右会显示错误信息,这里的错误信息如下:

g++: fatal error: Killed signal terminated program cc1plus
compilation terminated.
make[2]: *** [Source/CMakeFiles/CMakeLib.dir/build.make:1210: Source/CMakeFiles/CMakeLib.dir/cmGeneratorTarget.cxx.o] Error 1
make[2]: *** Deleting file 'Source/CMakeFiles/CMakeLib.dir/cmGeneratorTarget.cxx.o'
make[2]: *** Waiting for unfinished jobs....
make[2]: Leaving directory '/home/pinkbichon/poky/build/tmp/work/x86_64-linux/cmake-native/3.16.5-r0/build'
make[1]: *** [CMakeFiles/Makefile2:1864: Source/CMakeFiles/CMakeLib.dir/all] Error 2
make[1]: Leaving directory '/home/pinkbichon/poky/build/tmp/work/x86_64-linux/cmake-native/3.16.5-r0/build'
make: *** [Makefile:166: all] Error 2
ERROR: oe_runmake failed
WARNING: exit code 1 from a shell command.
ERROR: Execution of '/home/pinkbichon/poky/build/tmp/work/x86_64-linux/cmake-native/3.16.5-r0/temp/run.do_compile.631029' failed with exit code 1
  • 根本原因:物理内存不足,Killed signal terminated program cc1plus 表示编译进程被系统强制终止了。 cc1plus 是g++的前端编译器,处理复杂C++代码时需要大量内存,物理内存不足时,依赖交换空间,交换空间不足或太慢,进程被OOM Killer终止。

  • 解决方案:增加8GB交换空间然后优化并行编译。

  逐行输入如下指令来修复此异常。

  1. 先增加交换空间到16GB
sudo swapoff /swapfile 2>/dev/null
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile  
sudo swapon /swapfile
free -h

3260822b-ee3b-45ce-9863-914195553a53.jpg

  1. 调整配置
cd ~/poky/build
cat >> conf/local.conf << 'EOF'
BB_NUMBER_THREADS = "2"
PARALLEL_MAKE = "-j 2"
PARALLEL_MAKE_pn-cmake-native = "-j 1"
SELECTED_OPTIMIZATION = "-O1"
EOF

9bfca1be-0126-44b1-9268-c8a48b89732a.jpg

  1. 清理并重试
bitbake cmake-native -c cleansstate
bitbake cmake-native

ecd664c5-4706-4925-83c9-418605f05fb9.png

cmake-native 编译成功了。 5b773d06-5b62-4bc1-bef8-ded6a1000abf.png

问题已修复,接下来,再次输入如下指令,继续进行主干构建流程。

bitbake core-image-sato

在构建过程中,每个人都可能遇到不同的错误。但掌握正确的排查思路,你就能顺利解决问题。以下是经过我实践验证的五步排查法:
    1. 遇到错误信息不要慌,马上Ctrl+C停止构建。
    2. 定位日志,提取关键信息。
    3. 识别错误类型,匹配解决方案。
    4. 找到错误的原因和解决方案,实施针对性修复。
    5. 修复完成,重新开始主干流程的构建。

结语&加学习群

  到这里,你已经成功构建出了自己的第一个Yocto镜像文件。相信在工作中遇到定制化需求时,你也能从容应对了。

我是粉色小比熊

  • 一个待过大厂,混过外包,目前正在一家外企折腾的作死型前后端选手;
  • 一个遇到新技术就流口水的全干软件工程师;
  • 一个不咋正经的掘金作者;
  • 一个喜欢旅游和摄像的视频菜鸟;
  • 一个热衷自驾川西的业余改装菜鸟;
  • 一个英语不太好偏偏又喜欢没事儿抖两句的口语选手;

如果你也对以下话题感兴趣:

  • 前后端技术学习与成长
  • 简历优化与面试技巧
  • 视频拍摄与剪辑
  • 英语学习交流
  • 汽车改装与自驾游

点个赞加关注 欢迎私信我。 加油 努力成为大佬!