Files
NaviGlassClient/avaota_app_demo/MUSL_COMPILE.md
2025-12-31 15:13:39 +08:00

8.4 KiB
Raw Permalink Blame History

Musl 工具链编译说明

更新时间: 2025-12-04
问题: 开发板使用 musl libc但最初用 glibc 工具链编译导致无法运行
解决: 切换到 musl 工具链重新编译


📋 问题诊断过程

在开发板上的错误

root@(none):/# ldd /tmp/avaota_client
/bin/sh: /tmp/avaota_client: not found

root@(none):/# /lib/ld-musl-riscv32.so.1 /tmp/avaota_client
Error loading shared library ld-linux-riscv32-ilp32d.so.1: No such file or directory
Error relocating /tmp/avaota_client: __register_atfork: symbol not found

开发板环境确认

root@(none):/# /lib32/ilp32d/libc.so
musl libc (riscv32)
Version 1.2.4
Dynamic Program Loader

结论: 开发板运行 musl libc 1.2.4,但程序用 glibc 编译,导致:

  1. 动态链接器路径不匹配(ld-linux-riscv32-ilp32d.so.1 vs ld-musl-riscv32.so.1
  2. glibc 特有符号 __register_atfork 在 musl 中不存在

解决方案

已修改的文件

修改了 src/Makefile,添加 musl 工具链支持:

# 切换工具链:设置 USE_MUSL=1 使用 musl 工具链(推荐)
USE_MUSL := 1

ifeq ($(USE_MUSL),1)
    # musl 工具链(与开发板兼容)
    TOOLCHAIN_DIR := $(SDK_ROOT)/out/toolchain/nds32le-linux-musl-v5d/bin
    CROSS_COMPILE := riscv32-linux-musl-
    $(info [INFO] Using musl toolchain for board compatibility)
else
    # glibc 工具链(仅用于对比测试,开发板不支持)
    TOOLCHAIN_DIR := $(SDK_ROOT)/out/toolchain/nds32le-linux-glibc-v5d/bin
    CROSS_COMPILE := riscv32-unknown-linux-
    $(warning [WARNING] Using glibc toolchain - will NOT run on board!)
endif

🚀 编译步骤(在 Ubuntu 服务器上)

前提条件

确保 musl 工具链存在:

cd ~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release

# 检查 musl 工具链
ls -la out/toolchain/nds32le-linux-musl-v5d/bin/

# 应该看到类似这些文件:
# riscv32-linux-musl-gcc
# riscv32-linux-musl-g++
# riscv32-linux-musl-ar
# ...

如果不存在,可能需要:

  1. 解压工具链压缩包(如果在 out/toolchain/ 下有 .tar.xz.tar.gz 文件)
  2. 或在 prebuilt/rootfsbuilt/riscv/ 下查找
  3. 或重新编译 SDK会自动生成

步骤 1: 上传修改后的代码

将修改后的 avaota_app_demo 文件夹上传到 Ubuntu 服务器:

# 在 Windows 上(使用 SCP 或 WinSCP
# 目标路径:/home/rongye/ProgramFiles/AvaotaF1/avaota_app_demo

步骤 2: SSH 连接到服务器

ssh rongye@<服务器IP>

步骤 3: 验证工具链路径

cd ~/ProgramFiles/AvaotaF1/avaota_app_demo/src

# 检查 Makefile 变量
grep "TOOLCHAIN_DIR" Makefile
grep "CROSS_COMPILE" Makefile
grep "USE_MUSL" Makefile

# 测试编译器
SDK_ROOT=~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release
$SDK_ROOT/out/toolchain/nds32le-linux-musl-v5d/bin/riscv32-linux-musl-gcc --version

预期输出

riscv32-linux-musl-gcc (GCC) 10.x.x

步骤 4: 清理旧编译文件

cd ~/ProgramFiles/AvaotaF1/avaota_app_demo/src
make clean

步骤 5: 重新编译

cd ~/ProgramFiles/AvaotaF1/avaota_app_demo

# 方法 1: 使用构建脚本
./build_main.sh

# 方法 2: 直接 make
cd src
make all -j4

编译时应该看到:

[INFO] Using musl toolchain for board compatibility

步骤 6: 验证编译结果

cd ~/ProgramFiles/AvaotaF1/avaota_app_demo

# 查看文件信息
ls -lh build/bin/avaota_client
file build/bin/avaota_client

# 【关键】检查动态链接器
strings build/bin/avaota_client | grep "/lib/ld-"

正确结果应该是

/lib/ld-musl-riscv32.so.1

如果看到这个就是错的(说明还在用 glibc

/lib/ld-linux-riscv32-ilp32d.so.1

步骤 7: 上传到开发板

# 从服务器上传到开发板
cd ~/ProgramFiles/AvaotaF1/avaota_app_demo
scp build/bin/avaota_client root@<开发板IP>:/tmp/avaota_client_musl

步骤 8: 在开发板上测试

SSH 到开发板:

ssh root@<开发板IP>

# 添加执行权限
chmod +x /tmp/avaota_client_musl

# 验证依赖(现在应该正常显示)
ldd /tmp/avaota_client_musl

# 运行程序
/tmp/avaota_client_musl

成功标志

  • ldd 不再报 "not found" 错误
  • 能看到需要的动态库列表
  • 程序启动,打印初始化日志
  • 各模块开始工作

🔧 故障排查

问题 1: 找不到 musl 工具链

错误

make: /home/rongye/.../nds32le-linux-musl-v5d/bin/riscv32-linux-musl-gcc: No such file or directory

解决方案 A: 查找并解压

cd ~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release

# 查找压缩包
find . -name "*musl*.tar*" 2>/dev/null

# 如果找到,解压到 out/toolchain/
cd out/tool chain
tar -xJf nds32le-linux-musl-v5d.tar.xz  # 或 .tar.gz

解决方案 B: 使用其他位置的工具链

如果工具链在 prebuilt/ 目录,修改 Makefile

TOOLCHAIN_DIR := $(SDK_ROOT)/prebuilt/rootfsbuilt/riscv/nds32le-linux-musl-v5d/bin

解决方案 C: 临时切换回 glibc

如果实在找不到 musl 工具链,可以暂时用 glibc 重新编译(虽然不推荐):

USE_MUSL := 0

但这样编译的程序无法在开发板上运行


问题 2: 编译器前缀不对

错误

make: riscv32-linux-musl-gcc: command not found

解决方案:

检查实际的编译器名称:

ls ~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release/out/toolchain/nds32le-linux-musl-v5d/bin/riscv32-*gcc

可能的前缀:

  • riscv32-linux-musl-
  • riscv32-unknown-linux-musl-

修改 Makefile 中的 CROSS_COMPILE 变量。


问题 3: 编译时缺少头文件

错误

fatal error: xxx.h: No such file or directory

原因: musl 的系统头文件路径可能与 glibc 不同

解决方案:

在 Makefile 中添加 musl 头文件路径:

ifeq ($(USE_MUSL),1)
    CXXFLAGS += -I$(TOOLCHAIN_DIR)/../include
    CXXFLAGS += -I$(TOOLCHAIN_DIR)/../riscv32-linux-musl/include
endif

问题 4: 链接时找不到库

错误

cannot find -lxxx

解决方案:

检查库是否存在于 musl 环境:

find ~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release/out/v821/avaota_f1/openwrt/staging_dir/target/usr/lib -name "libxxx.a"

如果不存在,可能需要:

  1. 重新编译 SDK 以包含 musl 版本的库
  2. 或移除对该库的依赖

📊 工具链对比

项目 glibc 工具链 musl 工具链
路径 nds32le-linux-glibc-v5d nds32le-linux-musl-v5d
编译器前缀 riscv32-unknown-linux- riscv32-linux-musl-
C 库 glibc (GNU C Library) musl libc 1.2.4
动态链接器 /lib/ld-linux-riscv32-ilp32d.so.1 /lib/ld-musl-riscv32.so.1
二进制大小 较大 较小
兼容性 不兼容 Avaota F1 完美兼容
用途 仅用于实验 生产环境必须使用

编译验证清单

重新编译完成后,验证以下内容:

  • musl 工具链路径存在
  • Makefile 中 USE_MUSL := 1
  • make clean 清理旧文件
  • 编译时看到 "Using musl toolchain" 提示
  • 编译成功,生成 build/bin/avaota_client
  • strings 检查链接器为 ld-musl-riscv32.so.1
  • 上传到开发板
  • ldd 正常显示依赖
  • 程序成功运行

📝 后续优化

如果后续需要调整(比如完全静态链接),可以修改:

# 完全静态链接(不依赖任何动态库)
LDFLAGS := -static -static-libgcc -static-libstdc++

# 移除 -Wl,-Bdynamic 部分
# LDFLAGS += -Wl,-Bdynamic -lasound -lglog ...

# 全部静态链接
LDFLAGS += -lasound -lglog -llog -lpthread -lm -lstdc++ -lrt -ldl -lz

这样可以避免任何运行时库依赖问题,但会显著增加程序大小(可能从 3.9MB 增加到 6-8MB


下一步: 按照上述步骤在服务器上重新编译,然后在开发板上测试!🚀