Skip to content

Commit 3d26a15

Browse files
committed
[WIP]
1 parent 0881320 commit 3d26a15

File tree

8 files changed

+136
-13
lines changed

8 files changed

+136
-13
lines changed

Examples/API/Package.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ let package = Package(
1212
.package(name: "CDK", path: "../../")
1313
],
1414
targets: [
15-
.executableTarget(name: "API", dependencies: ["CDK"])
15+
.executableTarget(
16+
name: "API",
17+
dependencies: ["CDK"],
18+
linkerSettings: [
19+
.unsafeFlags([
20+
"-Xlinker", "--export=canister_init",
21+
]),
22+
]
23+
)
1624
]
1725
)

Examples/API/Sources/API/main.swift

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import CDK
2+
// import Foundation
23

34
@_cdecl("canister_init")
45
func `init`() {
56
CDK.print("Hello from Swift!")
7+
8+
CDK.print("time: \(CDK.time())")
9+
10+
// let timeInterval = Double(CDK.time() / 1_000_000_000)
11+
// let date = Date(timeIntervalSince1970: timeInterval)
12+
// CDK.print("date: \(date)")
613
}

Examples/API/dfx.json

+11
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,16 @@
77
"candid": "API.did",
88
"wasm": ".build/wasm32-unknown-wasi/release/API.wasm.gz"
99
}
10+
},
11+
"defaults": {
12+
"replica": {
13+
"subnet_type": "application"
14+
}
15+
},
16+
"networks": {
17+
"local": {
18+
"bind": "127.0.0.1:8000",
19+
"type": "ephemeral"
20+
}
1021
}
1122
}

Examples/API/index.html

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>title</title>
6+
<script>
7+
const importObject = {
8+
ic0: {
9+
debug_print: console.log,
10+
},
11+
// wasi_snapshot_preview1: {
12+
// args_get: (...args) => console.log("args_get", ...args),
13+
// args_sizes_get: (...args) => console.log("args_sizes_get", ...args),
14+
// clock_res_get: (...args) => console.log("clock_res_get", ...args),
15+
// clock_time_get: (...args) => console.log("clock_time_get", ...args),
16+
// environ_get: (...args) => console.log("environ_get", ...args),
17+
// environ_sizes_get: (...args) => console.log("environ_sizes_get", ...args),
18+
// fd_advise: (...args) => console.log("fd_advise", ...args),
19+
// fd_allocate: (...args) => console.log("fd_allocate", ...args),
20+
// fd_close: (...args) => console.log("fd_close", ...args),
21+
// fd_datasync: (...args) => console.log("fd_datasync", ...args),
22+
// fd_fdstat_get: (...args) => console.log("fd_fdstat_get", ...args),
23+
// fd_fdstat_set_flags: (...args) => console.log("fd_fdstat_set_flags", ...args),
24+
// fd_fdstat_set_rights: (...args) => console.log("fd_fdstat_set_rights", ...args),
25+
// fd_filestat_get: (...args) => console.log("fd_filestat_get", ...args),
26+
// fd_filestat_set_size: (...args) => console.log("fd_filestat_set_size", ...args),
27+
// fd_filestat_set_times: (...args) => console.log("fd_filestat_set_times", ...args),
28+
// fd_pread: (...args) => console.log("fd_pread", ...args),
29+
// /* fd_prestat_dir_name: (...args) => console.log("fd_prestat_dir_name", ...args), */
30+
// fd_prestat_dir_name: () => {},
31+
// /* fd_prestat_get: (...args) => console.log("fd_prestat_get", ...args), */
32+
// fd_prestat_get: () => {},
33+
// fd_pwrite: (...args) => console.log("fd_pwrite", ...args),
34+
// fd_read: (...args) => console.log("fd_read", ...args),
35+
// fd_readdir: (...args) => console.log("fd_readdir", ...args),
36+
// fd_renumber: (...args) => console.log("fd_renumber", ...args),
37+
// fd_seek: (...args) => console.log("fd_seek", ...args),
38+
// fd_sync: (...args) => console.log("fd_sync", ...args),
39+
// fd_tell: (...args) => console.log("fd_tell", ...args),
40+
// fd_write: (...args) => console.log("fd_write", ...args),
41+
// path_create_directory: (...args) => console.log("path_create_directory", ...args),
42+
// path_filestat_get: (...args) => console.log("path_filestat_get", ...args),
43+
// path_filestat_set_times: (...args) => console.log("path_filestat_set_times", ...args),
44+
// path_link: (...args) => console.log("path_link", ...args),
45+
// path_open: (...args) => console.log("path_open", ...args),
46+
// path_readlink: (...args) => console.log("path_readlink", ...args),
47+
// path_remove_directory: (...args) => console.log("path_remove_directory", ...args),
48+
// path_rename: (...args) => console.log("path_rename", ...args),
49+
// path_symlink: (...args) => console.log("path_symlink", ...args),
50+
// path_unlink_file: (...args) => console.log("path_unlink_file", ...args),
51+
// poll_oneoff: (...args) => console.log("poll_oneoff", ...args),
52+
// proc_exit: (...args) => console.log("proc_exit", ...args),
53+
// proc_raise: (...args) => console.log("proc_raise", ...args),
54+
// random_get: (...args) => console.log("random_get", ...args),
55+
// sched_yield: (...args) => console.log("sched_yield", ...args),
56+
// sock_recv: (...args) => console.log("sock_recv", ...args),
57+
// sock_send: (...args) => console.log("sock_send", ...args),
58+
// sock_shutdown: (...args) => console.log("sock_shutdown", ...args),
59+
// }
60+
};
61+
62+
WebAssembly.instantiateStreaming(fetch(".build/wasm32-unknown-wasi/release/API.wasm"), importObject)
63+
.then((obj) => {
64+
console.log("obj", obj);
65+
66+
obj.instance.exports.canister_init();
67+
})
68+
.catch(console.error);
69+
</script>
70+
</head>
71+
<body>
72+
</body>
73+
</html>

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ dfx start --clean --host 127.0.0.1:0
1414
```
1515
dfx deploy --network http://127.0.0.1:$(dfx info webserver-port) --no-wallet API_backend
1616
```
17+
18+
To debug Wasm in the browser:
19+
20+
```
21+
python3 -m http.server 1234
22+
```

Sources/CDK/CDK.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import IC
22

33
public func print(_ message: String) {
4-
withUnsafePointer(to: message) { src in
5-
let size = Int32(MemoryLayout.size(ofValue: message))
6-
IC.debug_print(src, size)
4+
message.withCString { body in
5+
let size = Int32(message.utf8.count)
6+
IC.ic0_debug_print(body, size)
77
}
88
}
99

10-
// public func time() -> Int64 {
11-
// IC.time()
12-
// }
10+
public func time() -> UInt64 {
11+
IC.ic0_time()
12+
}

Sources/IC/include/IC.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
#if __wasm32__
77

88
__attribute__((__import_module__("ic0"),__import_name__("debug_print")))
9-
extern void debug_print(const void *src, int32_t size);
9+
extern void ic0_debug_print(const void *src, int32_t size);
1010

11-
/* __attribute__((__import_module__("ic0"),__import_name__("time"))) */
12-
/* extern int64_t time(void); */
11+
__attribute__((__import_module__("ic0"),__import_name__("time")))
12+
extern uint64_t ic0_time(void);
1313

1414
#endif
1515
#endif /* ic_h */

flake.nix

+21-3
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,32 @@
7979
name = "cdk-swift-build";
8080
runtimeInputs = [
8181
ic-wasm
82+
pkgs.gnused
8283
swift-wasm
8384
wasm-snip-wasi
8485
];
8586
text = ''
86-
BUILD_DIR=.build/wasm32-unknown-wasi/release
87-
swift-wasm build -c release -Xlinker --export=canister_init
87+
BUILD_DIR=.build/release
88+
swift-wasm build -c release -Xswiftc -Osize
89+
90+
# TODO: use walrus crate instead of wat and sed
91+
92+
wasm2wat "$BUILD_DIR/$1.wasm" --generate-names --output "$BUILD_DIR/$1.wat"
93+
sed --in-place --null-data --regexp-extended "s/(call \\\$(_start|__wasilibc_populate_preopens|__stdio_exit|_GLOBAL__sub_I_GlobalObjects.cpp))/(; \1 ;)/g" "$BUILD_DIR/$1.wat"
94+
sed --in-place --null-data --regexp-extended "s/(call \\\$(__imported_wasi_snapshot_preview1_environ_sizes_get|__imported_wasi_snapshot_preview1_environ_get))/(; \1 ;)\n drop\n drop\n i32.const 0/g" "$BUILD_DIR/$1.wat"
95+
sed --in-place --null-data --regexp-extended "s/\(export \"(_start|memory)\"[^\n]+/\(; \0 ;\)/gm" "$BUILD_DIR/$1.wat"
96+
sed --in-place --null-data --regexp-extended "s/(i32\.const 71\n\s+)(call \\\$_Exit\n\s+unreachable)(\n?\s*\))/\1\(; \2 ;\)\3/g" "$BUILD_DIR/$1.wat"
97+
sed --in-place --null-data --regexp-extended "s/(call \\\$(_Exit|__wasi_proc_exit|__imported_wasi_snapshot_preview1_proc_exit)\n\s+)(unreachable)(\n?\s*\))/\1\(; \3 ;\)\4/g" "$BUILD_DIR/$1.wat"
98+
wat2wasm "$BUILD_DIR/$1.wat" --debug-names --output "$BUILD_DIR/$1.wasm"
99+
100+
# Stack traces (at least in the browser) are much nicer without
101+
# any of the post-processing that follows.
102+
88103
wasm-snip-wasi "$BUILD_DIR/$1.wasm" --output "$BUILD_DIR/$1.wasm"
89104
ic-wasm --output "$BUILD_DIR/$1.wasm" "$BUILD_DIR/$1.wasm" shrink
90-
wasm2wat "$BUILD_DIR/$1.wasm" --output "$BUILD_DIR/$1.wat"
105+
106+
wasm2wat "$BUILD_DIR/$1.wasm" --generate-names --output "$BUILD_DIR/$1.snipped.wat"
107+
91108
gzip --to-stdout --best "$BUILD_DIR/$1.wasm" > "$BUILD_DIR/$1.wasm.gz"
92109
'';
93110
};
@@ -158,6 +175,7 @@
158175
} ''
159176
makeWrapper ${wasm-snip}/bin/wasm-snip $out/bin/wasm-snip-wasi \
160177
--append-flags "\
178+
__exported_start \
161179
__imported_wasi_snapshot_preview1_args_get \
162180
__imported_wasi_snapshot_preview1_args_sizes_get \
163181
__imported_wasi_snapshot_preview1_clock_res_get \

0 commit comments

Comments
 (0)