对于嵌入式系统软件和应用软件的开发而言,编程语言的重要性次于整体的软件架构设计的重要性。不过仍有必要谨慎地选择编程语言,因为这涉及开发效率、软件性能,以及团队成员的技术能力。譬如,若整个嵌入式软件的绝大数组件是用C++编写的,那么招聘一些对C++不十分熟悉的开发人员,就是团队建设的不合理了:精通C++的开发人员相对较少。对于小型的团队,选择一些不常用的编程语言,(短期内)不用考虑团队建设的问题,同时可以很大程度上提升开发效率、减少软件缺陷,提高软件的可维护性、可扩展性。随着嵌入设备的性能越来越高,可以在嵌入式设备上选择Golang/NodeJS/MicroPython等高级的(脚本)编程语言来进行开发。Rust是一门新兴的系统编程语言,强大的语言特性及良好的底层设计,使得它可以为Cortex-M系列的ARM单片机写裸应用,可以在执行效上媲美C/C++,可以在面向对象编程方面接近Java。甚至目前开源社区正在努力将其整合到Linux内核中,作为Linux内核驱动开发的第二种编程语言。不过现在常用Rust语言开发的,可能在深度学习算法和区块链等领域。
本文记录了而笔者搭建Rust交叉编译环境的搭建过程,并在树霉派设备上运行了第一个由Rust编写的Hello World程序。
笔者常用的系统为ubuntu,可以通过官方软件源来安装Rust开发环境:
sudo apt install build-essential rustc rust-doc cargo cargo-doc
安装过后,可以通过浏览器打开/usr/share/doc/rust-doc/html/index.html
文件,包含了Rust的官方文档,含有丰富的开发资料。不过这种方式安装的Rust开发环境不能进行交叉编译,缺少rustup
命令行工具。该工具需要通过snap
来安装,但国内访问snap
源因网络问题很不容易。最终笔者选译通过Rust官方推荐的安装方式来安装。
安装的操作比较简单,首先,以超级用户执行:
export CARGO_HOME=/opt/rust-lang/cargo
export RUSTUP_HOME=/opt/rust-lang/rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > sh.rustup.rs
sh ./sh.rustup.rs
上面的两行export
指令指示cargo
和rustup
的安装路径。执行sh.rustup.rs
脚本就会执行Rust开发环境的安装。这是一个交互的安装过程,当提示选择时,选译第一个选项。以下是安装过程,根据网络环境的不同,可以会持续十几分钟:
root@rustling:~# sh ./sh.rustup.rs
info: downloading installer
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:
/opt/rust-lang/rustup
This can be modified with the RUSTUP_HOME environment variable.
The Cargo home directory located at:
/opt/rust-lang/cargo
This can be modified with the CARGO_HOME environment variable.
The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:
/opt/rust-lang/cargo/bin
This path will then be added to your PATH environment variable by
modifying the profile files located at:
/root/.profile
/root/.bashrc
You can uninstall at any time with rustup self uninstall and
these changes will be reverted.
Current installation options:
default host triple: x86_64-unknown-linux-gnu
default toolchain: stable (default)
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1
info: profile set to 'default'
info: default host triple is x86_64-unknown-linux-gnu
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2021-05-10, rust version 1.52.1 (9bc8c42bb 2021-05-09)
info: downloading component 'cargo'
6.0 MiB / 6.0 MiB (100 %) 2.7 MiB/s in 2s ETA: 0s
info: downloading component 'clippy'
info: downloading component 'rust-docs'
15.3 MiB / 15.3 MiB (100 %) 537.9 KiB/s in 21s ETA: 0s
info: downloading component 'rust-std'
24.1 MiB / 24.1 MiB (100 %) 1.9 MiB/s in 18s ETA: 0s
info: downloading component 'rustc'
48.4 MiB / 48.4 MiB (100 %) 50.3 KiB/s in 2m 7s ETA: 0s
info: downloading component 'rustfmt'
3.6 MiB / 3.6 MiB (100 %) 351.4 KiB/s in 16s ETA: 0s
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
15.3 MiB / 15.3 MiB (100 %) 3.7 MiB/s in 3s ETA: 0s
info: installing component 'rust-std'
24.1 MiB / 24.1 MiB (100 %) 7.9 MiB/s in 3s ETA: 0s
info: installing component 'rustc'
48.4 MiB / 48.4 MiB (100 %) 9.2 MiB/s in 5s ETA: 0s
info: installing component 'rustfmt'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'
stable-x86_64-unknown-linux-gnu installed - rustc 1.52.1 (9bc8c42bb 2021-05-09)
Rust is installed now. Great!
To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory (/opt/rust-lang/cargo/bin).
To configure your current shell, run:
source /opt/rust-lang/cargo/env
以上操作仅为开发系统安装了Rust开发环境,要进行交叉编译,仍需要以下操作:
source /opt/rust-lang/cargo/env
rustup target add aarch64-unknown-linux-gnu
rustup target add armv7-unknown-linux-gnueabihf
笔者安装了两个交叉编译Rust的支持:32位ARM和64位ARM。不过仍需要安装两者的gcc交叉编译器,因为Rust在构建时会调用aarch64-linux-gnu-gcc
等工具做为链接器。这个安装过程不再赘述,可以自行安装。以上操作完成后,就可以切换到普通用户,进行第一个Rust应用的交叉编译了。首先要配置环境变量:
export CARGO_HOME=/opt/rust-lang/cargo
export RUSTUP_HOME=/opt/rust-lang/rustup
export PATH=${CARGO_HOME}/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
export PATH=${PATH}:/opt/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin
之后,创建简单的可执行应用,并在主机上编译运行:
cargo new --bin hello
cd hello
cargo build
cargo run
以上操作的结果为:
yejq@rustling:~/hello$ cargo build
Compiling hello v0.1.0 (/home/yejq/hello)
Finished dev [unoptimized + debuginfo] target(s) in 7.73s
yejq@rustling:~/hello$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
Running `target/debug/hello`
Hello, world!
至此,为主机搭建的Rust开发环境功能正常。接下来需要为64位ARM交叉编译该简单应用,需要配置交叉编译的链接器:
mkdir ~/.cargo
cat < ~/.cargo/config
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-none-linux-gnu-gcc"
EOF
cargo build --release --target=aarch64-unknown-linux-gnu
交叉编译的结果如下:
yejq@rustling:~/hello$ cargo build --release --target=aarch64-unknown-linux-gnu
Compiling hello v0.1.0 (/home/yejq/hello)
Finished release [optimized] target(s) in 3.23s
yejq@rustling:~/hello$ ls ./target/
CACHEDIR.TAG aarch64-unknown-linux-gnu debug release
yejq@rustling:~/hello$ ls ./target/aarch64-unknown-linux-gnu/release/
build deps examples hello hello.d incremental
yejq@rustling:~/hello$ file ./target/aarch64-unknown-linux-gnu/release/hello
./target/aarch64-unknown-linux-gnu/release/hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, with debug_info, not stripped
将交叉编译生成的可执行文件hello
复制到嵌入式ARM设备上运行,可以得到期望的结果:
# ./hello
Hello, world!
至此,为嵌入式设备搭建Rust交叉编译开发环境就完成了,以后可以在嵌入式设备上用Rust编程语言来开发系统应用了。