嵌入式 ARM 设备交叉编译 mosquitto 2.0.20 (完整 TLS 支持) 详细教程 TRAE全程辅助,没敲一行代码

嵌入式 ARM 设备交叉编译 mosquitto 2.0.20 (完整 TLS 支持) 详细教程,TRAE全程辅助,没敲一行代码

本文记录了在 ARM 嵌入式设备上交叉编译 mosquitto 2.0.20 并启用 TLS 支持的完整过程,包括从下载、编译、部署到调试验证的每一步操作,以及遇到的所有问题和解决方案。其中全程是TRAE辅助编程实现,我发命令,发log,后来卡在8883端口不通,加我的经验判断应该是TLS版本问题,给TRAE仙人指路,最后数据通了!!~

目录

  1. 问题背景
  2. 环境说明
  3. [交叉编译 OpenSSL](#交叉编译 OpenSSL)
  4. [交叉编译 mosquitto](#交叉编译 mosquitto)
  5. 部署到开发板
  6. 问题排查与解决
  7. 最终验证
  8. 总结

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 目标

  1. 交叉编译 mosquitto 2.0.20 客户端(支持 TLS)
  2. 正确链接 OpenSSL 库
  3. 成功连接 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.solibcrypto.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 链接错误

解决:

  1. 部署新编译的 mosquitto_sub (2.0.20)
  2. 确保 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.solibcrypto.so

解决:

  1. 在开发电脑上重新编译 libmosquitto.so.1
  2. 使用完整路径指定 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 都正常,说明:

  1. 网络是通的
  2. 但 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进程未正常启动

原因分析:

  1. LD_LIBRARY_PATH 没有正确设置
  2. 输出重定向问题

解决:

在命令中显式设置环境变量:

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 客户端交叉编译全过程,包括所有遇到的问题和解决方案。

相关推荐
counterxing6 小时前
Agent 跑起来之后,难的是复用、观测和评测
node.js·agent·ai编程
uccs6 小时前
大模型底层机制与Agent开发
agent·ai编程·claude
counterxing7 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
夜雪闻竹7 小时前
vectra 向量索引文件损坏怎么办
ai编程·向量·vectra
ZzT7 小时前
Harness 到底指什么
openai·ai编程·claude
宅小年7 小时前
AI 创业最危险的地方:太容易做出来
openai·ai编程·claude
麦客奥德彪8 小时前
Android Skills
架构·ai编程
言萧凡_CookieBoty9 小时前
一文讲清 RAG:让 AI 读懂业务知识库的核心方法
ai编程
kyriewen9 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
Patrick_Wilson10 小时前
知识沉淀的四层模型:从个人笔记到企业资产,让文档真正长出复利
面试·程序员·ai编程