summaryrefslogtreecommitdiff
path: root/build.zig
blob: 2d7c1ce83457617aae5bd3c66b131e47edb911d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
const std = @import("std");
const builtin = @import("builtin");

const HEAD_location = ".git/HEAD";
const commit_location = ".git/refs/heads/master";

const common_c_files = &[_][]const u8 {
    "src/utils/stringBuilder.c",
    "src/utils/arena.c",
    "src/wren_inter/wren_inter.c",
    "src/resources/resources.c",
    "src/resources/config.c",
    "src/ui_elements/UI.c",
    "src/ui_elements/TextEditor.c",
    "src/ui_elements/Button.c",
    "src/scenes/sceneManager.c",
    "src/scenes/mainMenu.c",
    "src/scenes/resultView.c",
    "src/scenes/puzzleScene.c",
    "src/scenes/distractionScene.c",
    "src/scenes/collectionScene.c",
    "src/puzzles/puzzle.c",
    "src/puzzles/parser.c",
    "src/puzzles//distractions.c",
};

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // ========== Building a game ==========

    var game_root = b.addModule("game-mod", .{
        .optimize = optimize,
        .target = target,
        .link_libc = true,
    });
    FillModule(b, game_root, optimize);

    // The entry point. This is put there separatly to separate from tests entry point
    game_root.addCSourceFile(.{ .file = b.path("src/main.c") });

    const exe = b.addExecutable(.{
        .name = "game",
        .root_module = game_root,
    });

    b.installArtifact(exe);

    // ========== Running a game ==========

    const run_step = b.step("run", "Run the app");
    const run_cmd = b.addRunArtifact(exe);
    run_step.dependOn(&run_cmd.step);
    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    // ========== Building and running tests ==========
    
    const test_runner_root = b.addModule("test-runner-mod", .{
        .optimize = optimize,
        .target = target,
        .link_libc = true,
    });
    FillModule(b, test_runner_root, optimize);

    // The only difference is the additional files
    test_runner_root.addCSourceFiles(.{
        .files = &[_][]const u8 {
            "src/tests/runner.c",
            "src/tests/arena_tests.c",
        }
    });

    const test_runner_exe = b.addExecutable(.{
        .name = "game_tests",
        .root_module = test_runner_root,
    });

    const test_run_step = b.step("test", "Run the test app");
    const test_run_cmd = b.addRunArtifact(test_runner_exe);
    test_run_step.dependOn(&test_run_cmd.step);
    if (b.args) |args| {
        test_run_cmd.addArgs(args);
    }

}

fn FillModule(b: *std.Build, mod: *std.Build.Module, opt: std.builtin.OptimizeMode) void {
    // Adding a build version
    const build_ver = GetVersionString(b, opt) catch "Build UNTRACKED";
    if (build_ver.len > 0)
        mod.addCMacro("BUILD_VERSION", build_ver);

    mod.addCSourceFiles(.{
        .files = common_c_files,
    });

    // Linking raylib
    if (builtin.target.os.tag == .windows) {
        // If you are building on windows you need to provide your own 
        // raylib. Put it in the raylib dir
        mod.addLibraryPath(b.path("raylib/lib/"));
        mod.addIncludePath(b.path("raylib/include/"));
    }

    mod.linkSystemLibrary("raylib", .{.needed = true});
    mod.addIncludePath(b.path("include/"));

    // Linking wren. They do not provide system-wide libraries so you have to 
    // provide them yourself
    mod.addIncludePath(b.path("wren/src/include/"));
    mod.addLibraryPath(b.path("wren/lib/"));
    mod.linkSystemLibrary("wren", .{ 
        .needed = true, 
        .preferred_link_mode = .static,
    });
}

// Returns a build version. Returns an empty string if build in release mode
fn GetVersionString(b: *std.Build, optimization: std.builtin.OptimizeMode) ![]u8 {
    if (optimization != .Debug) {
        return "";
    }

    const allocator = b.allocator;
    var threaded = std.Io.Threaded.init(allocator, .{});
    defer threaded.deinit();

    const headContents = try std.Io.Dir.cwd().readFileAlloc(threaded.io(), HEAD_location, allocator, .limited(std.math.maxInt(usize)));
    var headIter = std.mem.tokenizeAny(u8, headContents[0..headContents.len - 1], "/");
    var branchName: []const u8 = "";
    while (headIter.next()) |token| {
        branchName = token;
    }
    const commitContents = try std.Io.Dir.cwd().readFileAlloc(threaded.io(), commit_location, allocator, .limited(std.math.maxInt(usize)));
    return try std.fmt.allocPrint(allocator, "\"Build {s}:{s}\"", .{
        branchName,
        commitContents[0..@min(commitContents.len-1, 10)]
    });
}