i’m posting this because i am Completely New to Swift WebAssembly, and i’ve wanted to learn it for a while now, so i figured i would give myself 30 minutes to see how far i could get with Swift WebAssembly and document what i saw along the way in the hopes it might illuminate ways to improve the “onboarding” process even more.
i’m gonna google swift webassembly
so i start by googling 'swift webassembly', and i write this down because a lot of times the helpful Swift documentation does not show up on the first, or third page of Google search results. but luckily, this does not happen here. the very first result is swiftwasm.org!
the website is really pretty. i like this a lot. A+ to whoever came up with this design.
does the fiddle work?
this website has a fiddle on the home page, which is great, and even better, the fiddle works when i click Run. marvelous!
how to get started…
the next thing i did was click the how to get started link above the fiddle, which takes me to the middle of this TSPL-like documentation website.
it tells me that i need to use something called the “Tokamak UI framework”, which is similar to SwiftUI, apparently.
in the next paragraph it tells me i can’t start using Tokamak UI either, first i have to start using another framework called “carton” before i can start using Tokamak UI, and that it will be Very Very Painful to use Swift WebAssembly without this framework.
i suppose whoever wrote this is correct. i will Eventually Have To start using Tokamak UI and carton
, because this is how real swiftwasm apps are built. but i do not want to build a Real Application yet, i just want to get to hello world.
luckily, when i Look To My Left, i see that the link dropped me off in some intermediate chapter called Creating a browser app, and that there is an earlier chapter called Hello, World so i just jump over to that.
hello world!
okay, so this is what i was actually looking for.
now, i’m not playing dumb, and i can see that there is a preceeding chapter called Installation, which suggests i would need to install something to make this work. but for the sake of science, i want to know what happens when i run these commands with the Swift toolchain i already have.
$ swiftc -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'
okay, nothing surprising here. it needs some SDK and i have not installed it.
is this thing still maintained?
so i go to the Installation page, and it tells me to install SwiftWasm 5.10, which is based on the swift-5.10.0-RELEASE
toolchain.
this is not the swift-6.0.3-RELEASE
toolchain we are using today, and it’s not even the swift-5.10.1-RELEASE
patch release that came out after the original 5.10 release.
i have seen this movie many times before, so my first thought is: is this project still maintained?
but when i go to the actual GitHub repository, i see that the project is indeed actively maintained, and they have nightlies tracking Swift 6.1.
i click through a few more links and find the 6.0.2 release, which is not the 6.0.3 release, but that’s Close Enough for me.
now i took a lot of screenshots to document the path i took, but truth be told, i did not have a hard time locating the latest swiftwasm release. the only point where they really could have potentially lost me was when reading the original anachronistic installation guide, which made me think the project was no longer active.
installing the sdk
i run the command that’s shown next to the release card, and it works! great!
$ swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip --checksum 6ffedb055cb9956395d9f435d03d53ebe9f6a8d45106b979d1b7f53358e1dcb4
Downloading a Swift SDK bundle archive from `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip`...
Downloading
100% [=====================================================================================================================================================================================]
Downloading swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip
Swift SDK bundle archive successfully downloaded from `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip`.
Verifying if checksum of the downloaded archive is valid...
Downloaded archive has a valid checksum.
Swift SDK bundle at `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip` is assumed to be an archive, unpacking...
Swift SDK bundle at `https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip` successfully installed as swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.
$ swift sdk list
6.0.2-RELEASE-wasm32-unknown-wasi
using the sdk
i re-ran the command from the Hello World tutorial, to see if it works this time. it doesn’t.
$ swiftc -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'
i also tried fuzzing the arguments for a few seconds, unsuccessfully.
$ swiftc --swift-sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: unknown argument: '--swift-sdk'
$ swiftc -swift-sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
error: unknown argument: '-swift-sdk'
$ swiftc -sdk wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
warning: no such SDK: wasm32-unknown-wasi
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'
$ swiftc -sdk 6.0.2-RELEASE-wasm32-unknown-wasi -target wasm32-unknown-wasi hello.swift -o hello.wasm
warning: no such SDK: 6.0.2-RELEASE-wasm32-unknown-wasi
error: missing external dependency '/home/ubuntu/x86_64/6.0.3/usr/lib/swift/wasi/static-executable-args.lnk'
luckily, i already knew that Swift SDKs are related to SwiftPM, so i didn’t waste too much time trying to get swiftc
to work. (but not everyone knows that? maybe? who knows…)
i noticed there were example commands for how to build things with the SDK and SwiftPM, and i am Not Allergic to SwiftPM, so i then spent a minute or two creating a rudimentary SwiftPM layout with my Hello World program in a SwiftPM executable target.
using SwiftPM
like many build systems, SwiftPM has a funny tendency to say that it failed when it actually successfully built an executable, and swiftwasm is no exception. it Just Works, even though at first glance, it looks like it didn’t.
$ swift build --swift-sdk wasm32-unknown-wasi
Building for debugging...
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
<unknown>:0: warning: libc not found for 'wasm32-unknown-wasi'; C stdlib may be unavailable
Build complete! (2.05s)
$ swift build -c release --swift-sdk wasm32-unknown-wasi
Building for production...
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
warning: Could not read SDKSettings.json for SDK at: /home/ubuntu/.swiftpm/swift-sdks/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle/6.0.2-RELEASE-wasm32-unknown-wasi/wasm32-unknown-wasi/WASI.sdk
[5/5] Linking test.wasm
Build complete! (0.90s)
$ ls .build/release
ModuleCache description.json swift-version--75355AAB4E86B17C.txt test.build test.product test.wasm
running the binary
i’m probably not going to get to Firefox in 30 minutes, but i at least want to try running this thing using wasmtime
.
so i go to docs.wasmtime.dev and run the command they tell me to run, and it doesn’t work.
$ curl https://wasmtime.dev/install.sh -sSf | bash
Installing latest version of Wasmtime (v28.0.1)
Checking for existing Wasmtime installation
Fetching archive for Linux, version v28.0.1
https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz
######################################################################## 100.0%
Creating directory layout
Extracting Wasmtime binaries
tar (child): xz: Cannot exec: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/wasmtime': No such file or directory
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/LICENSE': No such file or directory
cp: cannot stat '/tmp/tmp.vcHYenQBsa/wasmtime-v28.0.1-x86_64-linux/README.md': No such file or directory
i do a little debugging and i realize this is because GitHub uses an HTTP redirect (presumably to protect itself from scrapers), and the curl
command is missing an -L
option.
$ curl https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz -o wasmtime-v28.0.1-x86_64-linux.tar.xz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
$ ls
Package.swift Sources wasmtime-v28.0.1-x86_64-linux.tar.xz
$ ls -l
total 8
-rw-r--r-- 1 ubuntu ubuntu 274 Jan 20 00:19 Package.swift
drwxr-xr-x 3 ubuntu ubuntu 4096 Jan 20 00:16 Sources
-rw-r--r-- 1 ubuntu ubuntu 0 Jan 20 00:23 wasmtime-v28.0.1-x86_64-linux.tar.xz
$ curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v28.0.1/wasmtime-v28.0.1-x86_64-linux.tar.xz -o wasmtime-v28.0.1-x86_64-linux.tar.xz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 8605k 100 8605k 0 0 14.4M 0 --:--:-- --:--:-- --:--:-- 14.4M
i peer into the install.sh
script, and i confirm that it is indeed missing an -L
option, but then again i did not write this script, and i only spent a few seconds looking at it, so who knows.
EDIT: or not! it does actually have a --location
option, which is long for -L
. the mystery deepens.
download_release_from_repo() {
local version="$1"
local arch="$2"
local os_info="$3"
local tmpdir="$4"
local postfix=$(release_file_postfix $os_info)
local filename="wasmtime-$version-$arch-$os_info.$postfix"
local download_file="$tmpdir/$filename"
local archive_url="$(release_url)/download/$version/$filename"
info $archive_url
curl --progress-bar --show-error --location --fail "$archive_url" \
--output "$download_file" && echo "$download_file"
}
i manage to get a hold of the wasmtime
binary, and i use it to execute the binary i built with SwiftPM. it works! beautiful!
$ wasmtime-v28.0.1-x86_64-linux/wasmtime .build/release/test.wasm
Hi Barbie!
conclusion
overall, i would say i had a very positive experience in my first 30 minutes of Swift WebAssembly. the bad parts were… Poor/Stale Documentation (shocker), and a very bumpy path to installing the wasm runtime. but the second problem isn’t really Swift WebAssembly’s responsibility, it’s just WebAssembly’s responsibility. and the first problem isn’t any defect in the underlying technology, we just need to update those docs, and maybe change a couple links to point to the beginning of the tutorial, instead of a chapter in the middle of the book.
hopefully i have time later to actually run stuff in a browser and explore this Tokamak UI thing.
great job to everyone who worked on Swift WebAssembly! this was truly a refreshing experience