Rust 和 WebAssembly 大众化 - 简介
锈
锈
Rust 语言旨在自然地引导您实现可靠的目标,该目标在速度和内存使用方面非常高效 - Nicholas Matsakis 和 Aaron Turon
Rust 是一种系统级编程语言。Rust 提供低级内存管理来高效地表示数据。
Rust 确保安全性。这使得编写应用程序变得容易,而不必担心悬垂指针。
Rust 使并发变得轻松。
作为一门现代语言,Rust 提供了定义(设计)完善的 API。这使得 Rust 成为设计高性能应用程序、命令行界面应用程序(CLI 应用)以及其他应用程序的理想语言。
在这里查看我关于 Rust 和 WebAssembly 的书
Rust 的突出特性之一是它的compiler
。编译器会在您犯错时为您提供指导,并使您能够编写better code
。
Rust 中的所有权模型保证了线程和内存的安全。
总体而言,Rust 确保安全性、并发性,并使您远离风险、崩溃和漏洞。
Rust Web 世界
Rust 很容易上手(如果您了解所有权模型)并且有一个随时准备提供帮助的优秀社区作为后盾。
Rust 提供了first class
对 WebAssembly 的支持。Rust 和 WebAssembly 工具链使 WebAssembly 的入门变得更容易、更快捷。
JavaScript 是easy
……。它们使数百万(甚至数十亿)的开发人员能够开始编写应用程序。开发过程中的快速反馈循环和简单的 API。JavaScript 提供了良好的性能。如果经过正确的优化,JavaScript 可能会产生…… better performance
。
JavaScript 提供的性能并不可靠且不一致。任何旨在提升性能的优化在不同的 JavaScript 引擎中都不一致。这使得开发人员很难使用 JavaScript 提供更优化、更一致的性能。
WebAssembly
WebAssembly承诺提供更好的性能,因为它是静态类型的、编译的、针对生产进行了优化、使用线性内存布局等。
WebAssembly 可以轻松地在浏览器中运行原生代码。Rust 可以轻松地将 Rust 转换为 WebAssembly 二进制代码。
Rust 拥有最好的工具支持,可以与 JavaScript 开发人员熟悉的工具很好地集成。
为 WebAssembly 设置 Rust 工具链
Emscripten简化了将 C 或 C++ 编译为 WebAssembly 模块的环境设置。
Rust 将 WebAssembly 视为一等公民。它为 WebAssembly 提供了更完善的工具链和支持。
Rust 在标准 Rust 编译器 ( rustc
) 中构建了自己的 WebAssembly 工具链。这使得 Rust 开发人员能够将 Rust 代码编译成 WebAssembly 模块。
Rustup是Rust 的安装程序和版本管理工具。Rustup 工具类似于Node.js 的nvm。Rustup有助于安装、更新和删除rustc
、cargo
和rustup
其自身。
Rustc是 Rust 编译器。它将源代码转换为库或可执行文件。
Cargo是 Rust 的包管理器。Cargo 类似于 Node 的 NPM。Cargo 会下载包依赖项,然后编译、打包并上传到 Rust 的 crates 库 (crates.io)。
Cargo 下载你的 Rust 项目的依赖项并编译你的项目。 - Cargo 团队
Cargo 使创建、运行、下载、编译、测试和运行你的项目变得更加容易。cargo 命令内部调用 rustc 编译器来执行编译。
安装 Rust
那么让我们开始吧:
使用命令安装 Rust rustup
。
在 Linux 或 MacOs 中
$ curl https://sh.rustup.rs --sSf | sh
该脚本将下载并运行脚本文件。该脚本将安装 Rust 语言。rustc
和都cargo
安装在 中~/.cargo/bin
,并将所有访问权限委托给底层工具链。
安装成功完成后,您可以通过运行检查安装。
$ rustc --version
rustc 1.40.0 (73528e339 2019-12-16)
对于 Windows:
要安装 Rustup,请从此处提供的二进制文件下载 Rustup。rustc和 cargo 都安装在 users 文件夹中。
请注意,您需要 Visual Studio 2013 或更高版本的 C++ 构建工具。您可以从此处安装它们
通过运行检查安装rustc --version
拉斯特普
这是一个工具链多路复用器。它安装和管理多个 Rust 工具链,并通过安装在主目录中Rustup
的一组工具来代理它们。.cargo/bin
安装 rustup 命令后,我们可以轻松管理 Rust 的 .tar.gzrustc
和cargo
.tar.gz 编译器。rustup 还可以轻松地在 Rust 的 nightly、stable 和 beta 版本之间切换。
Rust 和 WebAssembly 现已在 Rust 稳定版(1.30 及以上版本)中可用。我们将切换到nightly
构建版本,以确保获得所有最新功能。
要切换到夜间版本,我们必须运行
$ rustup default nightly
上述命令将把默认的 Rust 编译器切换为该nightly
版本。rustc 代理~/.cargo/bin
将运行 nightly 编译器,而不是 stable 编译器。
要更新到最新版本的 nightly,我们可以运行
$ rustup update
成功更新后,我们可以通过运行以下命令检查当前安装的版本
$ rustc --version
rustc 1.42.0-nightly (da3629b05 2019-12-29)
Rust 到 WebAssembly 的编译器内置于默认的 rustc 编译器中。这意味着上述工具链设置现在可以将您的 Rust 代码编译为 WebAssembly 模块。让我们来实际看看。
Rust 到 WebAssembly
如果您认为 WebAssembly 最适合游戏应用程序、在线 IDE 以及其他资源密集型和内存密集型应用程序,那么从技术上讲您是正确的。但我们也可以在简单的应用程序中享受 WebAssembly 带来的好处。
对于我们开发的普通应用程序(即不需要始终保持超快速响应的应用程序),总会有一些需要性能调优的部分。有时,我们必须删除那些只在某些浏览器上运行而在其他浏览器上无法运行的、丑陋的意大利面条式代码。WebAssembly 在这方面提供了一个解决方案。
使用 Rust 和 WebAssembly,可以轻松地使用更快、一致的 WebAssembly 代码修补这些区域,并以此方式使用应用程序。
Rust 中针对 WebAssembly 的工具是目前最好的。使用 Rust,您可以用 Rust 创建整个应用程序(即前端和后端),也可以将 Rust 用于应用程序的一部分。
Rust 编译器使用底层的LLVM将 Rust 源代码转换为 WebAssembly 模块。
在此处阅读有关目标的更多信息
目标 wasm32-unknown-unknown
为了使用 Rust 的工具链创建 WebAssembly 模块,我们将使用目标wasm32-unknown-unknown
。
这里unknown-unknown
指示编译器,代码可以在任何机器上编译并运行。这将创建可在任何机器上运行的 WebAssembly 模块。
我们可以wasm32-unknown-unknown
使用
$ rustup target add wasm32-unknown-unknown
该wasm32-unknown-unknown
目标不增加任何运行时和工具链占用空间。前者是因为该目标假定只wasm32
存在指令集。后者是因为您不需要特殊的编译器、工具链或自定义链接器来进行编译。
写一些代码✍️
使用 cargo 创建一个新项目。
$ cargo new --lib car_fib
Created library `car_fib` package
创建了一个名为 car_fib 的新项目。该--lib
标志用于通知 Cargo 创建一个新的库项目,而不是默认的二进制项目。
二进制项目将生成可执行文件或实际运行的二进制文件。在我们的例子中,我们只是构建一个库,然后用它来创建 WebAssembly 模块。
src/lib.rs
启动我们最喜欢的文本编辑器并用以下内容替换内容。
#[no_mangle]
fn add(x: i32, y:i32) -> i32 {
x + y
}
该#[no_mangle]
注释告知编译器在生成库时不要破坏名称。
我们必须指定编译器要编译的包类型。我们可以在生成的文件crate-type
中指定。Cargo.toml
打开Cargo.toml
并在里面添加板条箱类型信息。
[package]
name = "car_fib"
version = "0.1.0"
authors = ["Sendil Kumar"]
[lib]
crate-type = ["cdylib"]
crate cdylib
-type 生成一个dynamic system library
。当需要从其他语言加载库时,使用此动态系统库。
让我们将 Rust 编译为 WebAssembly 模块。
$ cargo build --target wasm32-unknown-unknown
调用cargo build
Rust 编译器。Rust 编译器使用指定的目标wasm32-unknown-unknown
。它在里面生成 WebAssembly 模块/target/wasm32-unknown-unknown/
。
创建 HTML 文件
$ touch index.html
在中添加以下内容index.html
:
<script>
(async () => {
const bytes = await fetch("target/wasm32-unknown-unknown/debug/car_fib.wasm");
const response = await bytes.arrayBuffer();
const result = await WebAssembly.instantiate(response, {});
console.log(result.instance.exports.add(10,3));
})();
</script>
我们在这里使用了async-await,以使语法更加优雅并且在上下文中更容易理解。
首先,我们使用 获取 WebAssembly 模块fetch
。bytes.arrayBuffer()
返回以 解析的承诺ArrayBuffer
。
该WebAssembly.instantiate
函数允许你编译并实例化 WebAssembly 代码。生成的对象具有导出的方法。
正如预期的那样,这将打印输出13
。
发生了什么事?
这里,cargo build 命令调用 rust 编译器,将 Rust 代码编译为 MIR(中间表示),然后再编译为 LLVM IR。生成的 LLVM IR 随后被转换为 WebAssembly 模块。
值得注意的是,我们在这里没有使用emscripten 编译器,一切都由 rust 编译器本身处理。
让我们添加另一个函数。我们可以使用 Rust 创建一个斐波那契数生成器,并在浏览器上运行它们。
打开car_fib.rs
,将所有内容替换为以下内容
#[no_mangle]
fn fibonacci(num: i32) -> i32 {
match num {
0 => 0,
1 => 1,
_ => fibonacci(num-1) + fibonacci(num-2),
}
}
使用 来构建它cargo build --target wasm32-unknown-unknown
。
最后,index.html
用我们称之为斐波那契数列的方法来代替加法。
<script>
(async () => {
const bytes = await fetch("target/wasm32-unknown-unknown/debug/car_fib.wasm");
const response = await bytes.arrayBuffer();
const result = await WebAssembly.instantiate(response, {});
console.log(result.instance.exports.fibonacci(20));
})();
</script>
现在启动 HTML 服务器并检查浏览器控制台中的斐波那契值。
在下一篇博客中,让我们看看如何在 JavaScript 和 WebAssembly 模块之间传递各种值。
如果你喜欢这篇文章,那么你可能会喜欢我关于 Rust 和 WebAssembly 的书。点击此处查看。
👇 回购👇
sendilkumarn / rustwasm-introduction
Rust 和 WebAssembly 大众化 - 简介
有兴趣探索更多...
有关链接的更多信息请点击此处
讨论🐦 Twitter // 💻 GitHub // ✍️ 博客// 🔸 HackerNews
如果你喜欢这篇文章,请点赞或者留言。❤️
文章来源:https://dev.to/sendilkumarn/rust-and-web assembly-for-masses-introduction-1034