Skip to content

Commit 8a4dd0c

Browse files
authored
Update EMSDK and add Emmaloc (#1)
1 parent 2c5c40b commit 8a4dd0c

File tree

3 files changed

+153
-8
lines changed

3 files changed

+153
-8
lines changed

README.md

+19
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ Add zemscripten's "root" module to your wasm compile target., then create an `em
5252
b.getInstallStep().dependOn(emcc_step);
5353
```
5454

55+
To use a custom html file emccStep() accepts a shell_file_path option:
56+
```zig
57+
const emcc_step = @import("zemscripten").emccStep(
58+
b,
59+
wasm,
60+
.{
61+
.optimize = optimize,
62+
.flags = emcc_flags,
63+
.settings = emcc_settings,
64+
.use_preload_plugins = true,
65+
.embed_paths = &.{},
66+
.preload_paths = &.{},
67+
.install_dir = .{ .custom = "web" },
68+
.shell_file_path = "path/to/file"
69+
},
70+
);
71+
```
72+
5573
Now you can use the provided Zig panic and log overrides in your wasm's root module and define the entry point that invoked by the js output of `emcc` (by default it looks for a symbol named `main`). For example:
5674
```zig
5775
const std = @import("std");
@@ -85,3 +103,4 @@ You can also define a run step that invokes `emrun`. This will serve the html lo
85103
b.step("emrun", "Build and open the web app locally using emrun").dependOn(emrun_step);
86104
```
87105
See the [emrun documentation](https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html) for the difference args that can be used.
106+

build.zig

+16-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const std = @import("std");
33

44
pub const emsdk_ver_major = "3";
55
pub const emsdk_ver_minor = "1";
6-
pub const emsdk_ver_tiny = "52";
6+
pub const emsdk_ver_tiny = "73";
77
pub const emsdk_version = emsdk_ver_major ++ "." ++ emsdk_ver_minor ++ "." ++ emsdk_ver_tiny;
88

99
pub fn build(b: *std.Build) void {
@@ -32,6 +32,13 @@ pub fn emrunPath(b: *std.Build) []const u8 {
3232
}) catch unreachable;
3333
}
3434

35+
pub fn htmlPath(b: *std.Build) []const u8 {
36+
return std.fs.path.join(b.allocator, &.{
37+
b.dependency("emsdk", .{}).path("").getPath(b),
38+
"upstream/emscripten/src/shell.html",
39+
}) catch unreachable;
40+
}
41+
3542
pub fn activateEmsdkStep(b: *std.Build) *std.Build.Step {
3643
const emsdk_script_path = std.fs.path.join(b.allocator, &.{
3744
b.dependency("emsdk", .{}).path("").getPath(b),
@@ -77,9 +84,14 @@ pub const EmccFlags = std.StringHashMap(void);
7784

7885
pub fn emccDefaultFlags(allocator: std.mem.Allocator, optimize: std.builtin.OptimizeMode) EmccFlags {
7986
var args = EmccFlags.init(allocator);
80-
if (optimize == .Debug) {
81-
args.put("-Og", {}) catch unreachable;
82-
args.put("-gsource-map", {}) catch unreachable;
87+
switch (optimize) {
88+
.Debug => {
89+
args.put("-gsource-map", {}) catch unreachable;
90+
},
91+
.ReleaseSmall, .ReleaseFast => {
92+
args.put("-O3", {}) catch unreachable;
93+
},
94+
else => {},
8395
}
8496
return args;
8597
}

src/zemscripten.zig

+118-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ comptime {
66
_ = std.testing.refAllDeclsRecursive(@This());
77
}
88

9-
extern fn emscripten_err([*c]const u8) void;
10-
extern fn emscripten_console_error([*c]const u8) void;
11-
extern fn emscripten_console_warn([*c]const u8) void;
12-
extern fn emscripten_console_log([*c]const u8) void;
9+
pub extern fn emscripten_sleep(ms: u32) void;
1310

1411
pub const MainLoopCallback = *const fn () callconv(.C) void;
1512
extern fn emscripten_set_main_loop(MainLoopCallback, c_int, c_int) void;
@@ -21,6 +18,123 @@ pub const AnimationFrameCallback = *const fn (f64, ?*anyopaque) callconv(.C) c_i
2118
extern fn emscripten_request_animation_frame_loop(AnimationFrameCallback, ?*anyopaque) void;
2219
pub const requestAnimationFrameLoop = emscripten_request_animation_frame_loop;
2320

21+
pub const EmscriptenResult = enum(i16) {
22+
success = 0,
23+
deferred = 1,
24+
not_supported = -1,
25+
failed_not_deferred = -2,
26+
invalid_target = -3,
27+
unknown_target = -4,
28+
invalid_param = -5,
29+
failed = -6,
30+
no_data = -7,
31+
timed_out = -8,
32+
};
33+
pub const CanvasSizeChangedCallback = *const fn (
34+
i16,
35+
*anyopaque,
36+
?*anyopaque,
37+
) callconv(.C) c_int;
38+
pub fn setResizeCallback(
39+
cb: CanvasSizeChangedCallback,
40+
use_capture: bool,
41+
user_data: ?*anyopaque,
42+
) EmscriptenResult {
43+
const result = emscripten_set_resize_callback_on_thread(
44+
"2",
45+
user_data,
46+
@intFromBool(use_capture),
47+
cb,
48+
2,
49+
);
50+
return @enumFromInt(result);
51+
}
52+
extern fn emscripten_set_resize_callback_on_thread(
53+
[*:0]const u8,
54+
?*anyopaque,
55+
c_int,
56+
CanvasSizeChangedCallback,
57+
c_int,
58+
) c_int;
59+
60+
pub fn getElementCssSize(
61+
target_id: [:0]const u8,
62+
width: *f64,
63+
height: *f64,
64+
) EmscriptenResult {
65+
return @enumFromInt(emscripten_get_element_css_size(
66+
target_id,
67+
width,
68+
height,
69+
));
70+
}
71+
extern fn emscripten_get_element_css_size([*:0]const u8, *f64, *f64) c_int;
72+
73+
// EmmalocAllocator allocator
74+
// use with linker flag -sMALLOC=emmalloc
75+
// for details see docs: https://github.com/emscripten-core/emscripten/blob/main/system/lib/emmalloc.c
76+
extern fn emmalloc_memalign(u32, u32) ?*anyopaque;
77+
extern fn emmalloc_realloc_try(?*anyopaque, u32) ?*anyopaque;
78+
extern fn emmalloc_free(?*anyopaque) void;
79+
pub const EmmalocAllocator = struct {
80+
const Self = @This();
81+
dummy: u32 = undefined,
82+
83+
pub fn allocator(self: *Self) std.mem.Allocator {
84+
return .{
85+
.ptr = self,
86+
.vtable = &.{
87+
.alloc = &alloc,
88+
.resize = &resize,
89+
.free = &free,
90+
},
91+
};
92+
}
93+
94+
fn alloc(
95+
ctx: *anyopaque,
96+
len: usize,
97+
ptr_align_log2: u8,
98+
return_address: usize,
99+
) ?[*]u8 {
100+
_ = ctx;
101+
_ = return_address;
102+
const ptr_align: u32 = @as(u32, 1) << @as(u5, @intCast(ptr_align_log2));
103+
if (!std.math.isPowerOfTwo(ptr_align)) unreachable;
104+
const ptr = emmalloc_memalign(ptr_align, len) orelse return null;
105+
return @ptrCast(ptr);
106+
}
107+
108+
fn resize(
109+
ctx: *anyopaque,
110+
buf: []u8,
111+
buf_align_log2: u8,
112+
new_len: usize,
113+
return_address: usize,
114+
) bool {
115+
_ = ctx;
116+
_ = return_address;
117+
_ = buf_align_log2;
118+
return emmalloc_realloc_try(buf.ptr, new_len) != null;
119+
}
120+
121+
fn free(
122+
ctx: *anyopaque,
123+
buf: []u8,
124+
buf_align_log2: u8,
125+
return_address: usize,
126+
) void {
127+
_ = ctx;
128+
_ = buf_align_log2;
129+
_ = return_address;
130+
return emmalloc_free(buf.ptr);
131+
}
132+
};
133+
134+
extern fn emscripten_err([*c]const u8) void;
135+
extern fn emscripten_console_error([*c]const u8) void;
136+
extern fn emscripten_console_warn([*c]const u8) void;
137+
extern fn emscripten_console_log([*c]const u8) void;
24138
/// std.panic impl
25139
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
26140
_ = error_return_trace;

0 commit comments

Comments
 (0)