尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

第一次全量编译与打包—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】

第一次全量编译与打包—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】 路认清了。今天跑第一次全量编译从敲命令到认出产物哪些 img 是分区哪个整包能拿去刷。./build.sh --product-name rk3568_evb --ccache跑了三十多分钟最后一行看起来像成功。你在out/里转了一圈看见一堆.img随手拿一个叫update.img的丢进刷机工具工具打不开换boot_linux.img当整包刷工具说分区表不对。再过一天终于找到sd_image.img刷进去内核 panic串口在等fe310000.sdhci你这张卡明明插在 SD 槽里。构建成功只说明各分区镜像生成了。可刷的整包是另一次打包。打包用的工具不在./build.sh里空分区镜像构建也不生成。SD 和 eMMC 的差别不在内核在两份 fstab。这几件事叠在一起第一次全量的人会觉得镜像体系有病。它没病它只是把分区方案、瑞芯微的 RKFW、开源鸿蒙自己的 ramdisk缝在同一个目录里。环境那篇把 Ubuntu、依赖、白名单、khrplatform.h说过了。这篇从「已经能开始./build.sh」往下写命令、产物、打包脚本、两种整包头、fstab 介质、编完怎么验、OOM 137 和 ninja dupbuild。产品名rk3568_evb。1. 全量命令就是这一条时间是 3040 分钟cd /path/to/OpenHarmony ./build.sh --product-name rk3568_evb --ccache 21 | tee /tmp/ohos-build.log echo exit:$?16 核、32 GB 内存、SSD、ccache 已热大概 3040 分钟。冷 ccache、第一次、还要重编内核靠近 40。16 GB 内存硬编也能开机链接vmlinux和若干 thinLTO 的大 so 时会 OOM退出码137。那不是源码错。常用开关# 跳过 gn genout 已有 ninja 规则时省 34 分钟 ./build.sh --product-name rk3568_evb --ccache --fast-rebuild # 只跑某个 target不打大镜像 ./build.sh --product-name rk3568_evb --ccache --fast-rebuild \ --build-target kernel --disable-package-image # 列产品、列 targethb 若在 PATH hb status hb tool --ls | grep -E boot_linux|vendor|system|ramdisk | headninja -w dupbuildwarn必须在实际编译命令里。开源鸿蒙的 GN 偶尔让两个 target 写同一个输出ninja 默认当错误。板级包装脚本若没加你自己会在日志里看见ninja: error: multiple rules generate xxx看起来像两个模块抢文件。公版就这样。包装里应类似# 板级或 build.sh 调 ninja 的地方 ninja -w dupbuildwarn -C out/rk3568_evb -j$(nproc)没有包装就自己补。不要去「修」那两个 target 的输出路径那是跟整棵树作对。日志用tee留下来。失败时从末尾往上翻先看退出码再看最后一个FAILED。中间几千行 warning 多数可以当没看见。2. build.sh 停在零散镜像不停在可刷整包成功之后先去这里out/rk3568_evb/packages/phone/images/你应该能看到这些名字缺哪个后面说怎么补boot_linux.img 内核 Image extlinux 常打进一份 ramdisk resource.img logo rk-kernel.dtb system.img 用户态系统、系统应用 vendor.img 芯片厂商、HDF uhdf、init.rk30board、fstab.rk30board ramdisk.img 一阶段根fstab.required 在这里 userdata.img 空或几乎空的 data MiniLoaderAll.bin BootROM 之后第一段含 DDR 训练 uboot.img parameter.txt GPT 分区表打包和 U-Boot 都认它 updater.img sys_prod.img chip_prod.img eng_system.img以及构建不一定生成、打包却要的misc.img bootctrl.img chip_ckm.img eng_chipset.img这四个是占位。正常启动内容为空几百字节到 64K 全零。package-file点了名afptool找不到文件就直接 FAILED。它们固化在device/board/rk/rk3568_evb/loader/prebuilt-images/./build.sh不管它们。新机rm -rf out之后images 里没有这四个是正常的。看体积心里有个数IMGout/rk3568_evb/packages/phone/images ls -lh $IMG/*.img $IMG/MiniLoaderAll.bin $IMG/parameter.txt经验范围按产品裁剪会变差一个数量级才需要紧张文件常见大小小得离谱时system.img1.22 GB系统应用没打进去或 ext 镜像脚本提前失败vendor.img100400 MBhdf、相机 IQ、GPU so 缺boot_linux.img3264 MB 的 ext2空壳Image 没拷进去resource.img28 MB缺 dtb 或缺 logoramdisk.img几 MB缺 fstab.required 会在启动时删 system见启动链那篇userdata.img很小正常首启格式化MiniLoaderAll.bin几百 KB缺了整包打不出boot_linux.img必须是ext2。U-Boot 的bootrkp认这个格式、认分区名boot_linux。不要把它转成 FIT、不要改名成boot。file boot_linux.img应类似boot_linux.img: Linux rev 1.0 ext2 filesystem data里面至少有debugfs -R ls -l / out/rk3568_evb/packages/phone/images/boot_linux.img debugfs -R ls -l /extlinux out/rk3568_evb/packages/phone/images/boot_linux.img期望看到Image或内核文件、extlinux.conf、最好还有ramdisk.img。extlinux.conf缺initrd那一行是致命的启动链那篇写为什么会把 system 分区文件删光。这里先验存在debugfs -R cat /extlinux/extlinux.conf \ out/rk3568_evb/packages/phone/images/boot_linux.img里面要有类似label OpenHarmony kernel /Image initrd /extlinux/ramdisk.img fdt /extlinux/toybrick.dtbfdt那行可以有。开机真正用的 dtb 来自 resource 分区的rk-kernel.dtb不要以为改 boot_linux 里这份 dtb 就等于改了设备树。3. 打包afptool rkImageMaker package-file可刷整包不是./build.sh吐的。板级脚本pack_update_img.sh做四件事把工具就位、把空分区补齐、把 images 同步到打包目录、两步合成。三件套本身不在开源鸿蒙源码里构建也不生成。放在device/board/rk/rk3568_evb/loader/afptool device/board/rk/rk3568_evb/loader/rkImageMaker device/board/rk/rk3568_evb/loader/package-fileafptool、rkImageMaker是 x86-64 静态二进制。package-file是文本分区名必须和parameter.txt一致。一份能在新机上跑的pack_update_img.sh骨架如下。路径按产品名写死不要留占位符。#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR$(cd $(dirname $(realpath $0)) pwd) # 脚本若放在源码根 ROOT$SCRIPT_DIR PRODUCTrk3568_evb BOARD_LOADER$ROOT/device/board/rk/${PRODUCT}/loader IMG$ROOT/out/${PRODUCT}/packages/phone/images PKG$ROOT/out/${PRODUCT}/packages/phone/pack_update echo [0] tools mkdir -p $PKG $PKG/Image $PKG/loader for f in afptool rkImageMaker package-file; do src$BOARD_LOADER/$f dst$PKG/$f [ -f $src ] || { echo missing $src; exit 1; } if [ ! -f $dst ] || ! cmp -s $src $dst; then cp -f $src $dst fi done chmod x $PKG/afptool $PKG/rkImageMaker # MiniLoader 给 rkImageMaker -RK3568 用 cp -f $IMG/MiniLoaderAll.bin $PKG/loader/MiniLoaderAll.bin echo [1] prebuilt empty images for f in misc.img bootctrl.img chip_ckm.img eng_chipset.img; do if [ ! -s $IMG/$f ]; then cp -f $BOARD_LOADER/prebuilt-images/$f $IMG/$f echo filled $f fi done echo [2] sync images - pack_update/Image shopt -s nullglob for f in $IMG/*.img $IMG/MiniLoaderAll.bin $IMG/parameter.txt; do cp -f $f $PKG/Image/ done echo [3] afptool - RKAF update.img cd $PKG rm -f update.img ./afptool -pack . update.img echo [4] rkImageMaker - RKFW sd_image.img # -os_type:ANDROIDOS 必须有中间不能空格 rm -f sd_image.img ./rkImageMaker -RK3568 loader/MiniLoaderAll.bin update.img \ sd_image.img -os_type:ANDROIDOS ls -lh update.img sd_image.img echo RKFW: $PKG/sd_image.img关键点先同步再打包。pack_update/Image/不会因为images/新了就自己变。漏了 cp打出来的是昨天的 boot_linux。-os_type:ANDROIDOS一个空格都不能加。缺了报Error:Get image version failed!。rkImageMaker 从文件末尾附近读 PARM 块拿FIRMWARE_VER。-RK3568是芯片代号不是产品名。写成-RK3568_evb会失败。afptool 的工作目录要能看见package-file和Image/。package-file里的相对路径按这个目录解。package-file长这样分区名必须与 parameter.txt 里括号内的名字一致# NAME PATH package-file package-file bootloader Image/MiniLoaderAll.bin parameter Image/parameter.txt uboot Image/uboot.img misc Image/misc.img resource Image/resource.img boot_linux Image/boot_linux.img system Image/system.img vendor Image/vendor.img userdata Image/userdata.img sys_prod Image/sys_prod.img chip_prod Image/chip_prod.img updater Image/updater.img bootctrl Image/bootctrl.img chip_ckm Image/chip_ckm.img eng_system Image/eng_system.img eng_chipset Image/eng_chipset.img名字对不上的后果很阴afptool 仍可能成功对应镜像根本没写进整包。刷完板子用的还是旧分区或空分区。打包前对一次# parameter.txt 里括号中的名字 grep -oE \([a-z0-9_]:?[^)]*\) \ out/rk3568_evb/packages/phone/images/parameter.txt # package-file 第一列 awk NF2 $1 !~ /^#/ {print $1} \ device/board/rk/rk3568_evb/loader/package-fileboot_linux必须叫boot_linux。U-Boot 硬编码找这个名改成boot或kernel日志不一定有明显错误就是起不来。misc.img必须全零。U-Boot 看 misc 决定要不要进 recovery。非零的 misc 会让你「刷完怎么进了 recovery」。md5sum out/rk3568_evb/packages/phone/images/misc.img # 64K 全零的 md5 是固定的和你固化在 loader/prebuilt-images 里那份比 cmp device/board/rk/rk3568_evb/loader/prebuilt-images/misc.img \ out/rk3568_evb/packages/phone/images/misc.img echo misc_ok4. RKFW 才是拿去刷的RKAF 常加载失败打包目录最后躺两个文件文件头 4 字节谁产生干什么sd_image.imgRKFWrkImageMaker**真正刷的整包**。SDDiskTool、RKDevTool「升级固件」都吃这个update.imgRKAFafptool中间产物。本机 RKDevTool 经常「打开固件失败」看头不要看文件名xxd -l 4 out/rk3568_evb/packages/phone/pack_update/sd_image.img xxd -l 4 out/rk3568_evb/packages/phone/pack_update/update.img期望00000000: 524b 4657 RKFW 00000000: 524b 4146 RKAFWindows 上certutil -f -encodehex D:\ohos\sd_image.img D:\ohos\head.txt 4 type D:\ohos\head.txt52 4B 46 57是 RKFW52 4B 41 46是 RKAF。有人看见update.img眼熟公版文档也写 update。那是另一条烧录链路配config.cfg走「下载镜像」。本机实践里 RKAF 经常根本加载失败。eMMC 交付也交 RKFW只是把sd_image.img改名为emmc-xxx.img。文件头不会因为改名变成另一种格式。介质信息靠文件名约定不靠魔数。# 出 eMMC 包先把 fstab 改成 sdhci重打 ramdisk vendor再 pack cp out/rk3568_evb/packages/phone/pack_update/sd_image.img \ /mnt/hgfs/share/emmc-rk3568_evb.img # 出 SD 包fstab 改回 dwmmc再 pack cp out/rk3568_evb/packages/phone/pack_update/sd_image.img \ /mnt/hgfs/share/sd_image.img md5sum /mnt/hgfs/share/sd_image.img /mnt/hgfs/share/emmc-rk3568_evb.img共享目录、md5是给 Windows 那台刷机电脑用的。产物不要只停在out/。虚拟机共享盘性能不够编源码丢镜像可以。5. SD 和 eMMC 只差两份 fstab两个都要改内核、dtb、system.imgSD 版和 eMMC 版可以完全一样。差别在挂载路径里的控制器名介质控制器块设备常见fstab 里的路径片段SDdwmmcfe2b0000mmcblk1fe2b0000.dwmmceMMCsdhcife310000mmcblk0fe310000.sdhci两份文件device/board/rk/rk3568_evb/cfg/fstab.required → ramdisk一阶段 device/board/rk/rk3568_evb/cfg/fstab.rk30board → vendor二阶段fstab.required典型四条SD 版/dev/block/platform/fe2b0000.dwmmc/by-name/system /usr ext4 ro wait,required /dev/block/platform/fe2b0000.dwmmc/by-name/vendor /vendor ext4 ro wait,required /dev/block/platform/fe2b0000.dwmmc/by-name/sys_prod /sys_prod ext4 ro wait,required /dev/block/platform/fe2b0000.dwmmc/by-name/chip_prod /chip_prod ext4 ro wait,requiredeMMC 版把fe2b0000.dwmmc换成fe310000.sdhci。vendor 行必须带required。只有wait的话一阶段不挂 vendor二阶段找不到fstab.rk30board/data永远挂不上foundation 崩五十八秒重启。fstab.rk30board还要挂 userdata →/data、misc 等。同样按介质换控制器名。只改一份的后果按死亡时间就能认改了谁没改谁串口现象只改 required 为 sdhcirk30board 仍是 dwmmc刷到 eMMC一阶段过了约 58s ExecReboot/data 挂不上只改 rk30boardrequired 仍是 dwmmc刷到 eMMC约 16s panicwait for file .../fe2b0000.dwmmc/by-name/system两份都改成 sdhci刷到 SD对称的等 sdhci 等不到启动是串行的。先暴露第一个错。正确做法是一次 grep 全改不要「先修日志里那一个再看」grep -n fe2b0000.dwmmc\|fe310000.sdhci \ device/board/rk/rk3568_evb/cfg/fstab.required \ device/board/rk/rk3568_evb/cfg/fstab.rk30boardDTS 的boot_devicesfe2b0000.dwmmc,fe310000.sdhci是候选列表两个都列是正常的不要当 fstab 改。切介质可以做成幂等脚本只改挂载行不碰注释和 DTS#!/usr/bin/env bash # device/board/rk/rk3568_evb/switch_boot_media.sh set -euo pipefail CFG$(cd $(dirname $0) pwd)/cfg to${1:-} case $to in sd) fromfe310000.sdhci; todevfe2b0000.dwmmc ;; emmc) fromfe2b0000.dwmmc; todevfe310000.sdhci ;; status) echo fstab.required grep -E dwmmc|sdhci $CFG/fstab.required echo fstab.rk30board grep -E dwmmc|sdhci $CFG/fstab.rk30board exit 0 ;; *) echo usage: $0 sd|emmc|status; exit 1 ;; esac sed -i s|$from|$todev|g $CFG/fstab.required $CFG/fstab.rk30board echo now $to bash $0 status出完 eMMC 包立刻改回 SD 再打一份 ramdisk/vendor。否则下次你以为自己在编默认 SDfstab 还留着 sdhciSD 卡必 panic。源码树只应有一个「当前介质」状态。交付两份包是两次 pack 的产物不是树上长期并存两套 fstab。改 fstab 不必重编内核。但要让 ninja 重打对应镜像# 一阶段 rm -f out/rk3568_evb/packages/phone/images/ramdisk.img rm -f out/rk3568_evb/packages/phone/ramdisk/etc/fstab.required # 二阶段 rm -f out/rk3568_evb/packages/phone/images/vendor.img ./build.sh --product-name rk3568_evb --ccache --fast-rebuild # 打包前再确认打进镜像的那份 debugfs -R cat /etc/fstab.required \ out/rk3568_evb/packages/phone/images/ramdisk.img # vendor 是 ext4 mkdir -p /tmp/vendor sudo mount -o loop \ out/rk3568_evb/packages/phone/images/vendor.img /tmp/vendor grep -E dwmmc|sdhci /tmp/vendor/etc/fstab.rk30board sudo umount /tmp/vendorramdisk 里仍是 dwmmc、你以为已经切到 eMMC就是 staged 副本没清。刷之前以镜像内文件为准不以源码为准。6. 编完先验再 packexit 0 不够。至少做这三组。6.1 CONFIG 真的在 .config 和 vmlinux 里for k in CONFIG_GPIO_WATCHDOG CONFIG_CFI_PERMISSIVE CONFIG_I2C_CHARDEV; do echo -n $k grep -E ^$k|^# $k is not set out/kernel/OBJ/linux-5.10/.config || echo MISSING done strings out/kernel/OBJ/linux-5.10/vmlinux | grep -i gpio_wdt | head你这次没动内核可以跳过。动过 defconfig / 板级驱动 / khdf不要跳。6.2 dtb 反编译节点是你想要的状态DTB$(find out/kernel/OBJ/linux-5.10 -name *.dtb | grep -E rk3568 | head -1) echo DTB$DTB dtc -I dtb -O dts $DTB 2/dev/null | tee /tmp/live.dts /dev/null grep -n status /tmp/live.dts | grep -E okay|disabled | head # 针对这次改的节点 grep -A8 uart0\|hdmi\|i2cfe5c0000 /tmp/live.dts | head -40再解 resource确认 U-Boot 即将交出的那份# 若 resource_tool 在 PATH 或 out 里 resource_tool --unpack --imageout/rk3568_evb/packages/phone/images/resource.img \ --output/tmp/res dtc -I dtb -O dts /tmp/res/rk-kernel.dtb 2/dev/null | grep -A5 hdmi | head两份 dtb 对不上刷 resource 和刷 boot_linux 效果会分叉。以 resource 那份为准。6.3 MiniLoader 的 DDR 版本4 GB 内存板公版 MiniLoader 经常是 DDR V1.10 1560 MHz训练写完就停串口不再往下走。能稳定起来的是 V1.16频率常用 1056 MHz。strings out/rk3568_evb/packages/phone/images/MiniLoaderAll.bin | grep -E DDR|V1\. | head期望能看到V1.16。看到V1.10又是 4 GB 板先换 loader 再 pack。合成办法在启动链那篇用boot_merger和 rkbin 的 ini。刷卡会覆盖卡上 loader 区所以「我这张卡以前能起 4 GB」不能保证刷完还能起——新包把 loader 换掉了。6.4 记录 md5给 Windows 那头对cd out/rk3568_evb/packages/phone md5sum images/boot_linux.img images/resource.img images/vendor.img \ images/system.img images/ramdisk.img \ pack_update/sd_image.img | tee /tmp/ohos-md5.txt cp -f pack_update/sd_image.img /mnt/hgfs/share/ cp -f /tmp/ohos-md5.txt /mnt/hgfs/share/Windows 再 md5 一次。共享盘拷大文件可能截断头仍是 RKFW尾巴已经不是这次的 system。截断的包刷进去后面几个分区是垃圾现象随机。7. 退出码 137不是编译错误是被打死了日志末尾不是error: xxx.c:12: ...而是clang: error: unable to execute command: Killed ninja: build stopped: subcommand failed.echo $? # 137 dmesg | grep -i out of memory\|killed process | tail137 128 9SIGKILL。OOM killer 在链vmlinux或 thinLTO 某个大 so 时动手。16 GB 无 swap 几乎必中。加 swap不必重装系统free -h sudo fallocate -l 16G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab free -h正在跑的那次已经被杀。重新./build.sh --product-name rk3568_evb --ccache已经编完的.o和 ccache 还在不会从零开始。虚拟机「动态内存」在链接高峰来不及要页一样 137给成固定 32 GB 更省心。磁盘满的报错是No space left on device常出现在打 system.img 时看起来像镜像脚本的 bug。df -h .一眼能看出来。out/一次全量 6080 GB别和源码、prebuilts 挤在一块 256 GB 的盘上还留两份 out。8. 第一次全量还会撞的三块板级补丁环境那篇写过这里只把它接到「全量失败时别重装 Ubuntu」。init 服务白名单。板级在init.rk30board.cfg里加了自启服务preloader 扫描时服务名不在名单里报错在out/preloader。把产品登记过的名单拷进build/对应位置或rm -rf out/preloader普通./build.sh没有--fast-rebuild会重新生成 preloader。拷了名单还报看是不是 out 里旧副本。Lume 缺khrplatform.h。图形 3D 编到spirv_cross_helpers_gles.cppincludeKHR/khrplatform.h搜索路径指向third_party/openGLES/api/GL。文件常缺同仓库 EGL 里有mkdir -p third_party/openGLES/api/GL/KHR third_party/openGLES/api/KHR cp third_party/EGL/api/KHR/khrplatform.h third_party/openGLES/api/GL/KHR/ cp third_party/EGL/api/KHR/khrplatform.h third_party/openGLES/api/KHR/cdc_ncm.c的rx_speed。内核补丁删了字段公版驱动还在用。板级应覆盖一份改过的kernel/linux/linux-5.10/drivers/net/usb/cdc_ncm.c。没覆盖编到 USB 网卡停。这三件不是「依赖没装全」。重装 Ubuntu 解决不了。9. 增量这次全量之后别每次都 40 分钟全量的成本几乎全在用户态重链和大镜像。改一个驱动不要再走全量。三条捷径细节留给最小重建那篇这里只把边界划清# 1) 单个 .ko秒级。签名insmod。不碰镜像 make LLVM1 ARCHarm64 Mdrivers/misc modules # 2) 只重编 Image / dtb重打 boot_linux不碰 system/vendor # 3) 只重打 vendor 或 system改 dts / khdf / defconfig至少要让内核 action 跑起来删 checkpoint。改 uhdf / init.rk30board / 相机 json不要删 out/kernel否则你无偿买一次 8 分钟内核。第一次全量的意义是把out/热起来把 images 齐把 pack 脚本跑通拿到一份已知能进桌面的 RKFW。之后的每一次改动对着源码树那篇的表只重建对应那张 img。10. 失败判断product rk3568_evb not found。产品 json 没登记或板级 overlay 没 apply。先ls device/product、ls device/board/rk。ninja dupbuild 当错误退出。加-w dupbuildwarn。137 / Killed。OOM。加 swap看dmesg。No space left on device。盘满或 loop 挂载没卸导致假满。df -h、losetup -a。afptool not found。loader/里三件套没同步到 pack_update。rm -rf out之后必现除非脚本第 0 步会拷。Add file: ./Image/misc.imgopen failed。空分区没补。从loader/prebuilt-images/拷。Get image version failed。rkImageMaker 缺-os_type:ANDROIDOS或 update.img 损坏。整包头是 RKAF。你把update.img当交付了。要用sd_image.img。刷进去 16s panic wait dwmmc。介质和 fstab 错配。打包前 grep 两份 fstabgrep 镜像内副本。刷进去 DDR 训练后无 U-Boot。MiniLoader 版本。strings | grep DDR。pack 出来的 sd_image 里 boot_linux 还是旧的。第 2 步没 cp。比images/和pack_update/Image/的 md5。md5sum out/rk3568_evb/packages/phone/images/boot_linux.img \ out/rk3568_evb/packages/phone/pack_update/Image/boot_linux.img两行不同就不要刷这张整包。extlinux.conf没有 initrd。不要交付。缺 ramdisk 的启动会把 system 文件删光重刷才能救。第一次全量的验收不是「日志最后有 success」。验收是sd_image.img头为 RKFW、两份 fstab 与打算刷的介质一致、MiniLoader 能strings出正确 DDR 版本、boot_linux 是 ext2 且 conf 里有 initrd、md5 已经和即将拷走的那份对上。系列第 8 篇 · 芯片瑞芯微 RK3568 · OpenHarmony 4.1API 11 · Linux 5.10
返回列表