Ben Lynn has a blog post series about "Organic Apps", he creates canisters with
clang, and lld only.
Quint and Enzo, over beers, thought it would be fun to create a canister in zig, so we looked at Ben's Hello, Internet Computer blog post and decided to port it to Zig the following day.
Anyways, here is the C code from Ben:
#define IMPORT(m,n) __attribute__((import_module(m))) __attribute__((import_name(n)));
#define EXPORT(n) asm(n) __attribute__((visibility("default")))
void reply_append(void*, unsigned) IMPORT("ic0", "msg_reply_data_append");
void reply (void) IMPORT("ic0", "msg_reply");
void go() EXPORT("canister_query hi");
void go() {
char msg[] = "Hello, World!\n";
reply_append(msg, sizeof(msg) - 1);
reply();
}And here is our zig code:
extern "ic0" fn msg_reply_data_append(ptr: [*]const u8, len: usize) void;
extern "ic0" fn msg_reply() void;
export fn @"canister_query hi"() callconv(.C) void {
const msg = "Hello, World!\n";
msg_reply_data_append(msg, msg.len);
msg_reply();
}Let's compile the C code:
# we compile the object file
clang --target=wasm32 -c -O3 src/main.c -o main_c.o
# we link the object file
wasm-ld --no-entry --export-dynamic --allow-undefined main_c.o -o main_c.wasm
# translate to wat
wasm2wat main_c.wasm > main_c.wat
# we strip the wasm binary
wasm-strip main_c.wasmLet's compile the Zig code:
# we compile zig
zig build
# translate to wat
wasm2wat zig-out/bin/main.wasm > zig-out/bin/main.watNow let's compare the two WASMs:
enzo@merlaux:~/code/zig-cdk$ ll *.wasm
-rwxrwxr-x 1 enzo enzo 170 May 22 18:03 main.wasm*
-rwxrwxr-x 1 enzo enzo 308 May 22 18:04 main_c.wasm*We have created a 170 bytes canister in Zig. Let us see if it works. First we need to create a minimal dfx.json:
{
"canisters": {
"hello_zig": {
"type": "custom",
"build": "zig build",
"candid": "not.did",
"wasm": "zig-out/bin/main.wasm"
}
}
}Then let's create a minimal candid file not.did:
service: {}
We check if it actually works, start-up dfx:
dfx start
dfx deployNow, let's call the canister:
enzo@merlaux:~/code/zig-cdk$ dfx canister call hello_zig hi --output raw | xxd -r -p
WARN: Cannot fetch Candid interface for hi, sending arguments with inferred types.
Hello, World!IT WORKS!
To replicate the code, install nix and direnv:
- Install nix with Determinate Systems Nix Installer
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install-
Install direnv - installation page
Run direnv allow. You should be all set-up!