为什么大厂都在用Yocto?

科技   2024-11-05 12:04   北京  

大家好,我是鱼鹰。

Yocto 是什么?估计很多道友在第一次听到时都是一脸懵逼。当初鱼鹰从领导处了解到这个技术时,完全不知道是什么,只能摸着石头过河。

1、buildroot辛酸史

在此之前,领导刚刚让鱼鹰学习了 buildroot 编译内核镜像,因为我们有个老项目的镜像就是用它编译的。

以前这些镜像都是老外维护(鱼鹰目前在世界500强外企工作),我们只要从指定地址获取镜像,用工具烧录SD卡镜像就行。

后面领导想国内也能维护镜像,能自己编译镜像,于是让鱼鹰学习镜像编译(以前和领导聊过发展方向,知道鱼鹰想往 Linux 方向发展,因此给了机会)。

Buildroot 很多年前鱼鹰也了解过,也编译过,感觉不是特别难,觉得任务应该很快能完成。

但没想到,搞了半个多月才搞定,印象最深刻的就是 2.5 G左右的开源资源下载。以前编译镜像时,从来没遇到这些问题,都是半天到一天左右就搞定了。

现在想想,有这两点原因:

1、那些年,github 可以正常上网,很多国外资源都能轻松下载。

2、目前的镜像依赖的开源库太多,也太老了,以前只是为了学习Linux内核,只要基础的组件就行。

因此很顺利编译 uboot、内核、文件系统(镜像三大件)。

现在有些资源下载实在太慢,只能各种找资源,另外从 gitee 中转,总算是下载完成了(还好支持离线下载安装方式)。

但是 qt 这个功能最终还是没装上,不知道啥原因,因为不重要,就没管了。

另外,很多资源有指定的 hash 值,你只能下载相同 hash 值的资源,否则即使你修改了 hash 值适配新资源,最终可能导致系统不兼容。

还有就是,buildroot 环境本身的安装也有点麻烦,也需要时间熟悉。

2、Yocto苦难史

后来转 Yocto 开发后,发现学习难度比 buildroot 上升了十倍,资源(硬盘空间)消耗差不多也是十倍,但是熟悉后,简直 TMD 就是为嵌入式而生。
当时自己的 Ubuntu 是 18.04,因为有个老项目的编译需要这个版本才能正常编译。
而 Yocto 的推荐系统应该是 20.04 以上,最少剩 120 G硬盘空间:

IMX_YOCTO_PROJECT_USERS_GUIDE.pdf

鱼鹰不想重装Ubuntu系统(那个时候还不知道用 docker),于是走了一个岔路,遇到各种软件不兼容问题,比如 gcc (只能下载源码重新安装)、python,有些推荐安装的软件版本无法顺利安装。repo 工具本身由于国内网络环境原因,也得使用国内镜像才顺利。

最后生成 SDK 时,又卡在最后一步,没找到 dnf 这个python工具,还好通过别的命令生成了工具链,否则如果卡在编译镜像的最后一步,就麻烦大了(后面 docker 解决以上痛点)。

bitbake meta-toolchain
总之,问题很多!
几天时间,虽然开发环境问题解决了(有了docker,半天不用就能搞定),但是和 buildroot 一样,下载问题又遇到了,这次更狠,直接 30 G 资源下载(因为国内基本不使用 Yocto,即使用,imx6ull 居多,所以很难找到合适的)。

搞得鱼鹰一点脾气也没有,只能向供应商求助,拿到了他手里提前下载好的资源。

这样资源齐全了,终于可以开始编译了。

编译过程还算正常,只是相比 buildroot,编译贼慢,资源消耗极大(非常简单的一个进程,可能需要几百 M 资源,这也能看出为啥整个镜像需要100多G空间了)。

这里有个贼好用的命令,可以在出现错误时,不会立即打断,继续运行其它任务。

bitbake xxx -k

另外,推荐一个Yocto入门视频:B站:iMX6ULL采用Yocto构建嵌入式Linux系统 

总之,开发环境搭建、资源提前下载好后,编译也算相当顺利了。
三大件一个不缺,同时还能生成 SD 卡镜像。
为什么 Yocto 这么难学,资源消耗这么大,还是这么多大厂都在用?
比如 NXP、BMW、Amazon 、Facebook (Meta)、 General Electric 等。
对于现代计算机而言,资源消耗已经不是大问题,可维护性、灵活性、定制性、兼容性、生态才是首先要考虑的问题,而这些 Yocto 都具备了。
灵活性和定制性:Yocto项目提供了灵活的工具集和开发环境,允许开发者自由选择资源的使用,或者完善特定的组件(包括这些组件的特定版本)。这种灵活性使得开发者可以根据自己的需求定制Linux发行版,从而满足特定硬件平台的需求。避免重复工作:Yocto项目鼓励跨各种应用程序和设备类型的创新,支持多种硬件架构,如x86、ARM、RISC-V、PPC和MIPS等。通过共享技术、软件堆栈、配置和最佳实践,Yocto项目帮助开发者避免从零开始,减少重复工作和不必要的维护。强大的构建系统:Yocto项目的核心是BitBake,这是一个高效的任务调度器和执行系统,能够处理复杂的依赖关系,并优化构建过程。BitBake能够确保构建任务按正确的顺序执行,从而提高构建效率和可预测性。丰富的生态系统:Yocto项目拥有一个活跃的社区和丰富的文档资源,这为开发者提供了强大的支持。社区成员包括硬件制造商、操作系统供应商和独立顾问,他们共同为项目贡献资源和信息,形成了一个强大的生态系统。标准化和兼容性:Yocto项目提供了标准化的构建流程和工具,这有助于不同开发者和团队之间的协作。通过使用Yocto项目,开发者可以确保他们的定制Linux系统在不同硬件平台上具有高度的兼容性和可移植性。优化的资源利用:Yocto项目允许开发者精确地创建嵌入式设备所需的内容,只需添加设备绝对需要的功能支持或包。这有助于优化系统性能,减少不必要的资源占用,从而为嵌入式和物联网设备提供更高效的解决方案。可维护性和可扩展性:Yocto项目的设计允许用户使用自主开发的操作系统或商业操作系统,在迁移时不会丢失优化或功能。此外,商业操作系统也可以使用Yocto项目作为上游资源,从而确保最大化代码重用。支持多种构建目标:Yocto项目不仅可以用于创建Linux发行版,还可以为裸机开发生成实时操作系统(RTOS)工具链,如Zephyr项目所做的那样。
以上是 AI 给出的答案。

下面,再结合实际开发经验谈谈为什么 Yocto 大法好。

1、开发环境

docker 技术解决了环境搭建问题,因此环境搭建不再是问题。

年少不知docker好

2、可以编译各种代码

我们知道,一个项目,涉及到各种编程语言,比如 C/C++、Python、Java 等,涉及各种平台,比如 u-boot、Linux、MCU、qt,各种架构 ,arm、risc-v,x86 等,而 Yocto 可以把这些代码都编译好,放在一个压缩包里面,直接拿就行了。

而且同一套 meta,可以轻松编译 x86 和 arm,这样在没有arm板的情况下也能进行一些开发调试工作,自动化测试也更容易。

3、支持 qemu 调试

原生支持 qemu 调试,不过这一块鱼鹰没搞太懂,搞懂了,对开发效率又是一大提高了。

4、定制化

重点来了,估计这个才是各个大厂喜欢 Yocto 的原因。

很多时候,我们的工作是建立在别人的基础上,比如我想在 ubuntu 里面加一个 qt 界面。这个时候,如果已经有现成的 Ubuntu,那搞个 qt 就简单许多了。

同理类似,Yocto 项目里面有很多Linux发行版,包含各种组件(可能有几百上千个),完全可以自主添加或删除某些组件,并且这些组件版本也有社区负责维护更新。

比如,某个工具 vim 的某个版本,需要 Linux 内核某个版本以上才行,这些常用工具的兼容性,都会被处理好,你只要下载一个poky(Yocto的参考实现)发行版,指定某个版本,就能编译出整个镜像(就是下载的时候,可能又要花一些时间了,因为可能依赖的组件版本不同,需要重新下载)。芯片厂家也会在这些基础上,添加自己的特殊化定制。

另外,除了整个镜像的特殊化定制,单个组件,单条代码都能修改。最常用的,比如修改设备树、内核代码、驱动,这些都会以补丁的形式添加到基础 Linux 代码中(不会修改源码)。

而如果要升级 Linux 内核到最新版本,也非常容易,一般 poky 会同步最新内核,同时会把依赖的组件一并升级,这样在你的项目修改可能就只是一个 Poky 的一个commit 修改而已(如果修改了内核代码,可能需要同步修改一下),但是那些组件,比如 vim、nano、ssh 等工具会同步升级,不需要你关心。

Yocto生成的镜像也有多种选择,比如:

core-image-minimal:这是一个非常基础的镜像,包含必要的系统工具和Linux内核,适合作为定制更复杂系统的基础core-image-sato:这是一个为桌面环境优化的标准镜像,包含了更多的软件包和工具,适合用于桌面或展示设备core-image-full-cmdline:这个镜像包含了完整的命令行工具集,但不包含图形界面,适合需要完整命令行环境的嵌入式设备core-image-multimedia:这个镜像包含了多媒体相关的软件包,适合需要音频和视频处理能力的设备
你可以选择在这些镜像基础上添加自定义的功能。

并且如果有些组件代码,你不喜欢,也可以随时修改,这种修改不会修改源码,而是以补丁的形式修改到另一个编译环境中,这样可以保证源码的纯粹。

5、项目实用性

你有一块 Linux 板子V1,根据当前硬件适配了代码,发现有些问题,需要改硬件,变成 V2,另外可能还有其它 MCU 的代码也需要同步修改,而老版本板子也有在用。

如何处理这些依赖问题?

古老的方法是,人工维护两个环境依赖差异,高级一点通过脚本或者 repo 工具维护。

而 yocto 借助 kas 工具,可以完美处理这种情况,meta 仓库里面同一个分支可以同时拥有两款板子的信息,只要在编译前,setup 自己需要的机器类型就可以把对应的依赖处理好,再也不会出现Linux 和 mcu 不兼容情况了。

而且使用 kas 可以在 V1 的基础上进行 V2 的差异修改,只要把差异加上就行,避免重复造轮子,或拷贝或切分支。

6、SDK

可以轻松生成各种SDK,安装后适用于上层应用开发,而不需要占用太多空间,这样不会因为一个小小的功能而安装整个 Yocto 开发环境了。

标准SDK(Standard SDK):这种SDK包含了用于应用程序开发的工件,无论是引导加载程序、Linux内核开发,还是其他用户空间软件。它提供了一个交叉开发工具链和库,这些工具和库是针对特定图像优化的。你可以使用标准SDK独立开发和测试代码,这些代码旨在运行在某个目标机器上。可扩展SDK(Extensible SDK):除了包含标准SDK的所有功能外,可扩展SDK还提供了工具,允许你轻松地向图像中添加新的应用程序和库,修改现有组件的源代码,在目标硬件上测试更改,并轻松地将应用程序集成到OpenEmbedded构建系统中。可扩展SDK安装在任何机器上,并且可以用来开发应用程序、图像和内核。本地SDK(Native SDK):这种SDK的目标是在目标设备上运行,适用于那些功能足够强大的嵌入式设备,可以作为开发环境使用的情况。本地SDK包括头文件、库和工具链,允许在目标设备上直接进行应用程序的开发和测试。交叉开发SDK(Cross-development SDK):这种SDK用于在开发主机中生成目标机器的二进制文件。它包含了交叉编译工具链、库、头文件和二进制文件,以及可能的其他实用程序和应用程序。
这才是真正的大杂烩,包含了嵌入式软件所需的资源,开发、编译、调试,全给你考虑好了,你值得拥有。

7、生态

有很多meta开源,拿来就能用,很多芯片厂商也有适配 Yocto 环境,拥有众多开发者维护 Yocto,生态好。

最后说说缺点:

1、资源消耗大(每个任务都有单独的编译环境);

2、开始编译时速度非常慢,因为它需要在主机上编译各种工具;

3、入门困难,学习曲线陡峭,但适合复杂项目的维护工作;

4、资源嵌套深,不容易找,也不容易理解编译过程。

END

来源:鱼鹰谈单片机

版权归原作者所有,如有侵权,请联系删除

推荐阅读
KEIL MDK v6价格公布......
中国人竟然也能发明靠谱的编程语言!
C/C++大限将至,美国强硬要求2026年前全面剔除!

→点关注,不迷路←

嵌入式微处理器
关注嵌入式相关技术和资讯,你想知道的都在这里。
 最新文章