6 个版本
0.2.3 | 2020 年 10 月 14 日 |
---|---|
0.2.2 | 2020 年 9 月 14 日 |
0.2.1 | 2020 年 7 月 21 日 |
0.1.1 | 2020 年 5 月 24 日 |
在 #wasm-file 中排名 20
每月下载次数 25
82KB
859 行
cargo watt
Watt 是一个用于执行编译为 WebAssembly 的 Rust 过程宏的运行时。
我假设你熟悉 watt,dtolnay 用于在 WebAssembly 解释器中执行过程宏的 crate。
在那里,工具改进被列为 待完成的工作,而这个 cargo 子命令旨在实现这一点。其目的是
- 编译现有过程宏 crate 以供 watt 运行时使用,无需手动干预
- 验证 wasm 文件是否从特定的源编译而来
使用 cargo watt
编译的一些流行过程宏列表可在 此处 获取。
先决条件
要使用 cargo watt
,你需要安装 rustc 的 wasm32 工具链
$ rustup target add wasm32-unknown-unknown
此外,为了优化 wasm 文件的大小,将使用 wasm-strip (wabt) 和 wasm-opt (binaryen)。要排除优化,请使用 --no-wasm-opt
或 --no-wasm-strip
。
构建过程宏 crate (cargo watt build
)
首先通过复制一个crate(可以是本地目录、Git仓库或crates.io上的crate)到/tmp
来构建工作。然后,将crate类型更改为cdylib
,将proc-macro2
修复为dtolnay的proc_macro2
。接下来,将其中所有的过程宏替换为pub #[no_mangle] extern "C"
函数和将proc_macro
替换为proc_macro2
,请参见这里。
目前,简单的crate已经可以编译,但还需要做更多工作以支持更广泛的crate。因为我们只是更改了一些签名并寄希望于最好的结果,有时一些东西会停止工作。为了“修复”这个问题(尽管这更像是一种黑客行为),我们执行以下操作
- 将
syn
替换为这个syn补丁,该补丁基本上将所有实例的proc_macro
替换为proc_macro2
(请参见这里)并删除了对wasm32-unknown-unknown
的条件编译 - 对
proc_macro
进行字面搜索和替换为proc_macro2
。这听起来可能有些愚蠢,但在我测试中这效果不错。
当然,一些crate仍然无法编译,在这种情况下,你需要自己调整一些东西。值得注意的是,任何依赖于synstructure
或proc_macro_error
的东西都不会工作,也许将来会提供这些补丁。
最后,生成一个shim crate,它调用生成的WebAssembly文件并执行标记树转换。
作为用户,你所需要做的就是
$ cargo watt build --crate serde-derive
INFO cargo_watt > download crate 'serde-derive' into temporary directory...
INFO cargo_watt > begin compiling crate...
Updating git repository `https://github.com/dtolnay/watt`
Updating git repository `https://github.com/jakobhellermann/syn-watt`
Updating crates.io index
Compiling syn v1.0.22 (https://github.com/jakobhellermann/syn-watt#0f0ace5e)
Compiling serde_derive v1.0.110 (/tmp/cargo-watt-crate)
Finished release [optimized] target(s) in 19.65s
INFO cargo_watt > finished in 19.65s
INFO cargo_watt > compiled wasm file is 2.65mb large
INFO cargo_watt > generated crate in "serde_derive-watt"
或者,你可以获取一个Git仓库(cargo watt build --git https://github.com/idanarye/rust-typed-builder
)或使用本地路径(cargo watt build ./path/to/crate
)。
默认情况下,cargo watt
将包括原始crate的所有文件(即测试、文档等)在新生成的crate中。如果您只想有Cargo.toml
、src/lib.rs
和src/the-macro.wasm
,可以使用--only-copy-essential
选项。
注意事项
一些过程宏crate需要导出实际宏之外的其他东西,因此它们被分割成一个常规的Rust crate,导出一些Trait/函数,然后从这个crate中重新导出宏。
这就是为什么例如 cargo watt --crate thiserror
会告诉你 thiserror 不是一个 proc macro crate 的原因。相反,你需要运行 cargo watt --crate thiserror-impl
和 [patch]
thiserror-impl
到你的生成的 crate 中。
此外,如果 Cargo.lock
文件中指定的 syn 版本比 我修补的版本 更新,这将导致编译错误。在大多数情况下,更新就像在上游上重新分叉分支一样简单,但应该有一些自动化处理,但目前还没有。
验证编译(cargo watt verify
)
在 WebAssembly 中运行宏的隔离属性确保它无法无限制地访问文件或网络,但它生成的代码仍然可能是有害的。因此,能够验证编译的二进制 wasm 文件确实是由某个源编译的非常重要,这样就可以手动进行审计。
就像构建子命令一样,cargo watt verify
与本地项目、远程 git 仓库和 crates.io 的 crate 一起工作,你可以这样使用
$ cargo watt build --crate serde-derive
...
$ cargo watt verify serde-derive_watt/src/serde-derive.wasm --crate serde-derive
INFO cargo_watt::wasm > finished in 17.3s
Success!
然而,目前 Linux 上编译的 crate 将与 macOS 上的不同。如果你知道这是为什么以及如何修复它,请告诉我。
安装
$ cargo install cargo-watt
性能
这会对编译时间产生多大的影响?
我对以下依赖项的 crate 进行了分析
tokio = { version = "0.2", features = ["macros"] }
thiserror = "1.0"
[patch.crates-io]
tokio-macros = { git = "https://github.com/jakobhellermann/watt-contrib" }
thiserror-impl = { git = "https://github.com/jakobhellermann/watt-contrib" }
没有修补
有修补
这是一个 6 秒与 17 秒的差距,所以还不错。当然,在真实的项目中,你会有更多非宏的 crate,因此加速效果不那么明显,但仍然更快。
LICENSE
MIT © Jakob Hellermann
依赖项
~9–21MB
~323K SLoC