在华为AI开发者空间编译海思 WS63 星闪 SDK 全攻略

发布时间:2026/10/7 19:41:15
在华为AI开发者空间编译海思 WS63 星闪 SDK 全攻略 文章目录一、背景二、沙箱环境摸底三、下载代码四、踩坑与解决坑 1缺 Python 包 kconfiglib / pycparser坑 2预装 Python 3.12 没有 _curses坑 3核心aarch64 沙箱跑不动 x86-64 工具链(1) 搞到一个 aarch64 宿主、模拟 x86-64 guest 的静态 qemu(2) 给 qemu 准备 x86-64 guest 的运行时库(3) 用包装脚本替代 binfmt_misc坑 4qemu 下 dlopen 加载 liblto_plugin.so 失败坑 5签名工具也是 x86-64五、正式编译六、编译产物七、通过 AI Shell 下载编译产物7.1 一句话搞定7.2 浏览器下载7.3 手动操作了解原理7.4 清理八、方案小结与几点体会本文记录在华为AI开发者空间华为云 CodeArts 云端开发沙箱中从零下载并成功编译海思fbb_ws63星闪 SDK 的完整过程。沙箱为 aarch64 架构而 SDK 自带的 RISC-V 交叉工具链是 x86-64 二进制无法直接执行。文中给出一套** qemu-user 静态模拟 包装脚本 链接器插件禁用**的零侵入跨架构方案最终在 ARM64 云环境里跑通了原本只能在 x86-64 Linux/WSL 上编译的 WS63 固件。一、背景WS63是海思推出的 2.4GHz Wi-Fi 6 星闪NearLink多模 SoC 解决方案适用于大小家电、电工照明等物联网智能场景。fbb_ws63是基于 FBBFamily Big Box统一开发框架构建的 SDK 代码包开发者可在其上做二次开发应用易于移植到其他星闪方案。代码仓https://gitcode.com/HiSpark/fbb_ws63在线文档https://docs.hisilicon.com/repos/fbb_ws63/zh-CN/master/官方推荐在 Windows 上用 WSL 子系统预配置 x86-64 镜像或 HiSparkStudio 插件编译烧录。而华为AI开发者空间提供了一个开箱即用的云端 Linux 沙箱预装 git / cmake / make / python 等免本地环境搭建非常适合做这类 SDK 的云端编译与验证。华为AI开发者空间的体验版提供5小时的使用时间而持久化版本可以提供免费的8000核时使用时间。唯一的问题是沙箱是 aarch64 架构SDK 工具链是 x86-64。下文围绕这一核心矛盾展开。不过你并不需要手工解决这些问题只需要在华为AI开发者空间中使用CodeArts让它替你下载WS63的SDK并完成配置与编就可以了下面的步骤二到六只是告诉你CodeArts都完成了什么工作。二、沙箱环境摸底进入开发者空间终端先摸清家底$uname-maarch64 $cat/etc/os-release|head-2NAMEopenEulerVERSION22.03 LTS$whichpython3 cmakemakegitgcc /root/runtime/codearts/bin/python3# 预装 Python 3.12/root/runtime/codearts/bin/cmake# cmake 3.22/root/runtime/codearts/bin/make# GNU Make 4.3... $ /usr/bin/python3.9--version# 系统自带 Python 3.9Python3.9.9几个关键点先记下后面都会踩到预装python3是 3.12但没有_curses模块menuconfig 依赖。系统另有/usr/bin/python3.9带_curses但环境变量PYTHONPATH/PYTHONHOME默认指向 3.12直接跑会崩。沙箱/proc/self/mounts为空、binfmt_misc无法挂载权限拒绝这意味着没法用 binfmt_misc 透明模拟异架构二进制后面方案要绕开它。根分区是 7.5G tmpfs但/usr、/etc实为 80G overlayfsdnf因读不到挂载表会误报空间不足。三、下载代码沙箱自带 git直接克隆cd/workspacegitclone https://gitcode.com/HiSpark/fbb_ws63.git仓库约 1.8 万个文件几分钟拉完。目录结构目录说明docs软件资料、IO 复用表、用户指南srcSDK 源码包编译入口在这里tools开发工具与环境搭建文档vendor各厂商开发板硬件资料与案例编译入口是src/build.py目标名ws63-liteos-app。官方编译命令就一句cdsrc python3 build.py-cws63-liteos-app# -c 表示全量编译看起来很简单但在 aarch64 沙箱里直接跑会连环报错。下面按踩坑顺序讲。四、踩坑与解决坑 1缺 Python 包kconfiglib/pycparserbuild.py导入kconfiglibNV bin 生成阶段导入pycparser沙箱里都没有。解决用 pip 装上即可。但注意要装到能用的那个 Python 上见坑 2。坑 2预装 Python 3.12 没有_cursesbuild.py→usr_config.py→from menuconfig import menuconfig→import curses→import _curses在预装 3.12 上直接ModuleNotFoundError: No module named _curses3.12 是预编译环境没法补 C 扩展。好在系统自带的/usr/bin/python3.9有_curses。但它被 3.12 的环境变量干扰$echo$PYTHONPATH$PYTHONHOME/root/runtime/codearts/python3.12/lib/python3.12 /root/runtime/codearts/python3.12直接跑 3.9 会因为去 3.12 的库里找io而崩。解决运行时剥掉这两个变量并显式给 3.9 指定 user site# 给 python3.9 装包用干净环境HOME 指向 /root 以便装到 /root/.localenv-iPATH/usr/bin:/binHOME/root /usr/bin/python3.9-mensurepipenv-iPATH/usr/bin:/binHOME/root /usr/bin/python3.9-mpipinstallkconfiglib pycparser# 验证env-uPYTHONHOMEPYTHONPATH/root/.local/lib/python3.9/site-packages\/usr/bin/python3.9-cimport _curses, kconfiglib, pycparser; print(OK)之后所有编译命令统一用这个前缀PYenv-uPYTHONHOMEPYTHONPATH/root/.local/lib/python3.9/site-packages /usr/bin/python3.9坑 3核心aarch64 沙箱跑不动 x86-64 工具链装好 Python 后编译刷屏报/workspace/fbb_ws63/src/tools/bin/compiler/riscv/cc_riscv32_musl_105/cc_riscv32_musl/bin/riscv32-linux-musl-gcc: cannot execute binary file: Exec format error查一下就明白了$uname-maarch64 $file.../cc_riscv32_musl/bin/riscv32-linux-musl-gcc... ELF64-bit LSB pie executable, x86-64,... interpreter /lib64/ld-linux-x86-64.so.2SDK 自带的 RISC-V 交叉工具链gcc 7.3.0 musl是x86-64 宿主二进制在 ARM64 上根本执行不了。官方文档默认你在 x86-64 WSL 里跑所以没考虑这个。思路用qemu-user-static在 aarch64 上模拟跑 x86-64 二进制。但沙箱有两个限制没有qemu-user-static包openEuler 仓库也只有qemu-system-*全系统模拟太重。binfmt_misc挂不了没法做透明模拟——即 qemu 模拟的 gcc 去 fork/execcc1时内核不会自动用 qemu 接管cc1。解决分三步(1) 搞到一个 aarch64 宿主、模拟 x86-64 guest 的静态 qemuDebian bookworm 的qemu-user-staticarm64 包正好是 aarch64 宿主、静态链接、内含qemu-x86_64-static。从华为云镜像下载并提取单文件cd/workspacecurl-sL-oqemu.deb\https://mirrors.huaweicloud.com/debian/pool/main/q/qemu/qemu-user-static_7.2dfsg-7deb12u18b3_arm64.debar x qemu.deb data.tar.xztar-xJfdata.tar.xz ./usr/bin/qemu-x86_64-staticfileusr/bin/qemu-x86_64-static# ELF 64-bit LSB pie executable, ARM aarch64, ... static-pie linked(2) 给 qemu 准备 x86-64 guest 的运行时库工具链的 gcc/cc1 是动态链接的 x86-64依赖 x86-64 的ld-linux、libc、libz。从 Debian amd64 抓最小 sysrootmkdir-p/workspace/x86_64-rootcd/workspace/x86_64-root# glibccurl-sL-o/workspace/libc6.deb\https://mirrors.huaweicloud.com/debian/pool/main/g/glibc/libc6_2.36-9deb12u14_amd64.debar x /workspace/libc6.deb data.tar.xztar-xJfdata.tar.xz# zlibcc1 依赖 libz.so.1curl-sL-o/workspace/zlib1g.deb\https://mirrors.huaweicloud.com/debian/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_amd64.debar x /workspace/zlib1g.deb data.tar.xztar-xJfdata.tar.xz# Debian 的 /lib64/ld-linux-x86-64.so.2 是绝对符号链接qemu 解析不到改成真实文件rm-flib64/ld-linux-x86-64.so.2cplib/x86_64-linux-gnu/ld-linux-x86-64.so.2 lib64/ld-linux-x86-64.so.2验证 qemu 能跑工具链QEMU/workspace/usr/bin/qemu-x86_64-static$QEMU-L/workspace/x86_64-root\/workspace/fbb_ws63/src/tools/bin/compiler/riscv/cc_riscv32_musl_105/cc_riscv32_musl/bin/riscv32-linux-musl-gcc\--version# riscv32-linux-musl-gcc (build ver105.010 2024-06-18) 7.3.0看到7.3.0输出说明 qemu guest glibc 这条路通了。(3) 用包装脚本替代 binfmt_misc因为挂不了binfmt_miscgcc 去 execcc1/as/ld时内核不会自动套 qemu。办法是把工具链里每一个 x86-64 ELF 重命名为xxx.real原位置放一个 shell 脚本脚本里exec qemu xxx.real $。这样无论谁用绝对路径 exec 它都会先执行脚本→进 qemu。包装脚本wrap_toolchain.py#!/usr/bin/env python3importos,sys,stat QEMU/workspace/usr/bin/qemu-x86_64-staticSYSROOT/workspace/x86_64-rootdefis_x86_64_elf(path):try:withopen(path,rb)asf:hf.read(20)exceptException:returnFalsereturnlen(h)20andh[:4]b\x7fELFandh[4]2andh[18]0x3eandh[19]0defwrap_file(path):ifnotis_x86_64_elf(path):returnFalserealpath.realifos.path.exists(real):returnFalseos.rename(path,real)withopen(path,w)asf:f.write(#!/bin/sh\nexec %s -L %s %s $\n%(QEMU,SYSROOT,real))stos.stat(path)os.chmod(path,st.st_mode|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)returnTrueforrootinsys.argv[1:]:fordp,dirs,filesinos.walk(root):fornameinfiles:pos.path.join(dp,name)ifos.path.islink(p):continuetry:stos.stat(p)exceptException:continueifstat.S_ISREG(st.st_mode):wrap_file(p)对两套工具链普通版 fp 浮点版以及签名/压缩工具目录都做包装python3 wrap_toolchain.py\/workspace/fbb_ws63/src/tools/bin/compiler/riscv/cc_riscv32_musl_105/cc_riscv32_musl\/workspace/fbb_ws63/src/tools/bin/compiler/riscv/cc_riscv32_musl_105/cc_riscv32_musl_fp\/workspace/fbb_ws63/src/tools/bin/sign_tool\/workspace/fbb_ws63/src/tools/bin/derived_key_tool\/workspace/fbb_ws63/src/tools/bin/lzma_tool一共包装了约 100 个 x86-64 二进制。符号链接不动它指向的真实文件会被包装。坑 4qemu 下dlopen加载liblto_plugin.so失败包装完跑一个真实编译测试echoint main(){return 0;}t.c.../riscv32-linux-musl-gcc-ot.elf t.c报ld.real: .../liblto_plugin.so: error loading plugin: invalid ELF header collect2.real: error: ld returned 1 exit status原因gcc 7.3.0 默认开-fuse-linker-plugin让ld去dlopen一个 x86-64 的liblto_plugin.so。qemu-user 对 guest 的dlopen支持有限加载失败。--no-plugins传给 ld 也不顶用gcc 仍会塞-plugin。解决给 gcc driver 的包装脚本统一注入-fno-use-linker-plugin从 gcc 这一层就别让 ld 加载插件。先验证该选项对--version/-print-*等查询命令无害实测 gcc 直接忽略然后只改 gcc 系 drivergcc/g/c/gcc-7.3.0/cpp不要改as/ld/ar它们不认这个选项会报错importos drivers[riscv32-linux-musl-gcc,riscv32-linux-musl-g,riscv32-linux-musl-c,riscv32-linux-musl-gcc-7.3.0,riscv32-linux-musl-cpp]forbasein[cc_riscv32_musl/bin,cc_riscv32_musl_fp/bin]:fordindrivers:pos.path.join(base,d)ifnotos.path.exists(p)oros.path.islink(p):continuewithopen(p,rb)asf:rawf.read()ifnotraw.startswith(b#!)orb-fno-use-linker-plugininraw:continuewithopen(p,wb)asf:f.write(raw.replace(b$,b-fno-use-linker-plugin $))再编译t.c成功产出 RISC-V 32-bit ELFt.elf: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, ...坑 5签名工具也是 x86-64编译跑到 100% 链接出ws63-liteos-app.elf最后签名步骤又挂OSError: [Errno 8] Exec format error: .../sign_tool/sign_tool_pltunisign_tool_pltuni是 x86-64 静态 PIE。好在坑 3 步骤里已经把sign_tool等目录一起包装了这步自动解决。验证$.../sign_tool/sign_tool_pltuni sign_tool_pltuni - Version0.10(debug)Build2023.06.19五、正式编译所有坑填完一行命令开跑用前面准备好的 python3.9 前缀cd/workspace/fbb_ws63/srcenv-uPYTHONHOMEPYTHONPATH/root/.local/lib/python3.9/site-packages\/usr/bin/python3.9 build.py-cws63-liteos-app关键进度摘录[ 98%] Linking C executable flashboot.elf [100%] ws63 image sign [100%] Built target GENERAT_HEX [100%] Linking C executable ws63-liteos-app.elf Memory region Used Size Region Size %age Used ITCM: 12992 B 16 KB 79.30% DTCM: 14900 B 16 KB 90.94% SRAM: 181072 B 548608 B 33.01% PROGRAM: 1294248 B 2357504 B 54.90% [100%] Built target ws63-liteos-app [100%] post_build:gen rom and ram bin file packet success!packet success!即打包完成。编译过程中build.py会先编ws63-flashboot等依赖目标再编主目标ws63-liteos-app。中途若因缺包/缺工具中断修好后不带-c增量续编即可不必从头来。六、编译产物产物都在src/output/ws63/下output/ws63/ ├── acore/ws63-liteos-app/ │ ├── ws63-liteos-app.elf # ELF 可执行文件 │ ├── ws63-liteos-app.bin # 原始 bin │ ├── ws63-liteos-app-sign.bin # 签名 bin │ └── ws63-liteos-app_rom.bin ├── fwpkg/ws63-liteos-app/ │ ├── ws63-liteos-app_all.fwpkg # ★ 烧录包1.4M │ └── ws63-liteos-app_load_only.fwpkg └── pktbin/ws63-liteos-app.bin烧录时用ws63-liteos-app_all.fwpkg配合 BurnTool 选择 WS63 目标即可具体烧录步骤见仓库tools/WSL子系统编译及烧录.md。七、通过 AI Shell 下载编译产物编译完成后产物都在云端沙箱里本地电脑拿不到。华为AI开发者空间的沙箱没有直接的文件下载按钮但可以通过AI ShellAI 智能体终端快速把文件传回本地。思路很简单在沙箱里起一个 HTTP 文件服务器 → 通过 DevBridge 开发隧道暴露到公网 → 浏览器打开隧道 URL 直接下载。整个过程只需跟 AI Shell 说一句话它会自动完成。7.1 一句话搞定在 AI Shell 里直接输入在沙箱里启动 HTTP 文件服务器通过 DevBridge 让用户可以在浏览器中访问 src/output/ws63/ 目录下的编译产物AI Shell 会自动完成以下三步启动 HTTP 文件服务器在编译产物目录下执行python3 -m http.server 8080提供文件浏览与下载服务。启动 DevBridge 隧道创建或复用一条 DevBridge 开发隧道将沙箱的 8080 端口通过华为云中继暴露到公网。返回公网 URL形如https://tunnelId-8080.devbridge-s2.hwtunnel.com直接在浏览器打开即可。7.2 浏览器下载打开 AI Shell 返回的隧道 URL你会看到编译产物的目录列表Directory listing for / ├── acore/ │ ├── ws63-liteos-app/ │ │ ├── ws63-liteos-app.elf # ELF 可执行文件16M │ │ ├── ws63-liteos-app.bin # 原始 bin1.3M │ │ └── ws63-liteos-app-sign.bin # 签名 bin1.3M │ └── boot_bin/ │ ├── flashboot.bin │ └── ssb.bin ├── fwpkg/ws63-liteos-app/ │ ├── ws63-liteos-app_all.fwpkg # ★ 烧录包1.4M │ └── ws63-liteos-app_load_only.fwpkg └── pktbin/ ├── ws63-liteos-app.bin └── ...点击任意文件即可下载到本地。最关心的是fwpkg/ws63-liteos-app/ws63-liteos-app_all.fwpkg——这是最终烧录包配合 BurnTool 即可烧录到 WS63 开发板。7.3 手动操作了解原理如果想手动操作或脚本化三步命令如下# 1. 在编译产物目录下启动 HTTP 文件服务器cd/workspace/fbb_ws63/src/output/ws63 python3-mhttp.server8080--bind0.0.0.0# 2. 通过 DevBridge 隧道暴露 8080 端口AI Shell 中执行# AI Shell 会调用 DevBridge WebUI API端口 13000创建隧道并启动 host 进程source/root/.agents/skills/huawei-cloud-jobenv-devbridge-tunnel/scripts/devbridge_cmd.sh db_init# 确保沙箱运行TUNNEL_ID$(db_createws63-download下载编译产物72)# 创建隧道有效期 72 小时db_port_create$TUNNEL_ID8080autotrue# 添加端口开启匿名访问db_host$TUNNEL_ID# 启动 host 进程db_processes# 查看进程及隧道 URL# 3. 浏览器打开返回的 URL如# https://mufzmrtt-8080.devbridge-s2.hwtunnel.com7.4 清理下载完成后及时关闭服务避免文件长期暴露在公网# 停止 DevBridge host 进程db_process_stop进程ID# 停止 HTTP 文件服务器kill%1# 删除隧道可选db_delete$TUNNEL_ID安全提醒DevBridge 隧道开启匿名访问后任何拿到 URL 的人都能访问你的文件。建议下载完成后立即关闭 host 进程或删除隧道。隧道有效期默认 72 小时到期自动失效。八、方案小结与几点体会华为AI开发者空间适合做 SDK 云端编译预装工具链齐全、网络通畅可拉 GitCode/镜像、有大磁盘 overlayfs省去本地装环境的麻烦。唯一要适应的是 aarch64 架构。aarch64 跑 x86-64 工具链的三件套qemu-x86_64-staticaarch64 宿主 x86-64 guest glibc/zlib sysroot 包装脚本替代 binfmt_misc。这套方案对任何宿主架构 ≠ 工具链架构的交叉 SDK 都通用且不改动 SDK 源码只动工具链目录可.gitignore或脚本化复现。qemu-user 的两个暗坑guest 动态链接器若是绝对符号链接qemu 解析不到要改成真实文件qemu-user 下 guestdlopenguest.so不可靠遇到 gcc LTO plugin 这类要靠-fno-use-linker-plugin绕开。Python 双版本坑预装 3.12 缺_curses用系统 3.9 时记得剥掉PYTHONPATH/PYTHONHOME否则会串到 3.12 的库里崩掉。整个环境复现可以脚本化下载 qemu/glibc deb → 提取 → 包装工具链 → 注入-fno-use-linker-plugin→build.py。在开发者空间里开新会话也能一键跑通。希望这篇踩坑记能帮到在 ARM64 云环境不只是华为AI开发者空间也包括树莓派、Ampere 云主机等上玩 WS63 星闪 SDK 的同学。有问题欢迎在评论区交流。