sokol-zig と build.zig の構成

に公開

https://github.com/floooh/sokol-zig

20250306 zig-0.14 向けにリライト。

zig-sokol 最小限

とりあえず clear で動作確認。

init

$ git init
$ zig init
$ rm src/root.zig
.gitignore
.zig-cache
zig-out

sokol-zig への依存を追加

> zig fetch --save=sokol git+https://github.com/floooh/sokol-zig.git

example/clear.zig を src/main.zig にコピー

https://github.com/floooh/sokol-zig/blob/master/src/examples/clear.zig

build.zig

build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const exe_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // sokol dependency
    const dep_sokol = b.dependency("sokol", .{
        .target = target,
        .optimize = optimize,
    });
    exe_mod.addImport("sokol", dep_sokol.module("sokol"));

    const exe = b.addExecutable(.{
        .name = "zig_hello",
        .root_module = exe_mod,
    });
    b.installArtifact(exe);
}
$ zig build
$ .\zig-out\bin\zig_hello.exe

手順その2。sokol の shader を含むプロジェクト

zig-sokol では shader を前処理して zig モジュールとして import します。
コマンドラインツールの sokol-tools
を使って triangle.glsl から triangle.glsl.zig を生成します。
この、コマンドラインツールをダウンロードする、コマンドを実行して glsl.zig を生成する、
というステップを build.zig に組み込むんで自動化します。

init

$ git init
$ zig init
$ rm src/root.zig
.gitignore
.zig-cache
zig-out
*.glsl.zig
$ zig fetch --save=sokol git+https://github.com/floooh/sokol-zig.git
$ zig fetch --save=sokol-tools-bin git+https://github.com/floooh/sokol-tools-bin.git

example/triangle.zig を src/main.zig にコピー

https://github.com/floooh/sokol-zig/blob/master/src/examples/triangle.zig

examples/shaders/triangle.glsl を src/shaders/triangle.glsl にコピー

https://github.com/floooh/sokol-zig/blob/master/src/examples/shaders/triangle.glsl

build.zig

build.zig
const std = @import("std");
const builtin = @import("builtin");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const exe_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // sokol dependency
    const dep_sokol = b.dependency("sokol", .{
        .target = target,
        .optimize = optimize,
    });
    exe_mod.addImport("sokol", dep_sokol.module("sokol"));

    const exe = b.addExecutable(.{
        .name = "zig_hello",
        .root_module = exe_mod,
    });
    b.installArtifact(exe);

    const step = sokolShdc(
        b,
        target,
        "src/shaders/triangle.glsl",
    );
    exe.step.dependOn(step);
}

// a separate step to compile shaders
pub fn sokolShdc(
    b: *std.Build,
    target: std.Build.ResolvedTarget,
    comptime shader: []const u8,
) *std.Build.Step {
    const optional_shdc = comptime switch (builtin.os.tag) {
        .windows => "win32/sokol-shdc.exe",
        .linux => "linux/sokol-shdc",
        .macos => if (builtin.cpu.arch.isX86()) "osx/sokol-shdc" else "osx_arm64/sokol-shdc",
        else => @panic("unsupported host platform, skipping shader compiler step"),
    };
    const tools = b.dependency("sokol-tools-bin", .{}); // download して cache される
    const shdc_path = tools.path(b.pathJoin(&.{ "bin", optional_shdc })).getPath(b);
    const glsl = if (target.result.isDarwinLibC()) "glsl410" else "glsl430";
    const slang = glsl ++ ":metal_macos:hlsl5:glsl300es:wgsl";
    return &b.addSystemCommand(&.{
        shdc_path,
        "-i",
        shader,
        "-o",
        shader ++ ".zig",
        "-l",
        slang,
        "-f",
        "sokol_zig",
    }).step;
}

Discussion