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 {...@@ -92,23 +92,23 @@ pub fn main() !void {
92 // before arg parsing, check for the NO_COLOR environment variable92 // before arg parsing, check for the NO_COLOR environment variable
93 // if it exists, default the color setting to .off93 // if it exists, default the color setting to .off
94 // explicit --color arguments will still override this setting.94 // 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
97 while (nextArg(args, &arg_idx)) |arg| {97 while (nextArg(args, &arg_idx)) |arg| {
98 if (mem.startsWith(u8, arg, "-D")) {98 if (mem.startsWith(u8, arg, "-D")) {
99 const option_contents = arg[2..];99 const option_contents = arg[2..];
100 if (option_contents.len == 0) {100 if (option_contents.len == 0) {
101 std.debug.print("Expected option name after '-D'\n\n", .{});101 std.debug.print("Expected option name after '-D'\n\n", .{});
102 return usageAndErr(builder, false, stderr_stream);102 usageAndErr(builder, false, stderr_stream);
103 }103 }
104 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {104 if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
105 const option_name = option_contents[0..name_end];105 const option_name = option_contents[0..name_end];
106 const option_value = option_contents[name_end + 1 ..];106 const option_value = option_contents[name_end + 1 ..];
107 if (try builder.addUserInputOption(option_name, option_value))107 if (try builder.addUserInputOption(option_name, option_value))
108 return usageAndErr(builder, false, stderr_stream);108 usageAndErr(builder, false, stderr_stream);
109 } else {109 } else {
110 if (try builder.addUserInputFlag(option_contents))110 if (try builder.addUserInputFlag(option_contents))
111 return usageAndErr(builder, false, stderr_stream);111 usageAndErr(builder, false, stderr_stream);
112 }112 }
113 } else if (mem.startsWith(u8, arg, "-")) {113 } else if (mem.startsWith(u8, arg, "-")) {
114 if (mem.eql(u8, arg, "--verbose")) {114 if (mem.eql(u8, arg, "--verbose")) {
...@@ -118,61 +118,61 @@ pub fn main() !void {...@@ -118,61 +118,61 @@ pub fn main() !void {
118 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {118 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
119 install_prefix = nextArg(args, &arg_idx) orelse {119 install_prefix = nextArg(args, &arg_idx) orelse {
120 std.debug.print("Expected argument after {s}\n\n", .{arg});120 std.debug.print("Expected argument after {s}\n\n", .{arg});
121 return usageAndErr(builder, false, stderr_stream);121 usageAndErr(builder, false, stderr_stream);
122 };122 };
123 } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {123 } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {
124 return steps(builder, false, stdout_stream);124 return steps(builder, false, stdout_stream);
125 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {125 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
126 dir_list.lib_dir = nextArg(args, &arg_idx) orelse {126 dir_list.lib_dir = nextArg(args, &arg_idx) orelse {
127 std.debug.print("Expected argument after {s}\n\n", .{arg});127 std.debug.print("Expected argument after {s}\n\n", .{arg});
128 return usageAndErr(builder, false, stderr_stream);128 usageAndErr(builder, false, stderr_stream);
129 };129 };
130 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {130 } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
131 dir_list.exe_dir = nextArg(args, &arg_idx) orelse {131 dir_list.exe_dir = nextArg(args, &arg_idx) orelse {
132 std.debug.print("Expected argument after {s}\n\n", .{arg});132 std.debug.print("Expected argument after {s}\n\n", .{arg});
133 return usageAndErr(builder, false, stderr_stream);133 usageAndErr(builder, false, stderr_stream);
134 };134 };
135 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {135 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {
136 dir_list.include_dir = nextArg(args, &arg_idx) orelse {136 dir_list.include_dir = nextArg(args, &arg_idx) orelse {
137 std.debug.print("Expected argument after {s}\n\n", .{arg});137 std.debug.print("Expected argument after {s}\n\n", .{arg});
138 return usageAndErr(builder, false, stderr_stream);138 usageAndErr(builder, false, stderr_stream);
139 };139 };
140 } else if (mem.eql(u8, arg, "--sysroot")) {140 } else if (mem.eql(u8, arg, "--sysroot")) {
141 const sysroot = nextArg(args, &arg_idx) orelse {141 const sysroot = nextArg(args, &arg_idx) orelse {
142 std.debug.print("Expected argument after --sysroot\n\n", .{});142 std.debug.print("Expected argument after --sysroot\n\n", .{});
143 return usageAndErr(builder, false, stderr_stream);143 usageAndErr(builder, false, stderr_stream);
144 };144 };
145 builder.sysroot = sysroot;145 builder.sysroot = sysroot;
146 } else if (mem.eql(u8, arg, "--search-prefix")) {146 } else if (mem.eql(u8, arg, "--search-prefix")) {
147 const search_prefix = nextArg(args, &arg_idx) orelse {147 const search_prefix = nextArg(args, &arg_idx) orelse {
148 std.debug.print("Expected argument after --search-prefix\n\n", .{});148 std.debug.print("Expected argument after --search-prefix\n\n", .{});
149 return usageAndErr(builder, false, stderr_stream);149 usageAndErr(builder, false, stderr_stream);
150 };150 };
151 builder.addSearchPrefix(search_prefix);151 builder.addSearchPrefix(search_prefix);
152 } else if (mem.eql(u8, arg, "--libc")) {152 } else if (mem.eql(u8, arg, "--libc")) {
153 const libc_file = nextArg(args, &arg_idx) orelse {153 const libc_file = nextArg(args, &arg_idx) orelse {
154 std.debug.print("Expected argument after --libc\n\n", .{});154 std.debug.print("Expected argument after --libc\n\n", .{});
155 return usageAndErr(builder, false, stderr_stream);155 usageAndErr(builder, false, stderr_stream);
156 };156 };
157 builder.libc_file = libc_file;157 builder.libc_file = libc_file;
158 } else if (mem.eql(u8, arg, "--color")) {158 } else if (mem.eql(u8, arg, "--color")) {
159 const next_arg = nextArg(args, &arg_idx) orelse {159 const next_arg = nextArg(args, &arg_idx) orelse {
160 std.debug.print("expected [auto|on|off] after --color", .{});160 std.debug.print("expected [auto|on|off] after --color", .{});
161 return usageAndErr(builder, false, stderr_stream);161 usageAndErr(builder, false, stderr_stream);
162 };162 };
163 builder.color = std.meta.stringToEnum(@TypeOf(builder.color), next_arg) orelse {163 builder.color = std.meta.stringToEnum(@TypeOf(builder.color), next_arg) orelse {
164 std.debug.print("expected [auto|on|off] after --color, found '{s}'", .{next_arg});164 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);
166 };166 };
167 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {167 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
168 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {168 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {
169 std.debug.print("Expected argument after --zig-lib-dir\n\n", .{});169 std.debug.print("Expected argument after --zig-lib-dir\n\n", .{});
170 return usageAndErr(builder, false, stderr_stream);170 usageAndErr(builder, false, stderr_stream);
171 };171 };
172 } else if (mem.eql(u8, arg, "--debug-log")) {172 } else if (mem.eql(u8, arg, "--debug-log")) {
173 const next_arg = nextArg(args, &arg_idx) orelse {173 const next_arg = nextArg(args, &arg_idx) orelse {
174 std.debug.print("Expected argument after {s}\n\n", .{arg});174 std.debug.print("Expected argument after {s}\n\n", .{arg});
175 return usageAndErr(builder, false, stderr_stream);175 usageAndErr(builder, false, stderr_stream);
176 };176 };
177 try debug_log_scopes.append(next_arg);177 try debug_log_scopes.append(next_arg);
178 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {178 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
...@@ -180,7 +180,7 @@ pub fn main() !void {...@@ -180,7 +180,7 @@ pub fn main() !void {
180 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {180 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
181 builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse {181 builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse {
182 std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});182 std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});
183 return usageAndErr(builder, false, stderr_stream);183 usageAndErr(builder, false, stderr_stream);
184 };184 };
185 } else if (mem.eql(u8, arg, "--verbose-link")) {185 } else if (mem.eql(u8, arg, "--verbose-link")) {
186 builder.verbose_link = true;186 builder.verbose_link = true;
...@@ -231,7 +231,7 @@ pub fn main() !void {...@@ -231,7 +231,7 @@ pub fn main() !void {
231 break;231 break;
232 } else {232 } else {
233 std.debug.print("Unrecognized argument: {s}\n\n", .{arg});233 std.debug.print("Unrecognized argument: {s}\n\n", .{arg});
234 return usageAndErr(builder, false, stderr_stream);234 usageAndErr(builder, false, stderr_stream);
235 }235 }
236 } else {236 } else {
237 try targets.append(arg);237 try targets.append(arg);
...@@ -243,13 +243,10 @@ pub fn main() !void {...@@ -243,13 +243,10 @@ pub fn main() !void {
243 try builder.runBuild(root);243 try builder.runBuild(root);
244244
245 if (builder.validateUserInputDidItFail())245 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| {
249 switch (err) {249 switch (err) {
250 error.InvalidStepName => {
251 return usageAndErr(builder, true, stderr_stream);
252 },
253 error.UncleanExit => process.exit(1),250 error.UncleanExit => process.exit(1),
254 // This error is intended to indicate that the step has already251 // This error is intended to indicate that the step has already
255 // logged an error message and so printing the error return trace252 // logged an error message and so printing the error return trace
...@@ -261,6 +258,48 @@ pub fn main() !void {...@@ -261,6 +258,48 @@ pub fn main() !void {
261 };258 };
262}259}
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
264fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void {303fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void {
265 // run the build script to collect the options304 // run the build script to collect the options
266 if (!already_ran_build) {305 if (!already_ran_build) {
...@@ -269,7 +308,7 @@ fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi...@@ -269,7 +308,7 @@ fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
269 }308 }
270309
271 const allocator = builder.allocator;310 const allocator = builder.allocator;
272 for (builder.top_level_steps.items) |top_level_step| {311 for (builder.top_level_steps.values()) |top_level_step| {
273 const name = if (&top_level_step.step == builder.default_step)312 const name = if (&top_level_step.step == builder.default_step)
274 try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})313 try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})
275 else314 else
...@@ -374,7 +413,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi...@@ -374,7 +413,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
374 );413 );
375}414}
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 {
378 usage(builder, already_ran_build, out_stream) catch {};417 usage(builder, already_ran_build, out_stream) catch {};
379 process.exit(1);418 process.exit(1);
380}419}
lib/std/Build.zig+12-61
...@@ -67,7 +67,7 @@ invalid_user_input: bool,...@@ -67,7 +67,7 @@ invalid_user_input: bool,
67zig_exe: []const u8,67zig_exe: []const u8,
68default_step: *Step,68default_step: *Step,
69env_map: *EnvMap,69env_map: *EnvMap,
70top_level_steps: ArrayList(*TopLevelStep),70top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
71install_prefix: []const u8,71install_prefix: []const u8,
72dest_dir: ?[]const u8,72dest_dir: ?[]const u8,
73lib_dir: []const u8,73lib_dir: []const u8,
...@@ -217,7 +217,7 @@ pub fn create(...@@ -217,7 +217,7 @@ pub fn create(
217 .user_input_options = UserInputOptionsMap.init(allocator),217 .user_input_options = UserInputOptionsMap.init(allocator),
218 .available_options_map = AvailableOptionsMap.init(allocator),218 .available_options_map = AvailableOptionsMap.init(allocator),
219 .available_options_list = ArrayList(AvailableOption).init(allocator),219 .available_options_list = ArrayList(AvailableOption).init(allocator),
220 .top_level_steps = ArrayList(*TopLevelStep).init(allocator),220 .top_level_steps = .{},
221 .default_step = undefined,221 .default_step = undefined,
222 .env_map = env_map,222 .env_map = env_map,
223 .search_prefixes = ArrayList([]const u8).init(allocator),223 .search_prefixes = ArrayList([]const u8).init(allocator),
...@@ -241,8 +241,8 @@ pub fn create(...@@ -241,8 +241,8 @@ pub fn create(
241 .host = host,241 .host = host,
242 .modules = std.StringArrayHashMap(*Module).init(allocator),242 .modules = std.StringArrayHashMap(*Module).init(allocator),
243 };243 };
244 try self.top_level_steps.append(&self.install_tls);244 try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls);
245 try self.top_level_steps.append(&self.uninstall_tls);245 try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls);
246 self.default_step = &self.install_tls.step;246 self.default_step = &self.install_tls.step;
247 return self;247 return self;
248}248}
...@@ -288,7 +288,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc...@@ -288,7 +288,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
288 .zig_exe = parent.zig_exe,288 .zig_exe = parent.zig_exe,
289 .default_step = undefined,289 .default_step = undefined,
290 .env_map = parent.env_map,290 .env_map = parent.env_map,
291 .top_level_steps = ArrayList(*TopLevelStep).init(allocator),291 .top_level_steps = .{},
292 .install_prefix = undefined,292 .install_prefix = undefined,
293 .dest_dir = parent.dest_dir,293 .dest_dir = parent.dest_dir,
294 .lib_dir = parent.lib_dir,294 .lib_dir = parent.lib_dir,
...@@ -316,8 +316,8 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc...@@ -316,8 +316,8 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
316 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),316 .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
317 .modules = std.StringArrayHashMap(*Module).init(allocator),317 .modules = std.StringArrayHashMap(*Module).init(allocator),
318 };318 };
319 try child.top_level_steps.append(&child.install_tls);319 try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
320 try child.top_level_steps.append(&child.uninstall_tls);320 try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
321 child.default_step = &child.install_tls.step;321 child.default_step = &child.install_tls.step;
322 return child;322 return child;
323}323}
...@@ -389,10 +389,10 @@ fn applyArgs(b: *Build, args: anytype) !void {...@@ -389,10 +389,10 @@ fn applyArgs(b: *Build, args: anytype) !void {
389 b.resolveInstallPrefix(install_prefix, .{});389 b.resolveInstallPrefix(install_prefix, .{});
390}390}
391391
392pub fn destroy(self: *Build) void {392pub fn destroy(b: *Build) void {
393 self.env_map.deinit();393 b.env_map.deinit();
394 self.top_level_steps.deinit();394 b.top_level_steps.deinit(b.allocator);
395 self.allocator.destroy(self);395 b.allocator.destroy(b);
396}396}
397397
398/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.398/// 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...@@ -698,24 +698,6 @@ pub fn addTranslateC(self: *Build, options: TranslateCStep.Options) *TranslateCS
698 return TranslateCStep.create(self, options);698 return TranslateCStep.create(self, options);
699}699}
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
719pub fn getInstallStep(self: *Build) *Step {701pub fn getInstallStep(self: *Build) *Step {
720 return &self.install_tls.step;702 return &self.install_tls.step;
721}703}
...@@ -739,37 +721,6 @@ fn makeUninstall(uninstall_step: *Step) anyerror!void {...@@ -739,37 +721,6 @@ fn makeUninstall(uninstall_step: *Step) anyerror!void {
739 // TODO remove empty directories721 // TODO remove empty directories
740}722}
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
773pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {724pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
774 const name = self.dupe(name_raw);725 const name = self.dupe(name_raw);
775 const description = self.dupe(description_raw);726 const description = self.dupe(description_raw);
...@@ -910,7 +861,7 @@ pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {...@@ -910,7 +861,7 @@ pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {
910 .step = Step.initNoOp(.top_level, name, self.allocator),861 .step = Step.initNoOp(.top_level, name, self.allocator),
911 .description = self.dupe(description),862 .description = self.dupe(description),
912 };863 };
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");
914 return &step_info.step;865 return &step_info.step;
915}866}
916867