1 const std = @import("std");
2 const Build = std.Build;
3 const OptimizeMode = std.builtin.OptimizeMode;
4 const ResolvedTarget = Build.ResolvedTarget;
5 const Dependency = Build.Dependency;
6 const sokol = @import("sokol");
7 const cimgui = @import("cimgui");
9 pub fn build(b: *Build) !void {
10 const target = b.standardTargetOptions(.{});
11 const optimize = b.standardOptimizeOption(.{});
13 const opt_docking = b.option(bool, "docking", "Build with docking support") orelse false;
15 // Get the matching Zig module name, C header search path and C library for
16 // vanilla imgui vs the imgui docking branch.
17 const cimgui_conf = cimgui.getConfig(opt_docking);
19 // note that the sokol dependency is built with `.with_sokol_imgui = true`
20 const dep_sokol = b.dependency("sokol", .{
23 .with_sokol_imgui = true,
25 const dep_cimgui = b.dependency("cimgui", .{
30 // inject the cimgui header search path into the sokol C library compile step
31 dep_sokol.artifact("sokol_clib").addIncludePath(dep_cimgui.path(cimgui_conf.include_dir));
34 dep_sokol.artifact("sokol_clib").addIncludePath(b.path("ext/cimgui"));
35 const dep_shdc = dep_sokol.builder.dependency("shdc", .{});
36 const shdc_step = try sokol.shdc.createSourceFile(b, .{
38 .input = "src/shader/quad.glsl",
39 .output = "src/shader/quad.glsl.zig",
40 .slang = .{ .glsl430 = true },
43 // main module with sokol and cimgui imports
44 const mod_main = b.createModule(.{
45 .root_source_file = b.path("src/main.zig"),
49 .{ .name = "sokol", .module = dep_sokol.module("sokol") },
50 .{ .name = cimgui_conf.module_name, .module = dep_cimgui.module(cimgui_conf.module_name) },
53 const mod_options = b.addOptions();
54 mod_options.addOption(bool, "docking", opt_docking);
55 mod_main.addOptions("build_options", mod_options);
57 // from here on different handling for native vs wasm builds
58 if (target.result.cpu.arch.isWasm()) {
61 .dep_sokol = dep_sokol,
62 .dep_cimgui = dep_cimgui,
63 .cimgui_clib_name = cimgui_conf.clib_name,
66 const exe = try buildNative(b, mod_main);
67 exe.step.dependOn(shdc_step);
71 fn buildNative(b: *Build, mod: *Build.Module) !*Build.Step.Compile {
72 const exe = b.addExecutable(.{
76 b.installArtifact(exe);
77 b.step("run", "Run demo").dependOn(&b.addRunArtifact(exe).step);
81 const BuildWasmOptions = struct {
82 mod_main: *Build.Module,
83 dep_sokol: *Dependency,
84 dep_cimgui: *Dependency,
85 cimgui_clib_name: []const u8,
88 fn buildWasm(b: *Build, opts: BuildWasmOptions) !void {
89 // build the main file into a library, this is because the WASM 'exe'
90 // needs to be linked in a separate build step with the Emscripten linker
91 const demo = b.addLibrary(.{
93 .root_module = opts.mod_main,
96 // get the Emscripten SDK dependency from the sokol dependency
97 const dep_emsdk = opts.dep_sokol.builder.dependency("emsdk", .{});
99 // need to inject the Emscripten system header include path into
100 // the cimgui C library otherwise the C/C++ code won't find
102 const emsdk_incl_path = dep_emsdk.path("upstream/emscripten/cache/sysroot/include");
103 opts.dep_cimgui.artifact(opts.cimgui_clib_name).addSystemIncludePath(emsdk_incl_path);
105 // all C libraries need to depend on the sokol library, when building for
106 // WASM this makes sure that the Emscripten SDK has been setup before
107 // C compilation is attempted (since the sokol C library depends on the
108 // Emscripten SDK setup step)
109 opts.dep_cimgui.artifact(opts.cimgui_clib_name).step.dependOn(&opts.dep_sokol.artifact("sokol_clib").step);
111 // create a build step which invokes the Emscripten linker
112 const link_step = try sokol.emLinkStep(b, .{
114 .target = opts.mod_main.resolved_target.?,
115 .optimize = opts.mod_main.optimize.?,
118 .use_emmalloc = true,
119 .use_filesystem = false,
120 .shell_file_path = opts.dep_sokol.path("src/sokol/web/shell.html"),
122 // attach to default target
123 b.getInstallStep().dependOn(&link_step.step);
124 // ...and a special run step to start the web build output via 'emrun'
125 const run = sokol.emRunStep(b, .{ .name = "demo", .emsdk = dep_emsdk });
126 run.step.dependOn(&link_step.step);
127 b.step("run", "Run demo").dependOn(&run.step);