296 lines
8.9 KiB
Zig
296 lines
8.9 KiB
Zig
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;
|
|
}
|