news 2026/9/19 7:30:48

imx6 Yocto环境搭建实战:从主机准备到SD卡镜像生成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
imx6 Yocto环境搭建实战:从主机准备到SD卡镜像生成

简介:面向嵌入式Linux开发者的i.MX6开发环境搭建指南,以Yocto项目为主线,详细覆盖从Ubuntu系统版本选择、依赖软件包安装、Repo工具配置到环境初始化与编译的完整流程,特别适合因常规Qt5移植后无法运行eglfs而决定转向Yocto方案的开发者。包内为1个docx文档,约4.12MB,内容按安装准备、Repo设置、Yocto工程初始化与编译等阶段组织,给出Ubuntu 14.04/12.04下的安装要点、120G硬盘空间建议、必备依赖包命令、非root用户权限处理、Repo获取及国内镜像替代方式,命令与说明并排呈现,可直接对照执行。文档还针对Ubuntu 12.04 git版本过低、下载Repo需要访问Google等实际障碍提供了替代思路,并给出可复制的初始化与同步命令。目前已有1080人学习下载,适合刚接触i.MX6的嵌入式开发者快速搭建可用环境,减少环境配置中的反复试错成本。

1. imx6的Yocto环境先想清楚再动手

很多拿到imx6核心板的人都会先搜“imx6开发环境搭建”,然后一头扎进Yocto的文档里。这件事的复杂度不在bitbake命令本身,而在主机环境、BSP分支和构建配置三者的耦合:同一个MACHINE值在不同DISTRO下会拉出不同的GPU驱动和weston版本,同一份源码在Ubuntu 18.04和22.04上也会有OpenSSL库兼容性的差异。我在搭建imx6 Yocto环境时最直观的感受是,只要第一次正确地把repo同步干净、把local.conf里的缓存路径指向独立磁盘,后续的kernel和rootfs迭代完全可以做到分钟级。这里就把从空白Ubuntu到产出SD卡启动镜像的完整路径写清楚,适合正在做NXP i.MX6平台驱动移植的工程师,也给需要在多台机器间复用构建缓存的人一些可落地的参数。

2. 为imx6的Yocto构建准备主机环境与基础依赖

imx6的Yocto构建本质是在主机上跑一套BitBake任务流:先下载数百个上游源码包,再用交叉编译工具链把它们编成目标平台的二进制,最后通过rootfs组装出镜像。主机环境只要有一项不满足,任务就会在某个package的configure阶段以奇怪的方式失败,比如gcc版本太高导致stdio.h里的glibc符号检查报错,又或者缺了chrpath导致后续打包阶段找不到rpath工具。

2.1 磁盘、内存与Ubuntu版本怎么选

我一般优先用Ubuntu 20.04 LTS作为构建机系统。原因不是它最新,而是Yocto的Kirkstone和Dunfell发行版在20.04上被验证得最多;22.04的OpenSSL 3.0会让一些使用旧签名脚本的BSP在执行rootfs的加密钩子时报EVP_PKEY_CTX相关的接口错误。如果你已经用了22.04,不是一定失败,但如果同一套源在20.04上正常,就不要在22.04上耗时排查。

磁盘方面,一个imx6的full镜像完整构建后,deploy目录约15GB,tmp/work里的解包源码和工作目录可达60GB,加上downloads和sstate,整机预留180GB比较安心。我曾在120GB的机器上构建imx6,最后在打包rootfs的do_image_wic任务上被空间耗尽中断,那种进度损失比慢还难受。机械硬盘也不是不行,但Yocto有大量小文件随机读写,会让构建时间从3小时拉到6小时以上,建议至少用SATA SSD。

项目最低要求推荐配置说明
操作系统Ubuntu 18.04 / 20.04Ubuntu 20.04 LTS22.04 在部分BSP上有OpenSSL兼容问题
磁盘120GB180GB SSDtmp/work占大头,deploy约15GB
内存8GB16GB并行任务多时gcc开销大

内存按并行任务数线性增长。bitbake默认会根据CPU核心数起任务,每个gcc任务约占500MB到1GB内存。16GB内存配合4到6个任务是比较稳的配置;8GB机器强行构建会出现virtual memory exhausted: Cannot allocate memory,解决方式不是加swap,而是把PARALLEL_MAKE降为-j 2。另外一个容易忽略的点是/tmp分区也要留出至少10GB,某些包在编译时会直接在TMPDIR里做临时文件写入。

常见做法里有人用Docker容器来隔离构建环境,减少污染宿主机。但Yocto的构建需要访问/dev下的loop设备用于wic镜像的mkfs操作,容器里要额外给--device映射,而且sstate缓存挂载到容器时要注意属主和umask问题。普通单机开发直接用宿主机构建,维护成本更低。

2.2 用apt安装基础依赖包

Ubuntu 20.04最小安装后,需要先把Yocto所需的基础工具补齐。NXP官方手册里的依赖清单针对Ubuntu版本做了区分,常见的做法就是一次性装全,避免在某次构建中途发现缺chrpath或者zstd:

sudo apt update sudo apt install -y gawk wget git-core diffstat unzip texinfo \ 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 \ repo rsync curl zstd

这里逐项说明一下关键包的作用:gawk比默认的mawk更贴近Yocto中大量使用的awk语法;chrpath用于修改二进制文件的rpath,在打包SDK时几乎必用;socat被runqemu脚本用来建立串口和网络隧道;python3-git和python3-jinja2是bitbake服务端解析配置所依赖的Python库。repo在Ubuntu的universe源里有,但如果apt装不上,也可以跳过这一项改用下载脚本的方式。

安装完成后用下面三组命令确认版本:

gcc --version | head -n 1 python3 --version repo --version

gcc的版本要8.x以上,python3要3.8以上。目前Ubuntu 20.04自带的gcc 9和python 3.8都满足。如果repo --version提示找不到命令,说明apt源里没有打包,就转到下一步手动安装repo脚本。

注意:不要在host机器上使用系统自带的python2,也不要手工把默认python3改成python2,Yocto从Dunfell开始已经全面切换到python3。

2.3 单独安装repo脚本的方式

apt源里的repo可能停留在较老版本,在执行repo sync时会出现Unknown command syntax这类解析错误。所以更稳的方式是手动放repo脚本到/usr/local/bin:

curl -sSL https://storage.googleapis.com/git-repo-downloads/repo -o /usr/local/bin/repo chmod +x /usr/local/bin/repo repo --version

参数说明:-sSL中的三个flag分别表示静默、跟随重定向、出错时显示错误,用于保证下载过程不输出多余进度且能拿到最终内容。脚本不依赖安装包,运行时自动查找系统的git、python3。首次执行repo命令时,它会自动生成~/.repoconfig目录用于存放同步状态,这些残留文件在重新初始化不同manifest时需要手动删除,否则可能出现缓存的认证信息指向旧服务器。

到这里,主机环境基本就绪。下一章进入源码树的拉取阶段,这也是整个imx6开发环境搭建中最容易被网络和分支问题卡住的一步。

3. 用repo拉取imx6的Yocto BSP源码树与选定分支

3.1 manifest与分支命名规则

NXP的i.MX Yocto BSP在github的nxp-imx组织下维护了imx-manifest仓库,里面以XML文件的方式记录每一个组件的git仓库地址和revision。执行repo init只需要解析一份manifest,之后repo sync会按这份清单把上百个仓库并行克隆到本地。理解这个机制,你就知道为什么改分支比切分支更干净——直接在master分支上看不到的meta层,只有在指定manifest后才会被拉到。

分支命名规则有一个需要区分的点:imx-linux-kirkstone是Yocto发行版分支,对应Yocto 4.0;imx-linux-dunfell对应Yocto 3.1。NXP再按季度发布带版本号的manifest,比如imx-5.15.71-2.2.0.xml固定了kernel 5.15和u-boot 2022.04的组合。日常开发如果不想追新,直接锁定某个LTS版本xml是更稳妥的。

manifest分支Yocto版本kernel示例适用场景
imx-linux-dunfell3.15.4.x老项目维护、Qt 5.15兼容性稳定
imx-linux-kirkstone4.05.15.x新设计推荐,支持周期更久

初始化源码树的命令我建议把工作目录和构建目录分开,目录名不要带空格:

mkdir -p ~/imx6-yocto && cd ~/imx6-yocto repo init -u https://github.com/nxp-imx/imx-manifest \ -b imx-linux-kirkstone -m imx-5.15.71-2.2.0.xml

参数说明:-u指定manifest仓库的git地址;-b指定要跟踪的分支;-m指定该分支下的xml文件。如果你不写-m,repo会默认取分支下的default.xml,而default.xml通常是一个重定向文件,它会include最近一次正式发布的版本xml。对于开发环境搭建,我建议每次都用-m锁定,这样不同机器的同步结果一致,排查构建问题时不会出现“同一个版本但源码不同”的尴尬。

3.2 执行repo sync并确认meta层

初始化完成后执行同步。-j是并发任务数,不是越快越好:

repo sync -j4

-j4表示最多同时启动4个git fetch任务。在带宽充足时-j8可以缩短总时长,但会更容易被GitHub的并发连接限制盯上而报RPC failed; curl 56 OpenSSL SSL_read。如果同步中断,直接再次执行同一命令即可,repo会跳过已经完成的仓库,不会重复拉取。需要留意的是,repo sync结束后要确认所有仓库都已检出到manifest指定的提交:

repo status | grep -E '^\-\-' | wc -l

理论上这个输出是0。如果出现非零行,说明某个仓库没有完全同步,可以针对那个项目单独再跑repo sync sources/meta-imx。

同步完成后检查sources目录下的记录:

ls sources/

常见会看到meta-imx、meta-freescale、meta-openembedded等多层名字。其中meta-imx是NXP的官方层,meta-freescale是社区维护的freescale层,meta-openembedded是OE社区层。在imx6相关配置里,实际起作用的是meta-imx和meta-freescale的BSP层,它们通过conf/layer.conf里的BBFILES把下一层的recipes整合进来。如果看到一个meta层但它的依赖层不在sources里,通常是因为manifest没包含它,需要回到manifest里追加,而不是手动往sources里塞。

3.3 初始化构建环境脚本

源码树根目录下会有imx-setup-release.sh脚本,它干的事情比较多:创建build目录、在conf目录生成local.conf、bblayers.conf,并把Yocto的初始化脚本oe-init-build-env的上下文带入当前shell。

source imx-setup-release.sh -b build-imx6 -d fsl-imx-xwayland

这里的source不能换成bash去执行,因为脚本里的export命令要在当前shell生效,构建时bitbake才能找到交叉编译工具链的环境变量。-b build-imx6指定在源码树根目录下生成build-imx6作为构建目录;-d fsl-imx-xwayland指定DISTRO。对于不带GPU的imx6ull,fsl-imx-fb更轻量,不引入weston和wayland的依赖;带GPU的imx6dl/qp则建议用fsl-imx-xwayland,它同时提供X11和Wayland的backend,后期测试Qt应用更方便。

脚本执行后,当前目录会切到build-imx6。之后每次新开终端构建,都要回到源码树根目录,执行:

cd ~/imx6-yocto source setup-environment build-imx6

setup-environment是上面那个脚本复制到build目录里的,它修改变量让bitbake从当前目录读取conf/local.conf。如果提示找不到setup-environment,可以检查它是否被加上了执行权限,或者直接bash setup-environment build-imx6,但同一条规则:环境变量只对子进程和后续命令有效,必须用source才不会丢失。

4. 配置imx6的local.conf:MACHINE、并行度与缓存路径

4.1 MACHINE怎么对应你的板子

MACHINE变量告诉bitbake要为目标板卡的哪个SoC平台生成设备树和引导配置。imx6系列几个常见值的含义要记清楚:imx6qpsabresd是i.MX6QP的SABRE开发板,imx6qsabresd是i.MX6Q四核,imx6dlsabresd是i.MX6DL双核,imx6ulevk则是i.MX6UL/6ULL的评估板。在build-imx6/conf/local.conf里找到MACHINE这一行并修改:

MACHINE = "imx6ulevk"

MACHINE写错时最容易观察到的现象是:bitbake能进入解析阶段,但会提示No recipes available for: ...或者The following machine descriptions are not found,因为meta-imx-bsp/conf/machine目录下找不到对应的*.conf。也有写错后不报错的情况,比如把imx6ulevk写成imx6ulev,最终生成的设备树是imx6ul-14x14-evk.dtb,而板子实际需要的是imx6ull-14x14-evk.dtb,烧进去后控制台无输出。所以修改后先执行一次bitbake -e | grep MACHINE确认环境变量生效。

MACHINE值SoC设备树示例常见载体
imx6qpsabresdi.MX6QPimx6qp-sabresd.dtbSABRE开发板
imx6qsabresdi.MX6Qimx6q-sabresd.dtb四核板卡
imx6ulevki.MX6UL/ULLimx6ull-14x14-evk.dtb评估板、自研板

如果你的板子是自研的,正确的做法不是改原厂MACHINE值,而是创建自己的meta层,在layer.conf里设置MACHINE = "myboard",然后在该层的conf/machine/myboard.conf里通过require包含原厂的imx6ulevk.conf,再用KERNEL_DEVICETREE覆写设备树路径。这样原厂升级BSP时,你的板级配置可以通过git合并最小冲突。

4.2 并行度和内存的匹配关系

Yocto的并行分为BitBake任务级和make进程级两层。BB_NUMBER_THREADS控制同时执行多少recipe任务,PARALLEL_MAKE控制每个任务内部make用几个进程。两者都设成CPU核心数,在编译Linux内核或glibc时会在短时间内叠加出几倍的内存请求。我给它们的默认建议是:

BB_NUMBER_THREADS ?= "${@os.cpu_count()}" PARALLEL_MAKE ?= "-j 4"

?=的语义是“如果变量尚未被赋值才赋值”,这样如果后续meta层通过local.conf追加了不同值,不会被这里覆盖。os.cpu_count()是Python表达式,bitbake会在解析时读取宿主机的逻辑核心数。如果你的机器是4核8线程,BB_NUMBER_THREADS会是8,但PARALLEL_MAKE固定为4,在内存16GB时刚好;如果内存只有8GB,建议把BB_NUMBER_THREADS也手动改成4并给PARALLEL_MAKE降为-j 2。

一个常见误区是以为-j参数越大构建越快。实际上当CPU占用率达到100%后,再增加任务只会增加内存带宽和进程切换开销。观察构建是否过载的简单方法是开第二个终端跑htop,如果看到多个gcc进程的总内存超过物理内存,立刻bitbake -k结束本次构建,调低后重来。

4.3 DL_DIR和SSTATE_DIR的路径规划

DL_DIR存放所有从网络下载的源码压缩包,SSTATE_DIR存放编译生成的缓存。它们默认落在构建目录里,但如果你隔几天清理一次build目录,缓存的损失很可惜。把它们指向固定路径:

DL_DIR = "/data/yocto/downloads" SSTATE_DIR = "/data/yocto/sstate-cache"

两个路径需要在local.conf的注释区之外设置,建议写在文件末尾。DL_DIR的粒度是源码包,完全可以跨MACHINE跨DISTRO复用;SSTATE_DIR则绑定了MACHINE和DISTRO的组合,换一个DISTRO后,新DISTRO的构建仍会把旧缓存当作无效缓存自动跳过。需要说明的是:如果你启用了SSTATE_MIRRORS指向局域网内的sstate服务器,那么SSTATE_DIR本地的优先级更高,镜像只是回退选项。

这里补一个安全且常用的离线构建技巧:主机无法访问外网时,找一台能联网的机器先构建同一个manifest,然后整个拷贝它的downloads目录。Yocto在fetch阶段会先查找DL_DIR里是否存在同名压缩包,存在就跳过网络访问。downloads目录的优点是同一份源码包在多次构建中可以复用,不需要担心任务间的变更。

4.4 构建目标选哪个镜像并开始bitbake

imx6有两个常见的镜像目标:imx-image-core是一个精简的串口控制台镜像,包含busybox、网络工具和基础库,适合验证串口和网络驱动;imx-image-full会在core的基础上加入weston、GStreamer和多媒体编解码组件,体积更大。第一次构建强调验证流程,直接选core即可,避免把GUI依赖的编译时间计入排错周期。

bitbake imx-image-core

执行后第一个阶段是解析全部layer,命令行会卡在Loading cache较长时间,这是正常的。日志进入recipe任务阶段后,可以打开tmp/log/cooker/下的log观察执行进度。若想边编译边看log实时输出,另开终端:

tail -f tmp/work/*/*/temp/log.do_compile

如果构建中途失败,bitbake会在终端打印最后的错误任务名,比如ERROR: Task (virtual:.../linux-imx_5.15.bb:do_compile) failed。不要盲目重跑,先看对应构建目录temp/log.do_compile的最后几十行,大多数configure: error: C compiler cannot create executables这类报错都能从这里定位到缺少的依赖或错误的MACHINE值。

5. 从部署目录取出imx6镜像并复用sstate加速二次构建

5.1 定位镜像文件并完成烧录验证

构建成功后,所有产物汇聚在tmp/deploy/images/ /。以imx6ulevk为例,你要找的是imx-image-core-imx6ulevk.wic这个SD卡镜像,它既包含u-boot、设备树和kernel,也包含rootfs分区。先用file命令确认格式:

file tmp/deploy/images/imx6ulevk/imx-image-core-imx6ulevk.wic

正常输出会识别为DOS/MBR boot sector或filesystem数据,说明镜像头部已经有分区表。接着用lsblk确认SD卡设备名,比如/dev/sdb,然后执行:

sudo dd if=tmp/deploy/images/imx6ulevk/imx-image-core-imx6ulevk.wic of=/dev/sdb bs=1M conv=fsync status=progress sudo sync

bs=1M的块大小和conv=fsync保证数据写穿到设备后再返回,避免拔出SD卡时缓存未落盘。烧录后插入板卡,正常情况下串口输出能直接看到U-Boot启动,然后进入内核。这一步才真正验证了MACHINE配置和BSP版本没有跑偏。

5.2 sstate增量复用与rm_work的取舍

二次开发时的效率提升比首次构建更值得关注。修改了kernel配置后,直接在build目录再次bitbake imx-image-core即可,bitbake会以do_kernel_configcheck的任务调度让人以为它要重新编译整个内核,实际它的任务生命周期判断准确到单个recipe。不要习惯性使用bitbake -c cleanall linux-imx,除非你确定要放弃该recipe的所有缓存。

还有一个实用技巧是往local.conf里加INHERIT += "rm_work",它会在每个recipe完成构建后删除工作目录里的临时源码,只保留镜像和日志。这对长期构建能省下接近一半的磁盘,但会失去在tmp/work里手动调试编译问题的机会。如果你更看重调试体验,建议不加,而是定期用bitbake -c clean清理特定组件。

最后一招是给bitbake设置磁盘监控,防止第2章提到的磁盘写满问题再现:

BB_DISKMON_DIRS = "1G;100M;${DL_DIR} 1G;100M;${SSTATE_DIR}"

这个变量让bitbake在磁盘剩余低于1G时停止新任务,低于100M时直接abort,避免在do_image_wic阶段才因空间不足而失败。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 7:30:17

OpenClaw 模型返回 401?TaoToken 这样改 openclaw.json 的 baseUrl

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 7:29:33

WPF开发进阶:资源、样式与触发器深度解析

1. WPF UI开发核心三要素概述在桌面应用开发领域,WPF(Windows Presentation Foundation)始终保持着强大的生命力。作为.NET生态中最成熟的UI框架之一,其独特的资源系统与样式机制让界面开发效率产生质的飞跃。我经历过多个WPF大型…

作者头像 李华
网站建设 2026/9/19 7:27:05

FO开发环境搭建:VS2019版本锁定与Model创建避坑指南

1. 这不是“装个VS就能跑”的事:F&O开发者的第一个真实门槛Dynamics 365 Finance and Operations(简称F&O)的开发,从来就不是点开Visual Studio、新建一个项目、按F5就能跑通的轻量级体验。它是一套高度集成、强依赖、版本…

作者头像 李华
网站建设 2026/9/19 7:26:56

工控协议深度扫描:从Modbus TCP到S7comm的指纹识别实战

简介:一套聚焦工业互联网安全测试的PPT课件,系统讲解工控协议基础与扫描插件应用,面向工业控制系统安全测试人员、网络安全学习者及工业网络运维工程师。内容涵盖EPA现场总线标准、Ethernet/IP报文类型、Modbus TCP通信体系结构等关键协议&am…

作者头像 李华
网站建设 2026/9/19 7:26:19

移动端开发工具选型与跨平台技术实践指南

1. 移动端开发工具全景概览在智能手机普及率达到78%的今天,移动应用开发已成为技术领域的热门方向。作为一名经历过从原生开发到跨平台技术演进的老兵,我见证了开发工具从单一平台走向多元融合的完整历程。目前主流的移动端开发工具大致可分为三类&#…

作者头像 李华