3. 源码获取与Repo管理:RK3568 Linux SDK下载、Repo仓库初始化、分支切换、同步代码

做嵌入式Linux开发,第一步就是拿到源码。RK3568的SDK不像某些MCU开发包那样一个压缩包搞定,它是由上百个Git仓库组成的。你想想看,一个完整的BSP包含U-Boot、Kernel、Buildroot/Yocto、RK的专有库、工具链……如果全塞在一个仓库里,光是git log就能卡死你。

Google搞了个Repo工具来管理这种多仓库项目。说白了,Repo就是一堆Git仓库的管家。我刚开始接触时也觉得多此一举,直到有一次手动拉了30多个仓库,发现版本对不上,编译直接报错……嗯,从那以后我再也不敢跳过Repo了。

3.1 SDK整体结构

先看看RK3568 SDK长什么样。你从Rockchip官方或合作伙伴拿到SDK后,目录结构大致如下:

rk3568_linux_sdk/
├── .repo/          # Repo的元数据,别手贱去改
├── u-boot/         # 引导加载程序
├── kernel/         # Linux内核(5.10或4.19)
├── buildroot/      # Buildroot构建系统
├── device/         # 设备配置文件
├── external/       # 第三方库
├── rkbin/          # Rockchip的二进制固件
├── tools/          # 烧录、打包工具
└── docs/           # 文档(虽然经常过时)

这里面最关键的是.repo/目录。它记录了所有仓库的地址、分支、以及当前应该同步到哪个commit。我见过有人直接把.repo删了,然后手动一个一个clone……结果折腾了两天,版本还是对不上。

警告:千万不要手动修改.repo/manifest.xml里的commit SHA值,除非你清楚自己在做什么。我曾经为了“修复”一个bug直接改了manifest,结果整个团队的代码基线全乱了,花了半天才回滚。

3.2 安装Repo工具

Repo本身是一个Python脚本。安装很简单:

# 创建bin目录(如果还没有)
mkdir -p ~/bin

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

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

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

国内网络环境你懂的。如果连不上Google的服务器,可以用清华或中科大的镜像:

# 清华镜像
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'

# 或者中科大镜像
export REPO_URL='https://gitlab.com/nicolaiort/repo.git'

我个人习惯把REPO_URL写进~/.bashrc,省得每次都要export。你想想看,万一哪天忘了设这个环境变量,拉一半卡住了,多耽误时间。

3.3 初始化Repo仓库

拿到SDK的压缩包或者知道manifest仓库地址后,开始初始化:

# 创建工作目录
mkdir rk3568_sdk
cd rk3568_sdk

# 初始化(使用默认manifest)
repo init -u https://github.com/rockchip-linux/manifests -b master

# 如果指定分支(比如某个release版本)
repo init -u https://github.com/rockchip-linux/manifests -b rk356x_linux_release_v1.4.0

repo init做了什么?它其实只干了两件事:

  1. 在.repo/目录下clone你指定的manifest仓库
  2. 根据manifest文件生成所有子仓库的清单

这时候你去看.repo/manifest.xml,里面就是所有仓库的列表和它们应该对应的commit。我建议你打开看一眼,理解一下结构:

<manifest>
  <remote name="rockchip" fetch="https://github.com/rockchip-linux" />
  <default revision="refs/tags/rk356x_linux_release_v1.4.0" />
  <project path="kernel" name="kernel" />
  <project path="u-boot" name="u-boot" />
  <project path="buildroot" name="buildroot" />
  ...
</manifest>
小技巧:如果你在公司内网开发,可以自己搭建manifest仓库,把fetch地址改成内网GitLab地址。这样团队所有人都能统一代码源,避免“在我机器上能编译”的尴尬。

3.4 同步代码

初始化完成后,开始拉取真正的源码:

# 同步所有仓库(第一次会拉很久)
repo sync

# 如果网络不稳定,可以加参数
repo sync -j4 --fail-fast

# 只同步部分仓库(节省时间)
repo sync kernel u-boot

-j4表示并行任务数。我一般设成CPU核心数的两倍。但注意,如果网络带宽有限,并行太多反而会互相争抢,导致频繁超时。

同步过程中可能会遇到这些情况:

现象 原因 解决办法
卡在某个仓库不动 网络连接不稳定 Ctrl+C中断,重新repo sync
报错"fatal: unable to access" 仓库地址不可达 检查网络代理或换镜像源
提示"repo sync has finished"但目录是空的 manifest里revision指向了不存在的分支 检查.repo/manifest.xml里的分支名
本地有未提交的修改 之前改过代码没提交 git stash或repo sync -d丢弃修改

我第一次同步时,拉了整整一个下午。中间断了三次,每次都要重新跑。后来学乖了,用repo sync -j1慢慢拉,虽然慢但至少不会断。

3.5 分支切换

代码同步完了,怎么切换分支?很多人直接在kernel目录下git checkout,这样只切换了kernel一个仓库。正确的做法是用Repo统一管理:

# 查看当前所有仓库所在的分支
repo info

# 切换所有仓库到某个分支
repo init -b rk356x_linux_release_v1.4.0
repo sync

# 只切换部分仓库
repo forall kernel u-boot -c "git checkout rk356x_linux_release_v1.4.0"

repo forall是个很强大的命令。它会在指定仓库里执行你给的shell命令。比如你想看所有仓库的当前commit:

repo forall -c "echo \$REPO_PATH : \$(git rev-parse --short HEAD)"

这里有个坑:repo init -b只是修改了manifest里的默认分支,并不会自动帮你切过去。你必须再跑一次repo sync才能真正拉取新分支的代码。我刚开始不知道,切了分支发现代码没变,还以为是Repo坏了……

核心要点:Repo的分支切换流程是repo init -b 新分支 → repo sync。两步缺一不可。如果你只做了第一步,代码还是旧的。

3.6 常用Repo命令速查

我把平时用得最多的Repo命令整理了一下:

命令 作用 使用场景
repo init -u URL -b BRANCH 初始化Repo工作区 第一次搭建或切换基线
repo sync 同步所有仓库到manifest指定版本 日常更新代码
repo start BRANCH --all 在所有仓库创建新分支 开始新功能开发
repo status 查看所有仓库的修改状态 检查哪些文件被改了
repo diff 查看所有仓库的diff 提交前review
repo upload 推送代码到Gerrit审核 团队协作提交
repo forall -c "CMD" 在所有仓库执行命令 批量操作(如批量打tag)

3.7 避坑指南

做RK3568开发这一年多,我踩过不少Repo的坑。挑几个典型的说说:

  • 磁盘空间不足:完整SDK拉下来大概15-20GB。如果只做内核开发,可以只同步kernel和u-boot,别全拉。
  • 权限问题:有些仓库是私有的,需要配SSH key。记得在GitHub/GitLab上添加你的公钥。
  • manifest冲突:如果你改了.repo/manifest.xml,下次repo sync时会提示冲突。解决办法是cd .repo/manifests && git checkout -- .。
  • 网络代理:公司内网通常要配HTTP代理。在~/.gitconfig里设置[http] proxy = http://proxy:port。

我曾经在同步到一半时强行关机,结果.repo目录损坏了。修复起来特别麻烦,最后只能删掉重新init。所以,同步代码时别断电、别关机、别手贱Ctrl+C。

3.8 知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以对照着理解Repo的工作流程:

Repo管理核心流程 1. 安装Repo工具 2. repo init 3. repo sync 4. 切换分支 5. 再次sync 6. 日常开发 7. repo status 8. repo upload 核心概念说明 • Manifest:记录所有仓库的地址、分支、commit SHA,是Repo的“宪法” • .repo目录:Repo的元数据仓库,包含manifest和所有仓库的裸Git数据 • repo forall:批量执行命令的瑞士军刀,常用于全局操作 • 分支切换必须两步走:init + sync,缺一不可

这张图把Repo的完整工作流分成了三个阶段:初始化阶段(安装→init→sync)、分支管理阶段(切换→再次sync)、日常开发阶段(开发→status→upload)。你每次操作都可以对照这张图,看看自己处在哪个环节。

3.9 小结

Repo管理说难不难,说简单也不简单。核心就记住三点:

  • manifest是老大,所有仓库的版本都由它决定
  • sync是万能药,代码不对就sync一下
  • 别手贱改.repo,出了问题恢复起来很麻烦