色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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是指出常見編程錯誤、錯誤、樣式錯誤和可疑結構的工具。可以對程序進行更加廣泛的錯誤分析。

配置規則

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

    文章

    5032

    瀏覽量

    97372
  • Rust
    +關注

    關注

    1

    文章

    228

    瀏覽量

    6601
  • 鴻蒙
    +關注

    關注

    57

    文章

    2339

    瀏覽量

    42805
  • OpenHarmony
    +關注

    關注

    25

    文章

    3713

    瀏覽量

    16254
收藏 人收藏

    評論

    相關推薦

    OpenHarmony鴻蒙南向開發案例:【智能貓眼(基于Hi3518開發板)】

    基于Hi3518開發板,使用開源OpenHarmony開發的RTSP協議流媒體應用。達到將Hi3518開發板中攝像頭獲取的數據通過RTSP協議傳輸到手機并顯示 。
    的頭像 發表于 04-22 15:46 ?2010次閱讀
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>鴻蒙</b>南向<b class='flag-5'>開發</b>案例:【智能貓眼(基于Hi3518<b class='flag-5'>開發板</b>)】

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

    產品解決方案為基于開發板的完整產品,主要包含產品對OS的適配、部件拼裝配置、啟動配置和文件系統配置等。產品解決方案的源碼路徑規則為:**ve
    的頭像 發表于 05-09 10:32 ?1126次閱讀
    <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 ?1023次閱讀
    <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>】

    鴻蒙OpenHarmony開發板解析:【芯片解決方案】

    芯片解決方案是指基于某款開發板的完整解決方案,包含驅動、設備側接口適配、開發板sdk等。
    的頭像 發表于 05-10 15:42 ?1228次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>開發板</b><b class='flag-5'>解析</b>:【芯片解決方案】

    鴻蒙OpenHarmony南向/北向快速開發教程-迅為RK3568開發板

    大家期待已久的迅為RK3568開發板終于迎來了鴻蒙4.1系統的強勢支持!想知道如何實現快速開發學習嗎?跟著我們一起來探索吧! 迅為RK3568開發板: 想象一下,你手中的RK3568
    發表于 07-23 10:44

    TI DM388評估模塊開發板開發指導手冊

    TI DM388評估模塊開發板開發指導手冊
    發表于 11-25 18:06 ?15次下載

    openharmony開發openharmony開發板

    現在市面上支持OpenHarmony開發板已經非常多了,OpenHarmony不僅僅只能在海思系列芯片上運行,比較常見的有HiSpark、小熊派系列。這些開發板都是基于海思的Hi38
    的頭像 發表于 06-24 09:03 ?3670次閱讀

    [鴻蒙]OpenHarmony4.0的Rust開發

    背景 Rust 是一門靜態強類型語言,具有更安全的內存管理、更好的運行性能、原生支持多線程開發等優勢。Rust 官方也使用 Cargo 工具來專門為 Rust 代碼創建工程和構建編譯
    的頭像 發表于 02-26 17:28 ?876次閱讀
    [<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鴻蒙南向開發案例:【智能貓眼(基于3516開發板)】

    基于Hi3516開發板,使用開源OpenHarmony開發的RTSP協議流媒體應用。達到將Hi3516開發板中攝像頭獲取的數據通過RTSP協議傳輸到手機并顯示 。
    的頭像 發表于 04-19 22:01 ?599次閱讀
    <b class='flag-5'>OpenHarmony</b><b class='flag-5'>鴻蒙</b>南向<b class='flag-5'>開發</b>案例:【智能貓眼(基于3516<b class='flag-5'>開發板</b>)】

    鴻蒙OpenHarmony開發板解析:【系統能力配置規則

    SysCap(SystemCapability,系統能力)是部件向開發者提供的接口的集合。
    的頭像 發表于 05-11 10:10 ?529次閱讀
    <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>】

    瑞芯微RK3566鴻蒙開發板OpenHarmony標準系統應用兼容性測試指導

    本文OpenHarmony標準系統應用兼容性測試指導,適用鴻蒙系統軟件開發測試的新手入門學習課程,設備為觸覺智能的瑞芯微RK3566開發板
    的頭像 發表于 09-10 11:56 ?373次閱讀
    瑞芯微RK3566<b class='flag-5'>鴻蒙</b><b class='flag-5'>開發板</b><b class='flag-5'>OpenHarmony</b>標準系統應用兼容性測試<b class='flag-5'>指導</b>

    觸覺智能Purple Pi OH鴻蒙開發板成功適配OpenHarmony5.0 Release,開啟新征程

    觸覺智能Purple Pi OH鴻蒙開發板,成功適配OpenHarmony5.0 Release版本!為大家帶來OpenHarmony5.0特性講解!關注觸覺智能,為大家帶來更多
    的頭像 發表于 10-25 10:51 ?382次閱讀
    觸覺智能Purple Pi OH<b class='flag-5'>鴻蒙</b><b class='flag-5'>開發板</b>成功適配<b class='flag-5'>OpenHarmony</b>5.0 Release,開啟新征程

    如何在開源鴻蒙OpenHarmony開啟SELinux模式?RK3566鴻蒙開發板演示

    本文介紹開源鴻蒙OpenHarmony系統下,開啟/關閉SELinux權限的方法,觸覺智能Purple Pi OH鴻蒙開發板演示,已適配全新Open
    的頭像 發表于 11-18 19:03 ?312次閱讀
    如何在開源<b class='flag-5'>鴻蒙</b><b class='flag-5'>OpenHarmony</b>開啟SELinux模式?RK3566<b class='flag-5'>鴻蒙</b><b class='flag-5'>開發板</b>演示

    OpenHarmony屬性信息怎么修改?觸覺智能RK3566鴻蒙開發板來演示

    本文介紹開源鴻蒙OpenHarmony系統下,修改產品屬性信息的方法,觸覺智能Purple Pi OH鴻蒙開發板演示,已適配全新OpenHarmon
    的頭像 發表于 11-27 09:31 ?145次閱讀
    <b class='flag-5'>OpenHarmony</b>屬性信息怎么修改?觸覺智能RK3566<b class='flag-5'>鴻蒙</b><b class='flag-5'>開發板</b>來演示

    OpenHarmony默認30秒熄屏太麻煩?觸覺智能鴻蒙開發板教你輕松取消

    OpenHarmony系統開機后 30 秒會自動息屏,教大家兩招輕松取消自動息屏,觸覺智能Purple Pi OH鴻蒙開發板演示,已適配全新OpenHarmony5.0 Release
    的頭像 發表于 12-09 11:45 ?200次閱讀
    <b class='flag-5'>OpenHarmony</b>默認30秒熄屏太麻煩?觸覺智能<b class='flag-5'>鴻蒙</b><b class='flag-5'>開發板</b>教你輕松取消
    主站蜘蛛池模板: 中文字幕s级优女区| 黄色日本女人| 日欧一片内射VA在线影院| 97在线国内自拍视频| 久久久久久久久性潮| 亚洲破处女| 好满射太多了装不下了视频| 99久久久无码国产精品免费人妻| 国产一区二区波多野结衣| 日韩免费视频一区| 91麻豆精品国产一级| 黄色直接观看| 午夜福利理论片在线播放| 女子叉开腿让男子桶免费软件| 一二三四视频免费社区5| 国产蜜臀AV在线一区视频| 人人啪日日观看在线| 91精品国产91| 久久亚洲伊人中字综合精品| 亚洲精品国产高清嫩草影院| 国产成人99久久亚洲综合精品| 耽肉高h喷汁呻吟| 让人爽到湿的小黄书| 插我一区二区在线观看| 清冷受被CAO的合不拢| 草莓视频在线观看免费观看高清| 亲女乱h文小兰第一次| 扒开她的黑森林让我添动态图| 琪琪热热色原日韩在线| 成人在线观看国产| 少妇高潮久久久久7777| 国产精品无码无卡毛片不卡视 | 最近的中文字幕2019国语 | 久久草这在线观看免费| 一抽一出BGM免费3分钟| 久久青青草原| 97国产精品人妻无码免费| 欧美z000z猪| 岛国片在线免费观看| 同时被两个男人轮流舔| 国产精品久久自在自2021|