Gitignore zig crap

This commit is contained in:
2026-05-05 23:14:53 +02:00
parent c7897e55a8
commit 823d0ae29b
1533 changed files with 19 additions and 642271 deletions

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 zig-gamedev contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,94 +0,0 @@
# [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=emsdk 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 = optimize,
.fsanitize = false,
});
var emcc_settings = @import("zemscripten").emccDefaultSettings(b.allocator, .{
.optimize = optimize,
.emsdk_allocator = .emmalloc,
});
try emcc_settings.put("ALLOW_MEMORY_GROWTH", "1");
const emcc_step = @import("zemscripten").emccStep(
b,
&.{ }, // src file paths
&.{ wasm }, // src compile steps
.{
.optimize = optimize,
.flags = emcc_flags,
.settings = emcc_settings,
.use_preload_plugins = true,
.embed_paths = &.{},
.preload_paths = &.{},
.shell_file_path = null, // set this to override the default html shell
.js_library_path = null,
.out_file_name = "MyGame.html", // or "MyGame.js"
.install_dir = .{ .custom = "web" },
},
);
emcc_step.dependOn(activate_emsdk_step);
b.getInstallStep().dependOn(emcc_step);
```
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.

View File

@ -1,295 +0,0 @@
const builtin = @import("builtin");
const std = @import("std");
pub const emsdk_ver_major = "4";
pub const emsdk_ver_minor = "0";
pub const emsdk_ver_tiny = "19";
pub const emsdk_version = emsdk_ver_major ++ "." ++ emsdk_ver_minor ++ "." ++ emsdk_ver_tiny;
pub fn build(b: *std.Build) void {
_ = b.addModule("root", .{ .root_source_file = b.path("src/zemscripten.zig") });
}
pub fn emccPath(b: *std.Build) []const u8 {
return std.fs.path.join(b.allocator, &.{
b.dependency("emsdk", .{}).path("").getPath(b),
"upstream",
"emscripten",
"emcc.py",
}) catch unreachable;
}
pub fn emrunPath(b: *std.Build) []const u8 {
return std.fs.path.join(b.allocator, &.{
b.dependency("emsdk", .{}).path("").getPath(b),
"upstream",
"emscripten",
switch (builtin.target.os.tag) {
.windows => "emrun.bat",
else => "emrun",
},
}) catch unreachable;
}
pub fn htmlPath(b: *std.Build) []const u8 {
return std.fs.path.join(b.allocator, &.{
b.dependency("emsdk", .{}).path("").getPath(b),
"upstream",
"emscripten",
"src",
"shell.html",
}) catch unreachable;
}
pub fn activateEmsdkStep(b: *std.Build) *std.Build.Step {
const emsdk_script_path = std.fs.path.join(b.allocator, &.{
b.dependency("emsdk", .{}).path("").getPath(b),
switch (builtin.target.os.tag) {
.windows => "emsdk.bat",
else => "emsdk",
},
}) catch unreachable;
var emsdk_update = b.addSystemCommand(&.{ emsdk_script_path, "update" });
var emsdk_install = b.addSystemCommand(&.{ emsdk_script_path, "install", emsdk_version });
emsdk_install.step.dependOn(&emsdk_update.step);
switch (builtin.target.os.tag) {
.linux, .macos => {
emsdk_install.step.dependOn(&b.addSystemCommand(&.{ "chmod", "+x", emsdk_script_path }).step);
},
.windows => {
emsdk_install.step.dependOn(&b.addSystemCommand(&.{ "takeown", "/f", emsdk_script_path }).step);
},
else => {},
}
var emsdk_activate = b.addSystemCommand(&.{ emsdk_script_path, "activate", emsdk_version });
emsdk_activate.step.dependOn(&emsdk_install.step);
const step = b.allocator.create(std.Build.Step) catch unreachable;
step.* = std.Build.Step.init(.{
.id = .custom,
.name = "Activate EMSDK",
.owner = b,
.makeFn = &struct {
fn make(_: *std.Build.Step, _: std.Build.Step.MakeOptions) anyerror!void {}
}.make,
});
switch (builtin.target.os.tag) {
.linux, .macos => {
const chmod_emcc = b.addSystemCommand(&.{ "chmod", "a+x", emccPath(b) });
chmod_emcc.step.dependOn(&emsdk_activate.step);
step.dependOn(&chmod_emcc.step);
const chmod_emrun = b.addSystemCommand(&.{ "chmod", "a+x", emrunPath(b) });
chmod_emrun.step.dependOn(&emsdk_activate.step);
step.dependOn(&chmod_emrun.step);
},
.windows => {
const takeown_emcc = b.addSystemCommand(&.{ "takeown", "/f", emccPath(b) });
takeown_emcc.step.dependOn(&emsdk_activate.step);
step.dependOn(&takeown_emcc.step);
const takeown_emrun = b.addSystemCommand(&.{ "takeown", "/f", emrunPath(b) });
takeown_emrun.step.dependOn(&emsdk_activate.step);
step.dependOn(&takeown_emrun.step);
},
else => {},
}
return step;
}
pub const EmccFlags = std.StringHashMap(void);
pub const EmccDefaultFlagsOverrides = struct {
optimize: std.builtin.OptimizeMode,
fsanitize: bool,
};
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: EmccDefaultFlagsOverrides) EmccFlags {
var args = EmccFlags.init(allocator);
switch (options.optimize) {
.Debug => {
args.put("-O0", {}) catch unreachable;
args.put("-gsource-map", {}) catch unreachable;
if (options.fsanitize)
args.put("-fsanitize=undefined", {}) catch unreachable;
},
.ReleaseSafe => {
args.put("-O3", {}) catch unreachable;
if (options.fsanitize) {
args.put("-fsanitize=undefined", {}) catch unreachable;
args.put("-fsanitize-minimal-runtime", {}) catch unreachable;
}
},
.ReleaseFast => {
args.put("-O3", {}) catch unreachable;
},
.ReleaseSmall => {
args.put("-Oz", {}) catch unreachable;
},
}
return args;
}
pub const EmccSettings = std.StringHashMap([]const u8);
pub const EmsdkAllocator = enum {
none,
dlmalloc,
emmalloc,
@"emmalloc-debug",
@"emmalloc-memvalidate",
@"emmalloc-verbose",
mimalloc,
};
pub const EmccDefaultSettingsOverrides = struct {
optimize: std.builtin.OptimizeMode,
emsdk_allocator: EmsdkAllocator = .emmalloc,
};
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: EmccDefaultSettingsOverrides) EmccSettings {
var settings = EmccSettings.init(allocator);
switch (options.optimize) {
.Debug, .ReleaseSafe => {
settings.put("SAFE_HEAP", "1") catch unreachable;
settings.put("STACK_OVERFLOW_CHECK", "1") catch unreachable;
settings.put("ASSERTIONS", "1") catch unreachable;
},
else => {},
}
settings.put("MALLOC", @tagName(options.emsdk_allocator)) catch unreachable;
return settings;
}
pub const ResourceFile = struct {
src_path: std.Build.LazyPath,
virtual_path: ?[]const u8 = null,
pub fn get(self: ResourceFile, b: *std.Build) []const u8 {
return if (self.virtual_path) |virtual_path|
b.fmt(
"{s}@{s}",
.{ self.src_path.getPath(b), virtual_path },
)
else
self.src_path.getPath(b);
}
};
pub const StepOptions = struct {
optimize: std.builtin.OptimizeMode,
flags: EmccFlags,
settings: EmccSettings,
use_preload_plugins: bool = false,
embed_paths: ?[]const ResourceFile = null,
preload_paths: ?[]const ResourceFile = null,
shell_file_path: ?std.Build.LazyPath = null,
js_library_path: ?std.Build.LazyPath = null,
out_file_name: []const u8,
install_dir: std.Build.InstallDir,
};
pub fn emccStep(
b: *std.Build,
src_paths: []const std.Build.LazyPath,
compile_steps: []const *std.Build.Step.Compile,
options: StepOptions,
) *std.Build.Step {
var emcc = b.addSystemCommand(&.{emccPath(b)});
var iterFlags = options.flags.iterator();
while (iterFlags.next()) |kvp| {
emcc.addArg(kvp.key_ptr.*);
}
var iterSettings = options.settings.iterator();
while (iterSettings.next()) |kvp| {
emcc.addArg(std.fmt.allocPrint(
b.allocator,
"-s{s}={s}",
.{ kvp.key_ptr.*, kvp.value_ptr.* },
) catch unreachable);
}
for (src_paths) |src_path| {
emcc.addFileArg(src_path);
}
for (compile_steps) |compile_step| {
emcc.addArtifactArg(compile_step);
for (compile_step.root_module.getGraph().modules) |module| {
for (module.link_objects.items) |link_object| {
switch (link_object) {
.other_step => |linked_compile_step| {
switch (linked_compile_step.kind) {
.lib => {
emcc.addArtifactArg(linked_compile_step);
},
else => {},
}
},
else => {},
}
}
}
}
emcc.addArg("-o");
const out_file = emcc.addOutputFileArg(options.out_file_name);
if (options.use_preload_plugins) {
emcc.addArg("--use-preload-plugins");
}
if (options.embed_paths) |embed_paths| {
for (embed_paths) |path| {
emcc.addArg("--embed-file");
emcc.addFileArg(path.src_path);
}
}
if (options.preload_paths) |preload_paths| {
for (preload_paths) |path| {
emcc.addArg("--preload-file");
emcc.addFileArg(path.src_path);
}
}
if (options.shell_file_path) |shell_file_path| {
emcc.addArg("--shell-file");
emcc.addFileArg(shell_file_path);
}
if (options.js_library_path) |js_library_path| {
emcc.addArg("--js-library");
emcc.addFileArg(js_library_path);
}
const install_step = b.addInstallDirectory(.{
.source_dir = out_file.dirname(),
.install_dir = options.install_dir,
.install_subdir = "",
});
install_step.step.dependOn(&emcc.step);
return &install_step.step;
}
pub fn emrunStep(
b: *std.Build,
html_path: []const u8,
extra_args: []const []const u8,
) *std.Build.Step {
var emrun = b.addSystemCommand(&.{emrunPath(b)});
emrun.addArgs(extra_args);
emrun.addArg(html_path);
// emrun.addArg("--");
return &emrun.step;
}

View File

@ -1,13 +0,0 @@
.{
.name = .zemscripten,
.fingerprint = 0x2de6d80ca84319b1, // Changing this has security and trust implications.
.version = "0.2.0-dev",
.minimum_zig_version = "0.14.0",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"LICENSE",
"README.md",
},
}

View File

@ -1,222 +0,0 @@
//! Zig bindings and glue for Emscripten
const std = @import("std");
comptime {
_ = std.testing.refAllDeclsRecursive(@This());
}
pub extern fn emscripten_sleep(ms: u32) void;
pub const MainLoopCallback = *const fn () callconv(.c) void;
extern fn emscripten_set_main_loop(MainLoopCallback, c_int, c_int) void;
pub fn setMainLoop(cb: MainLoopCallback, maybe_fps: ?i16, simulate_infinite_loop: bool) void {
emscripten_set_main_loop(cb, maybe_fps orelse -1, @intFromBool(simulate_infinite_loop));
}
extern fn emscripten_cancel_main_loop() void;
pub fn cancelMainLoop() void {
emscripten_cancel_main_loop();
}
pub const MainLoopArgCallback = *const fn (arg: *anyopaque) callconv(.c) void;
extern fn emscripten_set_main_loop_arg(MainLoopArgCallback, arg: *anyopaque, c_int, c_int) void;
pub fn setMainLoopArg(cb: MainLoopArgCallback, arg: *anyopaque, maybe_fps: ?i16, simulate_infinite_loop: bool) void {
emscripten_set_main_loop_arg(cb, arg, maybe_fps orelse -1, @intFromBool(simulate_infinite_loop));
}
pub const AnimationFrameCallback = *const fn (f64, ?*anyopaque) callconv(.c) c_int;
extern fn emscripten_request_animation_frame_loop(AnimationFrameCallback, ?*anyopaque) void;
pub const requestAnimationFrameLoop = emscripten_request_animation_frame_loop;
pub const EmscriptenResult = enum(i16) {
success = 0,
deferred = 1,
not_supported = -1,
failed_not_deferred = -2,
invalid_target = -3,
unknown_target = -4,
invalid_param = -5,
failed = -6,
no_data = -7,
timed_out = -8,
};
pub const CanvasSizeChangedCallback = *const fn (
i16,
*anyopaque,
?*anyopaque,
) callconv(.c) c_int;
pub fn setResizeCallback(
cb: CanvasSizeChangedCallback,
use_capture: bool,
user_data: ?*anyopaque,
) EmscriptenResult {
const result = emscripten_set_resize_callback_on_thread(
"2",
user_data,
@intFromBool(use_capture),
cb,
2,
);
return @enumFromInt(result);
}
extern fn emscripten_set_resize_callback_on_thread(
[*:0]const u8,
?*anyopaque,
c_int,
CanvasSizeChangedCallback,
c_int,
) c_int;
pub fn getElementCssSize(
target_id: [:0]const u8,
width: *f64,
height: *f64,
) EmscriptenResult {
return @enumFromInt(emscripten_get_element_css_size(
target_id,
width,
height,
));
}
extern fn emscripten_get_element_css_size([*:0]const u8, *f64, *f64) c_int;
// EmmallocAllocator allocator
// use with linker flag -sMALLOC=emmalloc
// for details see docs: https://github.com/emscripten-core/emscripten/blob/main/system/lib/emmalloc.c
extern fn emmalloc_memalign(u32, u32) ?*anyopaque;
extern fn emmalloc_realloc_try(?*anyopaque, u32) ?*anyopaque;
extern fn emmalloc_free(?*anyopaque) void;
pub const EmmallocAllocator = struct {
const Self = @This();
dummy: u32 = undefined,
pub fn allocator(self: *Self) std.mem.Allocator {
return .{
.ptr = self,
.vtable = &.{
.alloc = &alloc,
.resize = &resize,
.remap = &remap,
.free = &free,
},
};
}
fn alloc(
ctx: *anyopaque,
len: usize,
ptr_align_log2: std.mem.Alignment,
return_address: usize,
) ?[*]u8 {
_ = ctx;
_ = return_address;
const ptr_align = ptr_align_log2.toByteUnits();
const ptr = emmalloc_memalign(@intCast(ptr_align), @intCast(len)) orelse return null;
return @ptrCast(ptr);
}
fn resize(
ctx: *anyopaque,
buf: []u8,
buf_align_log2: std.mem.Alignment,
new_len: usize,
return_address: usize,
) bool {
_ = ctx;
_ = return_address;
_ = buf_align_log2;
return emmalloc_realloc_try(buf.ptr, @intCast(new_len)) != null;
}
fn remap(
ctx: *anyopaque,
buf: []u8,
buf_align_log2: std.mem.Alignment,
new_len: usize,
return_address: usize,
) ?[*]u8 {
return if (resize(ctx, buf, buf_align_log2, new_len, return_address)) buf.ptr else null;
}
fn free(
ctx: *anyopaque,
buf: []u8,
buf_align_log2: std.mem.Alignment,
return_address: usize,
) void {
_ = ctx;
_ = buf_align_log2;
_ = return_address;
return emmalloc_free(buf.ptr);
}
};
extern fn emscripten_err([*c]const u8) void;
extern fn emscripten_console_error([*c]const u8) void;
extern fn emscripten_console_warn([*c]const u8) void;
extern fn emscripten_console_log([*c]const u8) void;
/// std.panic impl
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
_ = error_return_trace;
_ = ret_addr;
var buf: [1024]u8 = undefined;
const error_msg: [:0]u8 = std.fmt.bufPrintZ(&buf, "PANIC! {s}", .{msg}) catch unreachable;
emscripten_err(error_msg.ptr);
while (true) {
@breakpoint();
}
}
/// std.log impl
pub fn log(
comptime level: std.log.Level,
comptime scope: @TypeOf(.EnumLiteral),
comptime format: []const u8,
args: anytype,
) void {
const level_txt = comptime level.asText();
const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
const prefix = level_txt ++ prefix2;
var buf: [1024]u8 = undefined;
const msg = std.fmt.bufPrintZ(buf[0 .. buf.len - 1], prefix ++ format, args) catch |err| {
switch (err) {
error.NoSpaceLeft => {
emscripten_console_error("log message too long, skipped.");
return;
},
}
};
switch (level) {
.err => emscripten_console_error(@ptrCast(msg.ptr)),
.warn => emscripten_console_warn(@ptrCast(msg.ptr)),
else => emscripten_console_log(@ptrCast(msg.ptr)),
}
}
// Networking
extern fn emscripten_wget(url: [*c]const u8, file: [*c]const u8) c_int;
extern fn emscripten_wget_data(url: [*c]const u8, pbuffer: **anyopaque, pnum: *c_int, perror: *c_int) void;
pub fn wget(url: [:0]const u8, file: [:0]const u8) !void {
if (emscripten_wget(url.ptr, file.ptr) != 0) {
return error.WgetError;
}
}
pub fn wget_data(url: [:0]const u8) ![]u8 {
var buffer_ptr: *anyopaque = undefined;
var len: c_int = undefined;
var err: c_int = undefined;
emscripten_wget_data(url.ptr, &buffer_ptr, &len, &err);
if (err != 0) {
return error.WgetError;
}
return @as([*]u8, @ptrCast(buffer_ptr))[0..@intCast(len)];
}