嵌入式 ARM 设备交叉编译 mosquitto 2.0.20 (完整 TLS 支持) 详细教程,TRAE全程辅助,没敲一行代码
本文记录了在 ARM 嵌入式设备上交叉编译 mosquitto 2.0.20 并启用 TLS 支持的完整过程,包括从下载、编译、部署到调试验证的每一步操作,以及遇到的所有问题和解决方案。其中全程是TRAE辅助编程实现,我发命令,发log,后来卡在8883端口不通,加我的经验判断应该是TLS版本问题,给TRAE仙人指路,最后数据通了!!~
目录
1. 问题背景
1.1 项目需求
在嵌入式 TCU 设备上通过 Quectel EC20 4G 模块连接 MQTT Broker(EMQX),实现消息订阅功能。
1.2 初始问题
用户原有环境:
- mosquitto_sub 版本:2.0.10(不支持 TLS 选项)
- libmosquitto.so.1 版本:2.0.10
用户遇到的原始错误:
Error: Unknown option '--cafile'.
Use 'mosquitto_sub --help' to see usage.
1.3 目标
- 交叉编译 mosquitto 2.0.20 客户端(支持 TLS)
- 正确链接 OpenSSL 库
- 成功连接 EMQX Broker (端口 8883, mqtts://)
2. 环境说明
2.1 开发环境
| 项目 | 路径/值 |
|---|---|
| 开发主机 | x86_64 Linux |
| 交叉编译器 | /opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin/ |
| 编译器前缀 | arm-cortex_a8-linux-gnueabi- |
| GCC 版本 | 4.7.3 |
2.2 目标环境
| 项目 | 说明 |
|---|---|
| 目标设备 | TCU (嵌入式 ARM Cortex-A8) |
| 4G 模块 | Quectel EC20 |
| 系统 | 嵌入式 Linux (Buildroot) |
2.3 软件版本
| 软件 | 版本 | 存放位置 |
|---|---|---|
| OpenSSL | 1.1.1w | /tmp/openssl-1.1.1w → /tmp/openssl-arm |
| mosquitto | 2.0.20 | /tmp/mosquitto-2.0.20 |
3. 交叉编译 OpenSSL 1.1.1w
3.1 下载并解压
命令:
bash
cd /tmp
wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz
tar -xzf openssl-1.1.1w.tar.gz
预期输出:
--2026-04-10 09:30:15-- https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz
...
openssl-1.1.1w.tar.gz 100%[===================>] 9.8MB 890KB/s 用时 11s
2026-04-10 09:30:26 (890 KB/s) - 已保存 "openssl-1.1.1w.tar.gz" [10289152/10289152]
为什么这样做:
- OpenSSL 是 TLS 加密的基础库
- 必须使用
/tmp目录(项目目录可能只读) - 选择 1.1.1w 稳定版( LTS 版本)
3.2 配置编译环境
命令:
bash
cd /tmp/openssl-1.1.1w
export PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH
./Configure linux-armv4 --prefix=/tmp/openssl-arm shared
预期输出:
Operating system: linux-armv4
Configuring OpenSSL distribution for linux-armv4
If it fails, try a different target operating system, e.g. linux-generic32
Configured for linux-armv4
为什么用 linux-armv4:
- 必须指定 ARM 架构,不能用默认的 x86_64
- linux-armv4 适用于 ARMv4 及以上架构
3.3 编译 OpenSSL
命令:
bash
make -j4
预期输出(最后几行):
cc -O4 -fPIC ... -c ssl/ssl_lib.c -o ssl/ssl_lib.o
ar rcs libcrypto.a ...
ld -shared -soname libssl.so.1.1 -o libssl.so.1.1 ...
编译时间: 约 5-10 分钟(取决于 CPU)
3.4 安装 OpenSSL
命令:
bash
make install_sw
预期输出(最后几行):
install prefix: /tmp/openssl-arm
...
libcrypto.a -> /tmp/openssl-arm/lib/libcrypto.a
libssl.so.1.1 -> /tmp/openssl-arm/lib/libssl.so.1.1
libcrypto.so.1.1 -> /tmp/openssl-arm/lib/libcrypto.so.1.1
为什么用 install_sw:
- 只安装软件库和头文件
- 不安装文档和 man pages,减少安装体积
3.5 创建符号链接
问题: 安装后只有 libssl.so.1.1(带版本号),编译链接时需要 libssl.so(不带版本号)
命令:
bash
cd /tmp/openssl-arm/lib
ln -sf libssl.so.1.1 libssl.so
ln -sf libcrypto.so.1.1 libcrypto.so
验证:
bash
ls -la /tmp/openssl-arm/lib/
预期输出:
lrwxrwxrwx libssl.so -> libssl.so.1.1
-rwxrwxrwx libssl.so.1.1 556017 Apr 10 09:45 libssl.so.1.1
lrwxrwxrwx libcrypto.so -> libcrypto.so.1.1
-rwxrwxrwx libcrypto.so.1.1 2641145 Apr 10 09:45 libcrypto.so.1.1
3.6 验证 OpenSSL 架构
命令:
bash
file /tmp/openssl-arm/lib/libssl.so.1.1
预期输出:
libssl.so.1.1: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, with debug_info, not stripped
重要: 必须显示 ARM 架构,不能是 x86_64!
4. 交叉编译 mosquitto 2.0.20
4.1 下载 mosquitto
命令:
bash
cd /tmp
wget https://mosquitto.org/files/source/mosquitto-2.0.20.tar.gz
tar -xzf mosquitto-2.0.20.tar.gz
预期输出:
--2026-04-10 10:00:00-- https://mosquitto.org/files/source/mosquitto-2.0.20.tar.gz
...
mosquitto-2.0.20/CMakeLists.txt
mosquitto-2.0.20/Makefile
mosquitto-2.0.20/client/
mosquitto-2.0.20/lib/
...
4.2 清理之前的编译
命令:
bash
cd /tmp/mosquitto-2.0.20
make -C lib clean
make -C client clean
预期输出:
make: 进入目录"/tmp/mosquitto-2.0.20/lib"
rm -f *.o libmosquitto.so.1 ...
make: 离开目录"/tmp/mosquitto-2.0.20/lib"
4.3 第一次编译尝试(失败的尝试)
命令:
bash
PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH \
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- \
make -C lib WITH_TLS=yes WITH_CJSON=no WITH_SSL=/tmp/openssl-arm \
CFLAGS="-I/tmp/openssl-arm/include" \
LDFLAGS="-L/tmp/openssl-arm/lib" \
LIBS="-lssl -lcrypto"
预期输出:
arm-cortex_a8-linux-gnueabi-cc -shared ... -o libmosquitto.so.1 -lrt -lssl -lcrypto
编译成功,但后来发现问题:
在开发板上运行时出现:
Error: Problem setting TLS options: This feature is not supported.
4.4 问题排查(开发板上报错)
命令(开发板):
bash
strings /tmp/mosquitto-2.0.20/lib/libmosquitto.so.1 | grep -E "libssl|libcrypto"
预期输出:(空,说明没有链接 OpenSSL)
命令(开发电脑):
bash
readelf -d /tmp/mosquitto-2.0.20/lib/libmosquitto.so.1 | grep NEEDED
实际输出(发现问题):
0x00000001 (NEEDED) Shared library: [librt.so.1]
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
问题原因: libmosquitto.so.1 没有链接 libssl.so 和 libcrypto.so!
4.5 第二次编译尝试(解决链接问题)
关键发现: 必须使用完整路径指定 OpenSSL 库!
命令:
bash
cd /tmp/mosquitto-2.0.20
make -C lib clean
PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH \
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- \
make -C lib WITH_TLS=yes WITH_CJSON=no WITH_SSL=/tmp/openssl-arm \
CFLAGS="-I/tmp/openssl-arm/include" \
LDFLAGS="-L/tmp/openssl-arm/lib" \
LIBS="/tmp/openssl-arm/lib/libssl.so.1.1 /tmp/openssl-arm/lib/libcrypto.so.1.1"
预期输出:
arm-cortex_a8-linux-gnueabi-cc -shared -L/tmp/openssl-arm/lib ... -o libmosquitto.so.1 -lrt -lssl -lcrypto
make: 离开目录"/tmp/mosquitto-2.0.20/lib"
4.6 验证 libmosquitto.so.1 链接
命令:
bash
readelf -d /tmp/mosquitto-2.0.20/lib/libmosquitto.so.1 | grep NEEDED
预期输出(现在包含 libssl 和 libcrypto):
0x00000001 (NEEDED) Shared library: [librt.so.1]
0x00000001 (NEEDED) Shared library: [libssl.so.1.1]
0x00000001 (NEEDED) Shared library: [libcrypto.so.1.1]
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
4.7 编译 mosquitto_sub 客户端
命令:
bash
make -C client clean
PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH \
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- \
make -C client WITH_TLS=yes WITH_CJSON=no WITH_SSL=/tmp/openssl-arm \
CFLAGS="-I/tmp/openssl-arm/include" \
LDFLAGS="-L/tmp/openssl-arm/lib -Wl,-rpath-link,/tmp/openssl-arm/lib" \
LIBS="/tmp/openssl-arm/lib/libssl.so.1.1 /tmp/openssl-arm/lib/libcrypto.so.1.1"
预期输出:
arm-cortex_a8-linux-gnueabi-cc ... -o mosquitto_pub
arm-cortex_a8-linux-gnueabi-cc ... -o mosquitto_sub
make: 离开目录"/tmp/mosquitto-2.0.20/client"
4.8 验证 mosquitto_sub 支持 --cafile
命令:
bash
strings /tmp/mosquitto-2.0.20/client/mosquitto_sub | grep -E "cafile|--ca"
预期输出:
--cafile : path to a file containing trusted CA certificates to enable encrypted
--capath : path to a directory containing trusted CA certificates
Error: Only one of --psk or --cafile/--capath may be used at once.
4.9 复制到项目目录
命令:
bash
# 复制客户端
cp /tmp/mosquitto-2.0.20/client/mosquitto_pub \
/tmp/mosquitto-2.0.20/client/mosquitto_sub \
/home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/
# 复制 libmosquitto 库
cp /tmp/mosquitto-2.0.20/lib/libmosquitto.so.1 \
/home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/
# 确认文件
ls -la /home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/mosquitto_sub
预期输出:
-rwxrwxr-x 1 dcuser dcuser 71679 Apr 10 18:31 mosquitto_sub
5. 部署到开发板
5.1 部署文件清单
在开发电脑上执行(假设板子挂载在 /mnt/nandflash):
bash
# 1. 复制 mosquitto 客户端
cp /home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/mosquitto_sub /mnt/nandflash/sbin/mqtt/
cp /home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/mosquitto_pub /mnt/nandflash/sbin/mqtt/
# 2. 复制 libmosquitto 库
cp /home/dcuser/work/cartech_120_DOUB_NET/cartech_120/CSCU_A1_GIT/FileReleaseFiles/nandflash/sbin/mqtt/libmosquitto.so.1 /mnt/nandflash/sbin/mqtt/
# 3. 复制 OpenSSL 库(如果板子没有)
cp /tmp/openssl-arm/lib/libssl.so.1.1 /mnt/nandflash/sbin/mqtt/lib/
cp /tmp/openssl-arm/lib/libcrypto.so.1.1 /mnt/nandflash/sbin/mqtt/lib/
# 4. 创建符号链接
cd /mnt/nandflash/sbin/mqtt/lib
ln -sf libssl.so.1.1 libssl.so
ln -sf libcrypto.so.1.1 libcrypto.so
# 5. 设置权限
chmod 755 /mnt/nandflash/sbin/mqtt/mosquitto_sub
chmod 755 /mnt/nandflash/sbin/mqtt/mosquitto_pub
chmod 755 /mnt/nandflash/sbin/mqtt/libmosquitto.so.1
chmod 755 /mnt/nandflash/sbin/mqtt/lib/*.so*
5.2 部署后验证
命令(开发板):
bash
export LD_LIBRARY_PATH=/mnt/nandflash/sbin/mqtt:/mnt/nandflash/sbin/mqtt/lib:$LD_LIBRARY_PATH
/mnt/nandflash/sbin/mqtt/mosquitto_sub --version
预期输出:
mosquitto_sub version 2.0.20 running on libmosquitto 2.0.20.
可能遇到的问题:
如果出现:
mosquitto_sub version 2.0.20 running on libmosquitto 2.0.10.
说明系统找到的是旧版 libmosquitto.so.1(旧版在 /mnt/nandflash/lib/)
解决:
bash
mv /mnt/nandflash/lib/libmosquitto.so.1 /mnt/nandflash/lib/libmosquitto.so.1.old
6. 问题排查与解决
6.1 问题一:Error: Unknown option '--cafile'
报错位置: 开发板 mqtt_receive.log
错误内容:
Error: Unknown option '--cafile'.
Use 'mosquitto_sub --help' to see usage.
原因分析:
- mosquitto_sub 版本太旧(2.0.10),不支持 TLS 选项
- 或 libmosquitto.so.1 链接错误
解决:
- 部署新编译的 mosquitto_sub (2.0.20)
- 确保 LD_LIBRARY_PATH 指向正确的库目录
6.2 问题二:Error: Problem setting TLS options
报错位置: 开发板 mqtt_receive.log
错误内容:
Error: Problem setting TLS options: This feature is not supported.
原因分析:
- libmosquitto.so.1 没有正确链接 OpenSSL
readelf -d libmosquitto.so.1 | grep NEEDED不包含 libssl.so 和 libcrypto.so
解决:
- 在开发电脑上重新编译 libmosquitto.so.1
- 使用完整路径指定 OpenSSL 库:
bash
LIBS="/tmp/openssl-arm/lib/libssl.so.1.1 /tmp/openssl-arm/lib/libcrypto.so.1.1"
6.3 问题三:连接超时(卡住无输出)
报错位置: 开发板 - 命令一直卡住
原因分析:
尝试多个端口测试:
| 端口 | 结果 | 说明 |
|---|---|---|
| 8883 | 卡住 | TLS 端口 |
| 8083 | 卡住 | WebSocket 端口 |
| 80 | 卡住 | HTTP 端口 |
| 443 | 卡住 | HTTPS 端口 |
| 1883 | 卡住 | 明文 MQTT 端口 |
但 ping 和 DNS 都正常,说明:
- 网络是通的
- 但 TCP 连接被拦截
这里TRAE一直认为是运营商禁用了端口,不过根据我的经验应该是TLS版本问题,最后我强行介入,让TRAE给我换TLS版本,最后通了!!~
最终发现:

手动测试时发现:
bash
mosquitto_sub ... --tls-version tlsv1.2 -v
加上 -v 参数后能连接成功!
真正原因:
- mosquitto_sub 默认尝试 TLS 1.3
- EMQX 服务器只支持 TLS 1.2
- TLS 握手失败导致看起来像连接超时
解决:
添加 --tls-version tlsv1.2 参数
6.4 问题四:nohup 后台运行进程未启动
报错位置: mqtt_subscribe.log
错误内容:
mosquitto_sub进程未运行
错误: mosquitto_sub进程未正常启动
原因分析:
- LD_LIBRARY_PATH 没有正确设置
- 输出重定向问题
解决:
在命令中显式设置环境变量:
bash
LOG_CMD="export LD_LIBRARY_PATH=/mnt/nandflash/sbin/mqtt:/mnt/nandflash/sbin/mqtt/lib:\$LD_LIBRARY_PATH && cd /mnt/nandflash && $CMD > $MQTT_RECEIVE_LOG 2>&1"
7. 最终验证
7.1 测试 TLS 1.2 连接
命令(开发板):
bash
export LD_LIBRARY_PATH=/mnt/nandflash/sbin/mqtt:/mnt/nandflash/sbin/mqtt/lib:$LD_LIBRARY_PATH
/mnt/nandflash/sbin/mqtt/mosquitto_sub -h ue083e07.ala.cn-hangzhou.emqxsl.cn -p 8883 -t test -i tcu_tls12 --cafile /mnt/nandflash/sbin/mqtt/emqxsl-ca.crt -u DC120 -P DC120 --tls-version tlsv1.2 -v
预期输出:
Client tcu_tls12 sending CONNECT
Client tcu_tls12 received CONNACK
Client tcu_tls12 sending SUBSCRIBE (Mid: 1, Topic: test, QoS: 0)
7.2 运行完整脚本
命令(开发板):
bash
/mnt/nandflash/sbin/mqtt/mqtt_subscribe.sh
mqtt_subscribe.log 输出:
[2026-04-10 19:07:37] ================================================
[2026-04-10 19:07:37] MQTT订阅脚本启动
[2026-04-10 19:07:37] 脚本版本: 202604101900
[2026-04-10 19:07:37] ================================================
[2026-04-10 19:07:37] 检测到TLS连接,添加证书选项
[2026-04-10 19:07:40] 构建mosquitto_sub命令: ... --tls-version tlsv1.2 ...
[2026-04-10 19:07:42] mosquitto_sub进程已运行,PID: 24415
[2026-04-10 19:07:42] ========== MQTT订阅启动成功 ==========
7.3 MQTTX 测试
在开发电脑 MQTTX 上向 topic test 发送消息,开发板上的 mqtt_receive.log 应该能收到数据。
8. 总结
8.1 完整编译命令汇总
bash
# ==================== 1. 交叉编译 OpenSSL ====================
cd /tmp/openssl-1.1.1w
export PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH
./Configure linux-armv4 --prefix=/tmp/openssl-arm shared
make -j4 && make install_sw
cd /tmp/openssl-arm/lib
ln -sf libssl.so.1.1 libssl.so
ln -sf libcrypto.so.1.1 libcrypto.so
# ==================== 2. 交叉编译 mosquitto ====================
cd /tmp/mosquitto-2.0.20
make -C lib clean && make -C client clean
# 编译 libmosquitto(关键:用完整路径链接 OpenSSL)
PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH \
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- \
make -C lib WITH_TLS=yes WITH_CJSON=no WITH_SSL=/tmp/openssl-arm \
CFLAGS="-I/tmp/openssl-arm/include" \
LDFLAGS="-L/tmp/openssl-arm/lib" \
LIBS="/tmp/openssl-arm/lib/libssl.so.1.1 /tmp/openssl-arm/lib/libcrypto.so.1.1"
# 编译客户端
PATH=/opt/arm-cortex_a8-linux-gnueabi-4.7.3/bin:$PATH \
CROSS_COMPILE=arm-cortex_a8-linux-gnueabi- \
make -C client WITH_TLS=yes WITH_CJSON=no WITH_SSL=/tmp/openssl-arm \
CFLAGS="-I/tmp/openssl-arm/include" \
LDFLAGS="-L/tmp/openssl-arm/lib -Wl,-rpath-link,/tmp/openssl-arm/lib" \
LIBS="/tmp/openssl-arm/lib/libssl.so.1.1 /tmp/openssl-arm/lib/libcrypto.so.1.1"
# ==================== 3. 验证编译结果 ====================
# 检查架构
file /tmp/mosquitto-2.0.20/client/mosquitto_sub
# 应输出: ELF 32-bit LSB executable, ARM
# 检查动态链接
readelf -d /tmp/mosquitto-2.0.20/lib/libmosquitto.so.1 | grep NEEDED
# 应包含: libssl.so.1.1 和 libcrypto.so.1.1
# 检查 --cafile 选项
strings /tmp/mosquitto-2.0.20/client/mosquitto_sub | grep cafile
# 应输出: --cafile : path to a file containing...
8.2 关键要点
| 要点 | 说明 |
|---|---|
| 交叉编译器 | 必须使用 ARM 交叉编译器,不能用主机的 x86 gcc |
| OpenSSL 架构 | 必须确认是 ARM 架构:file libssl.so.1.1 |
| 库链接验证 | 用 `readelf -d libmosquitto.so.1 |
| TLS 版本 | EMQX 可能只支持 TLS 1.2,需加 --tls-version tlsv1.2 |
| LD_LIBRARY_PATH | 运行时必须设置,指向包含正确 .so 文件的目录 |
8.3 常见错误对照表
| 错误信息 | 报错位置 | 原因 | 解决方法 |
|---|---|---|---|
Error: Unknown option '--cafile' |
开发板 | mosquitto 版本太旧 | 部署新编译的 2.0.20 |
undefined reference to SSL_* |
开发电脑 | 未链接 OpenSSL | 添加 LIBS=".../libssl.so.1.1 ..." |
Error: Problem setting TLS options |
开发板 | libmosquitto.so.1 未链接 OpenSSL | 重新编译并验证 readelf -d |
| 连接超时/卡住 | 开发板 | TLS 版本不兼容 | 添加 --tls-version tlsv1.2 |
no version information available |
开发板 | 链接了旧版 libmosquitto | 设置正确的 LD_LIBRARY_PATH |
本文详细记录了嵌入式 MQTT 客户端交叉编译全过程,包括所有遇到的问题和解决方案。