背景
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是指出常见编程错误、错误、样式错误和可疑结构的工具。可以对程序进行更加广泛的错误分析。 |
配置规则
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,如下所示:
jsonimport("//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" ] }
-
执行编译得到的可执行文件,运行结果如下:
shell./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应用系统库示例
-
增加依赖
json// GN 里增加依赖 ohos_rust_executable("test_dylib_crate") { sources = [ "src/main.rs" ] deps = [ ":simple_printer_dylib" ] # 增加外部依赖 external_deps = [ "hilog:hilog_rust" ] } // bundle.json 里增加依赖 "components": [ "hilog" ],
-
增加调用
rustextern 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."); }
-
运行测试
shell// 运行 # ./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应用调用