diff options
Diffstat (limited to 'build.zig')
| -rw-r--r-- | build.zig | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..590d913 --- /dev/null +++ b/build.zig @@ -0,0 +1,128 @@ +const std = @import("std"); +const Build = std.Build; +const OptimizeMode = std.builtin.OptimizeMode; +const ResolvedTarget = Build.ResolvedTarget; +const Dependency = Build.Dependency; +const sokol = @import("sokol"); +const cimgui = @import("cimgui"); + +pub fn build(b: *Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const opt_docking = b.option(bool, "docking", "Build with docking support") orelse false; + + // Get the matching Zig module name, C header search path and C library for + // vanilla imgui vs the imgui docking branch. + const cimgui_conf = cimgui.getConfig(opt_docking); + + // note that the sokol dependency is built with `.with_sokol_imgui = true` + const dep_sokol = b.dependency("sokol", .{ + .target = target, + .optimize = optimize, + .with_sokol_imgui = true, + }); + const dep_cimgui = b.dependency("cimgui", .{ + .target = target, + .optimize = optimize, + }); + + // inject the cimgui header search path into the sokol C library compile step + dep_sokol.artifact("sokol_clib").addIncludePath(dep_cimgui.path(cimgui_conf.include_dir)); + + // shaders + dep_sokol.artifact("sokol_clib").addIncludePath(b.path("ext/cimgui")); + const dep_shdc = dep_sokol.builder.dependency("shdc", .{}); + const shdc_step = try sokol.shdc.createSourceFile(b, .{ + .shdc_dep = dep_shdc, + .input = "src/shader/quad.glsl", + .output = "src/shader/quad.glsl.zig", + .slang = .{ .glsl430 = true }, + }); + + // main module with sokol and cimgui imports + const mod_main = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ .name = "sokol", .module = dep_sokol.module("sokol") }, + .{ .name = cimgui_conf.module_name, .module = dep_cimgui.module(cimgui_conf.module_name) }, + }, + }); + const mod_options = b.addOptions(); + mod_options.addOption(bool, "docking", opt_docking); + mod_main.addOptions("build_options", mod_options); + + // from here on different handling for native vs wasm builds + if (target.result.cpu.arch.isWasm()) { + try buildWasm(b, .{ + .mod_main = mod_main, + .dep_sokol = dep_sokol, + .dep_cimgui = dep_cimgui, + .cimgui_clib_name = cimgui_conf.clib_name, + }); + } else { + const exe = try buildNative(b, mod_main); + exe.step.dependOn(shdc_step); + } +} + +fn buildNative(b: *Build, mod: *Build.Module) !*Build.Step.Compile { + const exe = b.addExecutable(.{ + .name = "demo", + .root_module = mod, + }); + b.installArtifact(exe); + b.step("run", "Run demo").dependOn(&b.addRunArtifact(exe).step); + return exe; +} + +const BuildWasmOptions = struct { + mod_main: *Build.Module, + dep_sokol: *Dependency, + dep_cimgui: *Dependency, + cimgui_clib_name: []const u8, +}; + +fn buildWasm(b: *Build, opts: BuildWasmOptions) !void { + // build the main file into a library, this is because the WASM 'exe' + // needs to be linked in a separate build step with the Emscripten linker + const demo = b.addLibrary(.{ + .name = "demo", + .root_module = opts.mod_main, + }); + + // get the Emscripten SDK dependency from the sokol dependency + const dep_emsdk = opts.dep_sokol.builder.dependency("emsdk", .{}); + + // need to inject the Emscripten system header include path into + // the cimgui C library otherwise the C/C++ code won't find + // C stdlib headers + const emsdk_incl_path = dep_emsdk.path("upstream/emscripten/cache/sysroot/include"); + opts.dep_cimgui.artifact(opts.cimgui_clib_name).addSystemIncludePath(emsdk_incl_path); + + // all C libraries need to depend on the sokol library, when building for + // WASM this makes sure that the Emscripten SDK has been setup before + // C compilation is attempted (since the sokol C library depends on the + // Emscripten SDK setup step) + opts.dep_cimgui.artifact(opts.cimgui_clib_name).step.dependOn(&opts.dep_sokol.artifact("sokol_clib").step); + + // create a build step which invokes the Emscripten linker + const link_step = try sokol.emLinkStep(b, .{ + .lib_main = demo, + .target = opts.mod_main.resolved_target.?, + .optimize = opts.mod_main.optimize.?, + .emsdk = dep_emsdk, + .use_webgl2 = true, + .use_emmalloc = true, + .use_filesystem = false, + .shell_file_path = opts.dep_sokol.path("src/sokol/web/shell.html"), + }); + // attach to default target + b.getInstallStep().dependOn(&link_step.step); + // ...and a special run step to start the web build output via 'emrun' + const run = sokol.emRunStep(b, .{ .name = "demo", .emsdk = dep_emsdk }); + run.step.dependOn(&link_step.step); + b.step("run", "Run demo").dependOn(&run.step); +} |
