<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙OpenHarmony開發板解析:【Rust模塊配置規則和指導】

jf_46214456 ? 來源: jf_46214456 ? 作者: jf_46214456 ? 2024-05-10 11:32 ? 次閱讀

概述

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框架,支持接口自動化轉換,最大程度簡化開發。

基本概念

術語描述
CargoCargo是Rust官方使用的構建工具,允許Rust項目聲明其各種依賴項,并確保您始終獲得可重復的構建。
cratecrate是一個獨立的可編譯單元。
LintLint是指出常見編程錯誤、錯誤、樣式錯誤和可疑結構的工具??梢詫Τ绦蜻M行更加廣泛的錯誤分析。

配置規則

OpenHarmony提供了用于Rust代碼編譯構建的各類型GN模板,可以用于編譯Rust可執行文件,動態庫和靜態庫等。各類型模板說明如下:

GN模板功能輸出
ohos_rust_executablerust可執行文件rust可執行文件,不帶后綴
ohos_rust_shared_liaryrust動態庫rust dylib動態庫,默認后綴.dylib.so
ohos_rust_static_liaryrust靜態庫rust rlib靜態庫,默認后綴.rlib
ohos_rust_proc_macrorust proc_macrorust proc_macro庫, 默認后綴.so
ohos_rust_shared_ffirust FFI動態庫rust cdylib動態庫,給C/C++模塊調用,默認后綴.so
ohos_rust_static_ffirust FFI靜態庫rust staticlib庫,給C/C++模塊調用,默認后綴.a
ohos_rust_cargo_crate三方包Cargo craterust三方crate,支持rlib、dylib、bin
ohos_rust_systemtestrust系統測試用例rust可執行系統測試用例,不帶后綴
ohos_rust_unittestrust單元測試用例rust可執行單元測試用例,不帶后綴
ohos_rust_fuzztestrust Fuzz測試用例rust可執行Fuzz測試用例,不帶后綴

配置指導

配置Rust模塊與C/C++模塊類似,參考[模塊配置規則]。下面是使用不同模板的示例。

開發前請熟悉鴻蒙開發指導文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

配置Rust靜態庫示例

該示例用于測試Rust可執行bin文件和靜態庫rlib文件的編譯,以及可執行文件對靜態庫的依賴,使用模板ohos_rust_executable和ohos_rust_static_library。操作步驟如下:

  1. 創建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)
    }
    
  2. 創建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);
    }
    
  3. 配置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" ]
    }
    
  4. 執行編譯得到的可執行文件,運行結果如下:
    test_rlib_crate

配置三方庫示例

rust三方庫的BUILD.gn文件可通過cargo2gn工具自動生成。參見:[Cargo2gn工具操作指導]

該示例用于測試包含預編譯文件build.rs的三方靜態庫rlib文件的編譯,使用了模板ohos_rust_executable和ohos_rust_cargo_crate。操作步驟如下:

  1. 創建build/rust/tests/test_rlib_cargo_crate/crate/src/lib.rs,如下所示:
    include!(concat!(env!("OUT_DIR"), "/generated/generated.rs"));
    
    pub fn say_hello_from_crate() {
        assert_eq!(run_some_generated_code(), 45);
        #[cfg(is_new_rustc)]
        println!("Is new rustc");
        #[cfg(is_old_rustc)]
        println!("Is old rustc");
        #[cfg(is_ohos)]
        println!("Is ohos");
        #[cfg(is_mac)]
        println!("Is darwin");
        #[cfg(has_feature_a)]
        println!("Has feature_a");
        #[cfg(not(has_feature_a))]
        panic!("Wasn't passed feature_a");
        #[cfg(not(has_feature_b))]
        #[cfg(test_a_and_b)]
        panic!("feature_b wasn't passed");
        #[cfg(has_feature_b)]
        #[cfg(not(test_a_and_b))]
        panic!("feature_b was passed");
    }
    
    #[cfg(test)]
    mod tests {
        /// Test features are passed through from BUILD.gn correctly. This test is the target configuration.
        #[test]
        #[cfg(test_a_and_b)]
        fn test_features_passed_target1() {
            #[cfg(not(has_feature_a))]
            panic!("feature a was not passed");
            #[cfg(not(has_feature_b))]
            panic!("feature b was not passed");
        }
    
        #[test]
        fn test_generated_code_works() {
            assert_eq!(crate::run_some_generated_code(), 45);
        }
    }
    
  2. 創建build/rust/tests/test_rlib_cargo_crate/crate/src/main.rs,如下所示:
    pub fn main() {
        test_rlib_crate::say_hello_from_crate();
    }
    
  3. 創建build/rust/tests/test_rlib_cargo_crate/crate/build.rs,如下所示:
    use std::env;
    use std::path::Path;
    use std::io::Write;
    use std::process::Command;
    use std::str::{self, FromStr};
    
    fn main() {
        println!("cargo:rustc-cfg=build_script_ran");
        let my_minor = match rustc_minor_version() {
            Some(my_minor) = > my_minor,
            None = > return,
        };
    
        if my_minor >= 34 {
            println!("cargo:rustc-cfg=is_new_rustc");
        } else {
            println!("cargo:rustc-cfg=is_old_rustc");
        }
    
        let target = env::var("TARGET").unwrap();
    
        if target.contains("ohos") {
            println!("cargo:rustc-cfg=is_ohos");
        }
        if target.contains("darwin") {
            println!("cargo:rustc-cfg=is_mac");
        }
    
        let feature_a = env::var_os("CARGO_FEATURE_MY_FEATURE_A").is_some();
        if feature_a {
            println!("cargo:rustc-cfg=has_feature_a");
        }
        let feature_b = env::var_os("CARGO_FEATURE_MY_FEATURE_B").is_some();
        if feature_b {
            println!("cargo:rustc-cfg=has_feature_b");
        }
    
        // Some tests as to whether we're properly emulating various cargo features.
        assert!(Path::new("build.rs").exists());
        assert!(Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("build.rs").exists());
        assert!(Path::new(&env::var_os("OUT_DIR").unwrap()).exists());
    
        // Confirm the following env var is set
        env::var_os("CARGO_CFG_TARGET_ARCH").unwrap();
    
        generate_some_code().unwrap();
    }
    
    fn generate_some_code() - > std::io::Result< () > {
        let test_output_dir = Path::new(&env::var_os("OUT_DIR").unwrap()).join("generated");
        let _ = std::fs::create_dir_all(&test_output_dir);
        // Test that environment variables from .gn files are passed to build scripts
        let preferred_number = env::var("ENV_VAR_FOR_BUILD_SCRIPT").unwrap();
        let mut file = std::fs::File::create(test_output_dir.join("generated.rs"))?;
        write!(file, "fn run_some_generated_code() - > u32 {{ {} }}", preferred_number)?;
        Ok(())
    }
    
    fn rustc_minor_version() - > Option< u32 > {
        let rustc_bin = match env::var_os("RUSTC") {
            Some(rustc_bin) = > rustc_bin,
            None = > return None,
        };
    
        let output = match Command::new(rustc_bin).arg("--version").output() {
            Ok(output) = > output,
            Err(_) = > return None,
        };
    
        let rustc_version = match str::from_utf8(&output.stdout) {
            Ok(rustc_version) = > rustc_version,
            Err(_) = > return None,
        };
    
        let mut pieces = rustc_version.split('.');
        if pieces.next() != Some("rustc 1") {
            return None;
        }
    
        let next_var = match pieces.next() {
            Some(next_var) = > next_var,
            None = > return None,
        };
    
        u32::from_str(next_var).ok()
    }
    
  4. 配置gn腳本build/rust/tests/test_rlib_cargo_crate/BUILD.gn,如下所示:
    import("http://build/templates/rust/ohos_cargo_crate.gni")
    
    ohos_cargo_crate("target") {
      crate_name = "test_rlib_crate"
      crate_root = "crate/src/lib.rs"
      sources = [ "crate/src/lib.rs" ]
    
      #To generate the build_script binary
      build_root = "crate/build.rs"
      build_sources = [ "crate/build.rs" ]
      build_script_outputs = [ "generated/generated.rs" ]
    
      features = [
        "my-feature_a",
        "my-feature_b",
        "std",
      ]
      rustflags = [
        "--cfg",
        "test_a_and_b",
      ]
      rustenv = [ "ENV_VAR_FOR_BUILD_SCRIPT=45" ]
    }
    
    # Exists to test the case that a single crate has both a library and a binary
    ohos_cargo_crate("test_rlib_crate_associated_bin") {
      crate_root = "crate/src/main.rs"
      crate_type = "bin"
      sources = [ "crate/src/main.rs" ]
    
      #To generate the build_script binary
      build_root = "crate/build.rs"
      build_sources = [ "crate/build.rs" ]
      features = [
        "my-feature_a",
        "my-feature_b",
        "std",
      ]
      rustenv = [ "ENV_VAR_FOR_BUILD_SCRIPT=45" ]
      deps = [ ":target" ]
    }
    
  5. 執行編譯得到的可執行文件,運行結果如下:
    test_rlib_cargo_crate

其他源碼實例

在build/rust/tests目錄下有Rust各類型模塊的配置實例可供參考:

用例目錄測試功能
build/rust/tests/test_bin_crate用ohos_rust_executable模板在host平臺編譯可執行文件,在target平臺上運行可執行文件。
build/rust/tests/test_static_link測試可執行文件對標準庫的靜態鏈接。
build/rust/tests/test_dylib_crate測試對動態庫的編譯和動態鏈接功能
build/rust/tests/test_rlib_crate測試對靜態庫的編譯和靜態鏈接功能
build/rust/tests/test_proc_macro_crate測試對Rust過程宏的編譯和鏈接功能。提供對不同類型的宏的測試用例。
build/rust/tests/test_cdylib_crate測試將Rust代碼編譯成C/C++動態庫。
build/rust/tests/test_staticlib_crate測試將Rust代碼編譯成C/C++靜態庫。
build/rust/tests/rust_test_ut測試Rust代碼單元測試模板功能(ability)。
build/rust/tests/rust_test_st測試Rust代碼系統測試模板功能(ability)。
build/rust/tests/test_bin_cargo_crate測試Rust三方可執行文件的編譯和運行。三方源碼中包含build.rs。
build/rust/tests/test_rlib_cargo_crate測試Rust三方靜態庫的編譯和靜態鏈接。三方源碼中包含build.rs。
build/rust/tests/test_proc_macro_cargo_crate測試Rust三方過程宏的編譯和鏈接。三方源碼中包含build.rs。
build/rust/tests/rust_test_fuzzb測試Rust代碼Fuzz測試模板功能。

參考

特性點實例

Rust源碼依賴調用C/C++庫

OpenHarmony上C/C++模塊動態庫默認用.z.so后綴,但是Rust的編譯命令通過-l鏈接時,默認只會鏈接.so后綴的動態庫。因此如果要依賴一個C/C++動態庫編譯模塊,需要在該動態庫的GN構建文件中添加output_extension = "so"的聲明,這樣編譯得到的動態庫將會以".so"作為后綴,而不是".z.so"。 在Rust源碼中如果直接鏈接動態庫,后綴也需要使用".so",這時使用動態庫的中間名,不需要添加lib前綴。例如Rust源碼中鏈接libhilog.so:

#[link(name = "hilog")]

externs使用

某個模塊如果依賴二進制的rlib庫,可以使用externs屬性:

executable("foo") {
    sources = [ "main.rs" ]
    externs = [{                    # 編譯時會轉成`--extern bar=path/to/bar.rlib`
        crate_name = "bar"
        path = "path/to/bar.rlib"
    }]
}

Lint規則

OpenHarmony框架支持rustc lints和clippy lints兩種Lint,每種Lint劃為三個等級的標準:"openharmony"、"vendor"和"none",嚴格程度按照"openharmony" -> "vendor" -> "none"逐級遞減。 配置Rust模塊時可以通過rustc_lints和clippy_lints來指定使用Lint的等級。 模塊中沒有配置rustc_lints或者clippy_lints時會根據模塊所在路徑來匹配lints等級。不同路徑下的Rust代碼的語法規范會有不同程度地約束,因此用戶在OpenHarmony配置Rust代碼編譯模塊時還應關注模塊所在路徑。

rustc lints和clippy lints的各等級標志

lints類型模塊屬性lints等級lints等級標志lints內容
rustc_lintsrustc_lintsopenharmonyRustOhosLints"-A deprecated", "-D missing-docs", "-D warnigngs"
rustc_lintsrustc_lintsvendorRustcVendorLints"-A deprecated", "-D warnigs"
rustc_lintsrustc_lintsnoneallowAllLints"-cap-lints allow"
clippy lintsclippy lintsopenharmonyClippyOhosLints"-A clippy::type-complexity", "-A clippy::unnecessary-wraps", "-A clippy::unusual-byte-groupings", "-A clippy::upper-case-acronyms"
clippy lintsclippy lintsvendorClippyVendorLints"-A clippy::complexity", "-A Clippy::perf", "-A clippy::style"
clippy lintsclippy lintsnoneallowAllLints"--cap-lints allow"

搜狗高速瀏覽器截圖20240326151450.png

代碼路徑與lints等級的對應關系

路徑Lints等級
thirdpartynone
prebuiltsnone
vendorvendor
devicevendor
othersopenharmony

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 開發板
    +關注

    關注

    25

    文章

    4560

    瀏覽量

    94881
  • Rust
    +關注

    關注

    1

    文章

    225

    瀏覽量

    6426
  • 鴻蒙
    +關注

    關注

    55

    文章

    1919

    瀏覽量

    42196
  • OpenHarmony
    +關注

    關注

    24

    文章

    3442

    瀏覽量

    15289
收藏 人收藏

    評論

    相關推薦

    鴻蒙OpenHarmony開發板:【產品配置規則

    產品解決方案為基于開發板的完整產品,主要包含產品對OS的適配、部件拼裝配置、啟動配置和文件系統配置等。產品解決方案的源碼路徑規則為:**ve
    的頭像 發表于 05-09 10:32 ?617次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發板</b>:【產品<b class='flag-5'>配置</b><b class='flag-5'>規則</b>】

    鴻蒙OpenHarmony開發板解析:【 模塊配置規則

    編譯子系統通過模塊、部件和產品三層配置來實現編譯和打包。模塊就是編譯子系統的一個目標,包括(動態庫、靜態庫、配置文件、預編譯模塊等)。
    的頭像 發表于 05-10 14:39 ?420次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發板</b><b class='flag-5'>解析</b>:【 <b class='flag-5'>模塊</b><b class='flag-5'>配置</b><b class='flag-5'>規則</b>】

    盤點那些硬件+項目學習套件:Hi3861鴻蒙開發板及入門常見問題解答

    的一款用于鴻蒙設備開發鴻蒙物聯網開發學習的開發板。主控為華為海思Hi3861LV100芯片,內置WiFi功能,支持
    發表于 02-01 16:55

    鴻蒙開發板試用】HiSpark Wi-Fi IoT 鴻蒙開發板 試用活動名單公布

    ``開發板來了~抱歉讓大家久等了~ 經過10天的申請,截止今天一共有399位開發者提交了HiSpark Wi-Fi IoT 鴻蒙開發板試用申請。試用鏈接:https
    發表于 09-21 19:57

    基于OpenHarmony應用開發的簽名配置

    開發OpenHarmony應用的第一步就是配置環境,如果你需要使用開發板(真機)進行調試,那就免不了配置簽名信息,本文詳細介紹了基于
    發表于 03-11 15:32

    鴻蒙openharmony刷到RK3566開發板上的步驟

    開發板可以控制更多的硬件,通過軟硬結合得方式更好得體驗鴻蒙。本文介紹的是如何把鴻蒙openharmony刷到瑞芯微RK3566開發板上。網上
    發表于 03-15 14:36

    RK3568開發板鴻蒙OpenHarmony系統固件燒寫步驟

    ”)的壓縮包到 Windows 的任意路徑,然后解壓壓縮包會得到 RKDevTool_release_v2.84 文件夾  2 拷貝鴻蒙鏡像到燒寫器中,鴻蒙鏡像網盤下載地址為“iTOP-3568 開發板
    發表于 07-15 16:15

    OpenHarmony 致遠開發板開發指南

    、在線教育等諸多行業需求?!爸逻h”開發板外觀圖如圖1所示:圖1:致遠開發板外觀圖致遠開發板開發指南本文檔用來指導
    發表于 07-21 11:03

    【重磅來襲】OpenHarmony生態開發板搶先體驗!

    “競”鴻蒙開發板硬件指導手冊6、潤和軟件大禹系列HH-SCDAYU200開發套件立即申請:https://bbs.elecfans.com/try_dayu200.html
    發表于 07-28 11:16

    每日推薦 | 鴻蒙IPC開發板免費試用,OpenHarmony內核對象隊列算法詳解

    HiSpark IPC DIY Camera開發板免費試用啦,想要申請的小伙伴看過來啦!推薦理由:各位開發者看過來了,還沒有試用過這塊鴻蒙IPC開發板
    發表于 08-10 10:26

    迅為RK3568開發板鴻蒙OpenHarmony系統固件燒寫步驟

    1、迅為RK3568開發板鴻蒙OpenHarmony系統固件燒寫首先拷貝燒寫器(燒寫器在光盤資料“iTOP-3568 開發板\01_【iTOP-RK3568
    發表于 08-26 17:45

    【軟通動力鴻湖萬聯揚帆系列“競”開發板試用體驗】鴻湖萬聯揚帆系列“競”開發板試用測評報告一初識鴻蒙系統

    鴻蒙操作系統的內容,但細心觀察會發現,我們拿到的鴻蒙開發板的系統叫 OpenHarmong,那么這個OpenHarMony 和HarMony 是什么關系呢?經過一番查詢資料,大概了解
    發表于 09-18 23:29

    【觸覺智能 Purple Pi OH 開發板體驗】一、OpenHarmony鴻蒙系統)開發環境配置以及示例代碼

    不同HarmonyOS 支持 previewer 預覽、模擬器運行、真機運行三種方式;OpenHarmony 支持 previewer 預覽、真機(目前主要使用 3516 系列開發板)運行。首先,目前
    發表于 08-31 11:03

    [鴻蒙]OpenHarmony4.0的Rust開發

    背景 Rust 是一門靜態強類型語言,具有更安全的內存管理、更好的運行性能、原生支持多線程開發等優勢。Rust 官方也使用 Cargo 工具來專門為 Rust 代碼創建工程和構建編譯
    的頭像 發表于 02-26 17:28 ?409次閱讀
    [<b class='flag-5'>鴻蒙</b>]<b class='flag-5'>OpenHarmony</b>4.0的<b class='flag-5'>Rust</b><b class='flag-5'>開發</b>

    鴻蒙OpenHarmony開發板:【子系統配置規則

    通過build倉下的subsystem_config.json可以查看所有子系統的配置規則。
    的頭像 發表于 05-08 22:07 ?85次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發板</b>:【子系統<b class='flag-5'>配置</b><b class='flag-5'>規則</b>】
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>