-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathbuild.zig
194 lines (155 loc) · 6.42 KB
/
build.zig
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
const std = @import("std");
const Build = std.Build;
const Flags = struct {
/// Whether or not to enable the Spall profiler
spall: bool = false,
/// Whether or not to enable the Tracy profiler
tracy: bool = false,
/// Whether or not to enable TSan for race detection,
/// lock inversion reports, thread leaks, etc.
race: bool = false,
/// Indicates that the binary being build will ship to customers
/// and should be hardened appropriately
release: bool = false,
/// Whether or not to build the binary with LLVM enabled. We need
/// LLVM for TSan.
llvm: bool = false,
};
pub fn build(b: *Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
//
// Define command line flags
//
const opts = b.addOptions();
var flags = Flags{};
const ci = b.option(bool, "ci", "True if running tests in CI (default: false)") orelse false;
opts.addOption(bool, "ci", ci);
const test_filter: ?[]const u8 = b.option([]const u8, "filter", "Filter running tests down to just the given name (default: null)") orelse null;
const imgui_demo = b.option(bool, "imgui-demo", "Show the IMGUI Demo, available in debug builds only (default: false)") orelse false;
opts.addOption(bool, "imgui_demo", imgui_demo);
flags.release = b.option(bool, "release", "Hardens the binary for production release to users (default: false)") orelse false;
opts.addOption(bool, "release", flags.release);
const reset_gui = b.option(bool, "reset-gui", "Delete the IMGUI config file on startup (default: false)") orelse false;
opts.addOption(bool, "reset_gui", reset_gui);
flags.spall = b.option(bool, "spall", "Enable spall (default: false)") orelse false;
opts.addOption(bool, "spall_enabled", flags.spall);
flags.tracy = b.option(bool, "tracy", "Enable tracy (default: false)") orelse false;
opts.addOption(bool, "tracy_enabled", flags.tracy);
flags.race = b.option(bool, "race", "Enable TSan (default: true)") orelse false;
opts.addOption(bool, "race", flags.race);
// @NOTE (jrc): swap to the self-hosted backend when it's more reliable
const llvm_default = true or flags.release or flags.race or flags.spall or flags.tracy or optimize != .Debug;
const llvm_help = try std.fmt.allocPrint(b.allocator, "Enable LLVM (default: {any})", .{llvm_default});
flags.llvm = b.option(bool, "llvm", llvm_help) orelse llvm_default;
opts.addOption(bool, "llvm", flags.llvm);
//
// Define all the possible executables and objects we'd ever want to build
//
// build and run the application
const run_exe = b.addExecutable(.{
.name = "uscope",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// build and run the tests
const test_exe = b.addTest(.{
.name = "uscope-tests",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.filters = if (test_filter) |f| &.{f} else &.{},
});
//
// Define the build steps and dependency graph using the
// set of exe's and obj's above
//
defineStep(b, stepDef{
.name = "run",
.description = "Build and run uscope",
.exes = &.{run_exe},
.opts = opts,
.flags = flags,
.target = target,
.optimize = optimize,
});
defineStep(b, stepDef{
.name = "test",
.description = "Build and run tests",
.exes = &.{test_exe},
.opts = opts,
.flags = flags,
.no_caching = true,
.target = target,
.optimize = optimize,
});
}
const stepDef = struct {
name: []const u8,
description: []const u8,
exes: []const *Build.Step.Compile,
depend_on: ?[]const *Build.Step = null,
opts: *Build.Step.Options,
flags: Flags,
no_caching: bool = false,
target: Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
};
fn defineStep(b: *Build, def: stepDef) void {
for (def.exes) |exe| {
const is_debug = exe.root_module.optimize == .Debug;
b.installArtifact(exe);
exe.linkLibC();
exe.root_module.addOptions("build_options", def.opts);
exe.use_llvm = def.flags.llvm;
exe.use_lld = def.flags.llvm;
exe.root_module.omit_frame_pointer = false;
exe.root_module.stack_check = !is_debug;
exe.root_module.stack_protector = !is_debug;
exe.root_module.sanitize_c = is_debug;
exe.root_module.sanitize_thread = def.flags.race;
exe.root_module.strip = def.flags.release;
const step = b.step(def.name, def.description);
if (def.depend_on != null) {
for (def.depend_on.?) |dep| step.dependOn(dep);
}
const cmd = b.addRunArtifact(exe);
if (def.no_caching) cmd.has_side_effects = true;
if (b.args) |args| cmd.addArgs(args);
step.dependOn(&cmd.step);
//
// Set up module dependencies
//
exe.root_module.addIncludePath(b.path("libs/stb_image"));
exe.addCSourceFile(.{ .file = b.path("libs/stb_image/stb_image.c") });
exe.root_module.addIncludePath(b.path("libs/spall"));
const time_dep = b.dependency("time", .{});
const time_mod = time_dep.module("time");
exe.root_module.addImport("time", time_mod);
const cimgui_dep = b.dependency("cimgui", .{
.target = def.target,
.optimize = def.optimize,
});
exe.root_module.addImport("cimgui", cimgui_dep.module("cimgui"));
exe.linkLibrary(cimgui_dep.artifact("cimgui"));
if (b.lazyDependency("system_sdk", .{})) |system_sdk| {
exe.addLibraryPath(system_sdk.path("linux/lib/x86_64-linux-gnu"));
}
const zglfw = b.dependency("zglfw", .{
.target = def.target,
.optimize = def.optimize,
});
exe.root_module.addImport("zglfw", zglfw.module("root"));
exe.linkLibrary(zglfw.artifact("glfw"));
const zopengl = b.dependency("zopengl", .{});
exe.root_module.addImport("zopengl", zopengl.module("root"));
const ztracy = b.dependency("ztracy", .{
.enable_ztracy = def.flags.tracy,
.target = def.target,
.optimize = def.optimize,
});
exe.root_module.addImport("ztracy", ztracy.module("root"));
exe.linkLibrary(ztracy.artifact("tracy"));
}
}