大家好,我是鱼鹰。
1、buildroot辛酸史
在此之前,领导刚刚让鱼鹰学习了 buildroot 编译内核镜像,因为我们有个老项目的镜像就是用它编译的。
以前这些镜像都是老外维护(鱼鹰目前在世界500强外企工作),我们只要从指定地址获取镜像,用工具烧录SD卡镜像就行。
后面领导想国内也能维护镜像,能自己编译镜像,于是让鱼鹰学习镜像编译(以前和领导聊过发展方向,知道鱼鹰想往 Linux 方向发展,因此给了机会)。
Buildroot 很多年前鱼鹰也了解过,也编译过,感觉不是特别难,觉得任务应该很快能完成。
但没想到,搞了半个多月才搞定,印象最深刻的就是 2.5 G左右的开源资源下载。以前编译镜像时,从来没遇到这些问题,都是半天到一天左右就搞定了。
现在想想,有这两点原因:
1、那些年,github 可以正常上网,很多国外资源都能轻松下载。
2、目前的镜像依赖的开源库太多,也太老了,以前只是为了学习Linux内核,只要基础的组件就行。
因此很顺利编译 uboot、内核、文件系统(镜像三大件)。
现在有些资源下载实在太慢,只能各种找资源,另外从 gitee 中转,总算是下载完成了(还好支持离线下载安装方式)。
但是 qt 这个功能最终还是没装上,不知道啥原因,因为不重要,就没管了。
另外,很多资源有指定的 hash 值,你只能下载相同 hash 值的资源,否则即使你修改了 hash 值适配新资源,最终可能导致系统不兼容。
2、Yocto苦难史
IMX_YOCTO_PROJECT_USERS_GUIDE.pdf
最后生成 SDK 时,又卡在最后一步,没找到 dnf 这个python工具,还好通过别的命令生成了工具链,否则如果卡在编译镜像的最后一步,就麻烦大了(后面 docker 解决以上痛点)。
bitbake meta-toolchain
搞得鱼鹰一点脾气也没有,只能向供应商求助,拿到了他手里提前下载好的资源。
这样资源齐全了,终于可以开始编译了。
编译过程还算正常,只是相比 buildroot,编译贼慢,资源消耗极大(非常简单的一个进程,可能需要几百 M 资源,这也能看出为啥整个镜像需要100多G空间了)。
这里有个贼好用的命令,可以在出现错误时,不会立即打断,继续运行其它任务。
bitbake xxx -k
另外,推荐一个Yocto入门视频:B站:iMX6ULL采用Yocto构建嵌入式Linux系统
灵活性和定制性:Yocto项目提供了灵活的工具集和开发环境,允许开发者自由选择资源的使用,或者完善特定的组件(包括这些组件的特定版本)。这种灵活性使得开发者可以根据自己的需求定制Linux发行版,从而满足特定硬件平台的需求。
避免重复工作:Yocto项目鼓励跨各种应用程序和设备类型的创新,支持多种硬件架构,如x86、ARM、RISC-V、PPC和MIPS等。通过共享技术、软件堆栈、配置和最佳实践,Yocto项目帮助开发者避免从零开始,减少重复工作和不必要的维护。
强大的构建系统:Yocto项目的核心是BitBake,这是一个高效的任务调度器和执行系统,能够处理复杂的依赖关系,并优化构建过程。BitBake能够确保构建任务按正确的顺序执行,从而提高构建效率和可预测性。
丰富的生态系统:Yocto项目拥有一个活跃的社区和丰富的文档资源,这为开发者提供了强大的支持。社区成员包括硬件制造商、操作系统供应商和独立顾问,他们共同为项目贡献资源和信息,形成了一个强大的生态系统。
标准化和兼容性:Yocto项目提供了标准化的构建流程和工具,这有助于不同开发者和团队之间的协作。通过使用Yocto项目,开发者可以确保他们的定制Linux系统在不同硬件平台上具有高度的兼容性和可移植性。
优化的资源利用:Yocto项目允许开发者精确地创建嵌入式设备所需的内容,只需添加设备绝对需要的功能支持或包。这有助于优化系统性能,减少不必要的资源占用,从而为嵌入式和物联网设备提供更高效的解决方案。
可维护性和可扩展性:Yocto项目的设计允许用户使用自主开发的操作系统或商业操作系统,在迁移时不会丢失优化或功能。此外,商业操作系统也可以使用Yocto项目作为上游资源,从而确保最大化代码重用。
支持多种构建目标:Yocto项目不仅可以用于创建Linux发行版,还可以为裸机开发生成实时操作系统(RTOS)工具链,如Zephyr项目所做的那样。
下面,再结合实际开发经验谈谈为什么 Yocto 大法好。
1、开发环境
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
→点关注,不迷路←