ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

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

2026/9/19 7:30:53 拓冰建站 浏览量
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目录约15GBtmp/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或者zstdsudo 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 --versiongcc的版本要8.x以上python3要3.8以上。目前Ubuntu 20.04自带的gcc 9和python 3.8都满足。如果repo --version提示找不到命令说明apt源里没有打包就转到下一步手动安装repo脚本。注意不要在host机器上使用系统自带的python2也不要手工把默认python3改成python2Yocto从Dunfell开始已经全面切换到python3。2.3 单独安装repo脚本的方式apt源里的repo可能停留在较老版本在执行repo sync时会出现Unknown command syntax这类解析错误。所以更稳的方式是手动放repo脚本到/usr/local/bincurl -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.0imx-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文件。如果你不写-mrepo会默认取分支下的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的imx6ullfsl-imx-fb更轻量不引入weston和wayland的依赖带GPU的imx6dl/qp则建议用fsl-imx-xwayland它同时提供X11和Wayland的backend后期测试Qt应用更方便。脚本执行后当前目录会切到build-imx6。之后每次新开终端构建都要回到源码树根目录执行cd ~/imx6-yocto source setup-environment build-imx6setup-environment是上面那个脚本复制到build目录里的它修改变量让bitbake从当前目录读取conf/local.conf。如果提示找不到setup-environment可以检查它是否被加上了执行权限或者直接bash setup-environment build-imx6但同一条规则环境变量只对子进程和后续命令有效必须用source才不会丢失。4. 配置imx6的local.confMACHINE、并行度与缓存路径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 imx6ulevkMACHINE写错时最容易观察到的现象是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 构建目标选哪个镜像并开始bitbakeimx6有两个常见的镜像目标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 iftmp/deploy/images/imx6ulevk/imx-image-core-imx6ulevk.wic of/dev/sdb bs1M convfsync statusprogress sudo syncbs1M的块大小和convfsync保证数据写穿到设备后再返回避免拔出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阶段才因空间不足而失败。本文还有配套的精品资源点击获取