1 import com.vanniktech.maven.publish.JavadocJar.Empty
2 import com.vanniktech.maven.publish.KotlinMultiplatform
3 import com.vanniktech.maven.publish.MavenPublishBaseExtension
4
<lambda>null5 plugins {
6 kotlin("multiplatform")
7 // TODO: Restore Dokka once this issue is resolved.
8 // https://github.com/Kotlin/dokka/issues/3038
9 // id("org.jetbrains.dokka")
10 id("com.vanniktech.maven.publish.base")
11 id("build-support")
12 id("binary-compatibility-validator")
13 }
14
<lambda>null15 kotlin {
16 configureOrCreateWasmPlatform(
17 js = false,
18 wasi = true,
19 )
20 sourceSets {
21 all {
22 languageSettings.optIn("kotlin.wasm.unsafe.UnsafeWasmMemoryApi")
23 }
24 val wasmWasiMain by getting {
25 dependencies {
26 implementation(projects.okio)
27 }
28 }
29 val wasmWasiTest by getting {
30 dependencies {
31 implementation(projects.okioTestingSupport)
32 implementation(libs.kotlin.test)
33 }
34 }
35 }
36 }
37
<lambda>null38 configure<MavenPublishBaseExtension> {
39 // TODO: switch from 'Empty' to 'Dokka' once this issue is resolved.
40 // https://github.com/Kotlin/dokka/issues/3038
41 configure(
42 KotlinMultiplatform(javadocJar = Empty()),
43 )
44 }
45
46 /**
47 * Inspired by runner.mjs in kowasm, this rewrites the JavaScript bootstrap script to set up WASI.
48 *
49 * See also:
50 * * https://github.com/kowasm/kowasm
51 * * https://github.com/nodejs/node/blob/main/doc/api/wasi.md
52 *
53 * This task overwrites the output of `compileTestDevelopmentExecutableKotlinWasmWasi` and must run
54 * after that task. It must also run before the WASM test execution tasks that read this script.
55 *
56 * Note that this includes which file paths are exposed to the WASI sandbox.
57 */
<lambda>null58 val injectWasiInit by tasks.creating {
59 dependsOn("compileTestDevelopmentExecutableKotlinWasmWasi")
60 val moduleName = "${rootProject.name}-${project.name}-wasm-wasi-test"
61
62 val entryPointMjs = File(
63 buildDir,
64 "compileSync/wasmWasi/test/testDevelopmentExecutable/kotlin/$moduleName.mjs"
65 )
66
67 outputs.file(entryPointMjs)
68
69 doLast {
70 val base = File(System.getProperty("java.io.tmpdir"), "okio-wasifilesystem-test")
71 val baseA = File(base, "a")
72 val baseB = File(base, "b")
73 base.mkdirs()
74 baseA.mkdirs()
75 baseB.mkdirs()
76
77 entryPointMjs.writeText(
78 """
79 import { WASI } from 'wasi';
80 import { argv, env } from 'node:process';
81
82 const wasi = new WASI({
83 version: 'preview1',
84 args: argv,
85 preopens: {
86 '/tmp': '$base',
87 '/a': '$baseA',
88 '/b': '$baseB'
89 },
90 env,
91 });
92
93 const fs = await import('node:fs');
94 const url = await import('node:url');
95 const wasmBuffer = fs.readFileSync(url.fileURLToPath(import.meta.resolve('./okio-parent-okio-wasifilesystem-wasm-wasi-test.wasm')));
96 const wasmModule = new WebAssembly.Module(wasmBuffer);
97 const wasmInstance = new WebAssembly.Instance(wasmModule, wasi.getImportObject());
98
99 wasi.initialize(wasmInstance);
100
101 const exports = wasmInstance.exports
102
103 export default new Proxy(exports, {
104 _shownError: false,
105 get(target, prop) {
106 if (!this._shownError) {
107 this._shownError = true;
108 throw new Error("Do not use default import. Use the corresponding named import instead.")
109 }
110 }
111 });
112 export const {
113 startUnitTests,
114 _initialize,
115 memory
116 } = exports;
117 """.trimIndent()
118 )
119 }
120 }
<lambda>null121 tasks.named("wasmWasiNodeTest").configure {
122 dependsOn(injectWasiInit)
123 }
124