authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-19 13:50:56-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
log959103c3fd544abe06f32b279a6ebd1a3cd1f61b
tree40cec1c748381e2065bdd765367b80a587f8588e
parent6b7ce1fa22b301ac06d3bfa0a8938546966f684c

Maker.Step.Compile: progress towards lowering zig args


9 files changed, 409 insertions(+), 575 deletions(-)

lib/compiler/Maker.zig+48-41
...@@ -124,7 +124,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -124,7 +124,6 @@ pub fn main(init: process.Init.Minimal) !void {
124 graph.cache.hash.addBytes(builtin.zig_version_string);124 graph.cache.hash.addBytes(builtin.zig_version_string);
125125
126 var step_names: std.ArrayList([]const u8) = .empty;126 var step_names: std.ArrayList([]const u8) = .empty;
127 var debug_log_scopes: std.ArrayList([]const u8) = .empty;
128 var help_menu = false;127 var help_menu = false;
129 var steps_menu = false;128 var steps_menu = false;
130 var print_configuration = false;129 var print_configuration = false;
...@@ -143,10 +142,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -143,10 +142,6 @@ pub fn main(init: process.Init.Minimal) !void {
143 var fuzz: ?Fuzz.Mode = null;142 var fuzz: ?Fuzz.Mode = null;
144 var debounce_interval_ms: u16 = 50;143 var debounce_interval_ms: u16 = 50;
145 var webui_listen: ?Io.net.IpAddress = null;144 var webui_listen: ?Io.net.IpAddress = null;
146 var verbose = false;
147 var sysroot: ?[]const u8 = null;
148 var search_prefixes: std.ArrayList([]const u8) = .empty;
149 var libc_file: ?[]const u8 = null;
150 var debug_pkg_config: bool = false;145 var debug_pkg_config: bool = false;
151 // After following the steps in https://codeberg.org/ziglang/infra/src/branch/master/libc-update/glibc.md,146 // After following the steps in https://codeberg.org/ziglang/infra/src/branch/master/libc-update/glibc.md,
152 // this will be the directory $glibc-build-dir/install/glibcs147 // this will be the directory $glibc-build-dir/install/glibcs
...@@ -159,7 +154,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -159,7 +154,6 @@ pub fn main(init: process.Init.Minimal) !void {
159 var enable_wasmtime = false;154 var enable_wasmtime = false;
160 var enable_darling = false;155 var enable_darling = false;
161 var enable_rosetta = false;156 var enable_rosetta = false;
162 var reference_trace: ?u32 = null;
163 var run_args: ?[]const []const u8 = null;157 var run_args: ?[]const []const u8 = null;
164158
165 if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| {159 if (std.zig.EnvVar.ZIG_BUILD_ERROR_STYLE.get(&graph.environ_map)) |str| {
...@@ -182,8 +176,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -182,8 +176,6 @@ pub fn main(init: process.Init.Minimal) !void {
182 steps_menu = true;176 steps_menu = true;
183 } else if (mem.eql(u8, arg, "--print-configuration")) {177 } else if (mem.eql(u8, arg, "--print-configuration")) {
184 print_configuration = true;178 print_configuration = true;
185 } else if (mem.eql(u8, arg, "--verbose")) {
186 verbose = true;
187 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {179 } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
188 override_install_prefix = nextArgOrFatal(args, &arg_idx);180 override_install_prefix = nextArgOrFatal(args, &arg_idx);
189 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {181 } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
...@@ -193,11 +185,12 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -193,11 +185,12 @@ pub fn main(init: process.Init.Minimal) !void {
193 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {185 } else if (mem.eql(u8, arg, "--prefix-include-dir")) {
194 override_include_dir = nextArgOrFatal(args, &arg_idx);186 override_include_dir = nextArgOrFatal(args, &arg_idx);
195 } else if (mem.eql(u8, arg, "--sysroot")) {187 } else if (mem.eql(u8, arg, "--sysroot")) {
196 sysroot = nextArgOrFatal(args, &arg_idx);188 graph.sysroot = nextArgOrFatal(args, &arg_idx);
197 } else if (mem.eql(u8, arg, "--maxrss")) {189 } else if (mem.eql(u8, arg, "--maxrss")) {
190 // TODO refactor and reuse the fuzz number parsing here
198 const max_rss_text = nextArgOrFatal(args, &arg_idx);191 const max_rss_text = nextArgOrFatal(args, &arg_idx);
199 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err|192 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err|
200 fatal("invalid byte size: '{s}': {t}", .{ max_rss_text, err });193 fatal("invalid byte size {q}: {t}", .{ max_rss_text, err });
201 } else if (mem.eql(u8, arg, "--skip-oom-steps")) {194 } else if (mem.eql(u8, arg, "--skip-oom-steps")) {
202 skip_oom_steps = true;195 skip_oom_steps = true;
203 } else if (mem.eql(u8, arg, "--test-timeout")) {196 } else if (mem.eql(u8, arg, "--test-timeout")) {
...@@ -217,7 +210,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -217,7 +210,7 @@ pub fn main(init: process.Init.Minimal) !void {
217 };210 };
218 const timeout_str = nextArgOrFatal(args, &arg_idx);211 const timeout_str = nextArgOrFatal(args, &arg_idx);
219 const num_end_idx = std.mem.findLastNone(u8, timeout_str, "abcdefghijklmnopqrstuvwxyz") orelse fatal(212 const num_end_idx = std.mem.findLastNone(u8, timeout_str, "abcdefghijklmnopqrstuvwxyz") orelse fatal(
220 "invalid timeout '{s}': expected unit (ns, us, ms, s, m, h)",213 "invalid timeout {q}: expected unit (ns, us, ms, s, m, h)",
221 .{timeout_str},214 .{timeout_str},
222 );215 );
223 const num_str = timeout_str[0 .. num_end_idx + 1];216 const num_str = timeout_str[0 .. num_end_idx + 1];
...@@ -227,57 +220,63 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -227,57 +220,63 @@ pub fn main(init: process.Init.Minimal) !void {
227 break @floatFromInt(unit_and_factor[1]);220 break @floatFromInt(unit_and_factor[1]);
228 }221 }
229 } else fatal(222 } else fatal(
230 "invalid timeout '{s}': invalid unit '{s}' (expected ns, us, ms, s, m, h)",223 "invalid timeout {q}: invalid unit {q} (expected ns, us, ms, s, m, h)",
231 .{ timeout_str, unit_str },224 .{ timeout_str, unit_str },
232 );225 );
233 const num_parsed = std.fmt.parseFloat(f64, num_str) catch |err| fatal(226 const num_parsed = std.fmt.parseFloat(f64, num_str) catch |err| fatal(
234 "invalid timeout '{s}': invalid number '{s}' ({t})",227 "invalid timeout {q}: invalid number {q} ({t})",
235 .{ timeout_str, num_str, err },228 .{ timeout_str, num_str, err },
236 );229 );
237 test_timeout_ns = std.math.lossyCast(u64, unit_factor * num_parsed);230 test_timeout_ns = std.math.lossyCast(u64, unit_factor * num_parsed);
238 } else if (mem.eql(u8, arg, "--search-prefix")) {231 } else if (mem.eql(u8, arg, "--search-prefix")) {
239 try search_prefixes.append(arena, nextArgOrFatal(args, &arg_idx));232 try graph.search_prefixes.append(arena, nextArgOrFatal(args, &arg_idx));
240 } else if (mem.eql(u8, arg, "--libc")) {233 } else if (mem.eql(u8, arg, "--libc")) {
241 libc_file = nextArgOrFatal(args, &arg_idx);234 graph.libc_file = nextArgOrFatal(args, &arg_idx);
242 } else if (mem.eql(u8, arg, "--color")) {235 } else if (mem.eql(u8, arg, "--color")) {
243 const next_arg = nextArg(args, &arg_idx) orelse236 const next_arg = nextArg(args, &arg_idx) orelse
244 fatalWithHint("expected [auto|on|off] after '{s}'", .{arg});237 fatalWithHint("expected [auto|on|off] after {q}", .{arg});
245 color = std.meta.stringToEnum(Color, next_arg) orelse {238 color = std.meta.stringToEnum(Color, next_arg) orelse {
246 fatalWithHint("expected [auto|on|off] after '{s}', found '{s}'", .{239 fatalWithHint("expected [auto|on|off] after {q}, found {q}", .{
247 arg, next_arg,240 arg, next_arg,
248 });241 });
249 };242 };
250 } else if (mem.eql(u8, arg, "--error-style")) {243 } else if (mem.eql(u8, arg, "--error-style")) {
251 const next_arg = nextArg(args, &arg_idx) orelse244 const next_arg = nextArg(args, &arg_idx) orelse
252 fatalWithHint("expected style after '{s}'", .{arg});245 fatalWithHint("expected style after {q}", .{arg});
253 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {246 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {
254 fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });247 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
255 };248 };
256 } else if (mem.eql(u8, arg, "--multiline-errors")) {249 } else if (mem.eql(u8, arg, "--multiline-errors")) {
257 const next_arg = nextArg(args, &arg_idx) orelse250 const next_arg = nextArg(args, &arg_idx) orelse
258 fatalWithHint("expected style after '{s}'", .{arg});251 fatalWithHint("expected style after {q}", .{arg});
259 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {252 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {
260 fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });253 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
261 };254 };
262 } else if (mem.eql(u8, arg, "--summary")) {255 } else if (mem.eql(u8, arg, "--summary")) {
263 const next_arg = nextArg(args, &arg_idx) orelse256 const next_arg = nextArg(args, &arg_idx) orelse
264 fatalWithHint("expected [all|new|failures|line|none] after '{s}'", .{arg});257 fatalWithHint("expected [all|new|failures|line|none] after {q}", .{arg});
265 summary = std.meta.stringToEnum(Summary, next_arg) orelse {258 summary = std.meta.stringToEnum(Summary, next_arg) orelse {
266 fatalWithHint("expected [all|new|failures|line|none] after '{s}', found '{s}'", .{259 fatalWithHint("expected [all|new|failures|line|none] after {q}, found {q}", .{
267 arg, next_arg,260 arg, next_arg,
268 });261 });
269 };262 };
270 } else if (mem.eql(u8, arg, "--seed")) {263 } else if (mem.eql(u8, arg, "--seed")) {
271 const next_arg = nextArg(args, &arg_idx) orelse264 const next_arg = nextArg(args, &arg_idx) orelse
272 fatalWithHint("expected u32 after '{s}'", .{arg});265 fatalWithHint("expected u32 after {q}", .{arg});
273 graph.random_seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {266 graph.random_seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {
274 fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {t}", .{ next_arg, err });267 fatal("unable to parse seed {q} as unsigned 32-bit integer: {t}", .{ next_arg, err });
275 };268 };
269 } else if (mem.eql(u8, arg, "--build-id")) {
270 graph.build_id = .fast;
271 } else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| {
272 graph.build_id = std.zig.BuildId.parse(style) catch |err|
273 fatal("unable to parse --build-id style {q}: {t}", .{ style, err });
276 } else if (mem.eql(u8, arg, "--debounce")) {274 } else if (mem.eql(u8, arg, "--debounce")) {
275 // TODO refactor and reuse the timeout parsing code also here
277 const next_arg = nextArg(args, &arg_idx) orelse276 const next_arg = nextArg(args, &arg_idx) orelse
278 fatalWithHint("expected u16 after '{s}'", .{arg});277 fatalWithHint("expected u16 after {q}", .{arg});
279 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {278 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {
280 fatal("unable to parse debounce interval '{s}' as unsigned 16-bit integer: {t}\n", .{279 fatal("unable to parse debounce interval {q} as unsigned 16-bit integer: {t}", .{
281 next_arg, err,280 next_arg, err,
282 });281 });
283 };282 };
...@@ -287,11 +286,15 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -287,11 +286,15 @@ pub fn main(init: process.Init.Minimal) !void {
287 const addr_str = arg["--webui=".len..];286 const addr_str = arg["--webui=".len..];
288 if (std.mem.eql(u8, addr_str, "-")) fatal("web interface cannot listen on stdio", .{});287 if (std.mem.eql(u8, addr_str, "-")) fatal("web interface cannot listen on stdio", .{});
289 webui_listen = Io.net.IpAddress.parseLiteral(addr_str) catch |err| {288 webui_listen = Io.net.IpAddress.parseLiteral(addr_str) catch |err| {
290 fatal("invalid web UI address '{s}': {t}", .{ addr_str, err });289 fatal("invalid web UI address {q}: {t}", .{ addr_str, err });
291 };290 };
292 } else if (mem.eql(u8, arg, "--debug-log")) {291 } else if (mem.eql(u8, arg, "--debug-log")) {
293 const next_arg = nextArgOrFatal(args, &arg_idx);292 const next_arg = nextArgOrFatal(args, &arg_idx);
294 try debug_log_scopes.append(arena, next_arg);293 try graph.debug_log_scopes.append(arena, next_arg);
294 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
295 graph.debug_compile_errors = true;
296 } else if (mem.eql(u8, arg, "--debug-incremental")) {
297 graph.debug_incremental = true;
295 } else if (mem.eql(u8, arg, "--debug-pkg-config")) {298 } else if (mem.eql(u8, arg, "--debug-pkg-config")) {
296 debug_pkg_config = true;299 debug_pkg_config = true;
297 } else if (mem.eql(u8, arg, "--debug-rt")) {300 } else if (mem.eql(u8, arg, "--debug-rt")) {
...@@ -302,6 +305,14 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -302,6 +305,14 @@ pub fn main(init: process.Init.Minimal) !void {
302 } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {305 } else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {
303 // --glibc-runtimes was the old name of the flag; kept for compatibility for now.306 // --glibc-runtimes was the old name of the flag; kept for compatibility for now.
304 libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);307 libc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
308 } else if (mem.eql(u8, arg, "--verbose")) {
309 graph.verbose = true;
310 } else if (mem.eql(u8, arg, "--verbose-air")) {
311 graph.verbose_air = true;
312 } else if (mem.eql(u8, arg, "--verbose-cc")) {
313 graph.verbose_cc = true;
314 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
315 graph.verbose_llvm_ir = true;
305 } else if (mem.eql(u8, arg, "--watch")) {316 } else if (mem.eql(u8, arg, "--watch")) {
306 watch = true;317 watch = true;
307 } else if (mem.eql(u8, arg, "--time-report")) {318 } else if (mem.eql(u8, arg, "--time-report")) {
...@@ -373,18 +384,15 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -373,18 +384,15 @@ pub fn main(init: process.Init.Minimal) !void {
373 } else if (mem.eql(u8, arg, "-fno-allow-so-scripts")) {384 } else if (mem.eql(u8, arg, "-fno-allow-so-scripts")) {
374 graph.allow_so_scripts = false;385 graph.allow_so_scripts = false;
375 } else if (mem.eql(u8, arg, "-freference-trace")) {386 } else if (mem.eql(u8, arg, "-freference-trace")) {
376 reference_trace = 256;387 graph.reference_trace = 256;
377 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {388 } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| {
378 const num = arg["-freference-trace=".len..];389 graph.reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err|
379 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {390 fatal("unable to parse reference_trace count {q}: {t}", .{ num, err });
380 std.debug.print("unable to parse reference_trace count '{s}': {t}", .{ num, err });
381 process.exit(1);
382 };
383 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {391 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
384 reference_trace = null;392 graph.reference_trace = null;
385 } else if (mem.cutPrefix(u8, arg, "-j")) |text| {393 } else if (mem.cutPrefix(u8, arg, "-j")) |text| {
386 const n = std.fmt.parseUnsigned(u32, text, 10) catch |err|394 const n = std.fmt.parseUnsigned(u32, text, 10) catch |err|
387 fatal("unable to parse jobs count '{s}': {t}", .{ text, err });395 fatal("unable to parse jobs count {q}: {t}", .{ text, err });
388 if (n < 1) fatal("number of jobs must be at least 1", .{});396 if (n < 1) fatal("number of jobs must be at least 1", .{});
389 threaded.setAsyncLimit(.limited(n));397 threaded.setAsyncLimit(.limited(n));
390 graph.max_jobs = n;398 graph.max_jobs = n;
...@@ -392,7 +400,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -392,7 +400,7 @@ pub fn main(init: process.Init.Minimal) !void {
392 run_args = argsRest(args, arg_idx);400 run_args = argsRest(args, arg_idx);
393 break;401 break;
394 } else {402 } else {
395 fatalWithHint("unrecognized argument: '{s}'", .{arg});403 fatalWithHint("unrecognized argument: {s}", .{arg});
396 }404 }
397 } else {405 } else {
398 try step_names.append(arena, arg);406 try step_names.append(arena, arg);
...@@ -1848,8 +1856,7 @@ const ScannedConfig = struct {...@@ -1848,8 +1856,7 @@ const ScannedConfig = struct {
1848 \\ --debug-rt Debug compiler runtime libraries1856 \\ --debug-rt Debug compiler runtime libraries
1849 \\ --verbose-link Enable compiler debug output for linking1857 \\ --verbose-link Enable compiler debug output for linking
1850 \\ --verbose-air Enable compiler debug output for Zig AIR1858 \\ --verbose-air Enable compiler debug output for Zig AIR
1851 \\ --verbose-llvm-ir[=file] Enable compiler debug output for LLVM IR1859 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
1852 \\ --verbose-llvm-bc=[file] Enable compiler debug output for LLVM BC
1853 \\ --verbose-cimport Enable compiler debug output for C imports1860 \\ --verbose-cimport Enable compiler debug output for C imports
1854 \\ --verbose-cc Enable compiler debug output for C compilation1861 \\ --verbose-cc Enable compiler debug output for C compilation
1855 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features1862 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
lib/compiler/Maker/Graph.zig+20
...@@ -23,3 +23,23 @@ time_report: bool = false,...@@ -23,3 +23,23 @@ time_report: bool = false,
23/// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also23/// Similar to the `Io.Terminal.Mode` returned by `Io.lockStderr`, but also
24/// respects the '--color' flag.24/// respects the '--color' flag.
25stderr_mode: ?Io.Terminal.Mode = null,25stderr_mode: ?Io.Terminal.Mode = null,
26reference_trace: ?u32 = null,
27debug_log_scopes: std.ArrayList([]const u8) = .empty,
28debug_compile_errors: bool = false,
29debug_incremental: bool = false,
30verbose: bool = false,
31verbose_air: bool = false,
32verbose_cc: bool = false,
33verbose_link: bool = false,
34verbose_llvm_cpu_features: bool = false,
35verbose_llvm_ir: bool = false,
36libc_file: ?[]const u8 = null,
37/// What does this do? Nobody bothered to document it, and I think it's a
38/// smelly option. So unless somebody deletes these passive aggressive comments
39/// and replaces them with actual documentation, I'm going to delete this
40/// option from the build system in a future release. In other words, this is
41/// deprecated due to lack of test coverage, lack of documentation, and a hunch
42/// that it's a bad option that should be avoided.
43sysroot: ?[]const u8 = null,
44search_prefixes: std.ArrayList([]const u8) = .empty,
45build_id: ?std.zig.BuildId = null,
lib/compiler/Maker/Step.zig+11-83
...@@ -298,7 +298,7 @@ pub fn captureChildProcess(...@@ -298,7 +298,7 @@ pub fn captureChildProcess(
298298
299 // If an error occurs, it's happened in this command:299 // If an error occurs, it's happened in this command:
300 assert(s.result_failed_command == null);300 assert(s.result_failed_command == null);
301 s.result_failed_command = try allocPrintCmd(gpa, .inherit, null, argv);301 s.result_failed_command = try std.zig.allocPrintCmd(gpa, .inherit, null, argv);
302302
303 try handleChildProcUnsupported(s);303 try handleChildProcUnsupported(s);
304 try handleVerbose(s, .inherit, argv);304 try handleVerbose(s, .inherit, argv);
...@@ -354,15 +354,15 @@ pub fn evalZigProcess(...@@ -354,15 +354,15 @@ pub fn evalZigProcess(
354 argv: []const []const u8,354 argv: []const []const u8,
355 prog_node: std.Progress.Node,355 prog_node: std.Progress.Node,
356 watch: bool,356 watch: bool,
357 web_server: ?*WebServer,357 maker: *Maker,
358 gpa: Allocator,
359) !?Cache.Path {358) !?Cache.Path {
359 const gpa = maker.gpa;
360 const b = s.owner;360 const b = s.owner;
361 const io = b.graph.io;361 const io = b.graph.io;
362362
363 // If an error occurs, it's happened in this command:363 // If an error occurs, it's happened in this command:
364 assert(s.result_failed_command == null);364 assert(s.result_failed_command == null);
365 s.result_failed_command = try allocPrintCmd(gpa, .inherit, null, argv);365 s.result_failed_command = try std.zig.allocPrintCmd(gpa, .inherit, null, argv);
366366
367 if (s.getZigProcess()) |zp| update: {367 if (s.getZigProcess()) |zp| update: {
368 assert(watch);368 assert(watch);
...@@ -374,7 +374,7 @@ pub fn evalZigProcess(...@@ -374,7 +374,7 @@ pub fn evalZigProcess(
374 zp.deinit(io);374 zp.deinit(io);
375 gpa.destroy(zp);375 gpa.destroy(zp);
376 } else zp.saveState(prog_node);376 } else zp.saveState(prog_node);
377 const result = zigProcessUpdate(s, zp, watch, web_server, gpa) catch |err| switch (err) {377 const result = zigProcessUpdate(s, zp, watch, maker) catch |err| switch (err) {
378 error.BrokenPipe, error.EndOfStream => |reason| {378 error.BrokenPipe, error.EndOfStream => |reason| {
379 std.log.info("{s} restart required: {t}", .{ argv[0], reason });379 std.log.info("{s} restart required: {t}", .{ argv[0], reason });
380 // Process restart required.380 // Process restart required.
...@@ -431,7 +431,7 @@ pub fn evalZigProcess(...@@ -431,7 +431,7 @@ pub fn evalZigProcess(
431431
432 const result = result: {432 const result = result: {
433 defer if (watch) zp.saveState(prog_node);433 defer if (watch) zp.saveState(prog_node);
434 break :result try zigProcessUpdate(s, zp, watch, web_server, gpa);434 break :result try zigProcessUpdate(s, zp, watch, maker);
435 };435 };
436436
437 if (!watch) {437 if (!watch) {
...@@ -485,7 +485,8 @@ pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.CreatePathStatus {...@@ -485,7 +485,8 @@ pub fn installDir(s: *Step, dest_path: []const u8) !Io.Dir.CreatePathStatus {
485 return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err });485 return s.fail("unable to create dir '{s}': {t}", .{ dest_path, err });
486}486}
487487
488fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*WebServer, gpa: Allocator) !?Path {488fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, maker: *Maker) !?Path {
489 const gpa = maker.gpa;
489 const b = s.owner;490 const b = s.owner;
490 const arena = b.allocator;491 const arena = b.allocator;
491 const io = b.graph.io;492 const io = b.graph.io;
...@@ -586,7 +587,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*WebSer...@@ -586,7 +587,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*WebSer
586 }587 }
587 }588 }
588 },589 },
589 .time_report => if (web_server) |ws| {590 .time_report => if (maker.web_server) |ws| {
590 const TimeReport = std.zig.Server.Message.TimeReport;591 const TimeReport = std.zig.Server.Message.TimeReport;
591 const tr: *align(1) const TimeReport = @ptrCast(body[0..@sizeOf(TimeReport)]);592 const tr: *align(1) const TimeReport = @ptrCast(body[0..@sizeOf(TimeReport)]);
592 ws.updateTimeReportCompile(.{593 ws.updateTimeReportCompile(.{
...@@ -641,11 +642,11 @@ pub fn handleVerbose(...@@ -641,11 +642,11 @@ pub fn handleVerbose(
641 opt_env: ?*const std.process.Environ.Map,642 opt_env: ?*const std.process.Environ.Map,
642 argv: []const []const u8,643 argv: []const []const u8,
643) error{OutOfMemory}!void {644) error{OutOfMemory}!void {
644 if (!s.verbose) return;
645 const graph = s.graph;645 const graph = s.graph;
646 if (!graph.verbose) return;
646 // Intention of verbose is to print all sub-process command lines to647 // Intention of verbose is to print all sub-process command lines to
647 // stderr before spawning them.648 // stderr before spawning them.
648 const text = try allocPrintCmd(arena, cwd, if (opt_env) |env| .{649 const text = try std.zig.allocPrintCmd(arena, cwd, if (opt_env) |env| .{
649 .child = env,650 .child = env,
650 .parent = &graph.environ_map,651 .parent = &graph.environ_map,
651 } else null, argv);652 } else null, argv);
...@@ -835,79 +836,6 @@ fn addWatchInputFromPath(step: *Step, path: Cache.Path, basename: []const u8) !v...@@ -835,79 +836,6 @@ fn addWatchInputFromPath(step: *Step, path: Cache.Path, basename: []const u8) !v
835 try gop.value_ptr.append(gpa, basename);836 try gop.value_ptr.append(gpa, basename);
836}837}
837838
838pub fn allocPrintCmd(
839 gpa: Allocator,
840 cwd: std.process.Child.Cwd,
841 opt_env: ?struct {
842 child: *const std.process.Environ.Map,
843 parent: *const std.process.Environ.Map,
844 },
845 argv: []const []const u8,
846) Allocator.Error![]u8 {
847 const shell = struct {
848 fn escape(writer: *Io.Writer, string: []const u8, is_argv0: bool) !void {
849 for (string) |c| {
850 if (switch (c) {
851 else => true,
852 '%', '+'...':', '@'...'Z', '_', 'a'...'z' => false,
853 '=' => is_argv0,
854 }) break;
855 } else return writer.writeAll(string);
856
857 try writer.writeByte('"');
858 for (string) |c| {
859 if (switch (c) {
860 std.ascii.control_code.nul => break,
861 '!', '"', '$', '\\', '`' => true,
862 else => !std.ascii.isPrint(c),
863 }) try writer.writeByte('\\');
864 switch (c) {
865 std.ascii.control_code.nul => unreachable,
866 std.ascii.control_code.bel => try writer.writeByte('a'),
867 std.ascii.control_code.bs => try writer.writeByte('b'),
868 std.ascii.control_code.ht => try writer.writeByte('t'),
869 std.ascii.control_code.lf => try writer.writeByte('n'),
870 std.ascii.control_code.vt => try writer.writeByte('v'),
871 std.ascii.control_code.ff => try writer.writeByte('f'),
872 std.ascii.control_code.cr => try writer.writeByte('r'),
873 std.ascii.control_code.esc => try writer.writeByte('E'),
874 ' '...'~' => try writer.writeByte(c),
875 else => try writer.print("{o:0>3}", .{c}),
876 }
877 }
878 try writer.writeByte('"');
879 }
880 };
881
882 var aw: Io.Writer.Allocating = .init(gpa);
883 defer aw.deinit();
884 const writer = &aw.writer;
885 switch (cwd) {
886 .inherit => {},
887 .path => |path| writer.print("cd {s} && ", .{path}) catch return error.OutOfMemory,
888 .dir => @panic("TODO"),
889 }
890 if (opt_env) |env| {
891 var it = env.child.iterator();
892 while (it.next()) |entry| {
893 const key = entry.key_ptr.*;
894 const value = entry.value_ptr.*;
895 if (env.parent.get(key)) |process_value| {
896 if (std.mem.eql(u8, value, process_value)) continue;
897 }
898 writer.print("{s}=", .{key}) catch return error.OutOfMemory;
899 shell.escape(writer, value, false) catch return error.OutOfMemory;
900 writer.writeByte(' ') catch return error.OutOfMemory;
901 }
902 }
903 shell.escape(writer, argv[0], true) catch return error.OutOfMemory;
904 for (argv[1..]) |arg| {
905 writer.writeByte(' ') catch return error.OutOfMemory;
906 shell.escape(writer, arg, false) catch return error.OutOfMemory;
907 }
908 return aw.toOwnedSlice();
909}
910
911fn oomWrap(s: *Step, result: error{OutOfMemory}!void) void {839fn oomWrap(s: *Step, result: error{OutOfMemory}!void) void {
912 result catch {840 result catch {
913 s.result_oom = true;841 s.result_oom = true;
lib/compiler/Maker/Step/Compile.zig+232-259
...@@ -10,6 +10,7 @@ const Io = std.Io;...@@ -10,6 +10,7 @@ const Io = std.Io;
10const Sha256 = std.crypto.hash.sha2.Sha256;10const Sha256 = std.crypto.hash.sha2.Sha256;
11const assert = std.debug.assert;11const assert = std.debug.assert;
12const mem = std.mem;12const mem = std.mem;
13const allocPrint = std.fmt.allocPrint;
1314
14const Step = @import("../Step.zig");15const Step = @import("../Step.zig");
15const Maker = @import("../../Maker.zig");16const Maker = @import("../../Maker.zig");
...@@ -17,6 +18,8 @@ const Maker = @import("../../Maker.zig");...@@ -17,6 +18,8 @@ const Maker = @import("../../Maker.zig");
17/// Populated during the make phase when there is a long-lived compiler process.18/// Populated during the make phase when there is a long-lived compiler process.
18/// Managed by the build runner, not user build script.19/// Managed by the build runner, not user build script.
19zig_process: ?*Step.ZigProcess = null,20zig_process: ?*Step.ZigProcess = null,
21/// Persisted to reuse memory on subsequent make.
22zig_args: std.ArrayList([]const u8) = .empty,
2023
21pub fn make(24pub fn make(
22 compile: *Compile,25 compile: *Compile,
...@@ -24,14 +27,15 @@ pub fn make(...@@ -24,14 +27,15 @@ pub fn make(
24 maker: *Maker,27 maker: *Maker,
25 progress_node: std.Progress.Node,28 progress_node: std.Progress.Node,
26) Step.ExtendedMakeError!void {29) Step.ExtendedMakeError!void {
27 if (true) @panic("TODO implement compile.make()");
28 const graph = maker.graph;30 const graph = maker.graph;
29 const step = maker.stepByIndex(step_index);31 const step = maker.stepByIndex(step_index);
30 const zig_args = try getZigArgs(compile, maker, false);32 compile.zig_args.clearRetainingCapacity();
33 if (true) @panic("TODO implement compile.make()");
34 try lowerZigArgs(compile, step_index, maker, &compile.zig_args, false);
31 const process_arena = graph.arena; // TODO don't leak into the process_arena35 const process_arena = graph.arena; // TODO don't leak into the process_arena
3236
33 const maybe_output_dir = step.evalZigProcess(37 const maybe_output_dir = step.evalZigProcess(
34 zig_args,38 compile.zig_args.items,
35 progress_node,39 progress_node,
36 (graph.incremental == true) and (maker.watch or maker.web_server != null),40 (graph.incremental == true) and (maker.watch or maker.web_server != null),
37 maker,41 maker,
...@@ -47,7 +51,7 @@ pub fn make(...@@ -47,7 +51,7 @@ pub fn make(
47 // Update generated files51 // Update generated files
48 if (maybe_output_dir) |output_dir| {52 if (maybe_output_dir) |output_dir| {
49 if (compile.emit_directory) |lp| {53 if (compile.emit_directory) |lp| {
50 lp.path = try std.fmt.allocPrint(process_arena, "{f}", .{output_dir});54 lp.path = try allocPrint(process_arena, "{f}", .{output_dir});
51 }55 }
5256
53 // zig fmt: off57 // zig fmt: off
...@@ -70,23 +74,26 @@ pub fn make(...@@ -70,23 +74,26 @@ pub fn make(
70 {74 {
71 try doAtomicSymLinks(75 try doAtomicSymLinks(
72 step,76 step,
73 compile.getEmittedBin().getPath2(step.owner, step),77 compile.getEmittedBin().getPath2(step),
74 compile.major_only_filename.?,78 compile.major_only_filename.?,
75 compile.name_only_filename.?,79 compile.name_only_filename.?,
76 );80 );
77 }81 }
78}82}
7983
80fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {84fn lowerZigArgs(
81 const step = &compile.step;85 compile: *Compile,
82 const b = step.owner;86 step_index: Configuration.Step.Index,
87 maker: *Maker,
88 zig_args: *std.ArrayList([]const u8),
89 fuzz: bool,
90) Allocator.Error!void {
91 const step = maker.stepByIndex(step_index);
83 const graph = maker.graph;92 const graph = maker.graph;
84 const arena = graph.arena; // TODO don't leak into the process arena93 const arena = graph.arena; // TODO don't leak into the process arena
94 const gpa = maker.gpa;
8595
86 var zig_args = std.array_list.Managed([]const u8).init(arena);96 try zig_args.append(gpa, graph.zig_exe);
87 defer zig_args.deinit();
88
89 try zig_args.append(graph.zig_exe);
9097
91 const cmd = switch (compile.kind) {98 const cmd = switch (compile.kind) {
92 .lib => "build-lib",99 .lib => "build-lib",
...@@ -95,10 +102,10 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -95,10 +102,10 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
95 .@"test" => "test",102 .@"test" => "test",
96 .test_obj => "test-obj",103 .test_obj => "test-obj",
97 };104 };
98 try zig_args.append(cmd);105 try zig_args.append(gpa, cmd);
99106
100 if (b.reference_trace) |some| {107 if (graph.reference_trace) |some| {
101 try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));108 try zig_args.append(gpa, try allocPrint(arena, "-freference-trace={d}", .{some}));
102 }109 }
103 try addFlag(&zig_args, "allow-so-scripts", compile.allow_so_scripts orelse graph.allow_so_scripts);110 try addFlag(&zig_args, "allow-so-scripts", compile.allow_so_scripts orelse graph.allow_so_scripts);
104111
...@@ -107,33 +114,31 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -107,33 +114,31 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
107 try addFlag(&zig_args, "new-linker", compile.use_new_linker);114 try addFlag(&zig_args, "new-linker", compile.use_new_linker);
108115
109 if (compile.root_module.resolved_target.?.query.ofmt) |ofmt| {116 if (compile.root_module.resolved_target.?.query.ofmt) |ofmt| {
110 try zig_args.append(try std.fmt.allocPrint(arena, "-ofmt={s}", .{@tagName(ofmt)}));117 try zig_args.append(gpa, try allocPrint(arena, "-ofmt={t}", .{ofmt}));
111 }118 }
112119
113 switch (compile.entry) {120 switch (compile.entry) {
114 .default => {},121 .default => {},
115 .disabled => try zig_args.append("-fno-entry"),122 .disabled => try zig_args.append(gpa, "-fno-entry"),
116 .enabled => try zig_args.append("-fentry"),123 .enabled => try zig_args.append(gpa, "-fentry"),
117 .symbol_name => |entry_name| {124 .symbol_name => |entry_name| {
118 try zig_args.append(try std.fmt.allocPrint(arena, "-fentry={s}", .{entry_name}));125 try zig_args.append(gpa, try allocPrint(arena, "-fentry={s}", .{entry_name}));
119 },126 },
120 }127 }
121128
122 {129 {
123 for (compile.force_undefined_symbols.keys()) |symbol_name| {130 for (compile.force_undefined_symbols.keys()) |symbol_name| {
124 try zig_args.append("--force_undefined");131 try zig_args.append(gpa, "--force_undefined");
125 try zig_args.append(symbol_name.*);132 try zig_args.append(gpa, symbol_name.*);
126 }133 }
127 }134 }
128135
129 if (compile.stack_size) |stack_size| {136 if (compile.stack_size) |stack_size| {
130 try zig_args.append("--stack");137 try zig_args.append(gpa, "--stack");
131 try zig_args.append(try std.fmt.allocPrint(arena, "{}", .{stack_size}));138 try zig_args.append(gpa, try allocPrint(arena, "{}", .{stack_size}));
132 }139 }
133140
134 if (fuzz) {141 try addBool(gpa, zig_args, fuzz, "-ffuzz");
135 try zig_args.append("-ffuzz");
136 }
137142
138 {143 {
139 // Stores system libraries that have already been seen for at least one144 // Stores system libraries that have already been seen for at least one
...@@ -183,14 +188,14 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -183,14 +188,14 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
183 switch (link_object) {188 switch (link_object) {
184 .static_path => |static_path| {189 .static_path => |static_path| {
185 if (my_responsibility) {190 if (my_responsibility) {
186 try zig_args.append(static_path.getPath2(mod.owner, step));191 try zig_args.append(gpa, static_path.getPath2(step));
187 total_linker_objects += 1;192 total_linker_objects += 1;
188 }193 }
189 },194 },
190 .system_lib => |system_lib| {195 .system_lib => |system_lib| {
191 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);196 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
192 if (system_lib_gop.found_existing) {197 if (system_lib_gop.found_existing) {
193 try zig_args.appendSlice(system_lib_gop.value_ptr.*);198 try zig_args.appendSlice(gpa, system_lib_gop.value_ptr.*);
194 continue;199 continue;
195 } else {200 } else {
196 system_lib_gop.value_ptr.* = &.{};201 system_lib_gop.value_ptr.* = &.{};
...@@ -205,16 +210,16 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -205,16 +210,16 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
205 {210 {
206 switch (system_lib.search_strategy) {211 switch (system_lib.search_strategy) {
207 .no_fallback => switch (system_lib.preferred_link_mode) {212 .no_fallback => switch (system_lib.preferred_link_mode) {
208 .dynamic => try zig_args.append("-search_dylibs_only"),213 .dynamic => try zig_args.append(gpa, "-search_dylibs_only"),
209 .static => try zig_args.append("-search_static_only"),214 .static => try zig_args.append(gpa, "-search_static_only"),
210 },215 },
211 .paths_first => switch (system_lib.preferred_link_mode) {216 .paths_first => switch (system_lib.preferred_link_mode) {
212 .dynamic => try zig_args.append("-search_paths_first"),217 .dynamic => try zig_args.append(gpa, "-search_paths_first"),
213 .static => try zig_args.append("-search_paths_first_static"),218 .static => try zig_args.append(gpa, "-search_paths_first_static"),
214 },219 },
215 .mode_first => switch (system_lib.preferred_link_mode) {220 .mode_first => switch (system_lib.preferred_link_mode) {
216 .dynamic => try zig_args.append("-search_dylibs_first"),221 .dynamic => try zig_args.append(gpa, "-search_dylibs_first"),
217 .static => try zig_args.append("-search_static_first"),222 .static => try zig_args.append(gpa, "-search_static_first"),
218 },223 },
219 }224 }
220 prev_search_strategy = system_lib.search_strategy;225 prev_search_strategy = system_lib.search_strategy;
...@@ -227,11 +232,11 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -227,11 +232,11 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
227 break :prefix "-l";232 break :prefix "-l";
228 };233 };
229 switch (system_lib.use_pkg_config) {234 switch (system_lib.use_pkg_config) {
230 .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),235 .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{ prefix, system_lib.name })),
231 .yes, .force => {236 .yes, .force => {
232 if (compile.runPkgConfig(maker, system_lib.name)) |result| {237 if (compile.runPkgConfig(maker, system_lib.name)) |result| {
233 try zig_args.appendSlice(result.cflags);238 try zig_args.appendSlice(gpa, result.cflags);
234 try zig_args.appendSlice(result.libs);239 try zig_args.appendSlice(gpa, result.libs);
235 try seen_system_libs.put(arena, system_lib.name, result.cflags);240 try seen_system_libs.put(arena, system_lib.name, result.cflags);
236 } else |err| switch (err) {241 } else |err| switch (err) {
237 error.PkgConfigInvalidOutput,242 error.PkgConfigInvalidOutput,
...@@ -243,7 +248,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -243,7 +248,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
243 .yes => {248 .yes => {
244 // pkg-config failed, so fall back to linking the library249 // pkg-config failed, so fall back to linking the library
245 // by name directly.250 // by name directly.
246 try zig_args.append(b.fmt("{s}{s}", .{251 try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
247 prefix,252 prefix,
248 system_lib.name,253 system_lib.name,
249 }));254 }));
...@@ -267,7 +272,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -267,7 +272,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
267 const included_in_lib_or_obj = !my_responsibility and272 const included_in_lib_or_obj = !my_responsibility and
268 (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);273 (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);
269 if (!already_linked and !included_in_lib_or_obj) {274 if (!already_linked and !included_in_lib_or_obj) {
270 try zig_args.append(other.getEmittedBin().getPath2(b, step));275 try zig_args.append(gpa, other.getEmittedBin().getPath2(step));
271 total_linker_objects += 1;276 total_linker_objects += 1;
272 }277 }
273 },278 },
...@@ -288,15 +293,15 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -288,15 +293,15 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
288 else293 else
289 try other.getGeneratedFilePath("generated_bin", &compile.step);294 try other.getGeneratedFilePath("generated_bin", &compile.step);
290295
291 try zig_args.append(full_path_lib);296 try zig_args.append(gpa, full_path_lib);
292 total_linker_objects += 1;297 total_linker_objects += 1;
293298
294 if (other.linkage == .dynamic and299 if (other.linkage == .dynamic and
295 compile.rootModuleTarget().os.tag != .windows)300 compile.rootModuleTarget().os.tag != .windows)
296 {301 {
297 if (Dir.path.dirname(full_path_lib)) |dirname| {302 if (Dir.path.dirname(full_path_lib)) |dirname| {
298 try zig_args.append("-rpath");303 try zig_args.append(gpa, "-rpath");
299 try zig_args.append(dirname);304 try zig_args.append(gpa, dirname);
300 }305 }
301 }306 }
302 },307 },
...@@ -306,11 +311,11 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -306,11 +311,11 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
306 if (!my_responsibility) break :l;311 if (!my_responsibility) break :l;
307312
308 if (prev_has_cflags) {313 if (prev_has_cflags) {
309 try zig_args.append("-cflags");314 try zig_args.append(gpa, "-cflags");
310 try zig_args.append("--");315 try zig_args.append(gpa, "--");
311 prev_has_cflags = false;316 prev_has_cflags = false;
312 }317 }
313 try zig_args.append(asm_file.getPath2(mod.owner, step));318 try zig_args.append(gpa, asm_file.getPath2(mod.owner, step));
314 total_linker_objects += 1;319 total_linker_objects += 1;
315 },320 },
316321
...@@ -318,24 +323,24 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -318,24 +323,24 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
318 if (!my_responsibility) break :l;323 if (!my_responsibility) break :l;
319324
320 if (prev_has_cflags or c_source_file.flags.len != 0) {325 if (prev_has_cflags or c_source_file.flags.len != 0) {
321 try zig_args.append("-cflags");326 try zig_args.append(gpa, "-cflags");
322 for (c_source_file.flags) |arg| {327 for (c_source_file.flags) |arg| {
323 try zig_args.append(arg);328 try zig_args.append(gpa, arg);
324 }329 }
325 try zig_args.append("--");330 try zig_args.append(gpa, "--");
326 }331 }
327 prev_has_cflags = (c_source_file.flags.len != 0);332 prev_has_cflags = (c_source_file.flags.len != 0);
328333
329 if (c_source_file.language) |lang| {334 if (c_source_file.language) |lang| {
330 try zig_args.append("-x");335 try zig_args.append(gpa, "-x");
331 try zig_args.append(lang.internalIdentifier());336 try zig_args.append(gpa, lang.internalIdentifier());
332 }337 }
333338
334 try zig_args.append(c_source_file.file.getPath2(mod.owner, step));339 try zig_args.append(gpa, c_source_file.file.getPath2(mod.owner, step));
335340
336 if (c_source_file.language != null) {341 if (c_source_file.language != null) {
337 try zig_args.append("-x");342 try zig_args.append(gpa, "-x");
338 try zig_args.append("none");343 try zig_args.append(gpa, "none");
339 }344 }
340 total_linker_objects += 1;345 total_linker_objects += 1;
341 },346 },
...@@ -344,27 +349,27 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -344,27 +349,27 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
344 if (!my_responsibility) break :l;349 if (!my_responsibility) break :l;
345350
346 if (prev_has_cflags or c_source_files.flags.len != 0) {351 if (prev_has_cflags or c_source_files.flags.len != 0) {
347 try zig_args.append("-cflags");352 try zig_args.append(gpa, "-cflags");
348 for (c_source_files.flags) |arg| {353 for (c_source_files.flags) |arg| {
349 try zig_args.append(arg);354 try zig_args.append(gpa, arg);
350 }355 }
351 try zig_args.append("--");356 try zig_args.append(gpa, "--");
352 }357 }
353 prev_has_cflags = (c_source_files.flags.len != 0);358 prev_has_cflags = (c_source_files.flags.len != 0);
354359
355 if (c_source_files.language) |lang| {360 if (c_source_files.language) |lang| {
356 try zig_args.append("-x");361 try zig_args.append(gpa, "-x");
357 try zig_args.append(lang.internalIdentifier());362 try zig_args.append(gpa, lang.internalIdentifier());
358 }363 }
359364
360 const root_path = c_source_files.root.getPath2(mod.owner, step);365 const root_path = c_source_files.root.getPath2(mod.owner, step);
361 for (c_source_files.files) |file| {366 for (c_source_files.files) |file| {
362 try zig_args.append(b.pathJoin(&.{ root_path, file }));367 try zig_args.append(gpa, try Dir.path.join(arena, &.{ root_path, file }));
363 }368 }
364369
365 if (c_source_files.language != null) {370 if (c_source_files.language != null) {
366 try zig_args.append("-x");371 try zig_args.append(gpa, "-x");
367 try zig_args.append("none");372 try zig_args.append(gpa, "none");
368 }373 }
369374
370 total_linker_objects += c_source_files.files.len;375 total_linker_objects += c_source_files.files.len;
...@@ -375,23 +380,23 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -375,23 +380,23 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
375380
376 if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {381 if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
377 if (prev_has_rcflags) {382 if (prev_has_rcflags) {
378 try zig_args.append("-rcflags");383 try zig_args.append(gpa, "-rcflags");
379 try zig_args.append("--");384 try zig_args.append(gpa, "--");
380 prev_has_rcflags = false;385 prev_has_rcflags = false;
381 }386 }
382 } else {387 } else {
383 try zig_args.append("-rcflags");388 try zig_args.append(gpa, "-rcflags");
384 for (rc_source_file.flags) |arg| {389 for (rc_source_file.flags) |arg| {
385 try zig_args.append(arg);390 try zig_args.append(gpa, arg);
386 }391 }
387 for (rc_source_file.include_paths) |include_path| {392 for (rc_source_file.include_paths) |include_path| {
388 try zig_args.append("/I");393 try zig_args.append(gpa, "/I");
389 try zig_args.append(include_path.getPath2(mod.owner, step));394 try zig_args.append(gpa, include_path.getPath2(mod.owner, step));
390 }395 }
391 try zig_args.append("--");396 try zig_args.append(gpa, "--");
392 prev_has_rcflags = true;397 prev_has_rcflags = true;
393 }398 }
394 try zig_args.append(rc_source_file.file.getPath2(mod.owner, step));399 try zig_args.append(gpa, rc_source_file.file.getPath2(mod.owner, step));
395 total_linker_objects += 1;400 total_linker_objects += 1;
396 },401 },
397 }402 }
...@@ -414,7 +419,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -414,7 +419,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
414 if (std.mem.eql(u8, import_cli_name, name)) {419 if (std.mem.eql(u8, import_cli_name, name)) {
415 zig_args.appendAssumeCapacity(import_cli_name);420 zig_args.appendAssumeCapacity(import_cli_name);
416 } else {421 } else {
417 zig_args.appendAssumeCapacity(b.fmt("{s}={s}", .{ name, import_cli_name }));422 zig_args.appendAssumeCapacity(try allocPrint(arena, "{s}={s}", .{ name, import_cli_name }));
418 }423 }
419 }424 }
420425
...@@ -427,9 +432,9 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -427,9 +432,9 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
427 // files must have a module parent.432 // files must have a module parent.
428 if (mod.root_source_file) |lp| {433 if (mod.root_source_file) |lp| {
429 const src = lp.getPath2(mod.owner, step);434 const src = lp.getPath2(mod.owner, step);
430 try zig_args.append(b.fmt("-M{s}={s}", .{ module_cli_name, src }));435 try zig_args.append(gpa, try allocPrint(arena, "-M{s}={s}", .{ module_cli_name, src }));
431 } else if (moduleNeedsCliArg(mod)) {436 } else if (moduleNeedsCliArg(mod)) {
432 try zig_args.append(b.fmt("-M{s}", .{module_cli_name}));437 try zig_args.append(gpa, try allocPrint(arena, "-M{s}", .{module_cli_name}));
433 }438 }
434 }439 }
435 }440 }
...@@ -441,275 +446,248 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -441,275 +446,248 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
441446
442 for (frameworks.keys(), frameworks.values()) |name, info| {447 for (frameworks.keys(), frameworks.values()) |name, info| {
443 if (info.needed) {448 if (info.needed) {
444 try zig_args.append("-needed_framework");449 try zig_args.append(gpa, "-needed_framework");
445 } else if (info.weak) {450 } else if (info.weak) {
446 try zig_args.append("-weak_framework");451 try zig_args.append(gpa, "-weak_framework");
447 } else {452 } else {
448 try zig_args.append("-framework");453 try zig_args.append(gpa, "-framework");
449 }454 }
450 try zig_args.append(name);455 try zig_args.append(gpa, name);
451 }456 }
452457
453 if (compile.is_linking_libcpp) {458 if (compile.is_linking_libcpp) {
454 try zig_args.append("-lc++");459 try zig_args.append(gpa, "-lc++");
455 }460 }
456461
457 if (compile.is_linking_libc) {462 if (compile.is_linking_libc) {
458 try zig_args.append("-lc");463 try zig_args.append(gpa, "-lc");
459 }464 }
460 }465 }
461466
462 if (compile.win32_manifest) |manifest_file| {467 if (compile.win32_manifest) |manifest_file| {
463 try zig_args.append(manifest_file.getPath2(b, step));468 try zig_args.append(gpa, manifest_file.getPath2(step));
464 }469 }
465470
466 if (compile.win32_module_definition) |module_file| {471 if (compile.win32_module_definition) |module_file| {
467 try zig_args.append(module_file.getPath2(b, step));472 try zig_args.append(gpa, module_file.getPath2(step));
468 }473 }
469474
470 if (compile.image_base) |image_base| {475 if (compile.image_base) |image_base| {
471 try zig_args.append("--image-base");476 try zig_args.appendSlice(gpa, &.{
472 try zig_args.append(b.fmt("0x{x}", .{image_base}));477 "--image-base", try allocPrint(arena, "0x{x}", .{image_base}),
478 });
473 }479 }
474480
475 for (compile.filters) |filter| {481 for (compile.filters) |filter| {
476 try zig_args.append("--test-filter");482 try zig_args.appendSlice(gpa, &.{ "--test-filter", filter });
477 try zig_args.append(filter);
478 }483 }
479484
480 if (compile.test_runner) |test_runner| {485 if (compile.test_runner) |test_runner| {
481 try zig_args.append("--test-runner");486 try zig_args.appendSlice(gpa, &.{ "--test-runner", test_runner.path.getPath2(step) });
482 try zig_args.append(test_runner.path.getPath2(b, step));
483 }487 }
484488
485 for (b.debug_log_scopes) |log_scope| {489 for (graph.debug_log_scopes) |log_scope| {
486 try zig_args.append("--debug-log");490 try zig_args.appendSlice(gpa, &.{ "--debug-log", log_scope });
487 try zig_args.append(log_scope);
488 }491 }
489492
490 if (b.debug_compile_errors) {493 try addBool(gpa, zig_args, graph.debug_compile_errors, "--debug-compile-errors");
491 try zig_args.append("--debug-compile-errors");494 try addBool(gpa, zig_args, graph.debug_incremental, "--debug-incremental");
492 }495 try addBool(gpa, zig_args, graph.verbose_air, "--verbose-air");
496 try addBool(gpa, zig_args, graph.verbose_llvm_ir, "--verbose-llvm-ir");
497 try addBool(gpa, zig_args, graph.verbose_link or compile.verbose_link, "--verbose-link");
498 try addBool(gpa, zig_args, graph.verbose_cc or compile.verbose_cc, "--verbose-cc");
499 try addBool(gpa, zig_args, graph.verbose_llvm_cpu_features, "--verbose-llvm-cpu-features");
500 try addBool(gpa, zig_args, graph.time_report, "--time-report");
493501
494 if (b.debug_incremental) {502 if (compile.generated_asm != null) try zig_args.append(gpa, "-femit-asm");
495 try zig_args.append("--debug-incremental");503 if (compile.generated_bin == null) try zig_args.append(gpa, "-fno-emit-bin");
496 }504 if (compile.generated_docs != null) try zig_args.append(gpa, "-femit-docs");
497505 if (compile.generated_implib != null) try zig_args.append(gpa, "-femit-implib");
498 if (b.verbose_air) try zig_args.append("--verbose-air");506 if (compile.generated_llvm_bc != null) try zig_args.append(gpa, "-femit-llvm-bc");
499 if (b.verbose_llvm_ir) |path| try zig_args.append(b.fmt("--verbose-llvm-ir={s}", .{path}));507 if (compile.generated_llvm_ir != null) try zig_args.append(gpa, "-femit-llvm-ir");
500 if (b.verbose_llvm_bc) |path| try zig_args.append(b.fmt("--verbose-llvm-bc={s}", .{path}));508 if (compile.generated_h != null) try zig_args.append(gpa, "-femit-h");
501 if (b.verbose_link or compile.verbose_link) try zig_args.append("--verbose-link");
502 if (b.verbose_cc or compile.verbose_cc) try zig_args.append("--verbose-cc");
503 if (b.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features");
504 if (graph.time_report) try zig_args.append("--time-report");
505
506 if (compile.generated_asm != null) try zig_args.append("-femit-asm");
507 if (compile.generated_bin == null) try zig_args.append("-fno-emit-bin");
508 if (compile.generated_docs != null) try zig_args.append("-femit-docs");
509 if (compile.generated_implib != null) try zig_args.append("-femit-implib");
510 if (compile.generated_llvm_bc != null) try zig_args.append("-femit-llvm-bc");
511 if (compile.generated_llvm_ir != null) try zig_args.append("-femit-llvm-ir");
512 if (compile.generated_h != null) try zig_args.append("-femit-h");
513509
514 try addFlag(&zig_args, "formatted-panics", compile.formatted_panics);510 try addFlag(&zig_args, "formatted-panics", compile.formatted_panics);
515511
516 switch (compile.compress_debug_sections) {512 switch (compile.compress_debug_sections) {
517 .none => {},513 .none => {},
518 .zlib => try zig_args.append("--compress-debug-sections=zlib"),514 .zlib => try zig_args.append(gpa, "--compress-debug-sections=zlib"),
519 .zstd => try zig_args.append("--compress-debug-sections=zstd"),515 .zstd => try zig_args.append(gpa, "--compress-debug-sections=zstd"),
520 }516 }
521517
522 if (compile.link_eh_frame_hdr) {518 if (compile.link_eh_frame_hdr) {
523 try zig_args.append("--eh-frame-hdr");519 try zig_args.append(gpa, "--eh-frame-hdr");
524 }520 }
525 if (compile.link_emit_relocs) {521 if (compile.link_emit_relocs) {
526 try zig_args.append("--emit-relocs");522 try zig_args.append(gpa, "--emit-relocs");
527 }523 }
528 if (compile.link_function_sections) {524 if (compile.link_function_sections) {
529 try zig_args.append("-ffunction-sections");525 try zig_args.append(gpa, "-ffunction-sections");
530 }526 }
531 if (compile.link_data_sections) {527 if (compile.link_data_sections) {
532 try zig_args.append("-fdata-sections");528 try zig_args.append(gpa, "-fdata-sections");
533 }529 }
534 if (compile.link_gc_sections) |x| {530 if (compile.link_gc_sections) |x| {
535 try zig_args.append(if (x) "--gc-sections" else "--no-gc-sections");531 try zig_args.append(gpa, if (x) "--gc-sections" else "--no-gc-sections");
536 }532 }
537 if (!compile.linker_dynamicbase) {533 if (!compile.linker_dynamicbase) {
538 try zig_args.append("--no-dynamicbase");534 try zig_args.append(gpa, "--no-dynamicbase");
539 }535 }
540 if (compile.linker_allow_shlib_undefined) |x| {536 if (compile.linker_allow_shlib_undefined) |x| {
541 try zig_args.append(if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");537 try zig_args.append(gpa, if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");
542 }538 }
543 if (compile.link_z_notext) {539 if (compile.link_z_notext) try zig_args.appendSlice(gpa, &.{ "-z", "notext" });
544 try zig_args.append("-z");540 if (!compile.link_z_relro) try zig_args.appendSlice(gpa, &.{ "-z", "norelro" });
545 try zig_args.append("notext");541 if (compile.link_z_lazy) try zig_args.appendSlice(gpa, &.{ "-z", "lazy" });
546 }542 if (compile.link_z_common_page_size) |size| try zig_args.appendSlice(gpa, &.{
547 if (!compile.link_z_relro) {543 "-z",
548 try zig_args.append("-z");544 try allocPrint(arena, "common-page-size={d}", .{size}),
549 try zig_args.append("norelro");545 });
550 }546 if (compile.link_z_max_page_size) |size| try zig_args.appendSlice(gpa, &.{
551 if (compile.link_z_lazy) {547 "-z",
552 try zig_args.append("-z");548 try allocPrint(arena, "max-page-size={d}", .{size}),
553 try zig_args.append("lazy");549 });
554 }550 if (compile.link_z_defs) try zig_args.appendSlice(gpa, &.{ "-z", "defs" });
555 if (compile.link_z_common_page_size) |size| {
556 try zig_args.append("-z");
557 try zig_args.append(b.fmt("common-page-size={d}", .{size}));
558 }
559 if (compile.link_z_max_page_size) |size| {
560 try zig_args.append("-z");
561 try zig_args.append(b.fmt("max-page-size={d}", .{size}));
562 }
563 if (compile.link_z_defs) {
564 try zig_args.append("-z");
565 try zig_args.append("defs");
566 }
567551
568 if (compile.libc_file) |libc_file| {552 if (compile.libc_file) |libc_file| {
569 try zig_args.append("--libc");553 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file.getPath2(step) });
570 try zig_args.append(libc_file.getPath2(b, step));554 } else if (graph.libc_file) |libc_file| {
571 } else if (b.libc_file) |libc_file| {555 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file });
572 try zig_args.append("--libc");
573 try zig_args.append(libc_file);
574 }556 }
575557
576 try zig_args.append("--cache-dir");558 try zig_args.append(gpa, "--cache-dir");
577 try zig_args.append(b.cache_root.path orelse ".");559 try zig_args.append(gpa, graph.cache_root.path orelse ".");
578560
579 try zig_args.append("--global-cache-dir");561 try zig_args.append(gpa, "--global-cache-dir");
580 try zig_args.append(graph.global_cache_root.path orelse ".");562 try zig_args.append(gpa, graph.global_cache_root.path orelse ".");
581563
582 if (graph.debug_compiler_runtime_libs) |mode|564 if (graph.debug_compiler_runtime_libs) |mode|
583 try zig_args.append(b.fmt("--debug-rt={t}", .{mode}));565 try zig_args.append(gpa, try allocPrint(arena, "--debug-rt={t}", .{mode}));
584566
585 try zig_args.append("--name");567 try zig_args.append(gpa, "--name");
586 try zig_args.append(compile.name);568 try zig_args.append(gpa, compile.name);
587569
588 if (compile.linkage) |some| switch (some) {570 if (compile.linkage) |some| switch (some) {
589 .dynamic => try zig_args.append("-dynamic"),571 .dynamic => try zig_args.append(gpa, "-dynamic"),
590 .static => try zig_args.append("-static"),572 .static => try zig_args.append(gpa, "-static"),
591 };573 };
592 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {574 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
593 if (compile.version) |version| {575 if (compile.version) |version| {
594 try zig_args.append("--version");576 try zig_args.append(gpa, "--version");
595 try zig_args.append(b.fmt("{f}", .{version}));577 try zig_args.append(gpa, try allocPrint(arena, "{f}", .{version}));
596 }578 }
597579
598 if (compile.rootModuleTarget().os.tag.isDarwin()) {580 if (compile.rootModuleTarget().os.tag.isDarwin()) {
599 const install_name = compile.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{581 const install_name = compile.install_name orelse try allocPrint(arena, "@rpath/{s}{s}{s}", .{
600 compile.rootModuleTarget().libPrefix(),582 compile.rootModuleTarget().libPrefix(),
601 compile.name,583 compile.name,
602 compile.rootModuleTarget().dynamicLibSuffix(),584 compile.rootModuleTarget().dynamicLibSuffix(),
603 });585 });
604 try zig_args.append("-install_name");586 try zig_args.append(gpa, "-install_name");
605 try zig_args.append(install_name);587 try zig_args.append(gpa, install_name);
606 }588 }
607 }589 }
608590
609 if (compile.entitlements) |entitlements| {591 if (compile.entitlements) |entitlements| {
610 try zig_args.appendSlice(&[_][]const u8{ "--entitlements", entitlements });592 try zig_args.appendSlice(gpa, &[_][]const u8{ "--entitlements", entitlements });
611 }593 }
612 if (compile.pagezero_size) |pagezero_size| {594 if (compile.pagezero_size) |pagezero_size| {
613 const size = try std.fmt.allocPrint(arena, "{x}", .{pagezero_size});595 const size = try allocPrint(arena, "{x}", .{pagezero_size});
614 try zig_args.appendSlice(&[_][]const u8{ "-pagezero_size", size });596 try zig_args.appendSlice(gpa, &[_][]const u8{ "-pagezero_size", size });
615 }597 }
616 if (compile.headerpad_size) |headerpad_size| {598 if (compile.headerpad_size) |headerpad_size| {
617 const size = try std.fmt.allocPrint(arena, "{x}", .{headerpad_size});599 const size = try allocPrint(arena, "{x}", .{headerpad_size});
618 try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size });600 try zig_args.appendSlice(gpa, &[_][]const u8{ "-headerpad", size });
619 }601 }
620 if (compile.headerpad_max_install_names) {602 if (compile.headerpad_max_install_names) {
621 try zig_args.append("-headerpad_max_install_names");603 try zig_args.append(gpa, "-headerpad_max_install_names");
622 }604 }
623 if (compile.dead_strip_dylibs) {605 if (compile.dead_strip_dylibs) {
624 try zig_args.append("-dead_strip_dylibs");606 try zig_args.append(gpa, "-dead_strip_dylibs");
625 }607 }
626 if (compile.force_load_objc) {608 if (compile.force_load_objc) {
627 try zig_args.append("-ObjC");609 try zig_args.append(gpa, "-ObjC");
628 }610 }
629 if (compile.discard_local_symbols) {611 if (compile.discard_local_symbols) {
630 try zig_args.append("--discard-all");612 try zig_args.append(gpa, "--discard-all");
631 }613 }
632614
633 try addFlag(&zig_args, "compiler-rt", compile.bundle_compiler_rt);615 try addFlag(&zig_args, "compiler-rt", compile.bundle_compiler_rt);
634 try addFlag(&zig_args, "ubsan-rt", compile.bundle_ubsan_rt);616 try addFlag(&zig_args, "ubsan-rt", compile.bundle_ubsan_rt);
635 try addFlag(&zig_args, "dll-export-fns", compile.dll_export_fns);617 try addFlag(&zig_args, "dll-export-fns", compile.dll_export_fns);
636 if (compile.rdynamic) {618 if (compile.rdynamic) {
637 try zig_args.append("-rdynamic");619 try zig_args.append(gpa, "-rdynamic");
638 }620 }
639 if (compile.import_memory) {621 if (compile.import_memory) {
640 try zig_args.append("--import-memory");622 try zig_args.append(gpa, "--import-memory");
641 }623 }
642 if (compile.export_memory) {624 if (compile.export_memory) {
643 try zig_args.append("--export-memory");625 try zig_args.append(gpa, "--export-memory");
644 }626 }
645 if (compile.import_symbols) {627 if (compile.import_symbols) {
646 try zig_args.append("--import-symbols");628 try zig_args.append(gpa, "--import-symbols");
647 }629 }
648 if (compile.import_table) {630 if (compile.import_table) {
649 try zig_args.append("--import-table");631 try zig_args.append(gpa, "--import-table");
650 }632 }
651 if (compile.export_table) {633 if (compile.export_table) {
652 try zig_args.append("--export-table");634 try zig_args.append(gpa, "--export-table");
653 }635 }
654 if (compile.initial_memory) |initial_memory| {636 if (compile.initial_memory) |initial_memory| {
655 try zig_args.append(b.fmt("--initial-memory={d}", .{initial_memory}));637 try zig_args.append(gpa, try allocPrint(arena, "--initial-memory={d}", .{initial_memory}));
656 }638 }
657 if (compile.max_memory) |max_memory| {639 if (compile.max_memory) |max_memory| {
658 try zig_args.append(b.fmt("--max-memory={d}", .{max_memory}));640 try zig_args.append(gpa, try allocPrint(arena, "--max-memory={d}", .{max_memory}));
659 }641 }
660 if (compile.shared_memory) {642 if (compile.shared_memory) {
661 try zig_args.append("--shared-memory");643 try zig_args.append(gpa, "--shared-memory");
662 }644 }
663 if (compile.global_base) |global_base| {645 if (compile.global_base) |global_base| {
664 try zig_args.append(b.fmt("--global-base={d}", .{global_base}));646 try zig_args.append(gpa, try allocPrint(arena, "--global-base={d}", .{global_base}));
665 }647 }
666648
667 if (compile.wasi_exec_model) |model| {649 if (compile.wasi_exec_model) |model| {
668 try zig_args.append(b.fmt("-mexec-model={s}", .{@tagName(model)}));650 try zig_args.append(gpa, try allocPrint(arena, "-mexec-model={t}", .{model}));
669 }651 }
670 if (compile.linker_script) |linker_script| {652 if (compile.linker_script) |linker_script| {
671 try zig_args.append("--script");653 try zig_args.append(gpa, "--script");
672 try zig_args.append(linker_script.getPath2(b, step));654 try zig_args.append(gpa, linker_script.getPath2(step));
673 }655 }
674656
675 if (compile.version_script) |version_script| {657 if (compile.version_script) |version_script| {
676 try zig_args.append("--version-script");658 try zig_args.append(gpa, "--version-script");
677 try zig_args.append(version_script.getPath2(b, step));659 try zig_args.append(gpa, version_script.getPath2(step));
678 }660 }
679 if (compile.linker_allow_undefined_version) |x| {661 if (compile.linker_allow_undefined_version) |x| {
680 try zig_args.append(if (x) "--undefined-version" else "--no-undefined-version");662 try zig_args.append(gpa, if (x) "--undefined-version" else "--no-undefined-version");
681 }663 }
682664
683 if (compile.linker_enable_new_dtags) |enabled| {665 if (compile.linker_enable_new_dtags) |enabled| {
684 try zig_args.append(if (enabled) "--enable-new-dtags" else "--disable-new-dtags");666 try zig_args.append(gpa, if (enabled) "--enable-new-dtags" else "--disable-new-dtags");
685 }667 }
686668
687 if (compile.kind == .@"test") {669 if (compile.kind == .@"test") {
688 if (compile.exec_cmd_args) |exec_cmd_args| {670 if (compile.exec_cmd_args) |exec_cmd_args| {
689 for (exec_cmd_args) |cmd_arg| {671 for (exec_cmd_args) |cmd_arg| {
690 if (cmd_arg) |arg| {672 if (cmd_arg) |arg| {
691 try zig_args.append("--test-cmd");673 try zig_args.append(gpa, "--test-cmd");
692 try zig_args.append(arg);674 try zig_args.append(gpa, arg);
693 } else {675 } else {
694 try zig_args.append("--test-cmd-bin");676 try zig_args.append(gpa, "--test-cmd-bin");
695 }677 }
696 }678 }
697 }679 }
698 }680 }
699681
700 if (b.sysroot) |sysroot| {682 if (graph.sysroot) |sysroot| try zig_args.appendSlice(gpa, &.{ "--sysroot", sysroot });
701 try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot });
702 }
703683
704 // -I and -L arguments that appear after the last --mod argument apply to all modules.684 // -I and -L arguments that appear after the last --mod argument apply to all modules.
705 const cwd: Io.Dir = .cwd();685 const cwd: Io.Dir = .cwd();
706 const io = graph.io;686 const io = graph.io;
707687
708 for (b.search_prefixes.items) |search_prefix| {688 for (graph.search_prefixes.items) |search_prefix| {
709 var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| {689 var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| {
710 return step.fail("unable to open prefix directory '{s}': {s}", .{690 return step.fail("unable to open prefix directory '{s}': {t}", .{ search_prefix, err });
711 search_prefix, @errorName(err),
712 });
713 };691 };
714 defer prefix_dir.close(io);692 defer prefix_dir.close(io);
715693
...@@ -718,58 +696,53 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -718,58 +696,53 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
718 // CLI parsing code, when the linker sees an -L directory that does not exist.696 // CLI parsing code, when the linker sees an -L directory that does not exist.
719697
720 if (prefix_dir.access(io, "lib", .{})) |_| {698 if (prefix_dir.access(io, "lib", .{})) |_| {
721 try zig_args.appendSlice(&.{699 try zig_args.appendSlice(gpa, &.{
722 "-L", b.pathJoin(&.{ search_prefix, "lib" }),700 "-L", try Dir.path.join(arena, &.{ search_prefix, "lib" }),
723 });701 });
724 } else |err| switch (err) {702 } else |err| switch (err) {
725 error.FileNotFound => {},703 error.FileNotFound => {},
726 else => |e| return step.fail("unable to access '{s}/lib' directory: {s}", .{704 else => |e| return step.fail("unable to access '{s}/lib' directory: {t}", .{ search_prefix, e }),
727 search_prefix, @errorName(e),
728 }),
729 }705 }
730706
731 if (prefix_dir.access(io, "include", .{})) |_| {707 if (prefix_dir.access(io, "include", .{})) |_| {
732 try zig_args.appendSlice(&.{708 try zig_args.appendSlice(gpa, &.{
733 "-I", b.pathJoin(&.{ search_prefix, "include" }),709 "-I", try Dir.path.join(arena, &.{ search_prefix, "include" }),
734 });710 });
735 } else |err| switch (err) {711 } else |err| switch (err) {
736 error.FileNotFound => {},712 error.FileNotFound => {},
737 else => |e| return step.fail("unable to access '{s}/include' directory: {s}", .{713 else => |e| return step.fail("unable to access '{s}/include' directory: {t}", .{ search_prefix, e }),
738 search_prefix, @errorName(e),
739 }),
740 }714 }
741 }715 }
742716
743 if (compile.rc_includes != .any) {717 if (compile.rc_includes != .any) {
744 try zig_args.append("-rcincludes");718 try zig_args.appendSlice(gpa, &.{ "-rcincludes", @tagName(compile.rc_includes) });
745 try zig_args.append(@tagName(compile.rc_includes));
746 }719 }
747720
748 try addFlag(&zig_args, "each-lib-rpath", compile.each_lib_rpath);721 try addFlag(&zig_args, "each-lib-rpath", compile.each_lib_rpath);
749722
750 if (compile.build_id orelse b.build_id) |build_id| {723 if (compile.build_id orelse graph.build_id) |build_id| {
751 try zig_args.append(switch (build_id) {724 try zig_args.append(gpa, switch (build_id) {
752 .hexstring => |hs| b.fmt("--build-id=0x{x}", .{hs.toSlice()}),725 .hexstring => |hs| try allocPrint(arena, "--build-id=0x{x}", .{hs.toSlice()}),
753 .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),726 .none, .fast, .uuid, .sha1, .md5 => try allocPrint(arena, "--build-id={t}", .{build_id}),
754 });727 });
755 }728 }
756729
757 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|730 const opt_zig_lib_dir = if (compile.zig_lib_dir) |dir|
758 dir.getPath2(b, step)731 dir.getPath2(step)
759 else if (graph.zig_lib_directory.path) |_|732 else if (graph.zig_lib_directory.path) |_|
760 b.fmt("{f}", .{graph.zig_lib_directory})733 try allocPrint(arena, "{f}", .{graph.zig_lib_directory})
761 else734 else
762 null;735 null;
763736
764 if (opt_zig_lib_dir) |zig_lib_dir| {737 if (opt_zig_lib_dir) |zig_lib_dir| {
765 try zig_args.append("--zig-lib-dir");738 try zig_args.append(gpa, "--zig-lib-dir");
766 try zig_args.append(zig_lib_dir);739 try zig_args.append(gpa, zig_lib_dir);
767 }740 }
768741
769 try addFlag(&zig_args, "PIE", compile.pie);742 try addFlag(&zig_args, "PIE", compile.pie);
770743
771 if (compile.lto) |lto| {744 if (compile.lto) |lto| {
772 try zig_args.append(switch (lto) {745 try zig_args.append(gpa, switch (lto) {
773 .full => "-flto=full",746 .full => "-flto=full",
774 .thin => "-flto=thin",747 .thin => "-flto=thin",
775 .none => "-fno-lto",748 .none => "-fno-lto",
...@@ -779,21 +752,20 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -779,21 +752,20 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
779 try addFlag(&zig_args, "sanitize-coverage-trace-pc-guard", compile.sanitize_coverage_trace_pc_guard);752 try addFlag(&zig_args, "sanitize-coverage-trace-pc-guard", compile.sanitize_coverage_trace_pc_guard);
780753
781 if (compile.subsystem) |subsystem| {754 if (compile.subsystem) |subsystem| {
782 try zig_args.append("--subsystem");755 try zig_args.appendSlice(gpa, &.{ "--subsystem", @tagName(subsystem) });
783 try zig_args.append(@tagName(subsystem));
784 }756 }
785757
786 if (compile.mingw_unicode_entry_point) {758 if (compile.mingw_unicode_entry_point) {
787 try zig_args.append("-municode");759 try zig_args.append(gpa, "-municode");
788 }760 }
789761
790 if (compile.error_limit) |err_limit| try zig_args.appendSlice(&.{762 if (compile.error_limit) |err_limit| try zig_args.appendSlice(gpa, &.{
791 "--error-limit", b.fmt("{d}", .{err_limit}),763 "--error-limit", try allocPrint(arena, "{d}", .{err_limit}),
792 });764 });
793765
794 try addFlag(&zig_args, "incremental", graph.incremental);766 try addFlag(&zig_args, "incremental", graph.incremental);
795767
796 try zig_args.append("--listen=-");768 try zig_args.append(gpa, "--listen=-");
797769
798 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux770 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux
799 // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and771 // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and
...@@ -804,7 +776,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -804,7 +776,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
804 args_length += arg.len + 1; // +1 to account for null terminator776 args_length += arg.len + 1; // +1 to account for null terminator
805 }777 }
806 if (args_length >= 30 * 1024) {778 if (args_length >= 30 * 1024) {
807 try b.cache_root.handle.createDirPath(io, "args");779 try graph.cache_root.handle.createDirPath(io, "args");
808780
809 const args_to_escape = zig_args.items[2..];781 const args_to_escape = zig_args.items[2..];
810 var escaped_args = try std.array_list.Managed([]const u8).initCapacity(arena, args_to_escape.len);782 var escaped_args = try std.array_list.Managed([]const u8).initCapacity(arena, args_to_escape.len);
...@@ -837,21 +809,21 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -837,21 +809,21 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
837 _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});809 _ = try std.fmt.bufPrint(&args_hex_hash, "{x}", .{&args_hash});
838810
839 const args_file = "args" ++ Dir.path.sep_str ++ args_hex_hash;811 const args_file = "args" ++ Dir.path.sep_str ++ args_hex_hash;
840 if (b.cache_root.handle.access(io, args_file, .{})) |_| {812 if (graph.cache_root.handle.access(io, args_file, .{})) |_| {
841 // The args file is already present from a previous run.813 // The args file is already present from a previous run.
842 } else |err| switch (err) {814 } else |err| switch (err) {
843 error.FileNotFound => {815 error.FileNotFound => {
844 var af = b.cache_root.handle.createFileAtomic(io, args_file, .{816 var af = graph.cache_root.handle.createFileAtomic(io, args_file, .{
845 .replace = false,817 .replace = false,
846 .make_path = true,818 .make_path = true,
847 }) catch |e| return step.fail("failed creating tmp args file {f}{s}: {t}", .{819 }) catch |e| return step.fail("failed creating tmp args file {f}{s}: {t}", .{
848 b.cache_root, args_file, e,820 graph.cache_root, args_file, e,
849 });821 });
850 defer af.deinit(io);822 defer af.deinit(io);
851823
852 af.file.writeStreamingAll(io, args) catch |e| {824 af.file.writeStreamingAll(io, args) catch |e| {
853 return step.fail("failed writing args data to tmp file {f}{s}: {t}", .{825 return step.fail("failed writing args data to tmp file {f}{s}: {t}", .{
854 b.cache_root, args_file, e,826 graph.cache_root, args_file, e,
855 });827 });
856 };828 };
857 // Note we can't clean up this file, not even after build829 // Note we can't clean up this file, not even after build
...@@ -862,7 +834,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -862,7 +834,7 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
862 // The args file was created by another concurrent build process.834 // The args file was created by another concurrent build process.
863 },835 },
864 else => |other_err| return step.fail("failed linking tmp file {f}{s}: {t}", .{836 else => |other_err| return step.fail("failed linking tmp file {f}{s}: {t}", .{
865 b.cache_root, args_file, other_err,837 graph.cache_root, args_file, other_err,
866 }),838 }),
867 };839 };
868 },840 },
...@@ -871,32 +843,34 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {...@@ -871,32 +843,34 @@ fn getZigArgs(compile: *Compile, maker: *Maker, fuzz: bool) ![][]const u8 {
871843
872 const resolved_args_file = try mem.concat(arena, u8, &.{844 const resolved_args_file = try mem.concat(arena, u8, &.{
873 "@",845 "@",
874 try b.cache_root.join(arena, &.{args_file}),846 try graph.cache_root.join(arena, &.{args_file}),
875 });847 });
876848
877 zig_args.shrinkRetainingCapacity(2);849 zig_args.shrinkRetainingCapacity(2);
878 try zig_args.append(resolved_args_file);850 try zig_args.append(gpa, resolved_args_file);
879 }851 }
880852
881 return try zig_args.toOwnedSlice();853 return try zig_args.toOwnedSlice();
882}854}
883855
884pub fn rebuildInFuzzMode(c: *Compile, maker: *Maker, progress_node: std.Progress.Node) !Path {856pub fn rebuildInFuzzMode(compile: *Compile, maker: *Maker, progress_node: std.Progress.Node) !Path {
885 const gpa = maker.graph.gpa;857 const gpa = maker.graph.gpa;
886858
887 c.step.result_error_msgs.clearRetainingCapacity();859 compile.step.result_error_msgs.clearRetainingCapacity();
888 c.step.result_stderr = "";860 compile.step.result_stderr = "";
889861
890 c.step.result_error_bundle.deinit(gpa);862 compile.step.result_error_bundle.deinit(gpa);
891 c.step.result_error_bundle = std.zig.ErrorBundle.empty;863 compile.step.result_error_bundle = std.zig.ErrorBundle.empty;
892864
893 if (c.step.result_failed_command) |cmd| {865 if (compile.step.result_failed_command) |cmd| {
894 gpa.free(cmd);866 gpa.free(cmd);
895 c.step.result_failed_command = null;867 compile.step.result_failed_command = null;
896 }868 }
897869
898 const zig_args = try getZigArgs(c, maker, true);870 const zig_args = &compile.zig_args;
899 const maybe_output_bin_path = try c.step.evalZigProcess(zig_args, progress_node, false, null, gpa);871 zig_args.clearRetainingCapacity();
872 try lowerZigArgs(compile, maker, zig_args, true);
873 const maybe_output_bin_path = try compile.step.evalZigProcess(zig_args.items, progress_node, false, maker);
900 return maybe_output_bin_path.?;874 return maybe_output_bin_path.?;
901}875}
902876
...@@ -907,24 +881,24 @@ pub fn doAtomicSymLinks(...@@ -907,24 +881,24 @@ pub fn doAtomicSymLinks(
907 filename_major_only: []const u8,881 filename_major_only: []const u8,
908 filename_name_only: []const u8,882 filename_name_only: []const u8,
909) !void {883) !void {
910 const b = step.owner;
911 const graph = maker.graph;884 const graph = maker.graph;
885 const arena = graph.arena; // TODO don't leak into process arena
912 const io = graph.io;886 const io = graph.io;
913 const out_dir = Dir.path.dirname(output_path) orelse ".";887 const out_dir = Dir.path.dirname(output_path) orelse ".";
914 const out_basename = Dir.path.basename(output_path);888 const out_basename = Dir.path.basename(output_path);
915 // sym link for libfoo.so.1 to libfoo.so.1.2.3889 // sym link for libfoo.so.1 to libfoo.so.1.2.3
916 const major_only_path = b.pathJoin(&.{ out_dir, filename_major_only });890 const major_only_path = try Dir.path.join(arena, &.{ out_dir, filename_major_only });
917 const cwd: Io.Dir = .cwd();891 const cwd: Io.Dir = .cwd();
918 cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| {892 cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| {
919 return step.fail("unable to symlink {s} -> {s}: {s}", .{893 return step.fail("unable to symlink {s} -> {s}: {t}", .{
920 major_only_path, out_basename, @errorName(err),894 major_only_path, out_basename, err,
921 });895 });
922 };896 };
923 // sym link for libfoo.so to libfoo.so.1897 // sym link for libfoo.so to libfoo.so.1
924 const name_only_path = b.pathJoin(&.{ out_dir, filename_name_only });898 const name_only_path = try Dir.path.join(arena, &.{ out_dir, filename_name_only });
925 cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| {899 cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| {
926 return step.fail("Unable to symlink {s} -> {s}: {s}", .{900 return step.fail("unable to symlink {s} -> {s}: {t}", .{
927 name_only_path, filename_major_only, @errorName(err),901 name_only_path, filename_major_only, err,
928 });902 });
929 };903 };
930}904}
...@@ -983,14 +957,13 @@ fn getPkgConfigList(b: *std.Build) ![]const PkgConfigPkg {...@@ -983,14 +957,13 @@ fn getPkgConfigList(b: *std.Build) ![]const PkgConfigPkg {
983 }957 }
984}958}
985959
986fn addFlag(args: *std.array_list.Managed([]const u8), comptime name: []const u8, opt: ?bool) !void {960fn addBool(gpa: Allocator, args: *std.ArrayList([]const u8), arg: []const u8, opt: bool) !void {
961 if (opt) try args.append(gpa, arg);
962}
963
964fn addFlag(gpa: Allocator, args: *std.ArrayList([]const u8), comptime name: []const u8, opt: ?bool) !void {
987 const cond = opt orelse return;965 const cond = opt orelse return;
988 try args.ensureUnusedCapacity(1);966 try args.append(gpa, if (cond) "-f" ++ name else "-fno-" ++ name);
989 if (cond) {
990 args.appendAssumeCapacity("-f" ++ name);
991 } else {
992 args.appendAssumeCapacity("-fno-" ++ name);
993 }
994}967}
995968
996const PkgConfigResult = struct {969const PkgConfigResult = struct {
...@@ -1267,7 +1240,7 @@ const CliNamedModules = struct {...@@ -1267,7 +1240,7 @@ const CliNamedModules = struct {
1267 try compile.modules.putNoClobber(arena, mod, {});1240 try compile.modules.putNoClobber(arena, mod, {});
1268 break;1241 break;
1269 }1242 }
1270 name = try std.fmt.allocPrint(arena, "{s}{d}", .{ orig_name, n });1243 name = try allocPrint(arena, "{s}{d}", .{ orig_name, n });
1271 n += 1;1244 n += 1;
1272 }1245 }
1273 }1246 }
lib/compiler/Maker/Step/Run.zig+2-2
...@@ -1564,7 +1564,7 @@ fn runCommand(...@@ -1564,7 +1564,7 @@ fn runCommand(
1564 const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit;1564 const cwd: process.Child.Cwd = if (run.cwd) |lazy_cwd| .{ .path = lazy_cwd.getPath2(b, step) } else .inherit;
15651565
1566 try step.handleChildProcUnsupported();1566 try step.handleChildProcUnsupported();
1567 try Step.handleVerbose2(step.owner, cwd, run.environ_map, argv);1567 try Step.handleVerbose(step.owner, cwd, run.environ_map, argv);
15681568
1569 const allow_skip = switch (run.stdio) {1569 const allow_skip = switch (run.stdio) {
1570 .check, .zig_test => run.skip_foreign_checks,1570 .check, .zig_test => run.skip_foreign_checks,
...@@ -1701,7 +1701,7 @@ fn runCommand(...@@ -1701,7 +1701,7 @@ fn runCommand(
17011701
1702 gpa.free(step.result_failed_command.?);1702 gpa.free(step.result_failed_command.?);
1703 step.result_failed_command = null;1703 step.result_failed_command = null;
1704 try Step.handleVerbose2(step.owner, cwd, run.environ_map, interp_argv.items);1704 try Step.handleVerbose(step.owner, cwd, run.environ_map, interp_argv.items);
17051705
1706 break :term spawnChildAndCollect(run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| {1706 break :term spawnChildAndCollect(run, maker, progress_node, interp_argv.items, &environ_map, has_side_effects, fuzz_context) catch |e| {
1707 if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;1707 if (!run.failing_to_execute_foreign_is_an_error) return error.MakeSkipped;
lib/compiler/configure_runner.zig+8-17
...@@ -148,39 +148,30 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -148,39 +148,30 @@ pub fn main(init: process.Init.Minimal) !void {
148 graph.release_mode = .any;148 graph.release_mode = .any;
149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {149 } else if (mem.cutPrefix(u8, arg, "--release=")) |text| {
150 graph.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse {150 graph.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse {
151 fatalWithHint("expected [off|any|fast|safe|small] in '{s}', found '{s}'", .{151 fatalWithHint("expected [off|any|fast|safe|small] in {q}, found {q}", .{
152 arg, text,152 arg, text,
153 });153 });
154 };154 };
155 } else if (mem.eql(u8, arg, "--color")) {155 } else if (mem.eql(u8, arg, "--color")) {
156 const next_arg = nextArg(args, &arg_idx) orelse156 const next_arg = nextArg(args, &arg_idx) orelse
157 fatalWithHint("expected [auto|on|off] after '{s}'", .{arg});157 fatalWithHint("expected [auto|on|off] after {q}", .{arg});
158 color = std.meta.stringToEnum(Color, next_arg) orelse {158 color = std.meta.stringToEnum(Color, next_arg) orelse {
159 fatalWithHint("expected [auto|on|off] after '{s}', found '{s}'", .{159 fatalWithHint("expected [auto|on|off] after {q}, found {q}", .{
160 arg, next_arg,160 arg, next_arg,
161 });161 });
162 };162 };
163 } else if (mem.eql(u8, arg, "--error-style")) {163 } else if (mem.eql(u8, arg, "--error-style")) {
164 const next_arg = nextArg(args, &arg_idx) orelse164 const next_arg = nextArg(args, &arg_idx) orelse
165 fatalWithHint("expected style after '{s}'", .{arg});165 fatalWithHint("expected style after {q}", .{arg});
166 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {166 error_style = std.meta.stringToEnum(ErrorStyle, next_arg) orelse {
167 fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });167 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
168 };168 };
169 } else if (mem.eql(u8, arg, "--multiline-errors")) {169 } else if (mem.eql(u8, arg, "--multiline-errors")) {
170 const next_arg = nextArg(args, &arg_idx) orelse170 const next_arg = nextArg(args, &arg_idx) orelse
171 fatalWithHint("expected style after '{s}'", .{arg});171 fatalWithHint("expected style after {q}", .{arg});
172 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {172 multiline_errors = std.meta.stringToEnum(MultilineErrors, next_arg) orelse {
173 fatalWithHint("expected style after '{s}', found '{s}'", .{ arg, next_arg });173 fatalWithHint("expected style after {q}, found {q}", .{ arg, next_arg });
174 };174 };
175 } else if (mem.eql(u8, arg, "--build-id")) {
176 builder.build_id = .fast;
177 } else if (mem.cutPrefix(u8, arg, "--build-id=")) |style| {
178 builder.build_id = std.zig.BuildId.parse(style) catch |err|
179 fatal("unable to parse --build-id style '{s}': {t}", .{ style, err });
180 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
181 builder.debug_compile_errors = true;
182 } else if (mem.eql(u8, arg, "--debug-incremental")) {
183 builder.debug_incremental = true;
184 } else if (mem.eql(u8, arg, "--system")) {175 } else if (mem.eql(u8, arg, "--system")) {
185 // The usage text shows another argument after this parameter176 // The usage text shows another argument after this parameter
186 // but it is handled by the parent process. The build runner177 // but it is handled by the parent process. The build runner
...@@ -189,7 +180,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -189,7 +180,7 @@ pub fn main(init: process.Init.Minimal) !void {
189 } else if (mem.eql(u8, arg, "--have-run-args")) {180 } else if (mem.eql(u8, arg, "--have-run-args")) {
190 graph.have_run_args = true;181 graph.have_run_args = true;
191 } else {182 } else {
192 fatalWithHint("unrecognized argument: '{s}'", .{arg});183 fatalWithHint("unrecognized argument: {q}", .{arg});
193 }184 }
194 }185 }
195186
lib/std/Build.zig+11-173
...@@ -46,8 +46,6 @@ install_prefix: []const u8,...@@ -46,8 +46,6 @@ install_prefix: []const u8,
46build_root: Cache.Directory,46build_root: Cache.Directory,
47cache_root: Cache.Directory,47cache_root: Cache.Directory,
48debug_log_scopes: []const []const u8 = &.{},48debug_log_scopes: []const []const u8 = &.{},
49debug_compile_errors: bool = false,
50debug_incremental: bool = false,
51/// Number of stack frames captured when a `StackTrace` is recorded for debug purposes,49/// Number of stack frames captured when a `StackTrace` is recorded for debug purposes,
52/// in particular at `Step` creation.50/// in particular at `Step` creation.
53/// Set to 0 to disable stack collection.51/// Set to 0 to disable stack collection.
...@@ -75,8 +73,6 @@ pkg_hash: []const u8,...@@ -75,8 +73,6 @@ pkg_hash: []const u8,
75/// A mapping from dependency names to package hashes.73/// A mapping from dependency names to package hashes.
76available_deps: AvailableDeps,74available_deps: AvailableDeps,
7775
78build_id: ?std.zig.BuildId = null,
79
80pub const ReleaseMode = enum {76pub const ReleaseMode = enum {
81 off,77 off,
82 any,78 any,
...@@ -227,13 +223,6 @@ pub fn create(...@@ -227,13 +223,6 @@ pub fn create(
227 .graph = graph,223 .graph = graph,
228 .build_root = build_root,224 .build_root = build_root,
229 .cache_root = cache_root,225 .cache_root = cache_root,
230 .verbose = false,
231 .verbose_link = false,
232 .verbose_cc = false,
233 .verbose_air = false,
234 .verbose_llvm_ir = null,
235 .verbose_llvm_bc = null,
236 .verbose_llvm_cpu_features = false,
237 .invalid_user_input = false,226 .invalid_user_input = false,
238 .allocator = arena,227 .allocator = arena,
239 .user_input_options = UserInputOptionsMap.init(arena),228 .user_input_options = UserInputOptionsMap.init(arena),
...@@ -302,22 +291,12 @@ fn createChild(...@@ -302,22 +291,12 @@ fn createChild(
302 .user_input_options = user_input_options,291 .user_input_options = user_input_options,
303 .available_options_map = AvailableOptionsMap.init(allocator),292 .available_options_map = AvailableOptionsMap.init(allocator),
304 .available_options_list = std.array_list.Managed(AvailableOption).init(allocator),293 .available_options_list = std.array_list.Managed(AvailableOption).init(allocator),
305 .verbose = parent.verbose,
306 .verbose_link = parent.verbose_link,
307 .verbose_cc = parent.verbose_cc,
308 .verbose_air = parent.verbose_air,
309 .verbose_llvm_ir = parent.verbose_llvm_ir,
310 .verbose_llvm_bc = parent.verbose_llvm_bc,
311 .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
312 .invalid_user_input = false,294 .invalid_user_input = false,
313 .default_step = undefined,295 .default_step = undefined,
314 .top_level_steps = .{},296 .top_level_steps = .{},
315 .sysroot = parent.sysroot,
316 .build_root = build_root,297 .build_root = build_root,
317 .cache_root = parent.cache_root,298 .cache_root = parent.cache_root,
318 .debug_log_scopes = parent.debug_log_scopes,299 .debug_log_scopes = parent.debug_log_scopes,
319 .debug_compile_errors = parent.debug_compile_errors,
320 .debug_incremental = parent.debug_incremental,
321 .enable_darling = parent.enable_darling,300 .enable_darling = parent.enable_darling,
322 .enable_qemu = parent.enable_qemu,301 .enable_qemu = parent.enable_qemu,
323 .enable_rosetta = parent.enable_rosetta,302 .enable_rosetta = parent.enable_rosetta,
...@@ -1125,7 +1104,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1125,7 +1104,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1125 if (std.zig.BuildId.parse(s)) |build_id| {1104 if (std.zig.BuildId.parse(s)) |build_id| {
1126 return build_id;1105 return build_id;
1127 } else |err| {1106 } else |err| {
1128 log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) });1107 log.err("unable to parse option '-D{s}': {t}", .{ name, err });
1129 b.markInvalidUserInput();1108 b.markInvalidUserInput();
1130 return null;1109 return null;
1131 }1110 }
...@@ -1594,8 +1573,9 @@ pub fn addCheckFile(...@@ -1594,8 +1573,9 @@ pub fn addCheckFile(
1594}1573}
15951574
1596pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.CreateDirError || Io.Dir.StatFileError)!void {1575pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.CreateDirError || Io.Dir.StatFileError)!void {
1597 const io = b.graph.io;1576 const graph = b.graph;
1598 if (b.verbose) log.info("truncate {s}", .{dest_path});1577 const io = graph.io;
1578 if (graph.verbose) log.info("truncate {s}", .{dest_path});
1599 const cwd = Io.Dir.cwd();1579 const cwd = Io.Dir.cwd();
1600 var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) {1580 var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) {
1601 error.FileNotFound => blk: {1581 error.FileNotFound => blk: {
...@@ -1705,9 +1685,13 @@ pub fn runAllowFail(...@@ -1705,9 +1685,13 @@ pub fn runAllowFail(
17051685
1706 const graph = b.graph;1686 const graph = b.graph;
1707 const io = graph.io;1687 const io = graph.io;
1688 const arena = graph.arena;
17081689
1709 const max_output_size = 400 * 1024;1690 const max_output_size = 400 * 1024;
1710 try Step.handleVerbose2(b, .inherit, &graph.environ_map, argv);1691 if (graph.verbose) {
1692 const text = std.zig.allocPrintCmd(arena, .inherit, null, argv);
1693 std.log.scoped(.verbose).info("{s}", .{text});
1694 }
17111695
1712 var child = try std.process.spawn(io, .{1696 var child = try std.process.spawn(io, .{
1713 .argv = argv,1697 .argv = argv,
...@@ -1718,10 +1702,10 @@ pub fn runAllowFail(...@@ -1718,10 +1702,10 @@ pub fn runAllowFail(
1718 });1702 });
17191703
1720 var stdout_reader = child.stdout.?.readerStreaming(io, &.{});1704 var stdout_reader = child.stdout.?.readerStreaming(io, &.{});
1721 const stdout = stdout_reader.interface.allocRemaining(b.allocator, .limited(max_output_size)) catch {1705 const stdout = stdout_reader.interface.allocRemaining(arena, .limited(max_output_size)) catch {
1722 return error.ReadFailure;1706 return error.ReadFailure;
1723 };1707 };
1724 errdefer b.allocator.free(stdout);1708 errdefer arena.free(stdout);
17251709
1726 const term = try child.wait(io);1710 const term = try child.wait(io);
1727 switch (term) {1711 switch (term) {
...@@ -2089,34 +2073,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {...@@ -2089,34 +2073,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
2089pub const GeneratedFile = struct {2073pub const GeneratedFile = struct {
2090 /// The step that generates the file.2074 /// The step that generates the file.
2091 step: *Step,2075 step: *Step,
2092 /// The path to the generated file. Must be either absolute or relative to the build runner cwd.
2093 /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
2094 path: ?[]const u8 = null,
2095
2096 /// Deprecated, see `getPath3`.
2097 pub fn getPath(gen: GeneratedFile) []const u8 {
2098 return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(
2099 "getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?",
2100 .{gen.step.name},
2101 ));
2102 }
2103
2104 /// Deprecated, see `getPath3`.
2105 pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
2106 return getPath3(gen, src_builder, asking_step) catch |err| switch (err) {
2107 error.Canceled => std.process.exit(1),
2108 };
2109 }
2110
2111 pub fn getPath3(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) Io.Cancelable![]const u8 {
2112 return gen.path orelse {
2113 const graph = gen.step.owner.graph;
2114 const io = graph.io;
2115 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
2116 dumpBadGetPathHelp(gen.step, stderr.terminal(), src_builder, asking_step) catch {};
2117 @panic("misconfigured build script");
2118 };
2119 }
2120};2076};
21212077
2122// dirnameAllowEmpty is a variant of fs.path.dirname2078// dirnameAllowEmpty is a variant of fs.path.dirname
...@@ -2290,94 +2246,6 @@ pub const LazyPath = union(enum) {...@@ -2290,94 +2246,6 @@ pub const LazyPath = union(enum) {
2290 }2246 }
2291 }2247 }
22922248
2293 /// Deprecated, see `getPath4`.
2294 pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 {
2295 return getPath2(lazy_path, src_builder, null);
2296 }
2297
2298 /// Deprecated, see `getPath4`.
2299 pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
2300 const p = getPath3(lazy_path, src_builder, asking_step);
2301 return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path });
2302 }
2303
2304 /// Deprecated, see `getPath4`.
2305 pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path {
2306 return getPath4(lazy_path, src_builder, asking_step) catch |err| switch (err) {
2307 error.Canceled => std.process.exit(1),
2308 };
2309 }
2310
2311 /// Intended to be used during the make phase only.
2312 ///
2313 /// `asking_step` is only used for debugging purposes; it's the step being
2314 /// run that is asking for the path.
2315 pub fn getPath4(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Io.Cancelable!Cache.Path {
2316 switch (lazy_path) {
2317 .src_path => |sp| return .{
2318 .root_dir = sp.owner.build_root,
2319 .sub_path = sp.sub_path,
2320 },
2321 .cwd_relative => |sub_path| return .{
2322 .root_dir = Cache.Directory.cwd(),
2323 .sub_path = sub_path,
2324 },
2325 .generated => |gen| {
2326 // TODO make gen.file.path not be absolute and use that as the
2327 // basis for not traversing up too many directories.
2328
2329 const graph = src_builder.graph;
2330
2331 var file_path: Cache.Path = .{
2332 .root_dir = Cache.Directory.cwd(),
2333 .sub_path = gen.file.path orelse {
2334 const io = graph.io;
2335 const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
2336 dumpBadGetPathHelp(gen.file.step, stderr.terminal(), src_builder, asking_step) catch {};
2337 io.unlockStderr();
2338 @panic("misconfigured build script");
2339 },
2340 };
2341
2342 if (gen.up > 0) {
2343 const cache_root_path = src_builder.cache_root.path orelse
2344 (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM"));
2345
2346 for (0..gen.up) |_| {
2347 if (mem.eql(u8, file_path.sub_path, cache_root_path)) {
2348 // If we hit the cache root and there's still more to go,
2349 // the script attempted to go too far.
2350 dumpBadDirnameHelp(gen.file.step, asking_step,
2351 \\dirname() attempted to traverse outside the cache root.
2352 \\This is not allowed.
2353 \\
2354 , .{}) catch {};
2355 @panic("misconfigured build script");
2356 }
2357
2358 // path is absolute.
2359 // dirname will return null only if we're at root.
2360 // Typically, we'll stop well before that at the cache root.
2361 file_path.sub_path = fs.path.dirname(file_path.sub_path) orelse {
2362 dumpBadDirnameHelp(gen.file.step, asking_step,
2363 \\dirname() reached root.
2364 \\No more directories left to go up.
2365 \\
2366 , .{}) catch {};
2367 @panic("misconfigured build script");
2368 };
2369 }
2370 }
2371
2372 return file_path.join(src_builder.allocator, gen.sub_path) catch @panic("OOM");
2373 },
2374 .dependency => |dep| return .{
2375 .root_dir = dep.dependency.builder.build_root,
2376 .sub_path = dep.sub_path,
2377 },
2378 }
2379 }
2380
2381 pub fn basename(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {2249 pub fn basename(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
2382 return fs.path.basename(switch (lazy_path) {2250 return fs.path.basename(switch (lazy_path) {
2383 .src_path => |sp| sp.sub_path,2251 .src_path => |sp| sp.sub_path,
...@@ -2451,36 +2319,6 @@ fn dumpBadDirnameHelp(...@@ -2451,36 +2319,6 @@ fn dumpBadDirnameHelp(
2451 stderr.setColor(.reset) catch {};2319 stderr.setColor(.reset) catch {};
2452}2320}
24532321
2454/// In this function the stderr mutex has already been locked.
2455pub fn dumpBadGetPathHelp(s: *Step, t: Io.Terminal, src_builder: *Build, asking_step: ?*Step) anyerror!void {
2456 const w = t.writer;
2457 try w.print(
2458 \\getPath() was called on a GeneratedFile that wasn't built yet.
2459 \\ source package path: {s}
2460 \\ Is there a missing Step dependency on step '{s}'?
2461 \\
2462 , .{
2463 src_builder.build_root.path orelse ".",
2464 s.name,
2465 });
2466
2467 t.setColor(.red) catch {};
2468 try w.writeAll(" The step was created by this stack trace:\n");
2469 t.setColor(.reset) catch {};
2470
2471 s.dump(t);
2472 if (asking_step) |as| {
2473 t.setColor(.red) catch {};
2474 try w.print(" The step '{s}' that is missing a dependency on the above step was created by this stack trace:\n", .{as.name});
2475 t.setColor(.reset) catch {};
2476
2477 as.dump(t);
2478 }
2479 t.setColor(.red) catch {};
2480 try w.writeAll(" Proceeding to panic.\n");
2481 t.setColor(.reset) catch {};
2482}
2483
2484pub const InstallDir = union(enum) {2322pub const InstallDir = union(enum) {
2485 prefix: void,2323 prefix: void,
2486 lib: void,2324 lib: void,
lib/std/Build/Step/Compile.zig+4
...@@ -87,9 +87,13 @@ libc_file: ?LazyPath = null,...@@ -87,9 +87,13 @@ libc_file: ?LazyPath = null,
87each_lib_rpath: ?bool = null,87each_lib_rpath: ?bool = null,
88/// On ELF targets, this will emit a link section called ".note.gnu.build-id"88/// On ELF targets, this will emit a link section called ".note.gnu.build-id"
89/// which can be used to coordinate a stripped binary with its debug symbols.89/// which can be used to coordinate a stripped binary with its debug symbols.
90///
90/// As an example, the bloaty project refuses to work unless its inputs have91/// As an example, the bloaty project refuses to work unless its inputs have
91/// build ids, in order to prevent accidental mismatches.92/// build ids, in order to prevent accidental mismatches.
93///
92/// The default is to not include this section because it slows down linking.94/// The default is to not include this section because it slows down linking.
95///
96/// This option overrides the CLI argument passed to `zig build`.
93build_id: ?std.zig.BuildId = null,97build_id: ?std.zig.BuildId = null,
9498
95/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF99/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
lib/std/zig.zig+73
...@@ -1157,6 +1157,79 @@ pub const ClangCliParam = struct {...@@ -1157,6 +1157,79 @@ pub const ClangCliParam = struct {
1157 }1157 }
1158};1158};
11591159
1160pub fn allocPrintCmd(
1161 gpa: Allocator,
1162 cwd: std.process.Child.Cwd,
1163 opt_env: ?struct {
1164 child: *const std.process.Environ.Map,
1165 parent: *const std.process.Environ.Map,
1166 },
1167 argv: []const []const u8,
1168) Allocator.Error![]u8 {
1169 const shell = struct {
1170 fn escape(writer: *Io.Writer, string: []const u8, is_argv0: bool) !void {
1171 for (string) |c| {
1172 if (switch (c) {
1173 else => true,
1174 '%', '+'...':', '@'...'Z', '_', 'a'...'z' => false,
1175 '=' => is_argv0,
1176 }) break;
1177 } else return writer.writeAll(string);
1178
1179 try writer.writeByte('"');
1180 for (string) |c| {
1181 if (switch (c) {
1182 std.ascii.control_code.nul => break,
1183 '!', '"', '$', '\\', '`' => true,
1184 else => !std.ascii.isPrint(c),
1185 }) try writer.writeByte('\\');
1186 switch (c) {
1187 std.ascii.control_code.nul => unreachable,
1188 std.ascii.control_code.bel => try writer.writeByte('a'),
1189 std.ascii.control_code.bs => try writer.writeByte('b'),
1190 std.ascii.control_code.ht => try writer.writeByte('t'),
1191 std.ascii.control_code.lf => try writer.writeByte('n'),
1192 std.ascii.control_code.vt => try writer.writeByte('v'),
1193 std.ascii.control_code.ff => try writer.writeByte('f'),
1194 std.ascii.control_code.cr => try writer.writeByte('r'),
1195 std.ascii.control_code.esc => try writer.writeByte('E'),
1196 ' '...'~' => try writer.writeByte(c),
1197 else => try writer.print("{o:0>3}", .{c}),
1198 }
1199 }
1200 try writer.writeByte('"');
1201 }
1202 };
1203
1204 var aw: Io.Writer.Allocating = .init(gpa);
1205 defer aw.deinit();
1206 const writer = &aw.writer;
1207 switch (cwd) {
1208 .inherit => {},
1209 .path => |path| writer.print("cd {s} && ", .{path}) catch return error.OutOfMemory,
1210 .dir => @panic("TODO"),
1211 }
1212 if (opt_env) |env| {
1213 var it = env.child.iterator();
1214 while (it.next()) |entry| {
1215 const key = entry.key_ptr.*;
1216 const value = entry.value_ptr.*;
1217 if (env.parent.get(key)) |process_value| {
1218 if (std.mem.eql(u8, value, process_value)) continue;
1219 }
1220 writer.print("{s}=", .{key}) catch return error.OutOfMemory;
1221 shell.escape(writer, value, false) catch return error.OutOfMemory;
1222 writer.writeByte(' ') catch return error.OutOfMemory;
1223 }
1224 }
1225 shell.escape(writer, argv[0], true) catch return error.OutOfMemory;
1226 for (argv[1..]) |arg| {
1227 writer.writeByte(' ') catch return error.OutOfMemory;
1228 shell.escape(writer, arg, false) catch return error.OutOfMemory;
1229 }
1230 return aw.toOwnedSlice();
1231}
1232
1160test {1233test {
1161 _ = Ast;1234 _ = Ast;
1162 _ = AstRlAnnotate;1235 _ = AstRlAnnotate;