-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.zig
171 lines (142 loc) · 5.72 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
const std = @import("std");
const builtin = @import("builtin");
const zvm_version = std.SemanticVersion.parse("0.2.14") catch unreachable;
pub fn build(b: *std.Build) void {
comptime {
const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse("0.11.0") catch unreachable;
if (current_zig.order(min_zig) == .lt) {
@compileError(std.fmt.comptimePrint("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig }));
}
}
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var allocator = gpa.allocator();
defer _ = gpa.deinit();
const options = b.addOptions();
const hash: ?[]const u8 = if (gitCommitHash(allocator)) |h| h[0..] else null;
options.addOption(?[]const u8, "git_commit_hash", hash);
options.addOption(?u32, "git_commit_count", gitCommitCount(allocator));
const branch = gitBranch(allocator);
options.addOption(?[]const u8, "git_branch", branch);
defer if (branch) |br| {
allocator.free(br);
};
const versionString = std.fmt.comptimePrint("{}", .{zvm_version});
options.addOption([]const u8, "version", versionString);
const isCi = blk: {
const ci = std.process.getEnvVarOwned(allocator, "CI") catch break :blk false;
defer allocator.free(ci);
break :blk std.mem.eql(u8, ci, "true");
};
options.addOption(bool, "is_ci", isCi);
options.addOption(?[DATE_SIZE]u8, "build_date", date(allocator) orelse null);
const known_folders_module = b.dependency("known_folders", .{}).module("known-folders");
const ansi_module = b.createModule(.{
.source_file = .{ .path = "src/ansi.zig" },
});
const zvm = b.addExecutable(.{
.name = "zvm",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
zvm.addModule("known-folders", known_folders_module);
zvm.addModule("ansi", ansi_module);
zvm.addOptions("zvm_build_options", options);
b.installArtifact(zvm);
const run_cmd = b.addRunArtifact(zvm);
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 test_step = b.step("test", "Run unit tests");
const arg_parser_test = registerTest(b, test_step, .{
.root_source_file = .{ .path = "src/arg_parser.zig" },
.target = target,
.optimize = optimize,
});
arg_parser_test.addModule("ansi", ansi_module);
_ = registerTest(b, test_step, .{
.root_source_file = .{ .path = "src/index.zig" },
.target = target,
.optimize = optimize,
});
_ = registerTest(b, test_step, .{
.root_source_file = .{ .path = "src/ansi.zig" },
.target = target,
.optimize = optimize,
});
_ = registerTest(b, test_step, .{
.root_source_file = .{ .path = "src/utils.zig" },
.target = target,
.optimize = optimize,
});
}
inline fn registerTest(b: *std.Build, step: *std.Build.Step, options: std.Build.TestOptions) *std.Build.CompileStep {
const exe_tests = b.addTest(options);
step.dependOn(&exe_tests.step);
return exe_tests;
}
fn gitCommitHash(allocator: std.mem.Allocator) ?[40]u8 {
const exec_result = std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &.{ "git", "rev-parse", "--verify", "HEAD" },
}) catch return null;
defer allocator.free(exec_result.stdout);
defer allocator.free(exec_result.stderr);
if (exec_result.term != .Exited or exec_result.term.Exited != 0) return null;
// +1 for trailing newline.
if (exec_result.stdout.len != 40 + 1) return null;
if (exec_result.stderr.len != 0) return null;
var output: [40]u8 = undefined;
std.mem.copy(u8, &output, exec_result.stdout[0..40]);
return output;
}
fn gitCommitCount(allocator: std.mem.Allocator) ?u32 {
const exec_result = std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &.{ "git", "rev-list", "--count", "HEAD" },
}) catch return null;
defer allocator.free(exec_result.stdout);
defer allocator.free(exec_result.stderr);
if (exec_result.term != .Exited or exec_result.term.Exited != 0) return null;
var number: u32 = 0;
for (exec_result.stdout) |c| {
switch (c) {
'\n' => break,
'0'...'9' => number = number * 10 + (c - '0'),
else => return null,
}
}
return number;
}
fn gitBranch(allocator: std.mem.Allocator) ?[]const u8 {
const exec_result = std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &.{ "git", "rev-parse", "--abbrev-ref", "HEAD" },
}) catch return null;
defer allocator.free(exec_result.stdout);
defer allocator.free(exec_result.stderr);
if (exec_result.stdout.len == 0) return null;
if (exec_result.stderr.len != 0) return null;
const idx = std.mem.indexOf(u8, exec_result.stdout[0..], "\n") orelse return null;
const allocated = allocator.alloc(u8, idx) catch return null;
std.mem.copy(u8, allocated, exec_result.stdout[0..allocated.len]);
return allocated;
}
const DATE_SIZE = 25;
fn date(allocator: std.mem.Allocator) ?[DATE_SIZE]u8 {
const exec_result = std.ChildProcess.exec(.{
.allocator = allocator,
.argv = &.{ "date", "+%Y-%m-%d %H:%M:%S %z" },
}) catch return null;
defer allocator.free(exec_result.stdout);
defer allocator.free(exec_result.stderr);
var output: [DATE_SIZE]u8 = undefined;
std.mem.copy(u8, &output, exec_result.stdout[0..DATE_SIZE]);
return output;
}