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

376 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Musl 工具链编译说明
**更新时间**: 2025-12-04
**问题**: 开发板使用 musl libc但最初用 glibc 工具链编译导致无法运行
**解决**: 切换到 musl 工具链重新编译
---
## 📋 问题诊断过程
### 在开发板上的错误
```bash
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
```
### 开发板环境确认
```bash
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 工具链支持:
```makefile
# 切换工具链:设置 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 工具链存在:
```bash
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 服务器:
```bash
# 在 Windows 上(使用 SCP 或 WinSCP
# 目标路径:/home/rongye/ProgramFiles/AvaotaF1/avaota_app_demo
```
---
### 步骤 2: SSH 连接到服务器
```bash
ssh rongye@<服务器IP>
```
---
### 步骤 3: 验证工具链路径
```bash
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: 清理旧编译文件
```bash
cd ~/ProgramFiles/AvaotaF1/avaota_app_demo/src
make clean
```
---
### 步骤 5: 重新编译
```bash
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: 验证编译结果
```bash
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: 上传到开发板
```bash
# 从服务器上传到开发板
cd ~/ProgramFiles/AvaotaF1/avaota_app_demo
scp build/bin/avaota_client root@<开发板IP>:/tmp/avaota_client_musl
```
---
### 步骤 8: 在开发板上测试
SSH 到开发板:
```bash
ssh root@<开发板IP>
# 添加执行权限
chmod +x /tmp/avaota_client_musl
# 验证依赖(现在应该正常显示)
ldd /tmp/avaota_client_musl
# 运行程序
/tmp/avaota_client_musl
```
**成功标志**
-`ldd` 不再报 "not found" 错误
- ✅ 能看到需要的动态库列表
- ✅ 程序启动,打印初始化日志
- ✅ 各模块开始工作
---
## 🔧 故障排查
### 问题 1: 找不到 musl 工具链
**错误**
```bash
make: /home/rongye/.../nds32le-linux-musl-v5d/bin/riscv32-linux-musl-gcc: No such file or directory
```
**解决方案 A**: 查找并解压
```bash
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
```makefile
TOOLCHAIN_DIR := $(SDK_ROOT)/prebuilt/rootfsbuilt/riscv/nds32le-linux-musl-v5d/bin
```
**解决方案 C**: 临时切换回 glibc
如果实在找不到 musl 工具链,可以暂时用 glibc 重新编译(虽然不推荐):
```makefile
USE_MUSL := 0
```
但这样编译的程序**无法在开发板上运行**。
---
### 问题 2: 编译器前缀不对
**错误**
```
make: riscv32-linux-musl-gcc: command not found
```
**解决方案**:
检查实际的编译器名称:
```bash
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 头文件路径:
```makefile
ifeq ($(USE_MUSL),1)
CXXFLAGS += -I$(TOOLCHAIN_DIR)/../include
CXXFLAGS += -I$(TOOLCHAIN_DIR)/../riscv32-linux-musl/include
endif
```
---
### 问题 4: 链接时找不到库
**错误**
```
cannot find -lxxx
```
**解决方案**:
检查库是否存在于 musl 环境:
```bash
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` 正常显示依赖
- [ ] 程序成功运行
---
## 📝 后续优化
如果后续需要调整(比如完全静态链接),可以修改:
```makefile
# 完全静态链接(不依赖任何动态库)
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
---
**下一步**: 按照上述步骤在服务器上重新编译,然后在开发板上测试!🚀