OpenHarmony 4.0 的 Rust 開發
背景
Rust是一門靜態強類型語言,具有更安全的內存管理、更好的運行性能、原生支持多線程開發等優勢。Rust官方也使用Cargo工具來專門為Rust代碼創建工程和構建編譯。 OpenHarmony為了集成C/C++ 代碼和提升編譯速度,使用了GN + Ninja的編譯構建系統。GN的構建語言簡潔易讀,Ninja的匯編級編譯規則直接高效。 為了在OpenHarmony中集成Rust代碼,并最大程度發揮Rust和OpenHarmony中原有C/C++ 代碼的交互性,采用GN作為統一構建工具,即通過GN構建Rust源碼文件(xxx.rs),并增加與C/C++互操作、編譯時lint、測試、IDL轉換、三方庫集成、IDE等功能。同時擴展gn框架,支持接口自動化轉換,最大程度簡化開發。
基本概念
術語 | 描述 |
Cargo | Cargo是Rust官方使用的構建工具,允許Rust項目聲明其各種依賴項,并確保您始終獲得可重復的構建。 |
crate | crate是一個獨立的可編譯單元。 |
Lint | Lint是指出常見編程錯誤、錯誤、樣式錯誤和可疑結構的工具??梢詫Τ绦蜻M行更加廣泛的錯誤分析。 |
配置規則
OpenHarmony提供了用于Rust代碼編譯構建的各類型GN模板,可以用于編譯Rust可執行文件,動態庫和靜態庫等。各類型模板說明如下:
GN模板 | 功能 | 輸出 |
ohos_rust_executable | rust可執行文件 | rust可執行文件,不帶后綴 |
ohos_rust_shared_library | rust動態庫 | rust dylib動態庫,默認后綴.dylib.so |
ohos_rust_static_library | rust靜態庫 | rust rlib靜態庫,默認后綴.rlib |
ohos_rust_proc_macro | rust proc_macro | rust proc_macro庫, 默認后綴.so |
ohos_rust_shared_ffi | rust FFI動態庫 | rust cdylib動態庫,給C/C++模塊調用,默認后綴.so |
ohos_rust_static_ffi | rust FFI靜態庫 | rust staticlib庫,給C/C++模塊調用,默認后綴.a |
ohos_rust_cargo_crate | 三方包Cargo crate | rust三方crate,支持rlib、dylib、bin |
ohos_rust_systemtest | rust系統測試用例 | rust可執行系統測試用例,不帶后綴 |
ohos_rust_unittest | rust單元測試用例 | rust可執行單元測試用例,不帶后綴 |
ohos_rust_fuzztest | rust Fuzz測試用例 | rust可執行Fuzz測試用例,不帶后綴 |
配置Rust靜態庫示例
該示例用于測試Rust可執行bin文件和靜態庫rlib文件的編譯,以及可執行文件對靜態庫的依賴,使用模板ohos_rust_executable和ohos_rust_static_library。操作步驟如下:
- 創建build/rust/tests/test_rlib_crate/src/simple_printer.rs,如下所示:
//! simple_printer
/// struct RustLogMessage
pub struct RustLogMessage {
/// i32: id
pub id: i32,
/// String: msg
pub msg: String,
}
/// function rust_log_rlib
pub fn rust_log_rlib(msg: RustLogMessage) {
println!("id:{} message:{:?}", msg.id, msg.msg)
}
創建build/rust/tests/test_rlib_crate/src/main.rs,如下所示:
//! rlib_crate example for Rust.
extern crate simple_printer_rlib;
use simple_printer_rlib::rust_log_rlib;
use simple_printer_rlib::RustLogMessage;
fn main() {
let msg: RustLogMessage = RustLogMessage {
id: 0,
msg: "string in rlib crate".to_string(),
};
rust_log_rlib(msg);
}
配置gn腳本build/rust/tests/test_rlib_crate/BUILD.gn,如下所示:
import("http://build/ohos.gni")
ohos_rust_executable("test_rlib_crate") {
sources = [ "src/main.rs" ]
deps = [ ":simple_printer_rlib" ]
}
ohos_rust_static_library("simple_printer_rlib") {
sources = [ "src/simple_printer.rs" ]
crate_name = "simple_printer_rlib"
crate_type = "rlib"
features = [ "std" ]
}
執行編譯得到的可執行文件,運行結果如下:
./build.sh --product-name rk3568 --build-target build/rust/tests:tests --no-prebuilt-sdk
hdc_std.exe shell mount -o rw,remount /
hdc_std.exe shell file send test_dylib_crate /data/local/tmp
hdc_std.exe file send libsimple_printer_dylib.dylib.so /system/lib
hdc_std.exe shell
# cd /data/local/tmp
# chmod +x test_dylib_crate
# ./test_dylib_crate
id:0 message:"string in rlib crate"
配置Rust應用系統庫示例
增加依賴:
// GN 里增加依賴
ohos_rust_executable("test_dylib_crate") {
sources = [ "src/main.rs" ]
deps = [ ":simple_printer_dylib" ]
# 增加外部依賴
external_deps = [ "hilog:hilog_rust" ]
}
// bundle.json 里增加依賴
"components": [
"hilog"
],
增加調用:
extern crate simple_printer_dylib;
use simple_printer_dylib::rust_log_dylib;
use simple_printer_dylib::RustLogMessage;
//! 增加引用
use std::ffi::{ c_char, CString };
use hilog_rust::{hilog, info, HiLogLabel, LogType};
const LOG_LABEL: HiLogLabel = HiLogLabel {
log_type: LogType::LogCore,
domain: 0xD002220,
tag: "TEST_RUST",
};
fn main() {
let msg: RustLogMessage = RustLogMessage {
id: 0,
msg: "string in rlib crate".to_string(),
};
rust_log_dylib(msg);
//! 增加調用
info!(LOG_LABEL, "Fnished enable all keys.");
}
運行測試:
// 運行
# ./test_dylib_crate
id:0 message:"string in rlib crate"
// 查看hilog
# hilog | grep Fnished
08-17 05:14:18.121 29293 29293 I C02220/TEST_RUST: Fnished enable all keys.
注意:rust和openharmony其他開源代碼可以混合使用,如rust可以生成C/C庫,給其他C/C應用使用,反之C/C++庫也可以給rust應用調用
總結
- OpenHarmony已經全面支持的rust開發,一些工具部件如hilog也有對應的rust版本。
- 社區文檔:https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-build-rust-compilation.md。
- 社區樣例:https://gitee.com/openharmony/build rust目錄下有各種樣例。