将 Swift 编译为 WebAssembly

Posted

技术标签:

【中文标题】将 Swift 编译为 WebAssembly【英文标题】:Compile Swift to WebAssembly 【发布时间】:2018-03-16 06:39:02 【问题描述】:

LLVM 基础架构现在支持从 LLVM IR to WebAssembly 编译(至少在实验上如此)。 Swift 使用 LLVM 编译器基础架构,可以轻松编译为 LLVM IR。所以我认为将一些 Swift 代码编译为 LLVM IR,然后编译为 WebAssembly 会很简单。

然而,事实证明并不是那么容易。看起来 LLVM IR 并不完全独立于平台?无论幕后的原因是什么,在将 Swift 编译为 LLVM IR 时,必须指定目标架构并且 WebAssembly 不可用。

那么我有两个问题:

1) 目前(截至 2017 年 10 月)没有办法,我是否正确?

2) 如何使 WebAssembly 成为 Swift 到 LLVM IR 编译的受支持目标?

【问题讨论】:

我相信你需要自己构建 LLVM,因为它默认不支持 webm。 是的,没错。我有一个定制的 LLVM 构建,支持 WebAssembly。我已经成功地使用它来将 C 代码编译为 WebAssembly。但现在我想将 Swift 代码编译为 WebAssembly,为此,LLVM 的正确构建似乎是必要的,但还不够。据我所知,对 WebAssembly 的一些支持需要在 Swift 本身中。 关注这个空间 - github.com/kripken/emscripten/issues/2427 【参考方案1】:

WebAssembly 目标就像 llvm 的通用 unix 目标,所以我认为有人需要开发那个端口。

请注意,浏览器中的 Swift -> Wasm 几乎没用,因为 Wasm 没有 DOM 或 DOM API 访问权限,因此您仍然需要 javascript 来做任何有意义的事情,因此问题是:为什么有人会费心制作端口?看起来 JavaScript 仍然是唯一的网络语言。如果你不喜欢 JavaScript,最好忘记 Web 开发。

Swift 很有可能会在运行在 Web 上之前在 android 上运行,因此请坚持使用 Swift/ios,然后在可能的情况下将其移植到 Android。无论如何,人们并不经常使用网络/浏览器。

【讨论】:

是的,支持 WASM 作为 Swift 的目标似乎需要额外的开发。问题#2 的重点是询问从哪里开始。不难想象,即使没有直接 DOM 访问,WASM 代码也可以用于 Web 开发的场景。例如,验证函数可以用 Swift 编写,用于服务器端和客户端,在客户端使用一些 JavaScript 代码来调用验证函数。也就是说,如果 WASM 确实具有 DOM 访问权限,它肯定会更多有用,但一步一步,不是吗?【参考方案2】:

1) 据我所知,截至 2017 年 11 月上旬,您是对的:没有通用的方法可以将 Swift 编译为 WebAssembly。也许某个地方的某个有进取心的黑客已经做到了,但如果是这样的话,她还没有与我们分享她的代码。

2) 为了启用 Wasm 支持,您可能需要修改几个不同的部分。我认为您可以在不了解编译器内部结构(例如解析器和优化器)的情况下做到这一点,但您需要了解工具链的工作原理以及它如何在运行时与平台集成。

您可以通过研究如何将 Swift 移植到 Android 来了解您需要做什么。幸运的是,Brian Gesiak 发布了一篇非常详细的博客文章,详细介绍了该端口的工作原理(警告:需要少量 Patreon 捐赠):

https://modocache.io/how-to-port-the-swift-runtime-to-android

说真的,如果你不阅读那篇文章就开始这个项目,你会发疯的。

虽然我不是专家,但基于该端口和我对 Swift 的(基本)理解,我认为您需要破解的粗略概述是:

Swift 编译器 您需要向它介绍 LLVM 使用的 Wasm“三元组”,以便它知道如何与其工具链的其余部分集成 您需要设置一个 WebAssembly 平台,以便人们可以在需要条件编译的地方编写 #if os(WebAssembly) 您还需要设置类似的构建时宏。 Android 文章很好地解释了这类事情。 Swift 运行时 这是用 C++ 编写的,需要在 Wasm 上运行 由于 Wasm 是一个不寻常的平台,因此这里可能会有一些工作。您可能需要为各种系统调用等提供兼容性填充程序。 Emscripten 等项目在将 C++ 编译为 Wasm 方面取得了巨大成功。 Swift 标准库 理论上,您可以编写和运行不使用标准库的 Swift 代码,但谁愿意呢? 如果运行时工作正常,理论上这应该“正常工作”,但您可能需要在此处使用 #if os(WebAssembly) 功能来解决平台违规问题 奖励:Foundation 和 Dispatch 库 如果您想使用现有的 Swift 代码,这两个库将是必不可少的。

链接:

Brian Gesiak 的精彩博文:https://modocache.io/how-to-port-the-swift-runtime-to-android 链接到 Android 端口的拉取请求:https://github.com/apple/swift/pull/1442 关于跨平台 Swift 的挑战和回报的有趣文章:https://medium.com/@ephemer/how-we-put-an-app-in-the-android-play-store-using-swift-67bd99573e3c

【讨论】:

在这个 Github 问题上主要跟踪这件事的进展:github.com/kripken/emscripten/issues/2427【参考方案3】:

截至 2019 年 5 月,有一个名为 SwiftWasm 的开源项目可让您将 Swift 代码编译为针对 WASI SDK 的 WebAssembly。这意味着 SwiftWasm 生成的二进制文件可以在带有 WASI polyfill 的浏览器或支持 WASI 的独立 WebAssembly 运行时(例如 wasmtime、lucet 或 wasmer)中执行。

【讨论】:

【参考方案4】:

看起来有一个商业产品支持将 Swift 编译为 WebAssembly。 RemObjects,开发者工具公司,有just announced support for WebAssembly with their Elements compiler,可以编译Java、Swift、C#和Oxygene。

【讨论】:

以上是关于将 Swift 编译为 WebAssembly的主要内容,如果未能解决你的问题,请参考以下文章

swift 使用枚举样本swift函数对象,允许将函数编译为枚举并被调用

尝试在 Swift 项目中使用 Objective C 可可豆荚,桥接文件编译为 Swift 代码

在 MacOS 上将 Vapor 编译为独立应用程序

强制将特定文件编译为 Objective-C/文件类型,但将整个项目编译为 Objective-C++

将现有 C# 代码编译为 WebAssembly

如何将 C++ 文件编译为 WebAssembly?