106 lines
3.6 KiB
Markdown
106 lines
3.6 KiB
Markdown
# [zemscripten](https://github.com/zig-gamedev/zemscripten)
|
|
|
|
Zig build package and shims for [Emscripten](https://emscripten.org) emsdk
|
|
|
|
## How to use it
|
|
|
|
Add `zemscripten` and (optionally) `emsdk` to your build.zig.zon dependencies
|
|
```sh
|
|
zig fetch --save https://github.com/emscripten-core/emsdk/archive/refs/tags/4.0.3.tar.gz
|
|
```
|
|
|
|
Emsdk must be activated before it can be used. You can use `activateEmsdkStep` to create a build step for that:
|
|
```zig
|
|
const activate_emsdk_step = @import("zemscripten").activateEmsdkStep(b);
|
|
```
|
|
|
|
Add zemscripten's "root" module to your wasm compile target., then create an `emcc` build step. We use zemscripten's default flags and settings which can be overridden for your project specific requirements. Refer to the [emcc documentation](https://emscripten.org/docs/tools_reference/emcc.html). Example build.zig code:
|
|
```zig
|
|
const wasm = b.addStaticLibrary(.{
|
|
.name = "MyGame",
|
|
.root_source_file = b.path("src/main.zig"),
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
|
|
const zemscripten = b.dependency("zemscripten", .{});
|
|
wasm.root_module.addImport("zemscripten", zemscripten.module("root"));
|
|
|
|
const emcc_flags = @import("zemscripten").emccDefaultFlags(b.allocator, optimize);
|
|
|
|
var emcc_settings = @import("zemscripten").emccDefaultSettings(b.allocator, .{
|
|
.optimize = optimize,
|
|
});
|
|
|
|
try emcc_settings.put("ALLOW_MEMORY_GROWTH", "1");
|
|
|
|
const emcc_step = @import("zemscripten").emccStep(
|
|
b,
|
|
wasm,
|
|
.{
|
|
.optimize = optimize,
|
|
.flags = emcc_flags,
|
|
.settings = emcc_settings,
|
|
.use_preload_plugins = true,
|
|
.embed_paths = &.{},
|
|
.preload_paths = &.{},
|
|
.install_dir = .{ .custom = "web" },
|
|
},
|
|
);
|
|
emcc_step.dependOn(activate_emsdk_step);
|
|
|
|
b.getInstallStep().dependOn(emcc_step);
|
|
```
|
|
|
|
To use a custom html file emccStep() accepts a shell_file_path option:
|
|
```zig
|
|
const emcc_step = @import("zemscripten").emccStep(
|
|
b,
|
|
wasm,
|
|
.{
|
|
.optimize = optimize,
|
|
.flags = emcc_flags,
|
|
.settings = emcc_settings,
|
|
.use_preload_plugins = true,
|
|
.embed_paths = &.{},
|
|
.preload_paths = &.{},
|
|
.install_dir = .{ .custom = "web" },
|
|
.shell_file_path = b.path("path/to/file"),
|
|
},
|
|
);
|
|
```
|
|
|
|
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:
|
|
```zig
|
|
const std = @import("std");
|
|
|
|
const zemscripten = @import("zemscripten");
|
|
pub const panic = zemscripten.panic;
|
|
|
|
pub const std_options = std.Options{
|
|
.logFn = zemscripten.log,
|
|
};
|
|
|
|
export fn main() c_int {
|
|
std.log.info("hello, world.", .{});
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
You can also define a run step that invokes `emrun`. This will serve the html locally over HTTP and try to open it using your default browser. Example build.zig code:
|
|
```zig
|
|
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
|
|
|
|
const emrun_args = .{};
|
|
const emrun_step = @import("zemscripten").emrunStep(
|
|
b,
|
|
b.getInstallPath(.{ .custom = "web" }, html_filename),
|
|
&emrun_args,
|
|
);
|
|
|
|
emrun_step.dependOn(emcc_step);
|
|
|
|
b.step("emrun", "Build and open the web app locally using emrun").dependOn(emrun_step);
|
|
```
|
|
See the [emrun documentation](https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html) for the difference args that can be used.
|