本文档详细介绍如何将mosquitto 2.0.14版本移植到基于AM335x处理器的Linux系统中。mosquitto是一个实现了MQTT协议版本5.0、3.1.1和3.1的开源消息代理和客户端实现库。本文将介绍mosquitto库的配置、编译以及运行过程,包括依赖库的处理、交叉编译环境的配置等内容。整个项目使用CMake作为构建系统。
项目使用arm-arago-linux-gnueabi工具链进行交叉编译。在toolchain.cmake中配置如下:
# toolchain.cmake
# 设置目标系统名称
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 指定交叉编译器的路径
set(CROSS_SYSROOT /opt/am335xt3-cross-devkit/arm-arago-linux-gnueabi)
set(CROSS_COMPILE_PATH /opt/am335xt3-cross-devkit/bin)
set(CROSS_PREFIX /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-)
set(CMAKE_C_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-g++)
set(CMAKE_ASM_COMPILER /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-as)
set(CMAKE_AR /opt/am335xt3-cross-devkit/bin/arm-arago-linux-gnueabi-ar)
set(CROSS_COMPILE_INCLUDE_PATH /opt/am335xt3-cross-devkit/arm-arago-linux-gnueabi/sysroot/usr/include)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/am335xt3_install)
set(CMAKE_INTERNAL_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/am335xt3_internal_install)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -ldl")
# 指定库的查找路径
set(CMAKE_LIBRARY_PATH ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib)
# 设置查找路径
set(CMAKE_FIND_ROOT_PATH ${CJSON_ROOT} ${OPENSSL_ROOT})
# 指定查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# 禁用 CMake 的默认查找路径(如系统路径 /usr 和 /lib)
set(CMAKE_FIND_NO_PACKAGE_PREFIX_PATH TRUE)
cJSON库是一个轻量级的JSON解析库,在本项目中使用CMake进行构建。
在thirdpart/cJSON-1.7.15/CMakeLists.txt中已经包含了完整的构建配置,无需额外修改。主要配置如下:
project(cJSON VERSION 1.7.15 LANGUAGES C)
add_library(cjson
cJSON.c
cJSON_Utils.c
)
target_include_directories(cjson
PUBLIC
$
)
OpenSSL库用于提供加密和SSL/TLS功能,是mosquitto的重要依赖。
在thirdpart/openssl/CMakeLists.txt中配置OpenSSL的编译选项:
project(openssl)
# 设置OpenSSL源码目录
set(OPENSSL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/openssl-1.1.1w)
# 设置编译选项
set(OPENSSL_CONFIG_OPTIONS
shared
no-ssl3
--prefix=${CMAKE_INTERNAL_INSTALL_PREFIX}
--openssldir=${CMAKE_INTERNAL_INSTALL_PREFIX}
linux-armv4
-DL_ENDIAN
)
# 将列表转换为空格分隔的字符串
string(REPLACE ";" " " OPENSSL_CONFIG_OPTIONS_STR "${OPENSSL_CONFIG_OPTIONS}")
# 设置环境变量
set(ENV{CC} "${CMAKE_C_COMPILER}")
set(ENV{AR} "${CMAKE_AR}")
set(ENV{RANLIB} "${CMAKE_RANLIB}")
set(ENV{PATH} "${CROSS_COMPILE_PATH}:$ENV{PATH}")
# 配置OpenSSL
add_custom_command(
OUTPUT ${OPENSSL_SOURCE_DIR}/Makefile
COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} ./Configure linux-armv4 --cross-compile-prefix=arm-arago-linux-gnueabi- --prefix=${CMAKE_INTERNAL_INSTALL_PREFIX} --openssldir=${CMAKE_INTERNAL_INSTALL_PREFIX} shared no-ssl3 no-async -DL_ENDIAN threads -lpthread
WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
COMMENT "Configuring OpenSSL"
)
# 编译OpenSSL
add_custom_command(
OUTPUT ${OPENSSL_SOURCE_DIR}/libssl.a ${OPENSSL_SOURCE_DIR}/libcrypto.a
COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} $(MAKE)
DEPENDS ${OPENSSL_SOURCE_DIR}/Makefile
WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
COMMENT "Building OpenSSL"
)
# 创建自定义目标
add_custom_target(openssl ALL
DEPENDS ${OPENSSL_SOURCE_DIR}/libssl.a ${OPENSSL_SOURCE_DIR}/libcrypto.a
)
# 安装规则
add_custom_target(openssl_install
COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{PATH} $(MAKE) install_sw
WORKING_DIRECTORY ${OPENSSL_SOURCE_DIR}
COMMENT "Installing OpenSSL"
DEPENDS openssl
)
注意:为了避免随机数生成导致的阻塞问题,建议在系统中配置使用/dev/urandom作为随机数源。
mosquitto源码位于thirdpart/mosquitto/mosquitto-2.0.14/目录下。
在thirdpart/mosquitto/CMakeLists.txt中配置mosquitto的编译选项:
project(mosquittomgr)
set(OPENSSL_INCLUDE_DIR ${CMAKE_INTERNAL_INSTALL_PREFIX}/include)
set(OPENSSL_LIBRARIES ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib/libssl.so ${CMAKE_INTERNAL_INSTALL_PREFIX}/lib/libcrypto.so)
add_subdirectory(mosquitto-2.0.14)
# 安装 mosquitto.conf 脚本到 etc 目录
install(
FILES mosquitto.conf
DESTINATION etc/mosquitto
)
注释掉thirdpart/mosquitto/mosquitto-2.0.14/CMakeLists.txt中
#find_package(OpenSSL REQUIRED ${CMAKE_INTERNAL_INSTALL_PREFIX})
#FIND_PACKAGE(cJSON)
PS:1.OpenSSL已经在上一级的cmake定义OPENSSL_INCLUDE_DIR和OPENSSL_LIBRARIES
2.cJSON是使用cmake编译的,所以不需要再使用FIND_PACKAGE(cJSON)
在编译过程中,可能会遇到mosquitto_property和mosquitto_plugin_id_t类型重复定义的问题。这是因为这些类型在mosquitto_broker.h和mosquitto.h中都有定义。解决方法如下:
在mosquitto-2.0.14/include/mosquitto_broker.h文件中,找到这些类型的定义部分。
添加条件编译宏来避免重复定义:
mosquitto_property重定义部分代码:
# mosquitto_broker.h
#ifndef MOSQ_PROP_TYPE_DEFINED
#define MOSQ_PROP_TYPE_DEFINED
typedef struct mqtt5__property mosquitto_property;
#endif
# mosquitto.h
#ifndef MOSQ_PROP_TYPE_DEFINED
#define MOSQ_PROP_TYPE_DEFINED
typedef struct mqtt5__property mosquitto_property;
#endif
mosquitto_plugin_id_t重定义部分代码:
// mosquitto_broker.h
#ifndef MOSQ_PLUGIN_ID_TYPE_DEFINED
#define MOSQ_PLUGIN_ID_TYPE_DEFINED
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;
#endif
// mosquitto_broker_internal.h
//typedef struct mosquitto_plugin_id_t{
// struct mosquitto__listener *listener;
//};
struct mosquitto_plugin_id_t{
struct mosquitto__listener *listener;
};
#ifndef MOSQ_PLUGIN_ID_TYPE_DEFINED
#define MOSQ_PLUGIN_ID_TYPE_DEFINED
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;
#endif
这样修改后,这些类型只会被定义一次,避免了重复定义导致的编译错误。
在/etc/mosquitto/mosquitto.conf中配置mosquitto的基本配置:
# mosquitto.conf
listener 1883 192.168.2.177
user root
allow_anonymous true
log_dest file /var/log/mosquitto.log
log_type all
log_timestamp true
./mosquitto -c /etc/mosquitto/mosquitto.conf
./mosquitto_sub -t test/topic -h 192.168.2.177 -p 1883 -v
./mosquitto_pub -t test/topic -h 192.168.2.177 -p 1883 -m "hello world"
问题描述:mosquitto服务在接收订阅连接请求时,使用OpenSSL的RAND_bytes函数生成client id时可能导致阻塞。
解决方法:配置OpenSSL使用/dev/urandom作为随机数源
问题描述:出现"Connection error: Connection Refused: not authorised"错误。
解决方法:
allow_anonymous true
allow_anonymous false
password_file /path/to/mosquitto.passwd