1、Dockerfile 加入实测必需的兼容包:libncurses5(Clang 依赖)、python2(Rockchip U-Boot make.sh 硬依赖)、libssl-dev、imagemagick、protobuf-compiler 等预防性包 2、新增编译后的 U-Boot 手动修复步骤:-F 参数不自动生成 MiniLoaderAll 和 trust.img,需手动调用 u-boot/make.sh rk3588 + trust.img 副本伪装 + -Mu 重打包 3、新增完整镜像产物清单,说明 update.img 作为 Rockchip 固件打包格式已包含所有分区镜像,首次烧录只需 update.img 4、新增分区单独烧录对照表,指导开发调试时精确刷分区(boot/super/uboot 等)节省时间 5、新增 10 个踩坑速查表,覆盖 SDK 下载、合并、编译、打包全流程 6、新增新电脑复现完整命令流水线,换电脑后按序执行可避开所有已知坑 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1392 lines
46 KiB
Markdown
1392 lines
46 KiB
Markdown
# Tailscale + SSH 远程开发操作指南
|
||
|
||
## 文档概述
|
||
|
||
Mac 电脑通过 Tailscale 跨网络 SSH 连接 Windows 电脑上的 Linux 虚拟机(VMware),实现远程 Android 底层开发。
|
||
|
||
## 当前环境信息(2026-04-17 已验证)
|
||
|
||
| 项目 | 信息 |
|
||
|------|------|
|
||
| Mac 电脑 | macOS, ClashX Pro (VPN), Tailscale |
|
||
| Windows 电脑 | VMware Workstation 17, Clash for Windows v0.19.10 |
|
||
| Linux 虚拟机 | Ubuntu 20.04 LTS, VMware 桥接模式 |
|
||
| 虚拟机用户 | zhangwenqi |
|
||
| Tailscale IP | 100.123.82.91 |
|
||
| 虚拟机局域网 IP | 192.168.6.60 |
|
||
| SSH 密钥 | Mac ~/.ssh/id_ed25519 已部署到虚拟机 |
|
||
| Docker | 28.1.1 |
|
||
| **Radxa CM5 环境** | Docker 镜像 android-builder:12.x (6.48GB, Ubuntu 20.04 基底),SDK 已编译验证 |
|
||
| **OrangePi CM5 环境** | Docker 镜像 android-builder-orangepi:13.x (待构建, Ubuntu 22.04 基底),SDK 已合并待解压 |
|
||
| 磁盘 | 700GB 虚拟磁盘,剩余空间足够双环境并行 |
|
||
|
||
---
|
||
|
||
# 第一部分:网络架构
|
||
|
||
## 1.1 整体架构
|
||
|
||
```
|
||
Mac (ClashX Pro VPN + Tailscale)
|
||
|
|
||
| Tailscale P2P (100.x.x.x)
|
||
|
|
||
Linux 虚拟机 (Tailscale, IP: 100.123.82.91)
|
||
|
|
||
| VMware 桥接 (192.168.6.60)
|
||
|
|
||
Windows (Clash for Windows, 端口 7890)
|
||
```
|
||
|
||
## 1.2 各设备职责
|
||
|
||
- Mac: 开发主机,VPN 翻墙 + SSH 远程开发
|
||
- Windows: 宿主机,运行 VMware 虚拟机 + Clash 代理
|
||
- Linux 虚拟机: 编译服务器,Docker + Android SDK 编译环境
|
||
|
||
---
|
||
|
||
# 第二部分:ClashX Pro 与 Tailscale 共存配置(关键)
|
||
|
||
Mac 上 ClashX Pro(增强模式/TUN)与 Tailscale 存在两个冲突,必须同时解决。
|
||
|
||
## 2.1 问题一:增强模式流量劫持
|
||
|
||
ClashX Pro 增强模式创建 TUN 虚拟网卡拦截所有流量,Tailscale 的 WireGuard UDP 流量也被劫持,导致 Tailscale 连不上。
|
||
|
||
**解决方法:** 在 ClashX Pro 代理配置文件的 rules 最前面添加直连规则。
|
||
|
||
配置文件路径: `~/.config/clash/你的订阅配置.yaml`
|
||
|
||
在 `rules:` 下方、第一条规则之前插入:
|
||
|
||
```yaml
|
||
rules:
|
||
- PROCESS-NAME,tailscaled,DIRECT
|
||
- IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
|
||
- IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT,no-resolve
|
||
- DOMAIN-SUFFIX,tailscale.com,DIRECT
|
||
- DOMAIN-SUFFIX,login.tailscale.com,DIRECT
|
||
# ... 原有规则保持不变 ...
|
||
```
|
||
|
||
各规则作用:
|
||
- `PROCESS-NAME,tailscaled,DIRECT` → Tailscale 进程所有流量直连(最关键)
|
||
- `IP-CIDR,100.64.0.0/10,DIRECT` → Tailscale 内网 IP 段直连
|
||
- `IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT` → Tailscale IPv6 段直连
|
||
- `DOMAIN-SUFFIX,tailscale.com,DIRECT` → Tailscale 控制服务器直连
|
||
- `DOMAIN-SUFFIX,login.tailscale.com,DIRECT` → Tailscale 认证直连
|
||
|
||
## 2.2 问题二:MagicDNS 劫持域名解析
|
||
|
||
Tailscale 默认开启 MagicDNS,将系统 DNS 改为 100.100.100.100,与 ClashX Pro 增强模式的 fake-ip DNS(198.18.0.2)冲突。
|
||
|
||
典型表现:浏览器能访问 YouTube,但 Claude Code 等终端应用无法连接。
|
||
|
||
**解决方法:** 关闭 Tailscale DNS 接管。
|
||
|
||
操作步骤:
|
||
1. 点击 Mac 菜单栏 Tailscale 图标
|
||
2. 进入 Preferences(偏好设置)
|
||
3. 找到 "Use Tailscale DNS Settings" → 关闭
|
||
|
||
或通过管理后台:浏览器打开 https://login.tailscale.com/admin/dns → 关闭 MagicDNS
|
||
|
||
## 2.3 订阅更新覆盖问题
|
||
|
||
ClashX Pro 订阅更新会覆盖配置文件,Tailscale 直连规则会丢失。
|
||
|
||
**应对:** 每次订阅更新后,重新在 `rules:` 下插入 2.1 中的 5 条规则,然后 ClashX Pro 菜单 → 配置 → 重新加载配置。
|
||
|
||
备份规则片段方便粘贴:
|
||
```
|
||
- PROCESS-NAME,tailscaled,DIRECT
|
||
- IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
|
||
- IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT,no-resolve
|
||
- DOMAIN-SUFFIX,tailscale.com,DIRECT
|
||
- DOMAIN-SUFFIX,login.tailscale.com,DIRECT
|
||
```
|
||
|
||
## 2.4 验证清单
|
||
|
||
1. 开启 ClashX Pro 增强模式 + 选择代理节点
|
||
2. 开启 Tailscale
|
||
3. 浏览器访问 YouTube → VPN 正常
|
||
4. 终端 `ssh zhangwenqi@100.123.82.91` → Tailscale SSH 正常
|
||
5. Claude Code 对话 → DNS 解析正常
|
||
|
||
失败排查:
|
||
- 第 3 步失败 → 检查代理节点
|
||
- 第 4 步失败 → 检查 rules 中 Tailscale 直连规则
|
||
- 第 5 步失败 → 检查 Tailscale DNS Settings 是否已关闭
|
||
|
||
---
|
||
|
||
# 第三部分:Linux 虚拟机环境配置
|
||
|
||
## 3.1 Tailscale 安装
|
||
|
||
```bash
|
||
# 安装
|
||
curl -fsSL https://tailscale.com/install.sh | sh
|
||
|
||
# 启动并认证(浏览器打开输出的链接登录)
|
||
sudo tailscale up
|
||
|
||
# 查看分配的 IP
|
||
tailscale ip -4
|
||
```
|
||
|
||
## 3.2 SSH 服务
|
||
|
||
```bash
|
||
# 安装(如未安装)
|
||
sudo apt update && sudo apt install openssh-server -y
|
||
|
||
# 启动
|
||
sudo systemctl enable --now ssh
|
||
|
||
# 检查状态
|
||
sudo systemctl status ssh
|
||
```
|
||
|
||
## 3.3 Docker 安装
|
||
|
||
```bash
|
||
# 添加 Docker 清华镜像源
|
||
sudo mkdir -p /etc/apt/keyrings
|
||
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu focal stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
|
||
# 安装
|
||
sudo apt-get update -y
|
||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||
|
||
# 当前用户加入 docker 组(免 sudo)
|
||
sudo usermod -aG docker $USER
|
||
# 需要重新登录生效
|
||
```
|
||
|
||
## 3.4 Docker 镜像加速(国内必须配置)
|
||
|
||
Docker Hub 在国内无法直接访问,需要配置镜像加速器:
|
||
|
||
```bash
|
||
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
|
||
{
|
||
"registry-mirrors": [
|
||
"https://docker.1ms.run",
|
||
"https://docker.xuanyuan.me",
|
||
"https://docker.m.daocloud.io"
|
||
]
|
||
}
|
||
EOF
|
||
sudo systemctl daemon-reload && sudo systemctl restart docker
|
||
```
|
||
|
||
注意:镜像加速器地址可能失效,届时搜索"Docker 镜像加速 2026"获取最新可用地址。
|
||
|
||
## 3.5 构建 Android 12 编译镜像
|
||
|
||
Dockerfile 位于虚拟机 `~/Radxa_CM5/docker/Dockerfile`,内容基于 Radxa 官方文档,使用清华镜像源。
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/docker
|
||
sudo docker build -t android-builder:12.x .
|
||
```
|
||
|
||
构建完成验证:
|
||
```bash
|
||
sudo docker run --rm android-builder:12.x bash -c \
|
||
'java -version 2>&1; python3 --version; gcc --version | head -1; which repo'
|
||
```
|
||
|
||
预期输出:
|
||
- Java: openjdk 1.8.0
|
||
- Python: 3.8.x
|
||
- GCC: 9.4.0
|
||
- Repo: /usr/local/bin/repo
|
||
|
||
### 与官方 Dockerfile 的差异(重要)
|
||
|
||
当前镜像**缺少官方 Dockerfile 中的 5 套 Linaro 交叉编译工具链 COPY**:
|
||
|
||
```
|
||
gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf → /opt/ 和 /opt/toolchains/
|
||
gcc-linaro-aarch64-none-elf-4.8-2013.11_linux → /opt/ 和 /opt/toolchains/
|
||
gcc-arm-none-eabi-6-2017-q2-update → /opt/toolchains/
|
||
gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu → /opt/toolchains/
|
||
gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf → /opt/toolchains/
|
||
```
|
||
|
||
**原因:** 这些工具链需要单独下载(官方文档未提供下载地址),放到 Dockerfile 同目录才能 COPY。
|
||
|
||
**影响评估:**
|
||
- Radxa Android SDK 的 `prebuilts/` 目录自带编译所需工具链
|
||
- 编译脚本 `build.sh` 优先使用 SDK 内的工具链
|
||
- 这些 Linaro 工具链主要给 U-Boot 和 kernel **单独编译**用
|
||
|
||
**编译时如果报错找不到工具链,按以下方式排查修复:**
|
||
|
||
1. 确认报错中缺少的具体工具链名称
|
||
2. 搜索 Linaro 官网下载对应版本:https://releases.linaro.org/components/toolchain/binaries/
|
||
3. 解压到 Docker 容器的 `/opt/toolchains/` 目录:
|
||
```bash
|
||
# 在容器内
|
||
cd /opt/toolchains
|
||
wget <工具链下载地址>
|
||
tar -xf <工具链压缩包>
|
||
```
|
||
4. 或者将工具链放到 `~/Radxa_CM5/docker/` 目录,取消 Dockerfile 中 COPY 行注释后重新构建镜像
|
||
|
||
## 3.6 Radxa CM5 Android 12 编译环境(基于 Ubuntu 20.04)
|
||
|
||
### 3.6.1 解压 SDK
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/SDK_Android
|
||
tar -xzf radxa_android_sdk_backup.tar.gz
|
||
# 解压后目录为 radxa-android-sdk/,耗时视磁盘速度而定
|
||
```
|
||
|
||
### 3.6.2 编译前必须修复的问题(重要)
|
||
|
||
SDK 存在两个已知问题,必须在编译前修复,否则编译会失败。
|
||
|
||
**问题一:GMS 引用不存在(lunch 阶段报错)**
|
||
|
||
错误信息:`vendor/partner_gms/products/gms.mk does not exist`
|
||
|
||
原因:RadxaCM5.mk 引用了 Google GMS 包(Google Play 服务),但开源 SDK 不包含 GMS(需 Google 授权)。
|
||
|
||
修复:注释掉 GMS 引用行。
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/SDK_Android/radxa-android-sdk
|
||
sed -i 's/$(call inherit-product, vendor\/partner_gms\/products\/gms.mk)/#$(call inherit-product, vendor\/partner_gms\/products\/gms.mk)/' device/rockchip/rk3588/RadxaCM5/RadxaCM5.mk
|
||
```
|
||
|
||
验证:
|
||
```bash
|
||
grep "gms" device/rockchip/rk3588/RadxaCM5/RadxaCM5.mk
|
||
# 应看到该行前面有 # 注释符
|
||
```
|
||
|
||
注意:注释 GMS 后编译出的系统不含 Google Play 商店和 Google 服务,其他功能不受影响。
|
||
|
||
**问题二:缺少 RadxaCM5.config 内核配置文件(kernel 编译阶段报错)**
|
||
|
||
错误信息:`No configuration exists for this target on this architecture - RadxaCM5.config`
|
||
|
||
原因:BoardConfig.mk 指定 `PRODUCT_KERNEL_CONFIG := rockchip_defconfig android-11.config RadxaCM5.config`,但 `kernel-5.10/kernel/configs/` 目录下没有 `RadxaCM5.config` 文件。
|
||
|
||
修复:参考 rock5b.config 创建 CM5 内核配置文件。
|
||
|
||
```bash
|
||
cat > kernel-5.10/kernel/configs/RadxaCM5.config << 'EOF'
|
||
CONFIG_SND_SOC_ES8316=y
|
||
CONFIG_RTL8852BE=m
|
||
CONFIG_BT_RTKBTUSB=y
|
||
CONFIG_SENSORS_PWM_FAN=y
|
||
CONFIG_TOUCHSCREEN_GT9XX=y
|
||
CONFIG_TOUCHSCREEN_FTS=y
|
||
CONFIG_TOUCHSCREEN_FTS_RADXA=y
|
||
CONFIG_DRM_PANEL_RADXA=y
|
||
CONFIG_DRM_PANEL_RASPBERRYPI_TC358762=y
|
||
CONFIG_ROCKPI_MCU=y
|
||
CONFIG_VIDEO_IMX219=y
|
||
EOF
|
||
```
|
||
|
||
### 3.6.3 编译前增大 Swap(防止 OOM,重要)
|
||
|
||
Android 全量编译内存峰值可超过 20GB,虚拟机默认 Swap 仅 1GB,编译到 99% 时会因内存不足被 OOM Killer 杀死进程。
|
||
|
||
```bash
|
||
# 创建 8GB Swap 文件
|
||
sudo fallocate -l 8G /swapfile
|
||
sudo chmod 600 /swapfile
|
||
sudo mkswap /swapfile
|
||
sudo swapon /swapfile
|
||
|
||
# 写入 fstab 永久生效
|
||
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
||
|
||
# 验证(应显示 9GB 左右 Swap)
|
||
free -h | grep -i swap
|
||
```
|
||
|
||
同时建议 VMware 虚拟机内存分配 **16GB 以上**(20GB+ 更佳)。
|
||
|
||
### 3.6.4 进入 Docker 编译环境
|
||
|
||
```bash
|
||
# 注意挂载的是解压后的 radxa-android-sdk 目录
|
||
sudo docker run -it \
|
||
--name android-build \
|
||
-v ~/Radxa_CM5/SDK_Android/radxa-android-sdk:/workspace \
|
||
-w /workspace \
|
||
android-builder:12.x \
|
||
bash
|
||
```
|
||
|
||
### 3.6.5 执行编译
|
||
|
||
```bash
|
||
# 在 Docker 容器内执行
|
||
source build/envsetup.sh
|
||
lunch RadxaCM5-userdebug
|
||
|
||
# 方法一:全量编译(推荐,约 5 小时)
|
||
# 如果虚拟机内存 ≤ 20GB,建议用 -j8 限制线程数减少内存峰值
|
||
./build.sh -AUCKup
|
||
|
||
# 方法二:如果 build.sh 因 OOM 中途失败,用 make 继续(会复用已编译缓存)
|
||
make -j8
|
||
```
|
||
|
||
编译参数说明:`-A` AOSP、`-U` U-Boot、`-C` Config、`-K` Kernel、`-u` update.img、`-p` 打包
|
||
|
||
编译过程中 `Build sandboxing disabled due to nsjail error` 是正常提示,Docker 容器内不支持 nsjail 沙箱,不影响编译。
|
||
|
||
### 3.6.6 编译后打包镜像
|
||
|
||
如果使用 `make -j8` 单独编译 AOSP(非 build.sh),需要手动打包:
|
||
|
||
```bash
|
||
# 在容器内执行
|
||
./mkimage.sh
|
||
```
|
||
|
||
### 3.6.7 验证编译结果
|
||
|
||
```bash
|
||
ls -lh rockdev/Image-RadxaCM5/
|
||
```
|
||
|
||
预期镜像文件:
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| MiniLoaderAll.bin | Bootloader 加载器 |
|
||
| idbloader.img | IDB Loader |
|
||
| uboot.img | U-Boot |
|
||
| boot.img | Boot 镜像(内核+ramdisk) |
|
||
| recovery.img | Recovery 模式镜像 |
|
||
| super.img | 系统分区(system+vendor+odm,约 1.6GB) |
|
||
| dtbo.img | 设备树 Overlay |
|
||
| resource.img | 内核资源 |
|
||
|
||
### 3.6.8 退出和重新进入容器
|
||
|
||
```bash
|
||
# 退出容器
|
||
exit
|
||
|
||
# 重新进入已创建的容器
|
||
sudo docker start -ai android-build
|
||
```
|
||
|
||
### 3.6.9 烧录到开发板
|
||
|
||
编译完成的镜像在虚拟机 `~/Radxa_CM5/SDK_Android/radxa-android-sdk/rockdev/Image-RadxaCM5/` 目录。
|
||
|
||
拿到 CM5 开发板后:
|
||
1. 将镜像文件拷贝到 Windows
|
||
2. 使用 **RKDevTool**(瑞芯微官方烧录工具)烧录
|
||
3. 开发板进入 Loader 模式(按住 Recovery 按键上电)
|
||
4. 在 RKDevTool 中加载各 img 文件烧录
|
||
|
||
## 3.7 OrangePi CM5 Android 13 编译环境(基于 Ubuntu 22.04 Docker)
|
||
|
||
OrangePi CM5 Base(RK3588S)使用 Android 13 源码,与 Radxa CM5 的 Android 12 并行存在。
|
||
为避免污染主机环境,使用独立的 Docker 镜像(基于 Ubuntu 22.04,对齐 OrangePi 官方推荐环境)。
|
||
|
||
### 3.7.1 官方参考文档
|
||
|
||
- 《OrangePi_CM5_Base_RK3588S_用户手册_v1.3.pdf》第 7 章:Android 13 源码的编译方法
|
||
- 《OrangePi_CM5_Base_Tablet_RK3588S_用户手册_v1.0.pdf》
|
||
|
||
### 3.7.2 SDK 文件准备
|
||
|
||
OrangePi Android 13 SDK 来自官方百度云/谷歌网盘,是 9 个分卷压缩包:
|
||
|
||
```
|
||
Android_13.tar.gz00 (4.0GB)
|
||
Android_13.tar.gz01 (4.0GB)
|
||
...
|
||
Android_13.tar.gz08 (1.9GB)
|
||
md5sum (校验文件)
|
||
```
|
||
|
||
存放路径:`~/OrangePi_CM5/Aandroid_OrangePi/`
|
||
|
||
### 3.7.3 MD5 校验
|
||
|
||
```bash
|
||
cd ~/OrangePi_CM5/Aandroid_OrangePi
|
||
md5sum -c md5sum
|
||
# 9 个文件全部显示"成功/确定"才能继续
|
||
```
|
||
|
||
### 3.7.4 合并压缩包(重要)
|
||
|
||
**经实测:官方文档的管道流式解压(`cat ... | tar -xzf -`)会在某个分卷边界出错**
|
||
(已解压 46GB 后报 `gzip: invalid compressed data--format violated`)。
|
||
|
||
**推荐做法:先合并成单个文件,再解压。**
|
||
|
||
```bash
|
||
cd ~/OrangePi_CM5/Aandroid_OrangePi
|
||
# 显式指定顺序合并(避免通配符顺序问题)
|
||
cat Android_13.tar.gz00 Android_13.tar.gz01 Android_13.tar.gz02 \
|
||
Android_13.tar.gz03 Android_13.tar.gz04 Android_13.tar.gz05 \
|
||
Android_13.tar.gz06 Android_13.tar.gz07 Android_13.tar.gz08 \
|
||
> Android_13.tar.gz
|
||
|
||
# 合并后约 34GB,耗时约 15 分钟(SSD 速度约 37MB/s)
|
||
ls -lh Android_13.tar.gz
|
||
```
|
||
|
||
### 3.7.5 解压源码
|
||
|
||
```bash
|
||
# 解压到当前目录,产生 Android_13/ 目录
|
||
tar -xzf Android_13.tar.gz
|
||
|
||
# 解压后预计 80-100GB,耗时约 20-30 分钟
|
||
du -sh Android_13/
|
||
```
|
||
|
||
解压成功后可以删除合并文件和分卷文件节省空间:
|
||
```bash
|
||
# 可选:保留分卷和 md5sum 作为备份源,删除合并文件
|
||
rm Android_13.tar.gz
|
||
|
||
# 或:已验证解压成功后,彻底清理(需确认 Android_13/ 完整)
|
||
# rm Android_13.tar.gz Android_13.tar.gz0*
|
||
```
|
||
|
||
### 3.7.6 创建 Dockerfile(含所有踩坑补丁,实测可用版)
|
||
|
||
Dockerfile 位于虚拟机 `~/OrangePi_CM5/docker/Dockerfile`,基于 Ubuntu 22.04。
|
||
官方文档 7.2 的依赖列表不完整,本版本已加入所有实际踩坑后补齐的包。
|
||
|
||
```dockerfile
|
||
# OrangePi CM5 Android 13 编译环境
|
||
# 基础镜像:Ubuntu 22.04(符合 OrangePi 官方推荐环境)
|
||
FROM ubuntu:22.04
|
||
|
||
# 清华镜像源
|
||
RUN sed -i 's@archive.ubuntu.com@mirrors.tuna.tsinghua.edu.cn@g; \
|
||
s@security.ubuntu.com@mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list
|
||
|
||
ENV DEBIAN_FRONTEND=noninteractive
|
||
ENV TZ=Asia/Shanghai
|
||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||
|
||
# 启用 i386 多架构(Android 编译需要 32 位兼容库)
|
||
RUN dpkg --add-architecture i386
|
||
|
||
# 官方文档 7.2 要求的编译依赖
|
||
RUN apt-get update -y && apt-get install -y \
|
||
git gnupg flex bison gperf build-essential \
|
||
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
|
||
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache \
|
||
libgl1-mesa-dev libxml2-utils xsltproc unzip \
|
||
&& apt-get install -y u-boot-tools
|
||
|
||
# Android 13 需要 OpenJDK 11
|
||
RUN apt-get install -y openjdk-11-jdk
|
||
|
||
# 【踩坑 1】Ubuntu 22.04 默认没有 libncurses.so.5
|
||
# 但 Android 预编译 Clang 工具链依赖它,不装会导致编译到 40+ 分钟时报错
|
||
RUN apt-get install -y libncurses5 libncurses5:i386
|
||
|
||
# 【踩坑 2】Ubuntu 22.04 编译 Android 可能需要的预防性包
|
||
RUN apt-get install -y \
|
||
libssl-dev pkg-config m4 imagemagick \
|
||
python-is-python3 python3-protobuf \
|
||
protobuf-compiler libprotobuf-dev \
|
||
libncurses-dev
|
||
|
||
# 【踩坑 3】Rockchip U-Boot 的 make.sh 硬依赖 Python 2
|
||
# 不装会导致 MiniLoaderAll 合成阶段报 "ERROR: No python2"
|
||
RUN apt-get install -y python2 python2-dev python2.7
|
||
|
||
# 辅助工具
|
||
RUN apt-get install -y python3 python3-pip rsync cpio bc kmod \
|
||
device-tree-compiler liblz4-tool lzop sudo vim nano \
|
||
fontconfig schedtool
|
||
|
||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||
|
||
WORKDIR /workspace
|
||
CMD ["/bin/bash"]
|
||
```
|
||
|
||
### 3.7.7 构建 Docker 镜像
|
||
|
||
```bash
|
||
cd ~/OrangePi_CM5/docker
|
||
sudo docker build -t android-builder-orangepi:13.x .
|
||
# 耗时约 5-10 分钟
|
||
```
|
||
|
||
验证镜像:
|
||
```bash
|
||
sudo docker images android-builder-orangepi
|
||
# 预期:TAG=13.x, SIZE 约 2GB
|
||
```
|
||
|
||
### 3.7.8 进入 Docker 编译环境
|
||
|
||
```bash
|
||
sudo docker run -it \
|
||
--name orangepi-build \
|
||
-v ~/OrangePi_CM5/Aandroid_OrangePi/Android_13:/workspace \
|
||
-w /workspace \
|
||
android-builder-orangepi:13.x \
|
||
bash
|
||
```
|
||
|
||
### 3.7.9 执行编译
|
||
|
||
按官方文档 7.2 节编译参数:
|
||
|
||
| 参数 | 作用 |
|
||
|------|------|
|
||
| `-B` | 编译 U-Boot |
|
||
| `-K` | 编译 Kernel |
|
||
| `-a` | 编译 Android |
|
||
| `-F` | 编译 U-Boot + Kernel + Android(三合一) |
|
||
| `-M` | 在 rockdev 目录生成分区镜像 |
|
||
| `-u` | 打包生成最终 update.img |
|
||
| `-b` | 指定开发板型号 |
|
||
| `--gapps` | 包含 Google Play 服务(GApps) |
|
||
|
||
推荐全量编译命令:
|
||
```bash
|
||
# 容器内或后台 docker run -d 执行
|
||
./make.sh -FMu -b orangepicm5 --gapps
|
||
```
|
||
|
||
实测耗时:**6 小时 11 分钟**(VMware 虚拟机 8 核 20GB RAM + 9GB Swap)。
|
||
|
||
推荐后台执行(避免 SSH 断开中断):
|
||
```bash
|
||
sudo docker run -d --name orangepi-build \
|
||
-v /home/zhangwenqi/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace \
|
||
android-builder-orangepi:13.x \
|
||
bash -c 'echo 开始: $(date) > /tmp/build.log && \
|
||
./make.sh -FMu -b orangepicm5 --gapps >> /tmp/build.log 2>&1; \
|
||
echo 结束: $(date) exit=$? >> /tmp/build.log'
|
||
|
||
# 查看进度
|
||
sudo docker exec orangepi-build tail -20 /tmp/build.log
|
||
sudo docker exec orangepi-build du -sh /workspace/out/
|
||
```
|
||
|
||
### 3.7.10 编译后的 U-Boot 修复(实测必需)
|
||
|
||
**`-F` 参数理论上会编译 U-Boot,但实际只产出 `u-boot.img` 等基础文件,
|
||
不会自动调用 Rockchip 脚本合成 `MiniLoaderAll.bin` 和 `trust.img`。**
|
||
|
||
如果 `make.sh -FMu` 最后日志中出现:
|
||
```
|
||
u-boot/trust.img not fount! Please make it from u-boot first!
|
||
u-boot/*MiniLoaderAll_*.bin not fount! Please make it from u-boot first!
|
||
Error:<AddFile> open file failed,err=2!
|
||
Make firmware FAILED
|
||
```
|
||
|
||
需要手动执行两步修复:
|
||
|
||
**修复步骤 1:合成 Rockchip U-Boot(生成 MiniLoaderAll + uboot.img 新版)**
|
||
|
||
```bash
|
||
# 启动临时容器执行 u-boot/make.sh rk3588
|
||
sudo docker run --rm \
|
||
-v /home/zhangwenqi/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace/u-boot \
|
||
android-builder-orangepi:13.x \
|
||
./make.sh rk3588
|
||
```
|
||
|
||
成功标志:
|
||
```
|
||
Image(no-signed, version=0): uboot.img (FIT with uboot, trust...) is ready
|
||
Image(no-signed): rk3588_spl_loader_v1.13.xxx.bin (with spl, ddr...) is ready
|
||
```
|
||
|
||
**修复步骤 2:创建 trust.img 符号文件(新版 Rockchip 已将 trust 合并到 uboot.img)**
|
||
|
||
```bash
|
||
# 在虚拟机宿主机执行(非容器内)
|
||
cd ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/u-boot/
|
||
sudo cp -a uboot.img trust.img
|
||
```
|
||
|
||
**修复步骤 3:重新打包(跳过编译,只做 mkimage + update.img)**
|
||
|
||
```bash
|
||
sudo docker run --rm \
|
||
-v /home/zhangwenqi/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace \
|
||
android-builder-orangepi:13.x \
|
||
./make.sh -Mu -b orangepicm5 --gapps
|
||
```
|
||
|
||
`-Mu` 只做"生成分区镜像 + 打包 update.img",不重新编译 Android,耗时约 5-10 分钟。
|
||
|
||
### 3.7.11 验证编译结果
|
||
|
||
成功后在 `rockdev/Image-rk3588s_t/` 目录生成所有镜像:
|
||
|
||
```bash
|
||
ls -lh ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/rockdev/Image-rk3588s_t/
|
||
```
|
||
|
||
预期产物(实测):
|
||
|
||
| 文件 | 大小 | 分区/作用 |
|
||
|------|------|----------|
|
||
| **update.img** | **2.3GB** | eMMC/TF 卡完整固件(首要烧录目标) |
|
||
| **update_spi_nvme.img** | **2.3GB** | SPI Flash + NVMe SSD 组合烧录 |
|
||
| MiniLoaderAll.bin | 465KB | bootloader 加载器(MaskROM 引导) |
|
||
| uboot.img | 4.0MB | U-Boot(已内含 trust) |
|
||
| trust.img | 4.0MB | Trust 镜像(副本,兼容脚本) |
|
||
| boot.img | 37MB | 内核 + ramdisk(boot 分区) |
|
||
| recovery.img | 47MB | Recovery 模式镜像 |
|
||
| super.img | 2.2GB | 超级分区(含 system+vendor+odm+product) |
|
||
| dtbo.img | 443B | 设备树 Overlay |
|
||
| resource.img | 2.5MB | 内核资源(开机动画、字体等) |
|
||
| vbmeta.img | 4KB | 验证启动元数据 |
|
||
| misc.img | 48KB | 其他信息分区 |
|
||
| baseparameter.img | 1MB | 显示屏参数 |
|
||
| parameter.txt | - | 分区表定义 |
|
||
|
||
### 3.7.12 烧录到 OrangePi CM5 开发板
|
||
|
||
#### 首次烧录:只需 update.img
|
||
|
||
**`update.img` 是完整的 Android 13 系统固件**,包含所有分区镜像。
|
||
烧录 update.img 会一次性写入所有分区,等于给开发板全新刷系统。
|
||
|
||
烧录步骤:
|
||
1. 从虚拟机拷贝 `update.img`(2.3GB)到 Windows 电脑:
|
||
```bash
|
||
# Mac 或虚拟机上执行(假设通过 Tailscale SSH)
|
||
scp zhangwenqi@100.123.82.91:/home/zhangwenqi/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/rockdev/Image-rk3588s_t/update.img ~/Desktop/
|
||
```
|
||
|
||
2. Windows 电脑下载并安装 **RKDevTool**(瑞芯微官方烧录工具)
|
||
|
||
3. OrangePi CM5 进入 **MaskROM 模式**:
|
||
- 按住板子上的 **Recovery / MaskROM 按键**
|
||
- 插入 USB 线到电脑
|
||
- 松开按键
|
||
|
||
4. RKDevTool 界面切换到 **升级固件** 标签
|
||
|
||
5. 点击 **固件** 按钮,选择 `update.img`
|
||
|
||
6. 点击 **升级** 按钮,等待烧录完成(约 2-5 分钟)
|
||
|
||
7. 烧录完成后开发板自动重启进入 Android 13
|
||
|
||
#### 镜像文件说明与高级烧录
|
||
|
||
`update.img` = Rockchip 打包格式,内部已包含所有其他 `.img` 文件。
|
||
单独的 `.img` 文件是给**开发调试**用的,用途:
|
||
|
||
| 场景 | 用哪个镜像 | 烧录方式 |
|
||
|------|-----------|---------|
|
||
| 首次刷机 / 完整升级 | `update.img` | RKDevTool 升级固件 |
|
||
| 只调试内核 | `boot.img` | `fastboot flash boot boot.img` |
|
||
| 只更新系统 | `super.img` | `fastboot flash super super.img` |
|
||
| 只更新 U-Boot | `uboot.img` | `fastboot flash uboot uboot.img` |
|
||
| 只刷 Recovery | `recovery.img` | `fastboot flash recovery recovery.img` |
|
||
| 改开机画面 | `resource.img` | `fastboot flash resource resource.img` |
|
||
| SPI Flash + NVMe 设备 | `update_spi_nvme.img` | RKDevTool 升级固件 |
|
||
|
||
**日常开发推荐**:
|
||
- 改内核 / 驱动 → 单独烧 `boot.img`(几秒到 1 分钟)
|
||
- 改应用 / 系统框架 → 单独烧 `super.img`(1-2 分钟)
|
||
- 改 Bootloader → 单独烧 `uboot.img` + `MiniLoaderAll.bin`
|
||
- 不确定或要彻底刷新 → 烧 `update.img`(2-5 分钟)
|
||
|
||
这样可以避免每次修改都重刷整个系统。
|
||
|
||
### 3.7.12 关键差异对比(与 Radxa CM5)
|
||
|
||
| 项目 | Radxa CM5 | OrangePi CM5 |
|
||
|------|-----------|--------------|
|
||
| Android 版本 | 12 | 13 |
|
||
| Docker 基础镜像 | ubuntu:20.04 | **ubuntu:22.04** |
|
||
| JDK 版本 | OpenJDK 8 | **OpenJDK 11** |
|
||
| 交叉编译工具链 | 需手动 COPY 5 套 Linaro | 编译脚本自动下载 |
|
||
| SDK 分发方式 | 单个压缩包 | 9 个分卷(需先合并) |
|
||
| 编译脚本 | `./build.sh -AUCKup` | `./make.sh -FMu -b orangepicm5 --gapps` |
|
||
| 镜像输出目录 | `rockdev/Image-RadxaCM5/` | `rockdev/Image-rk3588s_t/` |
|
||
| GMS 支持 | 需注释(官方不含) | `--gapps` 参数直接支持 |
|
||
| Docker 镜像名 | android-builder:12.x | android-builder-orangepi:13.x |
|
||
|
||
### 3.7.13 容器管理
|
||
|
||
```bash
|
||
# 退出容器(编译中断)
|
||
exit
|
||
|
||
# 重新进入已创建的容器(保留编译缓存)
|
||
sudo docker start -ai orangepi-build
|
||
|
||
# 删除容器(重新开始,会丢失容器内临时修改)
|
||
sudo docker rm -f orangepi-build
|
||
```
|
||
|
||
### 3.7.14 踩坑速查表(完整编译流水线)
|
||
|
||
以下所有坑都是实际编译过程中踩到的,新电脑按文档 3.7.1~3.7.12 操作时**严格按顺序**可以避开。
|
||
|
||
| # | 阶段 | 现象 | 根因 | 解决方法 |
|
||
|---|------|------|------|----------|
|
||
| 1 | SDK 校验 | gz03 分卷 MD5 校验通过但解压到 46GB 报 `invalid compressed data` | 百度网盘下载过程中该分卷损坏,但上游 md5sum 正好是损坏版本的 MD5 | 重新从百度网盘下载 gz03,对比同网盘其他用户汇报的 MD5 |
|
||
| 2 | SDK 合并 | 官方文档推荐的 `cat ... \| tar -xzf -` 管道式解压在分卷边界处出错 | 管道模式下 tar 无法定位错误位置 | 改用"先合并成单文件 → 再解压"两步法 |
|
||
| 3 | 构建镜像 | Android ninja 42 分钟时报 `libncurses.so.5: cannot open shared object file` | Ubuntu 22.04 默认只有 libncurses.so.6 | Dockerfile 装 `libncurses5 libncurses5:i386` |
|
||
| 4 | 主体编译 | 6 小时编译完成后打包失败:`u-boot/trust.img not fount` | `make.sh -F` 只跑 U-Boot 编译,没调用 Rockchip 合成脚本 | 手动 `cd u-boot && ./make.sh rk3588` |
|
||
| 5 | U-Boot 合成 | Rockchip make.sh 报 `ERROR: No python2` | Ubuntu 22.04 没 Python 2(默认只有 python3) | Dockerfile 装 `python2 python2-dev python2.7` |
|
||
| 6 | 打包阶段 | mkimage.sh 找不到 `trust.img` | 新版 Rockchip 把 trust 合并到 uboot.img,不单独生成 | `cp uboot.img trust.img`(副本伪装) |
|
||
| 7 | 打包阶段 | 手动 lunch 后执行 mkimage.sh 编译目标变成 `aosp_arm` | OrangePi make.sh 内部根据 `-b orangepicm5` 设置 lunch,手动设不对 | 直接用 `./make.sh -Mu -b orangepicm5 --gapps` 打包 |
|
||
| 8 | 资源管理 | Soong 阶段内存峰值 19GB,会耗 Swap | Android 构建系统需要巨大内存 | 虚拟机分配 **20GB 内存 + 9GB Swap**(已配) |
|
||
| 9 | 编译效率 | 编译中断重启后重新跑全部阶段 | 未保留 out/ 缓存 | 不要 `rm -rf out/`,重启时 make.sh 会增量继续 |
|
||
| 10 | Docker 默认源 | `docker build` 拉 `ubuntu:22.04` 超时 | Docker Hub 国内访问慢 | `/etc/docker/daemon.json` 配置镜像加速器 |
|
||
|
||
### 3.7.15 完整编译流水线(新电脑复现)
|
||
|
||
如果换新电脑后需要重新编译,按以下顺序:
|
||
|
||
```bash
|
||
# === 准备阶段 ===
|
||
# 1. 恢复 SDK 分卷到 ~/OrangePi_CM5/Aandroid_OrangePi/archive/
|
||
# 2. MD5 校验所有分卷
|
||
cd ~/OrangePi_CM5/Aandroid_OrangePi/archive
|
||
md5sum -c md5sum
|
||
|
||
# 3. 合并成单文件到 merged/
|
||
cd ..
|
||
cat archive/Android_13.tar.gz00 archive/Android_13.tar.gz01 \
|
||
archive/Android_13.tar.gz02 archive/Android_13.tar.gz03 \
|
||
archive/Android_13.tar.gz04 archive/Android_13.tar.gz05 \
|
||
archive/Android_13.tar.gz06 archive/Android_13.tar.gz07 \
|
||
archive/Android_13.tar.gz08 > merged/Android_13.tar.gz
|
||
|
||
# 4. 解压源码
|
||
cd merged && tar -xzf Android_13.tar.gz
|
||
|
||
# === 编译阶段 ===
|
||
# 5. 构建 Docker 镜像(按 3.7.6 的 Dockerfile)
|
||
cd ~/OrangePi_CM5/docker
|
||
sudo docker build -t android-builder-orangepi:13.x .
|
||
|
||
# 6. 主体编译(后台,约 6 小时)
|
||
sudo docker run -d --name orangepi-build \
|
||
-v ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace \
|
||
android-builder-orangepi:13.x \
|
||
bash -c './make.sh -FMu -b orangepicm5 --gapps > /tmp/build.log 2>&1'
|
||
|
||
# 7. 等主体编译完成(会报 trust.img 缺失,正常)
|
||
|
||
# === 修复阶段 ===
|
||
# 8. 手动合成 Rockchip U-Boot
|
||
sudo docker run --rm \
|
||
-v ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace/u-boot \
|
||
android-builder-orangepi:13.x \
|
||
./make.sh rk3588
|
||
|
||
# 9. 创建 trust.img 伪装
|
||
sudo cp -a ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/u-boot/uboot.img \
|
||
~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/u-boot/trust.img
|
||
|
||
# 10. 只打包(复用已编译产物,约 5-10 分钟)
|
||
sudo docker run --rm \
|
||
-v ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13:/workspace \
|
||
-w /workspace \
|
||
android-builder-orangepi:13.x \
|
||
./make.sh -Mu -b orangepicm5 --gapps
|
||
|
||
# === 完成 ===
|
||
# 11. 验证 update.img
|
||
ls -lh ~/OrangePi_CM5/Aandroid_OrangePi/merged/Android_13/rockdev/Image-rk3588s_t/update.img
|
||
# 预期:2.3GB
|
||
```
|
||
|
||
## 3.8 Linux 虚拟机共享 Windows VPN(外网访问)
|
||
|
||
虚拟机通过 VMware 桥接网络使用 Windows 的 Clash 代理上外网。已配置开机自动生效。
|
||
|
||
### 当前配置信息(2026-04-15 已验证)
|
||
|
||
| 项目 | 值 |
|
||
|------|-----|
|
||
| Windows 局域网 IP | 192.168.6.57 |
|
||
| Clash 代理端口 | 7890 |
|
||
| 虚拟机代理配置文件 | `/etc/profile.d/proxy.sh` |
|
||
|
||
### Windows 端配置(一次性)
|
||
|
||
1. Clash for Windows → 开启 **"允许局域网连接入Clash"**(Allow LAN)
|
||
2. Windows 防火墙放行 7890 端口(管理员 PowerShell 执行):
|
||
```powershell
|
||
netsh advfirewall firewall add rule name="Clash Proxy" dir=in action=allow protocol=tcp localport=7890
|
||
```
|
||
|
||
### Linux 虚拟机端配置(已完成,开机自动生效)
|
||
|
||
代理配置写入 `/etc/profile.d/proxy.sh`,每次登录自动加载:
|
||
|
||
```bash
|
||
export http_proxy="http://192.168.6.57:7890"
|
||
export https_proxy="http://192.168.6.57:7890"
|
||
export HTTP_PROXY="http://192.168.6.57:7890"
|
||
export HTTPS_PROXY="http://192.168.6.57:7890"
|
||
export no_proxy="localhost,127.0.0.1,100.64.0.0/10,192.168.0.0/16"
|
||
export NO_PROXY="localhost,127.0.0.1,100.64.0.0/10,192.168.0.0/16"
|
||
```
|
||
|
||
### 验证外网
|
||
|
||
```bash
|
||
curl -I https://www.google.com
|
||
curl -I https://releases.linaro.org/
|
||
```
|
||
|
||
### 前提条件
|
||
|
||
- Windows 电脑**开机且 Clash 运行中**
|
||
- Clash 的 "允许局域网连接入Clash" 保持开启
|
||
|
||
### 注意事项
|
||
|
||
- **Windows IP 变化**:如果 Windows 通过 DHCP 获取 IP,重启路由器后 IP 可能变化。届时需要修改 `/etc/profile.d/proxy.sh` 中的 IP 地址:
|
||
```bash
|
||
sudo nano /etc/profile.d/proxy.sh
|
||
# 将 192.168.6.57 替换为新的 Windows IP
|
||
```
|
||
然后重新登录或执行 `source /etc/profile.d/proxy.sh` 生效。
|
||
建议在 Windows 上设置静态 IP 或在路由器中绑定 DHCP 避免此问题。
|
||
|
||
- **Docker 容器内使用代理**:`/etc/profile.d/` 的代理对 Docker 容器内不生效,启动容器时需传入环境变量:
|
||
```bash
|
||
sudo docker run -it \
|
||
-e http_proxy="http://192.168.6.57:7890" \
|
||
-e https_proxy="http://192.168.6.57:7890" \
|
||
-e no_proxy="localhost,127.0.0.1" \
|
||
--name android-build \
|
||
-v ~/Radxa_CM5/SDK_Android:/workspace \
|
||
-w /workspace \
|
||
android-builder:12.x bash
|
||
```
|
||
|
||
---
|
||
|
||
# 第四部分:Mac 端 SSH 连接配置
|
||
|
||
## 4.1 生成 SSH 密钥
|
||
|
||
```bash
|
||
ssh-keygen -t ed25519 -C "mac-to-linux-vm"
|
||
# 一路回车使用默认设置
|
||
```
|
||
|
||
## 4.2 部署公钥到虚拟机
|
||
|
||
```bash
|
||
ssh-copy-id zhangwenqi@100.123.82.91
|
||
# 输入虚拟机密码,完成后即可免密登录
|
||
```
|
||
|
||
## 4.3 SSH 配置文件
|
||
|
||
编辑 `~/.ssh/config`:
|
||
|
||
```
|
||
Host linux-vm
|
||
HostName 100.123.82.91
|
||
User zhangwenqi
|
||
Port 22
|
||
ServerAliveInterval 30
|
||
TCPKeepAlive yes
|
||
ConnectTimeout 60
|
||
```
|
||
|
||
之后直接 `ssh linux-vm` 即可连接。
|
||
|
||
## 4.4 VS Code Remote-SSH
|
||
|
||
1. VS Code 安装 Remote - SSH 扩展
|
||
2. Cmd+Shift+P → "Remote-SSH: Connect to Host"
|
||
3. 选择 linux-vm
|
||
4. 连接成功后打开文件夹 `/home/zhangwenqi/Radxa_CM5`
|
||
|
||
---
|
||
|
||
# 第五部分:换新电脑配置指南
|
||
|
||
## 5.1 虚拟机备份说明
|
||
|
||
### 当前备份状态(2026-04-16)
|
||
|
||
| 项目 | 状态 |
|
||
|------|------|
|
||
| 备份格式 | OVF(.ovf + .vmdk + .mf 三个文件) |
|
||
| 备份内容 | 系统 + Docker(不含 SDK,不含工具链 COPY 到镜像) |
|
||
| Docker 镜像 | android-builder:12.x 基础环境已装,**未对齐官方工具链** |
|
||
| SDK 压缩包 | 单独存放在 Windows 电脑/移动硬盘 |
|
||
|
||
### OVF 备份包含的设置
|
||
|
||
| 配置项 | 是否备份 | 导入后能否修改 |
|
||
|--------|---------|---------------|
|
||
| 硬盘大小(700GB) | 包含 | 可扩大,不可缩小 |
|
||
| 内存大小 | 包含 | 可自由调整 |
|
||
| CPU 核心数 | 包含 | 可自由调整 |
|
||
| 网络适配器类型(桥接) | 包含 | 可改为 NAT/桥接/仅主机 |
|
||
| 操作系统和所有软件 | 包含 | — |
|
||
|
||
三个文件必须放在同一文件夹,缺一不可:
|
||
- `.ovf` — 虚拟机配置描述(CPU、内存、网卡等)
|
||
- `.vmdk` — 虚拟磁盘数据(系统和所有文件)
|
||
- `.mf` — 校验文件(验证完整性)
|
||
|
||
## 5.2 新电脑是 Windows — 完整恢复步骤
|
||
|
||
### 步骤 1:导入虚拟机
|
||
|
||
1. 新电脑安装 **VMware Workstation 17**(或更高版本)
|
||
2. VMware → 文件 → **打开** → 选择 `.ovf` 文件
|
||
3. 选择虚拟机存放位置(建议放在 SSD 上)
|
||
4. 等待导入完成
|
||
5. (可选)调整虚拟机参数:右键虚拟机 → 设置
|
||
- 内存:建议 16GB+(Android 编译非常吃内存)
|
||
- CPU:建议分配 8 核+
|
||
- 网络:选择**桥接模式**(与宿主机同网段)
|
||
|
||
### 步骤 2:启动虚拟机并恢复网络
|
||
|
||
1. 启动虚拟机,登录(用户: zhangwenqi)
|
||
|
||
2. 检查网络:
|
||
```bash
|
||
ip addr show # 确认获取到 IP
|
||
ping 8.8.8.8 # 测试内网连通性
|
||
```
|
||
|
||
3. 恢复 Tailscale:
|
||
```bash
|
||
sudo systemctl status tailscaled # 检查 Tailscale 服务
|
||
sudo tailscale up # 重新认证(可能需要)
|
||
tailscale ip -4 # 记录新的 Tailscale IP
|
||
```
|
||
|
||
4. 更新代理配置(Windows IP 可能变化):
|
||
```bash
|
||
# 在 Windows cmd 执行 ipconfig 获取新的局域网 IP
|
||
# 然后更新虚拟机代理配置
|
||
sudo nano /etc/profile.d/proxy.sh
|
||
# 将 192.168.6.57 替换为新 Windows 的局域网 IP
|
||
source /etc/profile.d/proxy.sh
|
||
|
||
# 测试外网
|
||
curl -I https://www.google.com
|
||
```
|
||
|
||
### 步骤 3:恢复 SDK
|
||
|
||
```bash
|
||
# 将 SDK 压缩包从移动硬盘拷贝到虚拟机
|
||
# 可以通过 VMware 共享文件夹、scp、或 USB 挂载
|
||
cd ~/Radxa_CM5/SDK_Android/
|
||
# 确认文件
|
||
ls -lh radxa_android_sdk_backup.tar.gz
|
||
# 校验 MD5
|
||
md5sum radxa_android_sdk_backup.tar.gz
|
||
```
|
||
|
||
### 步骤 4:对齐官方 Dockerfile 环境(重要)
|
||
|
||
备份的虚拟机中 Docker 镜像是基础版本,**缺少 5 套 Linaro 交叉编译工具链**。需要重新下载工具链并重建镜像。
|
||
|
||
#### 4.1 确认 Docker 和基础镜像正常
|
||
|
||
```bash
|
||
docker images android-builder
|
||
# 预期看到 android-builder:12.x 镜像
|
||
```
|
||
|
||
#### 4.2 确认代理可用(下载工具链需要外网)
|
||
|
||
```bash
|
||
curl -I https://releases.linaro.org/
|
||
# 预期 HTTP 200
|
||
```
|
||
|
||
如果不通,先按 3.7 节配置虚拟机代理。
|
||
|
||
#### 4.3 下载 5 套交叉编译工具链
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/docker
|
||
|
||
# 1. gcc-linaro-6.3.1 arm-linux-gnueabihf(99MB)
|
||
curl -L -o gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz \
|
||
'https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/arm-linux-gnueabihf/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz'
|
||
|
||
# 2. gcc-linaro-aarch64-none-elf-4.8(50MB)
|
||
curl -L -o gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2 \
|
||
'https://releases.linaro.org/archive/13.11/components/toolchain/binaries/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2'
|
||
|
||
# 3. gcc-arm-none-eabi-6-2017-q2-update(96MB)
|
||
curl -L -o gcc-arm-none-eabi-6-2017-q2-update.tar.bz2 \
|
||
'https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2'
|
||
|
||
# 4. gcc-linaro-6.3.1 aarch64-linux-gnu(106MB)
|
||
curl -L -o gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz \
|
||
'https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/aarch64-linux-gnu/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz'
|
||
|
||
# 5. gcc-linaro-7.2.1 aarch64-elf(51MB)
|
||
curl -L -o gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz \
|
||
'https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/aarch64-elf/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz'
|
||
```
|
||
|
||
#### 4.4 解压工具链
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/docker
|
||
tar -xf gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
|
||
tar -xf gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2
|
||
tar -xf gcc-arm-none-eabi-6-2017-q2-update.tar.bz2
|
||
tar -xf gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz
|
||
tar -xf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz
|
||
|
||
# 确认解压结果(应有 5 个目录)
|
||
ls -d gcc-*/
|
||
```
|
||
|
||
#### 4.5 确认 Dockerfile 包含 COPY 命令
|
||
|
||
查看 `~/Radxa_CM5/docker/Dockerfile`,确认包含以下 COPY 行:
|
||
|
||
```dockerfile
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
|
||
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
|
||
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/toolchains/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
|
||
COPY ./gcc-arm-none-eabi-6-2017-q2-update /opt/toolchains/gcc-arm-none-eabi-6-2017-q2-update
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu
|
||
COPY ./gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf /opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf
|
||
```
|
||
|
||
如果 Dockerfile 中没有这些行(备份时可能是旧版本),用以下完整 Dockerfile 替换:
|
||
|
||
```bash
|
||
cat > ~/Radxa_CM5/docker/Dockerfile << 'EOF'
|
||
FROM ubuntu:20.04
|
||
|
||
RUN rm /etc/apt/sources.list
|
||
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse" | tee /etc/apt/sources.list
|
||
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse" >> /etc/apt/sources.list
|
||
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse" >> /etc/apt/sources.list
|
||
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse" >> /etc/apt/sources.list
|
||
|
||
ENV DEBIAN_FRONTEND=noninteractive
|
||
|
||
RUN apt-get update -y && apt-get install -y software-properties-common apt-utils
|
||
RUN add-apt-repository -y ppa:deadsnakes/ppa
|
||
RUN apt-get update -y && apt-get install -y python3.8
|
||
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 150
|
||
RUN apt-get install -y python3-pip && pip install pycrypto
|
||
|
||
RUN apt-get update -y && apt-get install -y openjdk-8-jdk python git-core gnupg flex bison gperf build-essential \
|
||
zip curl gawk liblz4-tool zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
|
||
libncurses5 libncurses-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
|
||
libgl1-mesa-dev libxml2-utils xsltproc unzip mtools u-boot-tools \
|
||
htop iotop sysstat iftop pigz bc device-tree-compiler lunzip \
|
||
dosfstools vim-common parted udev libssl-dev sudo rsync python3-pyelftools cpio
|
||
|
||
RUN curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > /usr/local/bin/repo && \
|
||
chmod +x /usr/local/bin/repo && \
|
||
which repo
|
||
|
||
ENV REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
|
||
|
||
RUN apt-get install -y lzop swig
|
||
RUN apt-get update -y && apt-get install -y tzdata
|
||
|
||
RUN mkdir /opt/toolchains
|
||
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
|
||
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
|
||
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/toolchains/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
|
||
COPY ./gcc-arm-none-eabi-6-2017-q2-update /opt/toolchains/gcc-arm-none-eabi-6-2017-q2-update
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
|
||
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu
|
||
COPY ./gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf /opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf
|
||
|
||
RUN apt-get install -y net-tools gcc-arm-linux-gnueabihf gcc-arm-none-eabi
|
||
|
||
ENV TZ=Asia/Shanghai
|
||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||
EOF
|
||
```
|
||
|
||
#### 4.6 重建 Docker 镜像
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/docker
|
||
sudo docker build -t android-builder:12.x .
|
||
# 耗时约 10-15 分钟
|
||
```
|
||
|
||
#### 4.7 验证环境完整
|
||
|
||
```bash
|
||
sudo docker run --rm android-builder:12.x bash -c \
|
||
'echo "=== 工具链 ===" && ls /opt/toolchains/ && \
|
||
echo "" && echo "=== 编译器 ===" && \
|
||
/opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc --version | head -1 && \
|
||
/opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf-gcc --version | head -1 && \
|
||
/opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc --version | head -1 && \
|
||
java -version 2>&1 | head -1 && python3 --version && which repo'
|
||
```
|
||
|
||
预期输出:
|
||
- /opt/toolchains/ 下有 5 个工具链目录
|
||
- arm-linux-gnueabihf-gcc 6.3.1
|
||
- aarch64-elf-gcc 7.2.1
|
||
- aarch64-linux-gnu-gcc 6.3.1
|
||
- openjdk 1.8.0
|
||
- Python 3.8.x
|
||
- /usr/local/bin/repo
|
||
|
||
#### 4.8 清理下载的压缩包
|
||
|
||
```bash
|
||
cd ~/Radxa_CM5/docker
|
||
rm -f *.tar.xz *.tar.bz2
|
||
```
|
||
|
||
注意:Docker 镜像加速器配置(`/etc/docker/daemon.json`)在备份中已保留,但镜像加速地址可能失效。
|
||
如果 `docker build` 拉取 ubuntu:20.04 失败,参考 3.4 节更新加速器地址。
|
||
|
||
## 5.2 新电脑是 Windows — 快速恢复
|
||
|
||
### 步骤 1:导入虚拟机
|
||
|
||
1. 新电脑安装 **VMware Workstation 17**
|
||
2. VMware → 文件 → 打开 → 选择 `.ovf` 文件
|
||
3. 选择存放位置,等待导入
|
||
4. 调整参数(右键 → 设置):内存 16GB+,CPU 8 核+,网络桥接模式
|
||
|
||
### 步骤 2:恢复网络和代理
|
||
|
||
1. 启动虚拟机,检查网络
|
||
2. 更新 `/etc/profile.d/proxy.sh` 中的 Windows IP(如果 IP 变化)
|
||
3. Windows 安装 Clash,开启 Allow LAN,防火墙放行 7890
|
||
4. 安装 Tailscale(Windows + 虚拟机),同账号登录
|
||
|
||
### 步骤 3:恢复 SDK 并对齐 Dockerfile
|
||
|
||
1. 拷贝 SDK 压缩包到虚拟机 `~/Radxa_CM5/SDK_Android/`
|
||
2. 按上方 **步骤 4(4.1~4.8)** 对齐官方 Dockerfile 环境
|
||
3. 解压 SDK 并编译验证
|
||
|
||
### 步骤 4:配置 Mac 远程开发(如有)
|
||
|
||
按第四部分重新配置 Mac 端 SSH 和 Tailscale。
|
||
|
||
## 5.3 新电脑是 Mac(远程控制 Windows 开发)
|
||
|
||
Mac M 芯片无法运行 x86 虚拟机,采用 Mac 远程控制 Windows 方案。
|
||
|
||
### 前提条件
|
||
- Windows 电脑保持运行(作为编译服务器)
|
||
- Windows 上已按 5.2 完成虚拟机恢复和 Dockerfile 对齐
|
||
- Mac 和 Windows 都安装 Tailscale
|
||
|
||
### 步骤 1:Windows 端配置
|
||
|
||
1. 按 5.2 完成虚拟机导入、网络恢复、SDK 恢复、Dockerfile 对齐
|
||
|
||
2. 安装 Tailscale(Windows 版),用同一账号登录
|
||
|
||
3. 安装 Clash for Windows,导入订阅,开启 "允许局域网连接入Clash"
|
||
防火墙放行:
|
||
```powershell
|
||
netsh advfirewall firewall add rule name="Clash Proxy" dir=in action=allow protocol=tcp localport=7890
|
||
```
|
||
|
||
4. 启动虚拟机,确认服务正常:
|
||
```bash
|
||
tailscale status
|
||
sudo systemctl status ssh
|
||
curl -I https://www.google.com # 验证外网代理
|
||
docker images android-builder # 验证 Docker 镜像
|
||
```
|
||
|
||
5. (可选)设置虚拟机开机自启:VMware → 编辑 → 首选项 → 共享虚拟机 → 开机启动
|
||
|
||
### 步骤 2:新 Mac 端配置
|
||
|
||
1. 安装 Tailscale(App Store),用同一账号登录
|
||
|
||
2. 安装 ClashX Pro,导入订阅
|
||
|
||
3. 配置 ClashX Pro 与 Tailscale 共存(按第二部分操作):
|
||
- 添加 Tailscale 直连规则到代理配置
|
||
- 关闭 Tailscale DNS Settings
|
||
|
||
4. 生成 SSH 密钥并部署:
|
||
```bash
|
||
ssh-keygen -t ed25519 -C "new-mac-to-linux-vm"
|
||
ssh-copy-id zhangwenqi@<虚拟机Tailscale_IP>
|
||
```
|
||
注意:Tailscale IP 可能与之前不同,在虚拟机中执行 `tailscale ip -4` 确认。
|
||
|
||
5. 配置 SSH config(`~/.ssh/config`):
|
||
```
|
||
Host linux-vm
|
||
HostName <虚拟机Tailscale_IP>
|
||
User zhangwenqi
|
||
Port 22
|
||
ServerAliveInterval 30
|
||
TCPKeepAlive yes
|
||
ConnectTimeout 60
|
||
```
|
||
|
||
6. 安装 VS Code + Remote-SSH 扩展
|
||
|
||
7. Cmd+Shift+P → "Remote-SSH: Connect to Host" → linux-vm
|
||
|
||
### 步骤 3:验证
|
||
|
||
```bash
|
||
# Mac 终端测试
|
||
ping <虚拟机Tailscale_IP>
|
||
ssh linux-vm
|
||
|
||
# 验证 Docker 环境完整(应显示 5 套工具链)
|
||
ssh linux-vm "docker run --rm android-builder:12.x ls /opt/toolchains/"
|
||
|
||
# 验证 VPN
|
||
# 浏览器访问 YouTube
|
||
```
|
||
|
||
### 日常使用流程
|
||
|
||
1. Windows 电脑开机 → 虚拟机自动启动(或手动启动)
|
||
2. Mac 打开 Tailscale + ClashX Pro
|
||
3. VS Code → Remote-SSH → linux-vm
|
||
4. 打开 `/home/zhangwenqi/Radxa_CM5` 开始开发
|
||
|
||
---
|
||
|
||
# 第六部分:故障排除
|
||
|
||
## 6.1 Tailscale 连不上
|
||
|
||
```bash
|
||
# Linux 端检查
|
||
sudo tailscale status
|
||
sudo systemctl restart tailscaled
|
||
sudo tailscale up
|
||
|
||
# 诊断
|
||
tailscale netcheck
|
||
```
|
||
|
||
## 6.2 SSH 连接被拒绝
|
||
|
||
```bash
|
||
# Linux 端检查
|
||
sudo systemctl status ssh
|
||
sudo netstat -tlnp | grep :22
|
||
sudo ufw status
|
||
|
||
# 重启 SSH
|
||
sudo systemctl restart ssh
|
||
```
|
||
|
||
## 6.3 VPN 开启 Tailscale 后失效
|
||
|
||
检查两个配置:
|
||
1. ClashX Pro 配置文件中 Tailscale 直连规则是否存在(订阅更新会覆盖)
|
||
2. Tailscale DNS Settings 是否已关闭
|
||
|
||
## 6.4 Docker 拉取镜像超时
|
||
|
||
Docker Hub 被墙,检查镜像加速配置:
|
||
```bash
|
||
cat /etc/docker/daemon.json
|
||
# 确认 registry-mirrors 配置正确
|
||
sudo systemctl restart docker
|
||
```
|
||
|
||
## 6.5 VS Code Remote-SSH 连接超时
|
||
|
||
在 `~/.ssh/config` 中增大超时:
|
||
```
|
||
Host linux-vm
|
||
ConnectTimeout 120
|
||
ServerAliveInterval 30
|
||
ServerAliveCountMax 5
|
||
```
|
||
|
||
---
|
||
|
||
# 第七部分:快速参考
|
||
|
||
## 日常连接命令
|
||
|
||
```bash
|
||
# Mac 终端直连
|
||
ssh linux-vm
|
||
|
||
# 文件传输
|
||
scp file.txt linux-vm:~/
|
||
scp -r folder/ linux-vm:~/destination/
|
||
```
|
||
|
||
## VS Code 操作
|
||
|
||
- Cmd+Shift+P → "Remote-SSH: Connect to Host" → linux-vm
|
||
- Cmd+Shift+P → "Remote-SSH: Disconnect"
|
||
|
||
## Linux 虚拟机管理
|
||
|
||
```bash
|
||
# Tailscale
|
||
tailscale ip -4
|
||
tailscale status
|
||
sudo tailscale down / up
|
||
|
||
# Docker
|
||
docker images
|
||
docker run -it --name android-build -v ~/Radxa_CM5/SDK_Android:/workspace -w /workspace android-builder:12.x bash
|
||
docker start -ai android-build # 重新进入已创建的容器
|
||
|
||
# SSH
|
||
sudo systemctl status ssh
|
||
sudo systemctl restart ssh
|
||
```
|
||
|
||
---
|
||
|
||
文档版本: 2.0
|
||
最后更新: 2026-04-15
|
||
适用系统: Ubuntu 20.04 LTS (x86_64), macOS
|
||
网络环境: 跨网络远程开发(Tailscale + ClashX Pro 共存)
|