Chess engine in zig
const std = @import("std");
const builtin = @import("builtin");

pub fn build(b: *std.build.Builder) void {
    // Standard target options allows the person running `zig build` to choose
    // what target to build for. Here we do not override the defaults, which
    // means any target is allowed, and the default is native. Other options
    // for restricting supported target set are available.
    const target = b.standardTargetOptions(.{});

    // Standard release options allow the person running `zig build` to select
    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
    const optimize = b.standardOptimizeOption(.{});

    const nnue = b.option(bool, "nnue", "Enable NNUE") orelse false;
    const options = b.addOptions();
    options.addOption(bool, "nnue", nnue);

    const base_flags = [_][]const u8{
        "-Wall",
        "-fstrict-aliasing",
        "-fno-exceptions",
        "-fno-rtti",
        "-std=c++11",
        "-DIS_64BIT",
    };

    const flags = blk: {
        var f = std.BoundedArray([]const u8, 16).init(0) catch unreachable;
        f.appendSlice(&base_flags) catch unreachable;
        if (builtin.cpu.arch.isX86()) {
            // if (std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) {
            //     f.append("-DUSE_AVX2 -mavx2") catch unreachable;
            // }
            if (std.Target.x86.featureSetHas(builtin.cpu.features, .sse)) {
                f.append("-DUSE_SSE -msse") catch unreachable;
            }
            // if (std.Target.x86.featureSetHas(builtin.cpu.features, .sse2)) {
            //     f.append("-DUSE_SSE2 -msse2") catch unreachable;
            // }
            if (std.Target.x86.featureSetHas(builtin.cpu.features, .sse3)) {
                f.append("-DUSE_sse3 -msse3") catch unreachable;
            }
            if (std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) {
                f.append("-DUSE_SSE41 -msse4.1") catch unreachable;
            }
        } else if (builtin.cpu.arch.isAARCH64()) {
            // rpi4 does not report neon feature :-(
            f.append("-DUSE_NEON") catch unreachable;
            if (std.Target.arm.featureSetHas(builtin.cpu.features, .neon)) {
                f.append("-DUSE_NEON") catch unreachable;
            }
        }

        break :blk f.constSlice();
    };

    const exe = b.addExecutable(std.build.ExecutableOptions{
        .name = "pistike",
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });
    if (nnue) {
        exe.linkLibCpp();
        exe.addIncludePath(.{ .path = "src/nnue" });
        exe.addCSourceFiles(&[_][]const u8{ "src/nnue/nnue.cpp", "src/nnue/misc.cpp" }, flags);
    }
    exe.addOptions("build_options", options);

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    const exe_tests = b.addTest(std.build.TestOptions{
        .root_source_file = .{ .path = "src/main.zig" },
    });
    if (nnue) {
        exe_tests.linkLibCpp();
        exe_tests.addIncludePath(.{ .path = "src/nnue" });
        exe_tests.addCSourceFiles(&[_][]const u8{ "src/nnue/nnue.cpp", "src/nnue/misc.cpp" }, flags);
    }
    exe_tests.addOptions("build_options", options);

    b.installArtifact(exe_tests);

    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&exe_tests.step);
}