Skip to content

Commit

Permalink
deploy: 3baaabe
Browse files Browse the repository at this point in the history
  • Loading branch information
kateinoigakukun committed Mar 9, 2024
1 parent 0627f4f commit a154c49
Show file tree
Hide file tree
Showing 13 changed files with 418 additions and 444 deletions.
18 changes: 2 additions & 16 deletions contribution-guide/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,12 @@ <h1 class="menu-title">Swift and WebAssembly</h1>
<div id="content" class="content">
<main>
<h1><a class="header" href="#contribution-guide" id="contribution-guide">Contribution Guide</a></h1>
<h2><a class="header" href="#forum-posts" id="forum-posts">Forum posts</a></h2>
<ul>
<li><a href="https://forums.swift.org/t/wasm-support/16087/14">Design of this project</a></li>
<li><a href="https://forums.swift.org/t/webassembly-swiftpm/34343">Swift Package Manager Support</a></li>
</ul>
<h2><a class="header" href="#repositories" id="repositories">Repositories</a></h2>
<h3><a class="header" href="#a-hrefhttpsgithubcomswiftwasmswiftswiftwasmswifta" id="a-hrefhttpsgithubcomswiftwasmswiftswiftwasmswifta"><a href="https://github.com/swiftwasm/swift">swiftwasm/swift</a></a></h3>
<p>The main repository of this project. Forked from <a href="https://github.com/swiftwasm/swift">apple/swift</a>. We are tracking upstream changes using <a href="https://github.com/wei/pull">pull</a></p>
<h4><a class="header" href="#branching-scheme" id="branching-scheme">Branching scheme</a></h4>
<ul>
<li><code>swiftwasm</code> is the main development branch.</li>
<li><code>main</code> is a mirror of the <code>main</code> branch of the upstream <code>apple/swift</code> repository. This branch is necessary to avoid <a href="https://github.com/swiftwasm/swift/pull/36">some issues</a>.</li>
<li><code>swiftwasm-release/VERSION</code> is the branch where <code>VERSION</code> release of SwiftWasm is prepared.</li>
<li><code>release/VERSION</code> is a mirror of the upstream <code>release/VERSION</code> branch.</li>
</ul>
<h3><a class="header" href="#a-hrefhttpsgithubcomswiftwasmswiftwasm-buildswiftwasmswiftwasm-builda" id="a-hrefhttpsgithubcomswiftwasmswiftwasm-buildswiftwasmswiftwasm-builda"><a href="https://github.com/swiftwasm/swiftwasm-build">swiftwasm/swiftwasm-build</a></a></h3>
<p>The main development repository for the SwiftWasm project. It contains the build script and patches for building the Swift compiler and standard library for WebAssembly. See the <a href="https://github.com/swiftwasm/swiftwasm-build/blob/main/README.md">README</a> for more information.</p>
<h3><a class="header" href="#a-hrefhttpsgithubcomswiftwasmicu4c-wasiswiftwasmicu4c-wasia" id="a-hrefhttpsgithubcomswiftwasmicu4c-wasiswiftwasmicu4c-wasia"><a href="https://github.com/swiftwasm/icu4c-wasi">swiftwasm/icu4c-wasi</a></a></h3>
<p>Build script and patches for building ICU project for WebAssembly. <a href="https://github.com/unicode-org/icu/pull/990">The required changes to build
it</a> were merged to the upstream repository.</p>
<h3><a class="header" href="#a-hrefhttpsgithubcomswiftwasmwasi-sdk-buildswiftwasmwasi-sdk-builda" id="a-hrefhttpsgithubcomswiftwasmwasi-sdk-buildswiftwasmwasi-sdk-builda"><a href="https://github.com/swiftwasm/wasi-sdk-build">swiftwasm/wasi-sdk-build</a></a></h3>
<p>We apply some patches for <a href="https://github.com/WebAssembly/wasi-sdk">WebAssembly/wasi-sdk</a> and <a href="https://github.com/WebAssembly/wasi-libc">WebAssembly/wasi-libc</a> to build <code>wasi-sysroot</code> with pthread header. There aren't so many diff from upstream.</p>

</main>

Expand Down
17 changes: 17 additions & 0 deletions examples/exporting-function.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ <h1 class="menu-title">Swift and WebAssembly</h1>
<div id="content" class="content">
<main>
<h1><a class="header" href="#exporting-function-for-host-environment" id="exporting-function-for-host-environment">Exporting function for host environment</a></h1>
<h2><a class="header" href="#swift-510-or-earlier" id="swift-510-or-earlier">Swift 5.10 or earlier</a></h2>
<p>You can expose a Swift function for host environment using special attribute and linker option.</p>
<pre><code class="language-swift">// File name: lib.swift
@_cdecl(&quot;add&quot;)
Expand Down Expand Up @@ -210,6 +211,22 @@ <h1><a class="header" href="#exporting-function-for-host-environment" id="export
console.log(&quot;2 + 3 = &quot; + addFn(2, 3))
</code></pre>
<p>If you use SwiftPM package, you can omit linker flag using clang's <code>__atribute__</code>. Please see <a href="https://github.com/swiftwasm/JavaScriptKit/pull/91/files">swiftwasm/JavaScriptKit#91</a> for more detail info</p>
<h2><a class="header" href="#swift-60-or-later" id="swift-60-or-later">Swift 6.0 or later</a></h2>
<p>If you use Swift 6.0 or later, you can use <code>@_expose(wasm, &quot;add&quot;)</code> and omit the <code>--export</code> linker flag.</p>
<pre><code class="language-swift">// File name: lib.swift
@_expose(wasm, &quot;add&quot;)
@_cdecl(&quot;add&quot;) // This is still required to call the function with C ABI
func add(_ lhs: Int, _ rhs: Int) -&gt; Int {
return lhs + rhs
}
</code></pre>
<p>Then you can compile the Swift code with the following command without <code>--export</code> linker flag.</p>
<pre><code class="language-bash">$ swiftc \
-target wasm32-unknown-wasi \
-parse-as-library \
lib.swift -o lib.wasm \
-Xclang-linker -mexec-model=reactor
</code></pre>

</main>

Expand Down
69 changes: 34 additions & 35 deletions examples/importing-function.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ <h1 class="menu-title">Swift and WebAssembly</h1>
<div id="content" class="content">
<main>
<h1><a class="header" href="#importing-a-function-from-host-environments" id="importing-a-function-from-host-environments">Importing a function from host environments</a></h1>
<h2><a class="header" href="#swift-510-or-earlier" id="swift-510-or-earlier">Swift 5.10 or earlier</a></h2>
<p>You can import a function from your host environment using the integration of Swift Package Manager
with C targets. Firstly, you should declare a signature for your function in a C header with an
appropriate <code>__import_name__</code> attribute:</p>
Expand All @@ -169,15 +170,14 @@ <h1><a class="header" href="#importing-a-function-from-host-environments" id="im
<p>Here <code>__import_name__</code> specifies the name under which this function will be exposed to Swift code.
Move this C header to a separate target, we'll call it <code>HostFunction</code> in this example. Your
<code>Package.swift</code> manifest for your WebAssembly app would look like this:</p>
<pre><code class="language-swift">// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
<pre><code class="language-swift">// swift-tools-version:5.9
import PackageDescription

let package = Package(
name: &quot;SwiftWasmApp&quot;,
name: &quot;Example&quot;,
targets: [
.target(name: &quot;HostFunction&quot;, dependencies: []),
.target(name: &quot;SwiftWasmApp&quot;, dependencies: [&quot;HostFunction&quot;]),
.executableTarget(name: &quot;Example&quot;, dependencies: [&quot;HostFunction&quot;]),
]
)
</code></pre>
Expand All @@ -191,41 +191,24 @@ <h1><a class="header" href="#importing-a-function-from-host-environments" id="im
<p>Note that we use <code>env</code> as default import module name. You can specify the module name as
<code>__import_module__</code> in your C header. The full list of attributes in the header could look
like <code>__attribute__((__import_module__(&quot;env&quot;),__import_name__(&quot;add&quot;)))</code>.</p>
<pre><code class="language-javascript">const WASI = require(&quot;@wasmer/wasi&quot;).WASI;
const WasmFs = require(&quot;@wasmer/wasmfs&quot;).WasmFs;

const promisify = require(&quot;util&quot;).promisify;
const fs = require(&quot;fs&quot;);
const readFile = promisify(fs.readFile);
<pre><code class="language-javascript">// File name: main.mjs
import { WASI, File, OpenFile, ConsoleStdout } from &quot;@bjorn3/browser_wasi_shim&quot;;
import fs from &quot;fs/promises&quot;;

const main = async () =&gt; {
const wasmFs = new WasmFs();
// Output stdout and stderr to console
const originalWriteSync = wasmFs.fs.writeSync;
wasmFs.fs.writeSync = (fd, buffer, offset, length, position) =&gt; {
const text = new TextDecoder(&quot;utf-8&quot;).decode(buffer);
switch (fd) {
case 1:
console.log(text);
break;
case 2:
console.error(text);
break;
}
return originalWriteSync(fd, buffer, offset, length, position);
};

// Instantiate a new WASI Instance
let wasi = new WASI({
args: [],
env: {},
bindings: {
...WASI.defaultBindings,
fs: wasmFs.fs,
},
});

const wasmBinary = await readFile(&quot;lib.wasm&quot;);
// See https://github.com/bjorn3/browser_wasi_shim/ for more detail about constructor options
let wasi = new WASI([], [],
[
new OpenFile(new File([])), // stdin
ConsoleStdout.lineBuffered(msg =&gt; console.log(`[WASI stdout] ${msg}`)),
ConsoleStdout.lineBuffered(msg =&gt; console.warn(`[WASI stderr] ${msg}`)),
],
{ debug: false }
);

const wasmBinary = await fs.readFile(&quot;.build/wasm32-unknown-wasi/debug/Example.wasm&quot;);

// Instantiate the WebAssembly file
let { instance } = await WebAssembly.instantiate(wasmBinary, {
Expand All @@ -245,6 +228,22 @@ <h1><a class="header" href="#importing-a-function-from-host-environments" id="im
an integration with an imported host function.</p>
<p>A more streamlined way to import host functions will be implemented in the future version of the
SwiftWasm toolchain.</p>
<h2><a class="header" href="#swift-60-or-later" id="swift-60-or-later">Swift 6.0 or later</a></h2>
<p>If you are using Swift 6.0 or later, you can use experimental <code>@_extern(wasm)</code> attribute</p>
<p>Swift 6.0 introduces a new attribute <code>@_extern(wasm)</code> to import a function from the host environment.
To use this experimental feature, you need to enable it in your SwiftPM manifest file:</p>
<pre><code class="language-swift">.executableTarget(
name: &quot;Example&quot;,
swiftSettings: [
.enableExperimentalFeature(&quot;Extern&quot;)
]),
</code></pre>
<p>Then, you can import a function from the host environment as follows without using C headers:</p>
<pre><code class="language-swift">@_extern(wasm, module: &quot;env&quot;, name: &quot;add&quot;)
func add(_ a: Int, _ b: Int) -&gt; Int

print(add(2, 2))
</code></pre>

</main>

Expand Down
69 changes: 46 additions & 23 deletions getting-started/browser-app.html
Original file line number Diff line number Diff line change
Expand Up @@ -170,44 +170,67 @@ <h2><a class="header" href="#requirements" id="requirements">Requirements</a></h
already automated with <code>carton</code>.</p>
<h3><a class="header" href="#system-requirements" id="system-requirements">System Requirements</a></h3>
<ul>
<li>macOS 10.15 and Xcode 11.4 or later.</li>
<li><a href="https://swift.org/download/">Swift 5.2 or later</a> and Ubuntu 18.04 for Linux users.</li>
<li><a href="https://swift.org/download/">Swift 5.9.2 or later</a></li>
</ul>
<h3><a class="header" href="#installation" id="installation">Installation</a></h3>
<p>On macOS <code>carton</code> can be installed with <a href="https://brew.sh/">Homebrew</a>. Make sure you have Homebrew
installed and then run:</p>
<pre><code class="language-sh">brew install swiftwasm/tap/carton
</code></pre>
<p>You'll have to build <code>carton</code> from sources on Linux. Clone the repository and run
<code>swift build -c release</code>, the <code>carton</code> binary will be located in the <code>.build/release</code>
directory after that.
Assuming you already have Homebrew installed, you can create a new Tokamak
app by following these steps:</p>
<ol>
<li>Install <code>carton</code>:</li>
<li>Create a directory for your project and make it current:</li>
</ol>
<pre><code>brew install swiftwasm/tap/carton
</code></pre>
<p>If you had <code>carton</code> installed before this, make sure you have version 0.6.1 or greater:</p>
<pre><code>carton --version
<pre><code>mkdir MyApp &amp;&amp; cd MyApp
</code></pre>
<ol start="2">
<li>Create a directory for your project and make it current:</li>
<li>Initialize the project:</li>
</ol>
<pre><code>mkdir TokamakApp &amp;&amp; cd TokamakApp
<pre><code>swift package init --type executable
</code></pre>
<ol start="3">
<li>Initialize the project from a template with <code>carton</code>:</li>
<li>Add Tokamak and carton as dependencies to your <code>Package.swift</code>:</li>
</ol>
<pre><code>carton init --template tokamak
<pre><code class="language-swift">// swift-tools-version:5.8
import PackageDescription
let package = Package(
name: &quot;MyApp&quot;,
platforms: [.macOS(.v11), .iOS(.v13)],
dependencies: [
.package(url: &quot;https://github.com/TokamakUI/Tokamak&quot;, from: &quot;0.11.0&quot;),
.package(url: &quot;https://github.com/swiftwasm/carton&quot;, from: &quot;1.0.0&quot;),
],
targets: [
.executableTarget(
name: &quot;MyApp&quot;,
dependencies: [
.product(name: &quot;TokamakShim&quot;, package: &quot;Tokamak&quot;)
]),
]
)
</code></pre>
<ol start="4">
<li>Build the project and start the development server, <code>carton dev</code> can be kept running
during development:</li>
<li>Add your first view to <code>Sources/main.swift</code>:</li>
</ol>
<pre><code>carton dev
<pre><code class="language-swift">import TokamakDOM

@main
struct TokamakApp: App {
var body: some Scene {
WindowGroup(&quot;Tokamak App&quot;) {
ContentView()
}
}
}

struct ContentView: View {
var body: some View {
Text(&quot;Hello, world!&quot;)
}
}
</code></pre>
<ol start="5">
<li>Build the project and start the development server, <code>swift run carton dev</code> can be kept running
during development:</li>
</ol>
<pre><code>swift run carton dev
</code></pre>
<ol start="6">
<li>Open <a href="http://127.0.0.1:8080/">http://127.0.0.1:8080/</a> in your browser to see the app
running. You can edit the app source code in your favorite editor and save it, <code>carton</code>
will immediately rebuild the app and reload all browser tabs that have the app open.</li>
Expand Down
6 changes: 3 additions & 3 deletions getting-started/hello-world.html
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ <h2><a class="header" href="#2-compile-swift-code-into-webassembly-with-wasi" id
<pre><code>$ swiftc -target wasm32-unknown-wasi hello.swift -o hello.wasm
</code></pre>
<h2><a class="header" href="#3-run-the-produced-binary-on-webassembly-runtime" id="3-run-the-produced-binary-on-webassembly-runtime">3. Run the produced binary on WebAssembly runtime</a></h2>
<p>You can the run the produced binary with <a href="https://wasmer.io/">wasmer</a> (or other WebAssembly runtime):</p>
<pre><code class="language-sh">$ wasmer hello.wasm
<p>You can the run the produced binary with <a href="https://wasmtime.dev/">wasmtime</a> (or other WebAssembly runtime):</p>
<pre><code class="language-sh">$ wasmtime hello.wasm
</code></pre>
<p>The produced binary depends on WASI which is an interface of system call for WebAssembly.
So you need to use WASI supported runtime and when you run the binary on browser, you need WASI polyfill library like <a href="https://github.com/wasmerio/wasmer-js/tree/master/packages/wasi">@wasmer/wasi</a>.</p>
So you need to use WASI supported runtime and when you run the binary on browser, you need WASI polyfill library like <a href="https://github.com/bjorn3/browser_wasi_shim">@bjorn3/browser_wasi_shim</a>.</p>

</main>

Expand Down
56 changes: 28 additions & 28 deletions getting-started/porting.html
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ <h2><a class="header" href="#wasilibc-module" id="wasilibc-module"><code>WASILib
</code></pre>
<h3><a class="header" href="#limitations" id="limitations">Limitations</a></h3>
<p>WebAssembly and <a href="https://wasi.dev/">WASI</a> provide a constrained environment, which currently does
not directly support multi-threading, or filesystem access in the browser. Thus, you should not
not directly support multi-threading. Thus, you should not
expect these APIs to work when importing <code>WASILibc</code>. Please be aware of these limitations when
porting your code, which also has an impact on what <a href="#swift-foundation-and-dispatch">can be supported in the Swift
Foundation</a> at the moment.</p>
Expand All @@ -194,33 +194,33 @@ <h2><a class="header" href="#swift-foundation-and-dispatch" id="swift-foundation
library</a> is unavailable due to <a href="https://github.com/swiftwasm/swift/issues/1887">the lack of
standardized multi-threading support</a> in WebAssembly
and SwiftWasm itself. Many Foundation APIs rely on the presence of Dispatch under the hood,
specifically file system access and threading helpers. A few other types are unavailable in browsers
or aren't standardized in WASI hosts, such as support for sockets and low-level networking, or
support for time zone files, and they had to be disabled. These types are therefore absent in
SwiftWasm Foundation:</p>
<ul>
<li><code>FoundationNetworking</code> types, such as <code>URLSession</code> and related APIs</li>
<li><code>FileManager</code></li>
<li><code>Host</code></li>
<li><code>Notification</code></li>
<li><code>NotificationQueue</code></li>
<li><code>NSKeyedArchiver</code></li>
<li><code>NSKeyedArchiverHelpers</code></li>
<li><code>NSKeyedCoderOldStyleArray</code></li>
<li><code>NSKeyedUnarchiver</code></li>
<li><code>NSNotification</code></li>
<li><code>NSSpecialValue</code></li>
<li><code>Port</code></li>
<li><code>PortMessage</code></li>
<li><code>Process</code></li>
<li><code>ProcessInfo</code> (Partially available since 5.7)</li>
<li><code>PropertyListEncoder</code></li>
<li><code>RunLoop</code></li>
<li><code>Stream</code></li>
<li><code>Thread</code></li>
<li><code>Timer</code></li>
<li><code>UserDefaults</code></li>
</ul>
specifically threading helpers. A few other types are unavailable in browsers
or aren't standardized in WASI hosts, such as support for sockets and low-level networking,
and they had to be disabled. These types are therefore absent in SwiftWasm Foundation:</p>
<table><thead><tr><th>Type or module</th><th>Status</th></tr></thead><tbody>
<tr><td><code>FoundationNetworking</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>FileManager</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>Host</code></td><td>✅ Partially available after 6.0</td></tr>
<tr><td><code>Notification</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NotificationQueue</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>NSKeyedArchiver</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NSKeyedArchiverHelpers</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NSKeyedCoderOldStyleArray</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NSKeyedUnarchiver</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NSNotification</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>NSSpecialValue</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>Port</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>PortMessage</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>Process</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>ProcessInfo</code></td><td>✅ Partially available after 5.7</td></tr>
<tr><td><code>PropertyListEncoder</code></td><td>✅ Available after 6.0</td></tr>
<tr><td><code>RunLoop</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>Stream</code></td><td>✅ Partially available after 6.0</td></tr>
<tr><td><code>SocketPort</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>Thread</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>Timer</code></td><td>❌ Unavailable</td></tr>
<tr><td><code>UserDefaults</code></td><td>✅ Available after 6.0</td></tr>
</tbody></table>
<p>Related functions and properties on other types are also absent or disabled. We would like to make
them available in the future as soon as possible, and <a href="../contribution-guide/index.html">we invite you to
contribute</a> and help us in achieving this goal!</p>
Expand Down
Loading

0 comments on commit a154c49

Please sign in to comment.