V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gzf6
V2EX  ›  Rust

[请教] Rust 的跨平台与 wasm 的跨平台

  •  
  •   gzf6 · 2021-10-08 11:51:11 +08:00 · 3130 次点击
    这是一个创建于 1170 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Rust 可以用提供的工具链交叉编译成不同目标平台的可执行文件;实现了 wasi 的 wasm 需要不同平台相应的运行时,相当于一个虚拟环境,这么理解对么?这两种实现有什么明确的应用场景区分吗?

    6 条回复    2021-10-08 17:53:55 +08:00
    hronro
        1
    hronro  
       2021-10-08 12:45:22 +08:00
    对的,Rust 的跨平台和 C/C++ 的跨平台是一个概念,只是 Rust 提供的工具链更方便交叉编译一些。

    WASM 有点类似于 LLVM,所以 WASM 代码基本和 LLIR 差不多都是构架无关的中间代码,最后由 WASM 运行时编译成最终的 native 代码。从这点上来看,WASM 和 JVM 挺类似的。
    xuanzizhe
        2
    xuanzizhe  
       2021-10-08 14:13:26 +08:00
    先得区分下 Wasi 和 Wasm:Wasm 提供了一套栈式虚拟机的指令集,包括二进制(类似机器码)和文本两种表达(类似汇编),因为 Wasm 指令集的定义并不与 WEB 挂钩,因此不止浏览器可以实现它,也可以是其它的运行时程序甚至可以是一个操作系统。我们可以把这些实现了 Wasm 的浏览器、运行时、操作系统等看作是实现 Wasm 的宿主环境,我们也可以通过 Wasm 指令集提供的能力与宿主环境进行交互,比如将浏览器的 console.log 方法导入给 Wasm 内调用(实际可能有点复杂,因为要涉及到数据内存结构的转换等),总之,我们可以通过编写 C/C++/Rust 等语言的代码,借助一些实现了宿主环境代码到 Wasm 代码转换的库,比如针对浏览器环境里 C/C++有 emscripten,Rust 里有 wasm-bindgen,就能实现编译后的 Wasm 代码跑在 Wasm 虚拟机里但还能调用宿主环境提供的方法等能力。而 Wasi,相当于提供了一套标准接口,可以使得 Wasm 也能获得文件访问、网络、标准输入输出等与系统相关的能力,宿主环境如果想要提供这些能力供 Wasm 调用,就可以通过实现这套接口标准,提供给 Wasm 使用(可以大概理解为一套标准的方法集,与前面提到的 console.log 方法相似,由宿主环境实现,供 Wasm 使用,然后就可以将 C/C++/Rust 等代码中对前面提到的文件、网络等的操作转换为标准的 Wasm 代码),当然这些标准代码能否正常执行则有赖于宿主环境是否实现了 Wasi 。我的大概理解是这样的,可能并不完全准确,可以参看[wasi 示例]( https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md#running-common-languages-with-wasi) 应该可以有个大概了解~
    gzf6
        3
    gzf6  
    OP
       2021-10-08 15:10:47 +08:00
    @hronro @xuanzizhe 一个不恰当的比喻,rust 相当于可以编译为 iOS 和 Android 的 app 和 apk,wasm 以后相当于 web,在“浏览器”(运行时)里运行?两个跨平台的场景是类似的,完全取决于开发者的意愿?
    hronro
        4
    hronro  
       2021-10-08 15:47:25 +08:00
    @gzf6 没太看懂你这个比喻,“浏览器”也是个 app/apk,app/apk 也可以是基于 web 技术的浏览器套壳,所以你把 app/apk 和 浏览器分成对立的两个部分,不没太明白你的意思。

    我看你主要你纠结的点在于该用哪种方式跨平台?以 Rust 举例,Rust 代码可以编译成不同平台上的 native code,也可以编译成 WASM 。如果没有其他限制条件,直接编译成 native code 通常是最佳的方式。但如果调用你代码的人,需要在浏览器环境里使用你的代码,或者调用你代码的人不信任你的代码,希望你的代码跑在一个沙盒里,那么这个时候就需要编译到 WASM 。
    xuanzizhe
        5
    xuanzizhe  
       2021-10-08 17:15:21 +08:00
    @gzf6 我也没太明白你的问题的核心在哪,还是回归标题,Rust 跨平台是因为它可以将代码交叉编译成支持不同平台的代码,对应的就是 rustc 时的 target 参数,这里有 target 的列表和解释,https://doc.rust-lang.org/nightly/rustc/platform-support.html 看 target 的名称就可以知道,比如 Mac 上的 target 是 x86_64-apple-darwin,最重要的是两部分,首先是对应的是芯片 CPU 的架构(也就对应了二进制机器码指令集),这里是使用的 Intel 的 x86 架构,如果是 ARM 版本的 Mac,对应的 target 就是 aarch64-apple-darwin,使用 ARM64 位架构的指令集;另外就是操作系统名,这里是 darwin,对应也就是 macOs,有了这两部分,就能确定你的程序最终编译的二进制机器码该是怎样的。而 Wasm 跨平台是因为它提供了一套虚拟指令集,说是虚拟指令集是因为它并非像 Intel 的 x86 架构和 ARM 的 arm64 位架构那样,是提供用来制造真正的芯片的,Wasm 的真正执行还是通过对应的宿主环境实现的,然后比如在 mac 里最终的代码执行还是以 x86 或者 arm64 的机器指令来执行的。所以 Wasm 的跨平台是因为它处在比它的宿主环境浏览器或操作系统等更高的层面上,不管是什么平台架构,Wasm 代码都是用它自己的一套指令集编码出来的同一套代码,真正不同的是执行它的宿主环境能将 Wasm 的二进制机器码转译成对应平台架构里的真正机器码指令来执行,可以大致的理解为宿主环境运行了一个虚拟机,可以用来解释运行 wasm 代码,类比到 @hronro 说的那样,这个虚拟机就是 JVM,而 wasm 二进制代码就是 java 字节码~
    gzf6
        6
    gzf6  
    OP
       2021-10-08 17:53:55 +08:00
    @hronro @xuanzizhe 多谢指教,实现的基本原理我了解,主要是使用场景的问题,4 楼大概能回答我的问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2520 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 03:00 · PVG 11:00 · LAX 19:00 · JFK 22:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.