Skip to content

Mac 原生编译瑞芯微与地瓜机器人平台 ​

同一套 SDK,S100P kernel 从 63.5 分钟降到 9.1 分钟,RV1126B 从 1217 秒降到 293 秒。变化不是把 Linux SDK 改成 macOS 工程,而是把主要编译任务从 Rosetta 仿真的 x86 容器,移到 arm64 Linux 容器。

这里的“原生”指 Linux 容器里的编译器按 arm64 执行,不是 macOS 本机编译。下面的数据来自当时的构建记录,只代表那套环境;原文没有完整基准配置,不能据此推算任意一台 Mac 的耗时。

少等了多久? ​

图中 RV1126B 按分钟取一位小数;原始秒数和较短的 MCU 构建放在表里,避免被 kernel 的纵轴淹没。仿真均指 Rosetta,原生均指 arm64 Linux 容器。

构建项Rosetta 仿真arm64 原生记录口径
S100P kernel63.5 min9.1 min冷编译,约 7×
RV1126B kernel1217 s293 s冷编译,-j14,约 4.1×
S100P MCU22 s16 s冷编译
S100P MCU8 s3 s增量编译

收益并不统一:kernel 差距大,MCU 冷编译只少了 6 秒。两平台都完成过烧录上板验证;“编过”之外,还要确认镜像里的内容和板子启动后的状态。

把大头交给 arm64,打包保留 x86 ​

OrbStack 提供 Linux 环境。arm64 容器承担主要编译,原来的 amd64 路径保留,供兼容构建和同事的 x86 Linux 主机使用。Rockchip 的部分 rkbin 工具仍是 x86 ELF,但集中在打包阶段,不必为这段工作让整个 kernel 都跑仿真。

这些命令依赖项目已经完成的适配,不是给任意厂商 SDK 加一个变量就能用。记录中的默认平台仍为 amd64:

平台原生 kernel 构建入口
RV1126BRV1126B_BUILD_PLATFORM=linux/arm64 scripts/docker/build.sh kernel
S100PS100_BUILD_PLATFORM=linux/arm64 west s100-build kernel

rkbin 里的 mkimage、loaderimage、trust_merger、boot_merger、firmwareMerger、resource_tool 等需要分别处理:记录中静态链接 x86 程序由 OrbStack Rosetta 执行,动态链接程序用 qemu-user、multiarch 和 x86 运行库。

最容易误判的三件事 ​

1. ADB 起不来,不一定缺 USB 驱动 ​

S100P 刷完后报 udc: failed to start g_comp: -19。表面是 UDC 绑定失败,最后追到镜像选包和动态库路径,而不是补一个驱动就好。

查到的问题最终处理
在线打包先删本地新版 deb,拿远端旧包替代下载只补缺包,按 Debian Version 保留最新
旧 hobot-configs 没生成 /etc/ld.so.conf.d/hobot.conf,adbd 退出 127装包后直接补库路径配置并执行 ldconfig
virtiofs 上 sudoers 属主异常,postinst 中的 sudo 失败不再依赖那一步隐式修正,由 fix_rootfs_ld_path() 写进镜像

修完重新全刷,冷启动 ADB 自动恢复。这个案例让我把“产物生成成功”和“产物内容正确”分开检查。

2. 文件系统会在编译前就伤到源码 ​

macOS 默认 APFS 不区分大小写。Linux netfilter 中 xt_mark.c 和 xt_MARK.c 这样的成对文件会被合并,所以源码先放到 APFS(区分大小写)卷,再谈工具链。

层次RV1126BS100P
Mac 源码目录大小写敏感卷大小写敏感卷
容器工作目录Docker named volume(记录中为 btrfs)直接 bind mount,类型为 virtiofs
原因check-sdk 只放行部分文件系统,拒绝 virtiofs没有这项检查,但仍须处理权限与 owner 差异

当时查过的 check-sdk 没有宿主 arch 检查,只查 FSTYPE 和工具是否存在。把它拒绝 virtiofs 误读成“只能 x86 编译”,会走错方向。

3. 目标是 arm64,不代表工具链能在 arm64 上跑 ​

SDK 硬编码 aarch64-none-linux-gnu-*,但当时探测 ARM 11.3 / 12.2 / 13.3 下载地址和 D-Robotics 归档,没有找到所需的 aarch64 宿主版本。采用的办法是容器内 Ubuntu GCC,加同前缀符号链接,保留 SDK 的 CROSS_COMPILE 和 --host 约定。

RV1126B 还需给 get_toolchain 补“aarch64 宿主 → aarch64 目标”分支。MCU 是另一回事:RISC-V 仍需对应宿主版本的交叉编译器,scons 只读 rtconfig.py,仅设置 CROSS_COMPILE 不会生效。

做到了哪里,不能外推到哪里? ​

平台已走通的构建范围其余耗时 / 产物记录
S100PMCU、kernel、deb-all、完整镜像及 fastboot 烧录18 个 deb:7.6 min;镜像:4.6 min;emmc_disk.simg 8.85GB
RV1126Bkernel、buildroot、recovery、update.img,以及 AMP 板 RT-Thread RISC-V MCUbuildroot 约 70 min;recovery 约 37 min;update.img 1.4GB

这不是所有 Linux SDK 的通用移植方案。闭源宿主工具、旧 bootstrap 编译器、rootfs 打包和首次启动都可能留下架构或文件系统依赖。保留 amd64 兼容路径有实际价值;能省多少时间,要按自己的构建项测。

附录:打包、MCU 和烧录的具体坑

S100P 镜像工具要和板端配套 ​

问题当时的处理
deb-all 缺 rootfs sysroot先 image-prepare 下载 2.5GB samplefs
virtiofs 拒绝 tar --same-owner,容器 root 实为 uid 501检测 virtiofs,跳过 owner 修正
e2fsprogs 1.46 的 mkfs.ext4 -d 对 symlink 报 ENOENT改用 1.47,添加 -E no_copy_xattrs
1.47 默认 orphan_file,板端 1.46 无法首启扩容mke2fs 添加 -O ^orphan_file

RV1126B:别让编译通过掩盖地址错位 ​

问题当时的处理
RT_HW_CACHE_FLUSH 未声明sensor_acq.c 补 <rthw.h>
rpmsg / timesync 链接未定义ITS 的 rtt_config 从 evb1 改为 rv1126b_mcu_dev
RISC-V 工具链仍选 x86rtconfig.py 按宿主选 linux-arm64 / linux-x86
固件 245KB 超过预留 232KB,报 location counter backwardshpmcu 扩到 256KB,共享内存上移 0x6000
Linux 未把 uart2 让给 MCUDTS 从 amp-mcu 切到 mcu-dev
Go 1.4 bootstrap 不支持 aarch64用预编译 Go 1.19 作 stage1
rkaiq j2s 带冗余 x86 标志,如 -m64删除宿主架构不适用的标志
rsync 排除 rockdev/ 时误伤工具子目录只排除顶层 '/rockdev/'

那版 AMP 地址在 link.lds、ITS、DTS 和三处源码里各写一次,扩容必须同步六处;不要把这里的 0x6000 当成其它固件的通用补丁。原生 GCC 11.4 还触发过 rtl8733bu 的 -Wmisleading-indentation,当时以 KCFLAGS=-Wno-error 绕过 CONFIG_WERROR=y;这是兼容处理,不表示警告已经修好。

烧录不在容器里混用工具 ​

平台下载模式与工具
RV1126Badb reboot loader,记录中等 5–18s 枚举(VID 0x2207);用 upgrade_tool / rkdeveloptool,Mac 工具解压后须有执行权限
S100PAP 串口约每 100ms 发一个 Ctrl+C(0x03),见 Hobot$ 后输入 fastboot 0;用 Horizon fastboot,flash_all.sh -m all

S100P 每 10ms 连发 Ctrl+C 会淹没 U-Boot 输入缓冲,反而打不断启动。两块板并存时用 ANDROID_SERIAL 指定目标。板子不在身边时,走远程开发体系里的“传产物、远端刷写”。

留下可重复下载的工具链 ​

重要工具链另存云端,通过 fetch 脚本按 uname -m 下载并校验 SHA256,再由构建入口调用。原记录公网下载约 24 MB/s,只是那次传输速度。buildroot 上游曾慢到约 1KB/s,大包临时下载到 dl/;这和编译速度不是同一个问题。

容器里的小故障检查方向
代理连 127.0.0.1 被拒它指向容器自己,宿主代理用 host.docker.internal
找不到 uid 501 用户名Dockerfile 用 ARG 动态创建匹配用户
Docker metadata 拉取超时检查 auth.docker.io 的代理,别把所有下载都当成同一条链路
改源码仍报旧错buildroot 的 .stamp_extracted 阻止重提取,清理对应包构建目录后重建
这篇里有不清楚的地方,或者想聊类似的东西?私信我 →