lib/gpalloc/src/profiling/setup/install.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const sys = @import("sys");
3
4 const host = @import("host.zig");
5 const options_module = @import("options.zig");
6 const output = @import("output.zig");
7
8 const required_tools = [_][]const u8{ "git", "cmake", "make", "cc" };
9
10 pub fn run(
11 allocator: std.mem.Allocator,
12 process_io: std.Io,
13 env: *const sys.process.Environ.Map,
14 stdout: *std.Io.Writer,
15 stderr: *std.Io.Writer,
16 options: options_module.Options,
17 ) !u8 {
18 const suite_url = options.suite_url orelse
19 env.get("TINYALLOC_ALLOCATOR_SUITE_URL") orelse
20 options_module.default_suite_url;
21 const procs = options.procs orelse
22 env.get("TINYALLOC_ALLOCATOR_PROCS") orelse
23 try host.procs(allocator, process_io);
24
25 if (!options.dry_run) {
26 if (try missingTool(allocator, env)) |tool| {
27 try output.writePrettyFmt(
28 allocator,
29 stderr,
30 "gpalloc allocators: required tool not found on PATH: {s}\n",
31 .{tool},
32 );
33 return 1;
34 }
35 }
36
37 if (try ensureCheckout(allocator, process_io, stdout, options, suite_url)) |status| {
38 return status;
39 }
40 return try buildSuite(allocator, process_io, stdout, options, procs);
41 }
42
43 fn missingTool(
44 allocator: std.mem.Allocator,
45 env: *const sys.process.Environ.Map,
46 ) !?[]const u8 {
47 for (required_tools) |tool| {
48 if (!try host.commandOnPath(allocator, env, tool)) return tool;
49 }
50 return null;
51 }
52
53 fn ensureCheckout(
54 allocator: std.mem.Allocator,
55 process_io: std.Io,
56 stdout: *std.Io.Writer,
57 options: options_module.Options,
58 suite_url: []const u8,
59 ) !?u8 {
60 const git_dir = try std.fs.path.join(allocator, &.{ options.suite_dir, ".git" });
61 defer allocator.free(git_dir);
62 if (host.isDir(git_dir)) return null;
63
64 if (std.fs.path.dirname(options.suite_dir)) |parent| {
65 if (!options.dry_run) try sys.fs.createDirPath(parent);
66 }
67 try output.writePrettyFmt(
68 allocator,
69 stdout,
70 "gpalloc allocators: cloning {s} -> {s}\n",
71 .{ suite_url, options.suite_dir },
72 );
73 const clone_argv = [_][]const u8{
74 "git",
75 "clone",
76 "--depth",
77 "1",
78 suite_url,
79 options.suite_dir,
80 };
81 if (options.dry_run) {
82 try output.writeShellCommand(stdout, &clone_argv);
83 return null;
84 }
85
86 try stdout.flush();
87 const status = try host.runInherited(process_io, null, &clone_argv);
88 if (status != 0) return status;
89 return null;
90 }
91
92 fn buildSuite(
93 allocator: std.mem.Allocator,
94 process_io: std.Io,
95 stdout: *std.Io.Writer,
96 options: options_module.Options,
97 procs: []const u8,
98 ) !u8 {
99 try output.writeBuildLine(allocator, stdout, options);
100 const procs_arg = try std.fmt.allocPrint(allocator, "--procs={s}", .{procs});
101 defer allocator.free(procs_arg);
102 var build_argv: std.ArrayList([]const u8) = .empty;
103 defer build_argv.deinit(allocator);
104 try build_argv.append(allocator, "./build-bench-env.sh");
105 for (options.allocators) |name| try build_argv.append(allocator, name);
106 try build_argv.append(allocator, procs_arg);
107 if (options.dry_run) {
108 try output.writeShellCommand(stdout, build_argv.items);
109 return 0;
110 }
111
112 try stdout.flush();
113 const build_status = try host.runInherited(process_io, options.suite_dir, build_argv.items);
114 if (build_status == 0) {
115 try output.writePrettyFmt(
116 allocator,
117 stdout,
118 "gpalloc allocators: libraries are under {s}/extern\n",
119 .{options.suite_dir},
120 );
121 }
122 return build_status;
123 }