rust編譯新的wasm項目操作流程(原文: 編譯 Rust 爲 WebAssembly)

字號+ 編輯: 种花家 修訂: 种花家 來源: 网络转载 2023-09-12 我要說兩句(0)

這篇文章在官網也有, 不過是英文的。官方漢化的文章總是敦促開發者上傳代碼,所以並沒有採用。

如果你有一些 Rust 代碼,你可以將它編譯成WebAssembly (wasm)。本教程將帶您了解將 Rust 項目編譯爲 wasm 並在現有 Web 應用程序中使用它所需的所有知識。

Rust 和 WebAssembly 用例

Rust 和 WebAssembly 有兩個主要用例:

構建一個完整的應用程序——一個基於 Rust 的整個 Web 應用程序。

構建應用程序的一部分——在現有的 JavaScript 前耑中使用 Rust。

目前,Rust 團隊專注於後一種情況,這就是我們在這裡介紹的内容。對於前一種情況,請查看以下項目yew.

在本教程中,我們使用 構建一個包wasm-pack,這是一個在 Rust 中構建 JavaScript 包的工具。這個包將只包含 WebAssembly 和 JavaScript 代碼,因此包的用戶不需要安裝 Rust。他們甚至可能沒有注意到它是用 Rust 編寫的。

Rust 環境設置

讓我們完成所有必需的步驟來設置我們的環境。

安裝 Rust

轉到安裝 Rust安裝 Rust頁並按照說明進行操作。這會安裝一個名爲“rustup”的工具,它可以讓你管理多個版本的 Rust。默認情況下,它會安裝最新的穩定版 Rust,您可以將其用於一般的 Rust 開發。Rustup 安裝rustc,Rust 編譯器,以及cargoRust 的包管理器,rust-stdRust 的標準庫,以及一些有用的文档 — rust-docs.

注意:注意bin系統中需要cargo目錄的安裝後說明PATH。這是自動添加的,但您必須重新啓動終耑才能使其生效。

wasm包

要構建包,我們需要一個額外的工具,wasm-pack. 這有助於將代碼編譯爲 WebAssembly,並生成正確的打包以供在瀏覽器中使用。要下載並安裝它,請在終耑中輸入以下命令:

$ cargo install wasm-pack

構建我們的 WebAssembly 包

讓我們在 Rust 中創建一個新包。導航到您保存個人項目的位置,然後輸入:

$ cargo new --lib hello-wasm
  Created library `hello-wasm` project

這將在一個名爲的子目錄中創建一個新庫,其中hello-wasm包含您需要的所有内容:

+-- Cargo.toml
+-- src
+-- lib.rs

首先,我們有Cargo.toml;這是我們用來配置構建的文档。如果您使用Gemfile過 Bundler 或package.jsonnpm,這可能很熟悉;Cargo 的工作方式與他們兩者相似。

接下來,Cargo 爲我們生成了一些 Rust 代碼src/lib.rs:

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

請把這個小屎山刪除, 寫一些Rust程序

將這段代碼放入src/lib.rs:

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

這是我們 Rust 項目的内容。它有三個主要部分;讓我們依次討論它們。我們在這裡給出一個高層次的解釋,並掩飾一些細節;要了解有關 Rust 的更多信息,請查看免費在線書籍Rust 編程語言.

用於Rustwasm-bindgen和 JavaScript 之間的通信

第一部分如下所示:

use wasm_bindgen::prelude::*;

庫在 Rust 中稱爲“crates”。

這個套路你懂否? Cargo裝的都是crates.

第一行包含一個use命令,它將庫中的代碼導入到您的代碼中。在這種情況下,我們將導入wasm_bindgen::prelude模塊中的所有内容。我們將在下一節中使用這些功能。

在我們進入下一節之前,我們應該多談談wasm-bindgen.

wasm-pack使用wasm-bindgen另一個工具,在 JavaScript 和 Rust 類型之間架起一座橋梁。它允許 JavaScript 使用字符串調用 Rust API,或調用 Rust 函數來捕獲 JavaScript 異常。

我們在我們的包中使用wasm-bindgen's 功能。事實上,這是下一節。

從 Rust 調用 JavaScript 中的外部函數

下一部分如下所示:

#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
}

内部的位#[ ]稱爲“屬性”,它以某種方式修改下一條語句。在這種情況下,該語句是一個extern,它告訴 Rust 我們想要調用一些外部定義的函數。該屬性表示“wasm-bindgen 知道如何找到這些函數”。

第三行是函數簽名,用 Rust 編寫。它說“alert函數接受一個參數,一個名爲 . 的字符串s。”

您可能會懷疑,這是JavaScript 提供的alert功能。我們在下一節中調用這個函數。

每當您想調用 JavaScript 函數時,您都可以將它們添加到此文档中,並wasm-bindgen爲您完成所有設置。並非所有内容都受支持,但我們正在努力。請文档錯誤如果缺少某些東西。

生成 JavaScript 可以調用的 Rust 函數

最後一部分是這個:

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

再一次,我們看到了#[wasm_bindgen]屬性。在這種情況下,它不是修改一個extern塊,而是一個fn; 這意味著我們希望這個 Rust 函數能夠被 JavaScript 調用。它的反面extern:這些不是我們需要的功能,而是我們提供給世界的功能。

這個函數被命名爲greet,並接受一個參數,一個字符串(寫入&str),name。然後它調用我們在上面的塊中要求的alert函數。extern它傳遞一個對format!宏的調用,它允許我們連接字符串。

在這種format!情況下,宏接受兩個參數,一個格式字符串和一個要放入其中的變量。格式字符串是"Hello, {}!"位。它包含{}s,其中將插入變量。我們傳遞的變量是name函數的參數,所以如果我們調用greet("Steve")我們應該看到"Hello, Steve!".

這被傳遞給alert(),所以當我們調用這個函數時,我們會看到一個帶有“你好,史蒂夫!”的警告框。在裡面。

現在我們的庫已經寫好了,讓我們來構建它。

將我們的代碼編譯爲 WebAssembly

爲了正確編譯我們的代碼,我們首先需要使用Cargo.toml. 打開此文档,並將其内容更改爲如下所示:

[package]
name = "hello-wasm"version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"

git填寫您自己的存儲庫並使用與該authors字段相同的信息。

要添加的重要部分是[package]. 該[lib]部分告訴 Rust 構建cdylib我們包的一個版本;我們不會在本教程中討論這意味著什麽。更多信息,請諮詢貨物和鏽連杆文档。

最後一節是[dependencies]節。這裡是我們告訴 Cargowasm-bindgen我們想要依賴哪個版本的地方;在這種情況下,這是任何0.2.z版本(但不是0.3.0或更高版本)。

構建包

現在我們已經完成了所有設置,讓我們構建包。在終耑中輸入:

$ wasm-pack build --target web

這會做很多事情(它們會花費很多時間,尤其是第一次運行時wasm-pack)。要詳細了解它們,請查看這篇關於 Mozilla Hacks 的博文. 簡而言之,wasm-pack build:

將你的 Rust 代碼編譯爲 WebAssembly。

在該 WebAssembly 上運行wasm-bindgen,生成一個 JavaScript 文档,該文档將該 WebAssembly 文档包裝到瀏覽器可以理解的模塊中。

創建一個pkg目錄並將該 JavaScript 文档和您的 WebAssembly 代碼移動到其中。

讀取您的Cargo.toml並生成等效的package.json.

README.md將您的(如果有的話)複制到包裝中。

最終結果?您在pkg目錄中有一個包。

關於代碼大小的題外話

如果您查看生成的 WebAssembly 代碼大小,它可能是幾百 KB。我們根本沒有指示 Rust 優化大小,這樣做會大大減少大小。這超出了本教程的範圍,但是如果您想了解更多信息,請查看 Rust WebAssembly 工作組的文档縮小 .wasm 大小.

在網路上使用包

現在我們已經編譯好了 wasm 模塊。讓我們在瀏覽器中運行它。

index.html讓我們首先在項目的根目錄中創建一個名爲的文档,並爲其提供以下内容:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>hello-wasm example</title>
    </head>
    <body>
    <script type="module">
    import init, {greet} from "./pkg/hello_wasm.js";
    init().then(() => {
        greet("WebAssembly")
    });
    </script>
    </body>
</html>

該文档中的腳本會導入js膠水代碼,初始化wasm模塊,調用greet我們在rust中寫的函數。

使用本地 Web 服務器爲項目的根目錄提供服務(例如python3 -m http.server)。如果您不確定如何執行此操作,請參閲運行簡單的本地 HTTP 服務器。

注意:確保使用支持application/wasmMIME 類型的最新 Web 服務器。較舊的 Web 服務器可能還不支持它。

從 Web 服務器加載index.html, 舉個例子, 如果您電腦裡支持python3, 則在代碼根目錄路徑用命令行輸入

python3 -m http.server

進到locahost:8000耑口頁面, 屏幕上會出現一個警告框,其中包含Hello, WebAssembly!。我們已經成功地從 JavaScript 調用到 Rust,並從 Rust 調用到 JavaScript。

使我們的包對 npm 屎山系統可用

如果你想將 WebAssembly 模塊與 npm 屎山一起使用,我們需要進行一些更改。

讓我們從使用 target bundler 選項重新編譯 Rust 開始:

$ wasm-pack build --target bundler

安裝 Node.js 和npm屎山管理

我們正在構建一個 npm 包,因此您需要安裝 Node.js 和 npm。

要獲取 Node.js 和 npm,請轉到獲取 npm!頁面並按照說明進行操作。選擇版本時,請選擇您喜歡的任何版本;本教程不是特定於版本的。

接下來,讓我們使用 `npm link` 使這個包對安裝的其他 JavaScript 包可用

$ cd pkg
$ npm link

我們現在有一個 npm 包,用 Rust 編寫,但編譯爲 WebAssembly。它可以從 JavaScript 中使用,並且不需要用戶安裝 Rust;包含的代碼是 WebAssembly 代碼,而不是 Rust 源代碼。

在網路上使用npm屎山構造包

讓我們建立一個使用我們新的npm屎山構造包的網站。許多人通過各種打包工具使用 npm 包,我們將webpack在本教程中使用其中之一。它只是有點複雜,並顯示了一個現實的用例。

讓我們移出該pkg目錄,並創建一個新目錄 ,site來嘗試一下:

$ cd ..$ mkdir site
$ cd site
$ npm link hello-wasm

創建一個新文档 ,package.json並將以下代碼放入其中:

{
"scripts": {
"serve": "webpack-dev-server"
},
"dependencies": {
"hello-wasm": "^0.1.0"
},
"devDependencies": {
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
}

接下來,我們需要配置 Webpack。創建webpack.config.js並放入以下内容:

const path = require('path');
module.exports = {
    entry: "./index.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "index.js",
    },
    mode: "development"
};

接下來,創建一個名爲 的文档index.js,並爲其提供以下内容:

import("./node_modules/hello-wasm/hello_wasm.js").then((js) => {
 js.greet("WebAssembly with NPM");});

node_modules這將從文档夾中導入新模塊。這不被認爲是最佳實踐,但這是一個演示,所以現在可以了。加載後,它會greet從該模塊調用函數,並"WebAssembly"作爲字符串傳遞。請注意這裡沒有什麽特別之處,但我們正在調用 Rust 代碼。就 JavaScript 代碼而言,這只是一個普通的模塊。

最後,我們需要修改HTML文档;打開index.html文档並將當前内容替換爲以下内容:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>hello-wasm example</title>
 </head>
 <body>
 <script src="./index.js"></script>
 </body>
</html>

我們完成了制作文档。讓我們試一試:

$ npm install
$ npm run serve

這將啓動一個 Web 服務器。加載http://localhost:8080並在屏幕上出現一個警告框,其中包含Hello, WebAssembly with NPM!。我們已經成功地將 Rust 模塊與 npm 一起使用。

結論

我們的教程到此結束;我們希望您發現它有用。

閲完此文,您的感想如何?
  • 有用

    2

  • 沒用

    1

  • 開心

    2

  • 憤怒

    1

  • 可憐

    1

1.如文章侵犯了您的版權,請發郵件通知本站,該文章將在24小時内刪除;
2.本站標注原創的文章,轉發時煩請注明來源;
3.交流群: 2702237 13835667

相關課文
  • 在rust/axum框架中操作redis

  • axum框架當中獲取請求header, 和獲取header指定字段的方法

  • rust視圖模板庫askama的使用

  • 在M1 M2芯片的蘋果電腦上編譯intel x86的rust庫

我要說說
網上賓友點評