authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-13 13:10:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:12-07:00
logc6a895f6671d30e2db77ae4f4e0c2d9e40624787
tree7b3feb506d66860f14e64e08c26f2aa333b3d0ca
parenta2c6ecd6dc0bdbe2396be9b055852324f16d34c9

extract some logic from std.Build to build_runner.zig


2 files changed, 75 insertions(+), 85 deletions(-)

lib/build_runner.zig+63-24
......@@ -92,23 +92,23 @@ pub fn main() !void {
9292 // before arg parsing, check for the NO_COLOR environment variable
9393 // if it exists, default the color setting to .off
9494 // explicit --color arguments will still override this setting.
95 builder.color = if (std.process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
95 builder.color = if (process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
9696
9797 while (nextArg(args, &arg_idx)) |arg| {
9898 if (mem.startsWith(u8, arg, "-D")) {
9999 const option_contents = arg[2..];
100100 if (option_contents.len == 0) {
101101 std.debug.print("Expected option name after '-D'\n\n", .{});
102 return usageAndErr(builder, false, stderr_stream);
102 usageAndErr(builder, false, stderr_stream);
103103 }
104104 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
105105 const option_name = option_contents[0..name_end];
106106 const option_value = option_contents[name_end + 1 ..];
107107 if (try builder.addUserInputOption(option_name, option_value))
108 return usageAndErr(builder, false, stderr_stream);
108 usageAndErr(builder, false, stderr_stream);
109109 } else {
110110 if (try builder.addUserInputFlag(option_contents))
111 return usageAndErr(builder, false, stderr_stream);
111 usageAndErr(builder, false, stderr_stream);
112112 }
113113 } else if (mem.startsWith(u8, arg, "-")) {
114114 if (mem.eql(u8, arg, "--verbose")) {
......@@ -118,61 +118,61 @@ pub fn main() !void {
118118 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
119119 install_prefix = nextArg(args, &arg_idx) orelse {
120120 std.debug.print("Expected argument after {s}\n\n", .{arg});
121 return usageAndErr(builder, false, stderr_stream);
121 usageAndErr(builder, false, stderr_stream);
122122 };
123123 } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {
124124 return steps(builder, false, stdout_stream);
125125 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
126126 dir_list.lib_dir = nextArg(args, &arg_idx) orelse {
127127 std.debug.print("Expected argument after {s}\n\n", .{arg});
128 return usageAndErr(builder, false, stderr_stream);
128 usageAndErr(builder, false, stderr_stream);
129129 };
130130 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
131131 dir_list.exe_dir = nextArg(args, &arg_idx) orelse {
132132 std.debug.print("Expected argument after {s}\n\n", .{arg});
133 return usageAndErr(builder, false, stderr_stream);
133 usageAndErr(builder, false, stderr_stream);
134134 };
135135 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {
136136 dir_list.include_dir = nextArg(args, &arg_idx) orelse {
137137 std.debug.print("Expected argument after {s}\n\n", .{arg});
138 return usageAndErr(builder, false, stderr_stream);
138 usageAndErr(builder, false, stderr_stream);
139139 };
140140 } else if (mem.eql(u8, arg, "--sysroot")) {
141141 const sysroot = nextArg(args, &arg_idx) orelse {
142142 std.debug.print("Expected argument after --sysroot\n\n", .{});
143 return usageAndErr(builder, false, stderr_stream);
143 usageAndErr(builder, false, stderr_stream);
144144 };
145145 builder.sysroot = sysroot;
146146 } else if (mem.eql(u8, arg, "--search-prefix")) {
147147 const search_prefix = nextArg(args, &arg_idx) orelse {
148148 std.debug.print("Expected argument after --search-prefix\n\n", .{});
149 return usageAndErr(builder, false, stderr_stream);
149 usageAndErr(builder, false, stderr_stream);
150150 };
151151 builder.addSearchPrefix(search_prefix);
152152 } else if (mem.eql(u8, arg, "--libc")) {
153153 const libc_file = nextArg(args, &arg_idx) orelse {
154154 std.debug.print("Expected argument after --libc\n\n", .{});
155 return usageAndErr(builder, false, stderr_stream);
155 usageAndErr(builder, false, stderr_stream);
156156 };
157157 builder.libc_file = libc_file;
158158 } else if (mem.eql(u8, arg, "--color")) {
159159 const next_arg = nextArg(args, &arg_idx) orelse {
160160 std.debug.print("expected [auto|on|off] after --color", .{});
161 return usageAndErr(builder, false, stderr_stream);
161 usageAndErr(builder, false, stderr_stream);
162162 };
163163 builder.color = std.meta.stringToEnum(@TypeOf(builder.color), next_arg) orelse {
164164 std.debug.print("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
165 return usageAndErr(builder, false, stderr_stream);
165 usageAndErr(builder, false, stderr_stream);
166166 };
167167 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
168168 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {
169169 std.debug.print("Expected argument after --zig-lib-dir\n\n", .{});
170 return usageAndErr(builder, false, stderr_stream);
170 usageAndErr(builder, false, stderr_stream);
171171 };
172172 } else if (mem.eql(u8, arg, "--debug-log")) {
173173 const next_arg = nextArg(args, &arg_idx) orelse {
174174 std.debug.print("Expected argument after {s}\n\n", .{arg});
175 return usageAndErr(builder, false, stderr_stream);
175 usageAndErr(builder, false, stderr_stream);
176176 };
177177 try debug_log_scopes.append(next_arg);
178178 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
......@@ -180,7 +180,7 @@ pub fn main() !void {
180180 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
181181 builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse {
182182 std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});
183 return usageAndErr(builder, false, stderr_stream);
183 usageAndErr(builder, false, stderr_stream);
184184 };
185185 } else if (mem.eql(u8, arg, "--verbose-link")) {
186186 builder.verbose_link = true;
......@@ -231,7 +231,7 @@ pub fn main() !void {
231231 break;
232232 } else {
233233 std.debug.print("Unrecognized argument: {s}\n\n", .{arg});
234 return usageAndErr(builder, false, stderr_stream);
234 usageAndErr(builder, false, stderr_stream);
235235 }
236236 } else {
237237 try targets.append(arg);
......@@ -243,13 +243,10 @@ pub fn main() !void {
243243 try builder.runBuild(root);
244244
245245 if (builder.validateUserInputDidItFail())
246 return usageAndErr(builder, true, stderr_stream);
246 usageAndErr(builder, true, stderr_stream);
247247
248 builder.make(targets.items) catch |err| {
248 make(builder, targets.items) catch |err| {
249249 switch (err) {
250 error.InvalidStepName => {
251 return usageAndErr(builder, true, stderr_stream);
252 },
253250 error.UncleanExit => process.exit(1),
254251 // This error is intended to indicate that the step has already
255252 // logged an error message and so printing the error return trace
......@@ -261,6 +258,48 @@ pub fn main() !void {
261258 };
262259}
263260
261fn make(b: *std.Build, step_names: []const []const u8) !void {
262 var wanted_steps = ArrayList(*std.Build.Step).init(b.allocator);
263 defer wanted_steps.deinit();
264
265 if (step_names.len == 0) {
266 try wanted_steps.append(b.default_step);
267 } else {
268 for (step_names) |step_name| {
269 const s = b.top_level_steps.get(step_name) orelse {
270 std.debug.print("no step named '{s}'. Access the help menu with 'zig build -h'\n", .{step_name});
271 process.exit(1);
272 };
273 try wanted_steps.append(&s.step);
274 }
275 }
276
277 for (wanted_steps.items) |s| {
278 try makeOneStep(b, s);
279 }
280}
281
282fn makeOneStep(b: *std.Build, s: *std.Build.Step) anyerror!void {
283 if (s.loop_flag) {
284 std.debug.print("dependency loop detected:\n {s}\n", .{s.name});
285 return error.DependencyLoopDetected;
286 }
287 s.loop_flag = true;
288
289 for (s.dependencies.items) |dep| {
290 makeOneStep(b, dep) catch |err| {
291 if (err == error.DependencyLoopDetected) {
292 std.debug.print(" {s}\n", .{s.name});
293 }
294 return err;
295 };
296 }
297
298 s.loop_flag = false;
299
300 try s.make();
301}
302
264303fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void {
265304 // run the build script to collect the options
266305 if (!already_ran_build) {
......@@ -269,7 +308,7 @@ fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
269308 }
270309
271310 const allocator = builder.allocator;
272 for (builder.top_level_steps.items) |top_level_step| {
311 for (builder.top_level_steps.values()) |top_level_step| {
273312 const name = if (&top_level_step.step == builder.default_step)
274313 try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})
275314 else
......@@ -374,7 +413,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
374413 );
375414}
376415
377fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) void {
416fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) noreturn {
378417 usage(builder, already_ran_build, out_stream) catch {};
379418 process.exit(1);
380419}
lib/std/Build.zig+12-61
......@@ -67,7 +67,7 @@ invalid_user_input: bool,
6767zig_exe: []const u8,
6868default_step: *Step,
6969env_map: *EnvMap,
70top_level_steps: ArrayList(*TopLevelStep),
70top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
7171install_prefix: []const u8,
7272dest_dir: ?[]const u8,
7373lib_dir: []const u8,
......@@ -217,7 +217,7 @@ pub fn create(
217217 .user_input_options = UserInputOptionsMap.init(allocator),
218218 .available_options_map = AvailableOptionsMap.init(allocator),
219219 .available_options_list = ArrayList(AvailableOption).init(allocator),
220 .top_level_steps = ArrayList(*TopLevelStep).init(allocator),
220 .top_level_steps = .{},
221221 .default_step = undefined,
222222 .env_map = env_map,
223223 .search_prefixes = ArrayList([]const u8).init(allocator),
......@@ -241,8 +241,8 @@ pub fn create(
241241 .host = host,
242242 .modules = std.StringArrayHashMap(*Module).init(allocator),
243243 };
244 try self.top_level_steps.append(&self.install_tls);
245 try self.top_level_steps.append(&self.uninstall_tls);
244 try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls);
245 try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls);
246246 self.default_step = &self.install_tls.step;
247247 return self;
248248}
......@@ -288,7 +288,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
288288 .zig_exe = parent.zig_exe,
289289 .default_step = undefined,
290290 .env_map = parent.env_map,
291 .top_level_steps = ArrayList(*TopLevelStep).init(allocator),
291 .top_level_steps = .{},
292292 .install_prefix = undefined,
293293 .dest_dir = parent.dest_dir,
294294 .lib_dir = parent.lib_dir,
......@@ -316,8 +316,8 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
316316 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
317317 .modules = std.StringArrayHashMap(*Module).init(allocator),
318318 };
319 try child.top_level_steps.append(&child.install_tls);
320 try child.top_level_steps.append(&child.uninstall_tls);
319 try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
320 try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
321321 child.default_step = &child.install_tls.step;
322322 return child;
323323}
......@@ -389,10 +389,10 @@ fn applyArgs(b: *Build, args: anytype) !void {
389389 b.resolveInstallPrefix(install_prefix, .{});
390390}
391391
392pub fn destroy(self: *Build) void {
393 self.env_map.deinit();
394 self.top_level_steps.deinit();
395 self.allocator.destroy(self);
392pub fn destroy(b: *Build) void {
393 b.env_map.deinit();
394 b.top_level_steps.deinit(b.allocator);
395 b.allocator.destroy(b);
396396}
397397
398398/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
......@@ -698,24 +698,6 @@ pub fn addTranslateC(self: *Build, options: TranslateCStep.Options) *TranslateCS
698698 return TranslateCStep.create(self, options);
699699}
700700
701pub fn make(self: *Build, step_names: []const []const u8) !void {
702 var wanted_steps = ArrayList(*Step).init(self.allocator);
703 defer wanted_steps.deinit();
704
705 if (step_names.len == 0) {
706 try wanted_steps.append(self.default_step);
707 } else {
708 for (step_names) |step_name| {
709 const s = try self.getTopLevelStepByName(step_name);
710 try wanted_steps.append(s);
711 }
712 }
713
714 for (wanted_steps.items) |s| {
715 try self.makeOneStep(s);
716 }
717}
718
719701pub fn getInstallStep(self: *Build) *Step {
720702 return &self.install_tls.step;
721703}
......@@ -739,37 +721,6 @@ fn makeUninstall(uninstall_step: *Step) anyerror!void {
739721 // TODO remove empty directories
740722}
741723
742fn makeOneStep(self: *Build, s: *Step) anyerror!void {
743 if (s.loop_flag) {
744 log.err("Dependency loop detected:\n {s}", .{s.name});
745 return error.DependencyLoopDetected;
746 }
747 s.loop_flag = true;
748
749 for (s.dependencies.items) |dep| {
750 self.makeOneStep(dep) catch |err| {
751 if (err == error.DependencyLoopDetected) {
752 log.err(" {s}", .{s.name});
753 }
754 return err;
755 };
756 }
757
758 s.loop_flag = false;
759
760 try s.make();
761}
762
763fn getTopLevelStepByName(self: *Build, name: []const u8) !*Step {
764 for (self.top_level_steps.items) |top_level_step| {
765 if (mem.eql(u8, top_level_step.step.name, name)) {
766 return &top_level_step.step;
767 }
768 }
769 log.err("Cannot run step '{s}' because it does not exist", .{name});
770 return error.InvalidStepName;
771}
772
773724pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
774725 const name = self.dupe(name_raw);
775726 const description = self.dupe(description_raw);
......@@ -910,7 +861,7 @@ pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {
910861 .step = Step.initNoOp(.top_level, name, self.allocator),
911862 .description = self.dupe(description),
912863 };
913 self.top_level_steps.append(step_info) catch @panic("OOM");
864 self.top_level_steps.put(self.allocator, step_info.step.name, step_info) catch @panic("OOM");
914865 return &step_info.step;
915866}
916867