4、Yocto源码获取:Repo初始化、manifest仓库选择、同步源码、分支切换、常见问题处理

源码获取,是整个Yocto构建流程的第一步。这一步要是没走对,后面全是白费功夫。我见过不少新手,上来就repo sync,结果同步到一半报错,或者同步完了发现分支不对,又得重来。

说白了,Yocto的源码管理,核心就是Google的Repo工具。它不直接管理代码,而是管理一堆Git仓库。你想想看,一个完整的Yocto BSP,动辄上百个Git仓库,一个个手动git clone,那得搞到猴年马月?Repo就是干这个的——它通过一个manifest清单文件,告诉你该拉哪些仓库、拉哪个分支、放到哪个目录。

核心逻辑: Repo + Manifest = 批量Git仓库管理方案。Manifest是“菜单”,Repo是“服务员”,你只需要告诉服务员你要哪个菜单(哪个XML文件),他就能帮你把菜(源码)全部端上来。

Yocto 源码获取核心流程 安装 Repo 工具 选择 Manifest 仓库 repo init 初始化 repo sync 同步 分支切换 常见问题处理 提示:Manifest 仓库决定了你拉取的是哪个厂商、哪个版本的 BSP。选错 Manifest,后面全错。

4.1 安装Repo工具

大多数Linux发行版不会预装Repo。你得手动装。我个人习惯把它放在~/bin目录下,这样不影响系统全局。

# 创建本地bin目录(如果不存在)
mkdir -p ~/bin

# 下载Repo脚本
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo

# 赋予执行权限
chmod a+x ~/bin/repo

# 将~/bin加入PATH(建议写入~/.bashrc)
export PATH=$PATH:~/bin

小技巧: 国内网络环境,Google的源可能很慢。你可以用清华或中科大的镜像源:

# 使用清华镜像
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo

4.2 选择Manifest仓库

Manifest仓库,就是那个包含default.xml的Git仓库。Rockchip官方、第三方BSP厂商、甚至你自己公司,都可能维护着不同的Manifest。

以Rockchip官方Yocto BSP为例,常用的Manifest仓库有:

Manifest仓库地址 适用平台 说明
https://github.com/rockchip-linux/repo.git RK3399 / RK3288 / RK3568 等 Rockchip官方维护,分支对应不同Linux内核版本
https://github.com/radxa/manifests.git Radxa系列开发板 第三方厂商定制,通常包含更多板级配置
https://github.com/amarula/rockchip-manifests.git 通用Rockchip平台 Amarula社区维护,更新较快

嗯,这里要注意。Manifest仓库的分支决定了你拉取的BSP版本。比如Rockchip官方repo仓库,master分支可能对应最新的开发版,而linux-5.10分支对应稳定版。我在项目中遇到过,有人拉了master分支,结果编译到一半发现某个驱动接口变了,折腾了两天才定位到问题。

避坑指南: 选择Manifest仓库时,先确认它是否包含你目标芯片的machine配置。比如你要做RK3588,但Manifest里只有RK3399的配置,那后面编译时会直接报错。我曾经因为这个浪费了半天时间。

4.3 repo init 初始化

选好Manifest仓库后,就可以初始化了。命令格式如下:

# 基本格式
repo init -u <manifest仓库URL> -b <分支名> -m <manifest文件名>

# 示例:拉取Rockchip官方RK3568的Yocto BSP(基于Linux 5.10)
mkdir rk3568-yocto
cd rk3568-yocto
repo init -u https://github.com/rockchip-linux/repo.git -b linux-5.10 -m rockchip-yocto.xml

几个参数的含义:

  • -u:Manifest仓库的URL
  • -b:指定仓库的分支(不是BSP的分支,是Manifest仓库本身的分支)
  • -m:指定使用哪个XML文件。如果不指定,默认用default.xml

执行成功后,会在当前目录生成一个.repo隐藏目录。这个目录里包含了Manifest仓库的克隆和Repo的配置信息。你可以进去看看:

ls -la .repo/
# 你会看到 manifest.xml(指向实际manifest的软链接)
#         manifests/(manifest仓库的完整克隆)
#         repo/(repo工具自身的副本)

关键点: repo init 只是初始化了Repo环境,并没有下载任何BSP源码。它只下载了Manifest仓库本身。真正的源码下载,在下一步。

4.4 repo sync 同步源码

这是最耗时的一步。执行后,Repo会根据Manifest文件中的描述,逐个克隆或拉取所有Git仓库。

# 同步所有仓库(默认4个并发任务)
repo sync

# 如果你网络不错,可以增加并发数
repo sync -j8

# 如果中途断了,重新执行会自动断点续传
repo sync --force-sync

同步完成后,你会看到当前目录下出现了大量子目录。比如poky/、meta-openembedded/、meta-rockchip/、meta-qt5/等等。这些就是Yocto的各个layer。

为什么会这么慢?因为Yocto的源码量确实大。一个完整的Rockchip BSP,包括Poky核心层、OpenEmbedded层、Rockchip硬件适配层、Qt图形层等,加起来可能有几十个Git仓库,总大小超过10GB。我第一次同步时,用了将近两个小时。

加速技巧:

  • 使用国内镜像源(如清华、中科大)替换Google的Git源
  • 如果公司有GitLab,可以先把Manifest和所有子仓库镜像到内网
  • 用 repo sync -c 只同步当前分支,不同步所有远程分支,能省不少时间

4.5 分支切换

同步完成后,你可能需要切换到特定的开发分支。比如官方BSP默认拉取了linux-5.10分支,但你想试试linux-6.1的实验性分支。

分支切换有两种方式:

方式一:重新init + sync(推荐)

# 重新初始化,指定新分支
repo init -u https://github.com/rockchip-linux/repo.git -b linux-6.1 -m rockchip-yocto.xml

# 强制同步,覆盖本地修改
repo sync --force-sync

方式二:手动切换(不推荐,容易漏仓库)

# 遍历所有仓库切换分支
repo forall -c 'git checkout linux-6.1'

我个人强烈建议用方式一。为什么?因为Manifest文件里可能对不同仓库指定了不同的分支或提交ID。手动切换很容易漏掉某个仓库,导致编译时出现莫名其妙的版本不匹配错误。我在项目中吃过这个亏,后来就老老实实重新init了。

注意: 如果你在某个子仓库里有未提交的修改,repo sync --force-sync 会强制覆盖。建议先 repo status 检查一下本地状态,或者用 git stash 暂存修改。

4.6 常见问题处理

源码获取阶段,我遇到过的坑不少。挑几个典型的说说:

问题现象 原因 解决方法
fatal: unable to access '...' 网络不通,或Git服务器被墙 换镜像源,或配置代理
repo sync 卡在 99% 某个子仓库的tag或commit不存在 按 Ctrl+C 中断,检查Manifest中指定的commit是否有效
error: revision refs/tags/xxx not found Manifest中指定的tag在远程仓库中不存在 联系BSP提供商确认tag名称,或改用分支名
repo init 报错 "fatal: Not a git repository" 当前目录不是空目录,或已有.repo目录 换一个空目录,或先 rm -rf .repo 再重试

我的经验: 遇到网络问题,别死磕。先检查 git ls-remote 能不能访问到Manifest仓库。如果连不上,换源或挂代理。如果连得上但同步慢,用 repo sync -j1 单线程跑,虽然慢但稳定,不容易断。

还有一个容易被忽略的问题:磁盘空间。Yocto源码加上后续的编译缓存,轻松吃掉50GB以上。我建议至少预留100GB的空闲空间。用 df -h 先看一眼,别等到编译到一半报磁盘满才后悔。

好了,源码获取这块,核心就是记住三步:装Repo → 选Manifest → repo init + sync。分支切换尽量用重新init的方式,别偷懒。网络问题多准备几个镜像源做备用。把这些搞定了,后面的编译工作才能顺利开展。