为嵌入式设备编译paho.mqtt.rust应用

为嵌入式MIPS准备rust开发环境

在此前的一篇文章中,笔者对Rust的交叉编译开发环境的安装作了说明,演示了简单Hello World应用的交叉编译。笔者在该文章中记录了较为复杂的rust应用(paho.mqtt.rust)的编译过程,目柡设备为运行openwrt系统的MT7628设备。此处简要重复笔者安装嵌入式MIPSrust交叉编译工具链的过程。首先,以根用户权限安装rust编译器:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o sh.rust.rs
export CARGO_HOME=/opt/rust-lang/cargo
export RUSTUP_HOME=/opt/rust-lang/rustup
sh ./sh.rust.rs # 选择`(default)以完成安装
source /opt/rust-lang/cargo/env
rustup target add mipsel-unknown-linux-musl # 安装MIPS架构的rust柡准库

之后下载并安装openwrt官方提供的交叉编译器至/opt目录下:

wget https://mirror.sjtu.edu.cn/openwrt/releases/21.02.3/targets/ramips/mt76x8/openwrt-sdk-21.02.3-ramips-mt76x8_gcc-8.4.0_musl.Linux-x86_64.tar.xz
sudo tar -Jxf openwrt-sdk-ramips-mt76x8_gcc-11.2.0_musl.Linux-x86_64.tar.xz -C /opt

如果在本地已有构建了的openwrt工程,可以不下载官方的编译器,直接采用本地的编译器;这一点笔者在后面会简要说明。编译paho.mqtt.rust需要依赖openssl库,一种方案是使用下载的gcc编译器交叉编译openssl,另一种是直接复用现有的openwrt编译结果的openssl库。笔者采用了第二种方案:

/opt/openwrt-sdk-21.02.3-ramips-mt76x8_gcc-8.4.0_musl.Linux-x86_64/staging_dir/target-mipsel_24kc_musl$ find .
.
./usr
./usr/include
./include
/opt/openwrt-sdk-21.02.3-ramips-mt76x8_gcc-8.4.0_musl.Linux-x86_64/staging_dir/target-mipsel_24kc_musl$ sudo rm -rf *
~/8.06.4/build_dir/target-mipsel_24kc_musl/openssl-1.0.2s/ipkg-install$ ls    
etc  usr
~/openwrt-18.06.4/build_dir/target-mipsel_24kc_musl/openssl-1.0.2s/ipkg-install$ sudo cp -r -p -P * \
> /opt/openwrt-sdk-21.02.3-ramips-mt76x8_gcc-8.4.0_musl.Linux-x86_64/staging_dir/target-mipsel_24kc_musl/

笔者使用的openssl库源于openwrt-18.04编译工程,其版本为1.0.2s,与目柡设备已安装的openssl库版本不同,后面需要将该版本的动态库复制到设备上。

编译paho.mqtt.rust的环境变量

在之前的博客中笔者提到,需要编辑~/.cargo/config文件,增加交叉编译时的链接器选项。不过本次编译通过环境变量指定交叉编译器;为加速crates包的下载,~/.cargo/config文件的全部内容为:

[source.crates-io]
replace-with = 'tuna'

[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"

以上配置文件创建后,需要手动创建/opt/rust-lang/cargo/registry目录,该目录为crates包的下载路径;创建后需要将属主设置为普通用户:

sudo mkdir /opt/rust-lang/cargo/registry
sudo chown username:username /opt/rust-lang/cargo/registry

之后,修改用户的环境变量,在~/.profile中增加:

export CARGO_HOME=/opt/rust-lang/cargo
export RUSTUP_HOME=/opt/rust-lang/rustup
export PATH=${CARGO_HOME}/bin:${PATH}

不过以上环境变量的修改,仅用于基本的rust编程开发(如主机端的rust应用开发),不足以交叉构建paho.rust.mqtt;它需要的环境变量要复杂一些,笔者编写了rust-mips-env.sh用于配置环境变量,其内容如下:

#!/bin/bash
# rust-mips-env.sh
export OPENWRT_DIR="/opt/openwrt-sdk-21.02.3-ramips-mt76x8_gcc-8.4.0_musl.Linux-x86_64"
export STAGING_DIR="${OPENWRT_DIR}/staging_dir/target-mipsel_24kc_musl"
export OPENSSL_DIR="${STAGING_DIR}/usr"
export PATH="${OPENWRT_DIR}/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin"
export PATH="${PATH}:/opt/rust-lang/cargo/bin:/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/snap/bin"
export TARGET_CC=mipsel-openwrt-linux-musl-gcc
export CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER="${TARGET_CC}"
export TARGET_CFLAGS="-pipe -mno-branch-likely -mips32r2 -mtune=24kc -msoft-float -mips16 -minterlink-mips16"

值得强调的是上面的CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER环境变量,它替代了~/.cargo/config中相应交叉编译的链接器配置选项,这样可以通过环境变量动态地指定不同的交叉构建中的链接器,更灵活地实现rust软件项目的构建;与rust交叉编译相关的环境变量请参考官方文根档。执行source ./rust-mips-env.sh后,就可以编译paho.rust.mqtt了;编译分为两个步骤,先编译paho.mqtt.rust库,之后再编译演示例程(--examples):

~/paho.mqtt.rust$ source ../rust-mips-env.sh
~/paho.mqtt.rust$ cargo build --release --target=mipsel-unknown-linux-musl
    Updating `tuna` index
   Compiling proc-macro2 v1.0.37
   ....
   Compiling paho-mqtt v0.11.0 (/home/username/paho.mqtt.rust)
    Finished release [optimized] target(s) in 48.27s
~/paho.mqtt.rust$ cargo build --release --target=mipsel-unknown-linux-musl --examples
   Compiling fastrand v1.7.0
   ...
   Compiling paho-mqtt v0.11.0 (/home/username/paho.mqtt.rust)
    Finished release [optimized] target(s) in 2m 08s
~/paho.mqtt.rust$ cd target/mipsel-unknown-linux-musl/release
~/paho.mqtt.rust/target/mipsel-unknown-linux-musl/release$ file examples/async_publish
examples/async_publish: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-mipsel-sf.so.1, with debug_info, not stripped
~/paho.mqtt.rust/target/mipsel-unknown-linux-musl/release$ patchelf --print-needed examples/async_publish
libssl.so.1.0.0
libcrypto.so.1.0.0
libgcc_s.so.1
libc.so

在MIPS嵌入式设备上演示async_publish

首先,将上面复制的openssl-1.0.2s库复制到目柡设备的/tmp目录下,再确认async_publish的依赖库都存在:

root@OpenWrt:/tmp# export LD_LIBRARY_PATH=/tmp
root@OpenWrt:/tmp# ldd ./async_publish 
        /lib/ld-musl-mipsel-sf.so.1 (0x77df3000)
        libssl.so.1.0.0 => /tmp/libssl.so.1.0.0 (0x77bd6000)
        libcrypto.so.1.0.0 => /tmp/libcrypto.so.1.0.0 (0x77a73000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x77a4f000)
        libc.so => /lib/ld-musl-mipsel-sf.so.1 (0x77df3000)

之后,在网关上访问一个带有公网IP的broker(笔者这里选择了一台带有IPv6地址的openwrt路由器),订阅所有的消息:

root@OpenWrt:~# mosquitto_sub -h '2409:8a28:e77:6740:5870:XXXX:XXXX:XXXX' -p 1883 -v -t '#'
test Hello Rust MQTT world!

上面第二行为接收到的async_publish发布的消息。最后,运行async_publish的操作为:

root@OpenWrt:/tmp# ./async_publish tcp://[2409:8a28:e77:6740:5870:XXXX:XXXX:XXXX]:1883
Connecting to the MQTT server
Publishing a message on the topic 'test'
Disconnecting

本地openwrt工程的编译环境变量

如果本地已经编译了openwrt,构建paho.mqtt.rust所需的环境变量与上面大同小异,内容如下:

#!/bin/bash
# rust-mips.sh
export TARGET_CC=mipsel-openwrt-linux-musl-gcc
export TARGET_CFLAGS='-mno-branch-likely -mips32r2 -mtune=24kc'
export CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER="${TARGET_CC}"
export OPENWRT_DIR=$HOME/openwrt-18.06.4
export STAGING_DIR=${OPENWRT_DIR}/staging_dir/target-mipsel_24kc_musl
export OPENSSL_DIR=${STAGING_DIR}/usr
export PATH="${OPENWRT_DIR}/staging_dir/host/bin:${PATH}"
export PATH="${OPENWRT_DIR}/staging_dir/hostpkg/bin:${PATH}"
export PATH="${OPENWRT_DIR}/staging_dir/toolchain-mipsel_24kc_gcc-7.3.0_musl/bin:${PATH}"

如果需要在openwrt增加rust的软件包,以上某些环境变量(例如STAGING_DIR)已经定义了,不需重复定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值