3. 开发环境搭建
做全志Tina Linux开发,第一步就是拿到源码。这事儿听起来简单,但里面坑不少。我见过不少新手,甚至一些老手,在源码同步上栽跟头——要么下载到一半断了,要么分支切得乱七八糟,最后编译出来的东西莫名其妙。
今天咱们就把这块彻底捋清楚。
3.1 Repo工具:Android遗产,Tina标配
Tina Linux的源码仓库,用的是Google为Android设计的Repo工具。说白了,Repo就是一个Python脚本,它帮你管理一堆Git仓库。Tina的源码不是单个仓库,而是由上百个Git仓库组成的集合——内核一个、uboot一个、各个组件各一个。
你想想看,要是手动一个个去git clone,光敲命令就得半天。Repo就是干这个的。
核心概念:Repo通过一个manifest.xml文件,描述所有子仓库的位置、分支和版本。你只需要操作Repo,它自动帮你搞定底层的Git。
3.1.1 安装Repo
先装Repo。我个人习惯把它放在用户目录下的bin文件夹里:
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
嗯,这里要注意:国内网络环境,有时候连Google的服务器不太稳。我建议你提前把repo脚本下载好,或者用国内镜像源。我曾经在项目赶进度时,就因为网络问题卡在repo init这一步,急得直跺脚。
小技巧:把repo脚本放到版本管理里,团队统一使用同一个版本,避免因repo版本差异导致行为不一致。
3.1.2 Repo init:初始化工作区
拿到Tina的manifest仓库地址后,执行:
repo init -u <manifest仓库URL> -b <分支名> --depth=1
参数说明:
| 参数 | 作用 | 我的建议 |
|---|---|---|
| -u | 指定manifest仓库地址 | 用公司内部GitLab地址,别用公共的 |
| -b | 指定分支或tag | 明确到具体版本号,别用master |
| --depth=1 | 浅克隆,只拉最新提交 | 强烈建议加,省时间省空间 |
为什么加--depth=1?Tina完整历史可能有几千个提交,全拉下来几十个G。你只是要编译,要历史干嘛?我刚开始做的时候没加这个参数,结果磁盘空间直接爆了。
3.2 Git仓库管理:理解Tina的仓库结构
初始化完成后,你会看到.repo目录和一堆.git文件。别慌,这是Repo的魔法。
实际开发中,你主要操作的是这些子仓库:
- lichee/:存放boot0、uboot、内核等底层代码
- brandy/:一些基础库和工具链相关
- package/:各个应用和组件的源码
- target/:板级配置和镜像打包脚本
每个子仓库都是独立的Git仓库。你可以cd进去,执行git log、git status、git diff——跟普通Git仓库一模一样。
注意:不要在顶层目录执行git命令!顶层目录不是Git仓库,是Repo管理的。你需要在子仓库里操作Git。
3.3 分支切换与同步策略
这块是实战中的重头戏。Tina开发通常涉及多个分支:开发分支、稳定分支、客户定制分支。怎么切、怎么同步,有讲究。
3.3.1 查看当前分支状态
先看看所有子仓库分别在哪个分支上:
repo status
这个命令会列出所有有变动的仓库。如果想看所有仓库的分支信息:
repo info -o
3.3.2 切换分支
切换所有子仓库到同一个分支:
repo init -b <新分支名>
repo sync
注意顺序:先repo init改manifest的分支,再repo sync拉取。
但有时候你只想切换个别仓库。比如内核要切到某个fix分支,其他仓库不动:
cd lichee/linux-5.4
git checkout <fix分支名>
我个人习惯是:尽量用repo统一管理分支,只在特殊情况下手动切个别仓库。否则时间一长,你都不知道哪些仓库在哪个分支上,编译出来一堆奇怪的问题。
3.3.3 同步策略:避免冲突的秘诀
团队协作时,同步是家常便饭。但同步不当,冲突能让你改到怀疑人生。
我总结了一套同步流程:
- 先提交本地修改:有未提交的改动,先git commit或者git stash
- 执行repo sync:拉取远程最新代码
- 处理冲突:如果有冲突,手动解决
- 重新编译验证:确保同步后能编译通过
我的血泪教训:曾经有一次,我没提交本地修改就直接repo sync,结果本地改动被覆盖了。虽然Git有reflog能找回,但折腾了大半天。从那以后,我每次同步前必先git status检查一遍。
3.3.4 分支同步的高级技巧
有时候你需要把开发分支的改动合并到稳定分支。这时候别直接repo sync,要用repo upload或者手动cherry-pick。
我常用的做法:
# 在开发分支上
git format-patch <基准提交>..HEAD --output-directory=/tmp/patches
# 切到稳定分支
repo init -b stable-v1.0
repo sync
# 逐个应用补丁
cd <对应仓库>
git am /tmp/patches/*.patch
这样能精确控制哪些改动过去,哪些留下。比直接merge干净得多。
3.4 知识结构图:源码获取与同步全流程
下面这张图,把整个流程串起来了。你对照着看,心里就有谱了。
3.5 常见问题与避坑指南
最后,分享几个我踩过的坑,你遇到了直接照着处理就行。
| 问题 | 现象 | 解决办法 |
|---|---|---|
| repo sync卡住不动 | 进度条停在某个仓库 | Ctrl+C中断,执行repo sync --no-clone-bundle绕过bundle下载 |
| 分支混乱 | 不同仓库在不同分支 | 执行repo forall -c git checkout <目标分支>统一切换 |
| 磁盘空间不足 | repo sync报错 | 加--depth=1重新init,或者清理.repo目录中的旧对象 |
| 冲突无法解决 | git merge冲突 | 用git mergetool可视化解决,或者回退后重新cherry-pick |
曾经有一次,我在客户现场做技术支持,需要紧急同步一个补丁。结果repo sync到一半网络断了,再执行就报错说.repo目录锁住了。后来发现是之前sync进程没完全退出,锁文件没释放。解决办法:rm -f .repo/.repo_lock,然后重新sync。这事儿让我养成了一个习惯——每次sync前先检查有没有残留的锁文件。
好了,源码获取与同步这块,核心就是这些。记住:Repo是壳,Git是核。理解了这个关系,你就能驾驭Tina的源码管理。动手试试吧,光看是学不会的。