8.4 KiB
8.4 KiB
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 编译,导致:
- 动态链接器路径不匹配(
ld-linux-riscv32-ilp32d.so.1vsld-musl-riscv32.so.1) - 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
# ...
如果不存在,可能需要:
- 解压工具链压缩包(如果在
out/toolchain/下有.tar.xz或.tar.gz文件) - 或在
prebuilt/rootfsbuilt/riscv/下查找 - 或重新编译 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"
如果不存在,可能需要:
- 重新编译 SDK 以包含 musl 版本的库
- 或移除对该库的依赖
📊 工具链对比
| 项目 | 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)。
下一步: 按照上述步骤在服务器上重新编译,然后在开发板上测试!🚀