authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-01 20:20:58-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:08-08:00
logf28802a9c6c3bd36368101981243aab7cf4f453f
treeb8a360cce73dae4e14bfa7f8ae23eae909ebb539
parent960c512efd71ab4b658952fe8761453128cc8292

zig libc: fix subcommand

This branch regressed the child process "run" mechanism because it didn't pass the correct stdin, stdout, stderr values to process.spawn Fixed now.

23 files changed, 167 insertions(+), 199 deletions(-)

lib/compiler/aro/main.zig+2-2
...@@ -18,7 +18,7 @@ var debug_allocator: std.heap.DebugAllocator(.{...@@ -18,7 +18,7 @@ var debug_allocator: std.heap.DebugAllocator(.{
18 .canary = @truncate(0xc647026dc6875134),18 .canary = @truncate(0xc647026dc6875134),
19}) = .{};19}) = .{};
2020
21pub fn main() u8 {21pub fn main(init: std.process.Init.Minimal) u8 {
22 const gpa = if (@import("builtin").link_libc)22 const gpa = if (@import("builtin").link_libc)
23 std.heap.c_allocator23 std.heap.c_allocator
24 else24 else
...@@ -37,7 +37,7 @@ pub fn main() u8 {...@@ -37,7 +37,7 @@ pub fn main() u8 {
3737
38 const fast_exit = @import("builtin").mode != .Debug;38 const fast_exit = @import("builtin").mode != .Debug;
3939
40 const args = process.argsAlloc(arena) catch {40 const args = init.args.toSlice(arena) catch {
41 std.debug.print("out of memory\n", .{});41 std.debug.print("out of memory\n", .{});
42 if (fast_exit) process.exit(1);42 if (fast_exit) process.exit(1);
43 return 1;43 return 1;
lib/compiler/libc.zig+12-13
...@@ -24,23 +24,19 @@ const usage_libc =...@@ -24,23 +24,19 @@ const usage_libc =
2424
25var stdout_buffer: [4096]u8 = undefined;25var stdout_buffer: [4096]u8 = undefined;
2626
27pub fn main() !void {27pub fn main(init: std.process.Init) !void {
28 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);28 const arena = init.arena.allocator();
29 defer arena_instance.deinit();29 const gpa = init.gpa;
30 const arena = arena_instance.allocator();30 const io = init.io;
31 const gpa = arena;31 const args = try init.minimal.args.toSlice(arena);
32 const env_map = init.env_map;
3233
33 var threaded: std.Io.Threaded = .init(gpa, .{});
34 defer threaded.deinit();
35 const io = threaded.io();
36
37 const args = try std.process.argsAlloc(arena);
38 const zig_lib_directory = args[1];34 const zig_lib_directory = args[1];
3935
40 var input_file: ?[]const u8 = null;36 var input_file: ?[]const u8 = null;
41 var target_arch_os_abi: []const u8 = "native";37 var target_arch_os_abi: []const u8 = "native";
42 var print_includes: bool = false;38 var print_includes: bool = false;
43 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);39 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
44 const stdout = &stdout_writer.interface;40 const stdout = &stdout_writer.interface;
45 {41 {
46 var i: usize = 2;42 var i: usize = 2;
...@@ -77,7 +73,7 @@ pub fn main() !void {...@@ -77,7 +73,7 @@ pub fn main() !void {
77 const libc_installation: ?*LibCInstallation = libc: {73 const libc_installation: ?*LibCInstallation = libc: {
78 if (input_file) |libc_file| {74 if (input_file) |libc_file| {
79 const libc = try arena.create(LibCInstallation);75 const libc = try arena.create(LibCInstallation);
80 libc.* = LibCInstallation.parse(arena, libc_file, &target) catch |err| {76 libc.* = LibCInstallation.parse(arena, io, libc_file, &target) catch |err| {
81 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });77 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
82 };78 };
83 break :libc libc;79 break :libc libc;
...@@ -90,11 +86,13 @@ pub fn main() !void {...@@ -90,11 +86,13 @@ pub fn main() !void {
9086
91 const libc_dirs = std.zig.LibCDirs.detect(87 const libc_dirs = std.zig.LibCDirs.detect(
92 arena,88 arena,
89 io,
93 zig_lib_directory,90 zig_lib_directory,
94 &target,91 &target,
95 is_native_abi,92 is_native_abi,
96 true,93 true,
97 libc_installation,94 libc_installation,
95 env_map,
98 ) catch |err| {96 ) catch |err| {
99 const zig_target = try target.zigTriple(arena);97 const zig_target = try target.zigTriple(arena);
100 fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err });98 fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err });
...@@ -114,7 +112,7 @@ pub fn main() !void {...@@ -114,7 +112,7 @@ pub fn main() !void {
114 }112 }
115113
116 if (input_file) |libc_file| {114 if (input_file) |libc_file| {
117 var libc = LibCInstallation.parse(gpa, libc_file, &target) catch |err| {115 var libc = LibCInstallation.parse(gpa, io, libc_file, &target) catch |err| {
118 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });116 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
119 };117 };
120 defer libc.deinit(gpa);118 defer libc.deinit(gpa);
...@@ -125,6 +123,7 @@ pub fn main() !void {...@@ -125,6 +123,7 @@ pub fn main() !void {
125 var libc = LibCInstallation.findNative(gpa, io, .{123 var libc = LibCInstallation.findNative(gpa, io, .{
126 .verbose = true,124 .verbose = true,
127 .target = &target,125 .target = &target,
126 .env_map = env_map,
128 }) catch |err| {127 }) catch |err| {
129 fatal("unable to detect native libc: {t}", .{err});128 fatal("unable to detect native libc: {t}", .{err});
130 };129 };
lib/compiler/reduce.zig+17-24
...@@ -47,19 +47,11 @@ const Interestingness = enum { interesting, unknown, boring };...@@ -47,19 +47,11 @@ const Interestingness = enum { interesting, unknown, boring };
47// - reduce flags sent to the compiler47// - reduce flags sent to the compiler
48// - integrate with the build system?48// - integrate with the build system?
4949
50pub fn main() !void {50pub fn main(init: std.process.Init) !void {
51 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);51 const arena = init.arena.allocator();
52 defer arena_instance.deinit();52 const gpa = init.gpa;
53 const arena = arena_instance.allocator();53 const io = init.io;
5454 const args = try init.minimal.args.toSlice(arena);
55 var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init;
56 const gpa = general_purpose_allocator.allocator();
57
58 var threaded: std.Io.Threaded = .init(gpa, .{});
59 defer threaded.deinit();
60 const io = threaded.io();
61
62 const args = try std.process.argsAlloc(arena);
6355
64 var opt_checker_path: ?[]const u8 = null;56 var opt_checker_path: ?[]const u8 = null;
65 var opt_root_source_file_path: ?[]const u8 = null;57 var opt_root_source_file_path: ?[]const u8 = null;
...@@ -73,8 +65,7 @@ pub fn main() !void {...@@ -73,8 +65,7 @@ pub fn main() !void {
73 const arg = args[i];65 const arg = args[i];
74 if (mem.startsWith(u8, arg, "-")) {66 if (mem.startsWith(u8, arg, "-")) {
75 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {67 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
76 const stdout = Io.File.stdout();68 try Io.File.stdout().writeStreamingAll(io, usage);
77 try stdout.writeAll(usage);
78 return std.process.cleanExit(io);69 return std.process.cleanExit(io);
79 } else if (mem.eql(u8, arg, "--")) {70 } else if (mem.eql(u8, arg, "--")) {
80 argv = args[i + 1 ..];71 argv = args[i + 1 ..];
...@@ -131,12 +122,10 @@ pub fn main() !void {...@@ -131,12 +122,10 @@ pub fn main() !void {
131122
132 if (!skip_smoke_test) {123 if (!skip_smoke_test) {
133 std.debug.print("smoke testing the interestingness check...\n", .{});124 std.debug.print("smoke testing the interestingness check...\n", .{});
134 switch (try runCheck(arena, interestingness_argv.items)) {125 switch (try runCheck(arena, io, interestingness_argv.items)) {
135 .interesting => {},126 .interesting => {},
136 .boring, .unknown => |t| {127 .boring, .unknown => |t| {
137 fatal("interestingness check returned {s} for unmodified input\n", .{128 fatal("interestingness check returned {t} for unmodified input\n", .{t});
138 @tagName(t),
139 });
140 },129 },
141 }130 }
142 }131 }
...@@ -238,7 +227,7 @@ pub fn main() !void {...@@ -238,7 +227,7 @@ pub fn main() !void {
238 try Io.Dir.cwd().writeFile(io, .{ .sub_path = root_source_file_path, .data = rendered.written() });227 try Io.Dir.cwd().writeFile(io, .{ .sub_path = root_source_file_path, .data = rendered.written() });
239 // std.debug.print("trying this code:\n{s}\n", .{rendered.items});228 // std.debug.print("trying this code:\n{s}\n", .{rendered.items});
240229
241 const interestingness = try runCheck(arena, interestingness_argv.items);230 const interestingness = try runCheck(arena, io, interestingness_argv.items);
242 std.debug.print("{d} random transformations: {t}. {d}/{d}\n", .{231 std.debug.print("{d} random transformations: {t}. {d}/{d}\n", .{
243 subset_size, interestingness, start_index, transformations.items.len,232 subset_size, interestingness, start_index, transformations.items.len,
244 });233 });
...@@ -293,20 +282,24 @@ fn sortTransformations(transformations: []Walk.Transformation, rng: std.Random)...@@ -293,20 +282,24 @@ fn sortTransformations(transformations: []Walk.Transformation, rng: std.Random)
293282
294fn termToInteresting(term: std.process.Child.Term) Interestingness {283fn termToInteresting(term: std.process.Child.Term) Interestingness {
295 return switch (term) {284 return switch (term) {
296 .Exited => |code| switch (code) {285 .exited => |code| switch (code) {
297 0 => .interesting,286 0 => .interesting,
298 1 => .unknown,287 1 => .unknown,
299 else => .boring,288 else => .boring,
300 },289 },
301 else => b: {290 .signal => |sig| {
291 std.debug.print("interestingness check terminated with signal {t}\n", .{sig});
292 return .boring;
293 },
294 else => {
302 std.debug.print("interestingness check aborted unexpectedly\n", .{});295 std.debug.print("interestingness check aborted unexpectedly\n", .{});
303 break :b .boring;296 return .boring;
304 },297 },
305 };298 };
306}299}
307300
308fn runCheck(arena: Allocator, io: Io, argv: []const []const u8) !Interestingness {301fn runCheck(arena: Allocator, io: Io, argv: []const []const u8) !Interestingness {
309 const result = try std.process.run(arena, io, .{ .spawn_options = .{ .argv = argv } });302 const result = try std.process.run(arena, io, .{ .argv = argv });
310 if (result.stderr.len != 0)303 if (result.stderr.len != 0)
311 std.debug.print("{s}", .{result.stderr});304 std.debug.print("{s}", .{result.stderr});
312 return termToInteresting(result.term);305 return termToInteresting(result.term);
lib/compiler/resinator/main.zig+2-2
...@@ -19,7 +19,7 @@ const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;...@@ -19,7 +19,7 @@ const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
19const aro = @import("aro");19const aro = @import("aro");
20const compiler_util = @import("../util.zig");20const compiler_util = @import("../util.zig");
2121
22pub fn main() !void {22pub fn main(init: std.process.Init.Minimal) !void {
23 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;23 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
24 defer std.debug.assert(debug_allocator.deinit() == .ok);24 defer std.debug.assert(debug_allocator.deinit() == .ok);
25 const gpa = debug_allocator.allocator();25 const gpa = debug_allocator.allocator();
...@@ -32,7 +32,7 @@ pub fn main() !void {...@@ -32,7 +32,7 @@ pub fn main() !void {
32 defer arena_state.deinit();32 defer arena_state.deinit();
33 const arena = arena_state.allocator();33 const arena = arena_state.allocator();
3434
35 const args = try std.process.argsAlloc(arena);35 const args = try init.args.toSlice(arena);
3636
37 if (args.len < 2) {37 if (args.len < 2) {
38 const stderr = try io.lockStderr(&.{}, null);38 const stderr = try io.lockStderr(&.{}, null);
lib/compiler/translate-c/main.zig+1-1
...@@ -14,7 +14,7 @@ pub fn main(init: std.process.Init) u8 {...@@ -14,7 +14,7 @@ pub fn main(init: std.process.Init) u8 {
14 const arena = init.arena.allocator();14 const arena = init.arena.allocator();
15 const io = init.io;15 const io = init.io;
1616
17 const args = process.argsAlloc(arena) catch {17 const args = init.minimal.args.toSlice(arena) catch {
18 std.debug.print("ran out of memory allocating arguments\n", .{});18 std.debug.print("ran out of memory allocating arguments\n", .{});
19 if (fast_exit) process.exit(1);19 if (fast_exit) process.exit(1);
20 return 1;20 return 1;
lib/std/Build/Step.zig+2-2
...@@ -360,11 +360,11 @@ pub fn captureChildProcess(...@@ -360,11 +360,11 @@ pub fn captureChildProcess(
360 try handleChildProcUnsupported(s);360 try handleChildProcUnsupported(s);
361 try handleVerbose(s.owner, null, argv);361 try handleVerbose(s.owner, null, argv);
362362
363 const result = std.process.run(arena, io, .{ .spawn_options = .{363 const result = std.process.run(arena, io, .{
364 .argv = argv,364 .argv = argv,
365 .env_map = &graph.env_map,365 .env_map = &graph.env_map,
366 .progress_node = progress_node,366 .progress_node = progress_node,
367 } }) catch |err| return s.fail("failed to run {s}: {t}", .{ argv[0], err });367 }) catch |err| return s.fail("failed to run {s}: {t}", .{ argv[0], err });
368368
369 if (result.stderr.len > 0) {369 if (result.stderr.len > 0) {
370 try s.result_error_msgs.append(arena, result.stderr);370 try s.result_error_msgs.append(arena, result.stderr);
lib/std/Random/benchmark.zig+6-5
...@@ -123,14 +123,15 @@ fn mode(comptime x: comptime_int) comptime_int {...@@ -123,14 +123,15 @@ fn mode(comptime x: comptime_int) comptime_int {
123 return if (builtin.mode == .Debug) x / 64 else x;123 return if (builtin.mode == .Debug) x / 64 else x;
124}124}
125125
126pub fn main() !void {126pub fn main(init: std.process.Init) !void {
127 const io = init.io;
128 const arena = init.arena.allocator();
129
127 var stdout_buffer: [0x100]u8 = undefined;130 var stdout_buffer: [0x100]u8 = undefined;
128 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);131 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
129 const stdout = &stdout_writer.interface;132 const stdout = &stdout_writer.interface;
130133
131 var buffer: [1024]u8 = undefined;134 const args = try init.minimal.args.toSlice(arena);
132 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
133 const args = try std.process.argsAlloc(fixed.allocator());
134135
135 var filter: ?[]u8 = "";136 var filter: ?[]u8 = "";
136 var count: usize = mode(128 * MiB);137 var count: usize = mode(128 * MiB);
lib/std/crypto/benchmark.zig+8-12
...@@ -503,16 +503,16 @@ fn mode(comptime x: comptime_int) comptime_int {...@@ -503,16 +503,16 @@ fn mode(comptime x: comptime_int) comptime_int {
503 return if (builtin.mode == .Debug) x / 64 else x;503 return if (builtin.mode == .Debug) x / 64 else x;
504}504}
505505
506pub fn main() !void {506pub fn main(init: std.process.Init) !void {
507 const io = init.io;
508 const arena = init.arena.allocator();
509
507 // Size of buffer is about size of printed message.510 // Size of buffer is about size of printed message.
508 var stdout_buffer: [0x100]u8 = undefined;511 var stdout_buffer: [0x100]u8 = undefined;
509 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);512 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
510 const stdout = &stdout_writer.interface;513 const stdout = &stdout_writer.interface;
511514
512 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);515 const args = try init.minimal.args.toSlice(arena);
513 defer arena.deinit();
514 const arena_allocator = arena.allocator();
515 const args = try std.process.argsAlloc(arena_allocator);
516516
517 var filter: ?[]u8 = "";517 var filter: ?[]u8 = "";
518518
...@@ -556,13 +556,9 @@ pub fn main() !void {...@@ -556,13 +556,9 @@ pub fn main() !void {
556 }556 }
557 }557 }
558558
559 var io_threaded = std.Io.Threaded.init(arena_allocator, .{});
560 defer io_threaded.deinit();
561 const io = io_threaded.io();
562
563 inline for (parallel_hashes) |H| {559 inline for (parallel_hashes) |H| {
564 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {560 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {
565 const throughput = try benchmarkHashParallel(H.ty, mode(128 * MiB), arena_allocator, io);561 const throughput = try benchmarkHashParallel(H.ty, mode(128 * MiB), arena, io);
566 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });562 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
567 try stdout.flush();563 try stdout.flush();
568 }564 }
...@@ -634,7 +630,7 @@ pub fn main() !void {...@@ -634,7 +630,7 @@ pub fn main() !void {
634630
635 inline for (pwhashes) |H| {631 inline for (pwhashes) |H| {
636 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {632 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {
637 const throughput = try benchmarkPwhash(arena_allocator, H.ty, H.params, mode(64), io);633 const throughput = try benchmarkPwhash(arena, H.ty, H.params, mode(64), io);
638 try stdout.print("{s:>17}: {d:10.3} s/ops\n", .{ H.name, throughput });634 try stdout.print("{s:>17}: {d:10.3} s/ops\n", .{ H.name, throughput });
639 try stdout.flush();635 try stdout.flush();
640 }636 }
lib/std/hash/benchmark.zig+6-5
...@@ -353,14 +353,15 @@ fn mode(comptime x: comptime_int) comptime_int {...@@ -353,14 +353,15 @@ fn mode(comptime x: comptime_int) comptime_int {
353 return if (builtin.mode == .Debug) x / 64 else x;353 return if (builtin.mode == .Debug) x / 64 else x;
354}354}
355355
356pub fn main() !void {356pub fn main(init: std.process.Init) !void {
357 const io = init.io;
358 const arena = init.arena.allocator();
359
357 var stdout_buffer: [0x100]u8 = undefined;360 var stdout_buffer: [0x100]u8 = undefined;
358 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);361 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
359 const stdout = &stdout_writer.interface;362 const stdout = &stdout_writer.interface;
360363
361 var buffer: [1024]u8 = undefined;364 const args = try init.minimal.args.toSlice(arena);
362 var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
363 const args = try std.process.argsAlloc(fixed.allocator());
364365
365 var filter: ?[]u8 = "";366 var filter: ?[]u8 = "";
366 var count: usize = mode(128 * MiB);367 var count: usize = mode(128 * MiB);
lib/std/process.zig+40-2
...@@ -463,8 +463,33 @@ pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix...@@ -463,8 +463,33 @@ pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix
463};463};
464464
465pub const RunOptions = struct {465pub const RunOptions = struct {
466 spawn_options: SpawnOptions,466 argv: []const []const u8,
467 max_output_bytes: usize = 50 * 1024,467 max_output_bytes: usize = 50 * 1024,
468
469 /// Set to change the current working directory when spawning the child process.
470 cwd: ?[]const u8 = null,
471 /// Set to change the current working directory when spawning the child process.
472 /// This is not yet implemented for Windows. See https://github.com/ziglang/zig/issues/5190
473 /// Once that is done, `cwd` will be deprecated in favor of this field.
474 cwd_dir: ?Io.Dir = null,
475 /// Replaces the child environment when provided. The PATH value from here
476 /// is not used to resolve `argv[0]`; that resolution always uses parent
477 /// environment.
478 env_map: ?*const Environ.Map = null,
479 expand_arg0: ArgExpansion = .no_expand,
480 /// When populated, a pipe will be created for the child process to
481 /// communicate progress back to the parent. The file descriptor of the
482 /// write end of the pipe will be specified in the `ZIG_PROGRESS`
483 /// environment variable inside the child process. The progress reported by
484 /// the child will be attached to this progress node in the parent process.
485 ///
486 /// The child's progress tree will be grafted into the parent's progress tree,
487 /// by substituting this node with the child's root node.
488 progress_node: std.Progress.Node = std.Progress.Node.none,
489 /// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess.
490 create_no_window: bool = true,
491 /// Darwin-only. Disable ASLR for the child process.
492 disable_aslr: bool = false,
468};493};
469494
470pub const RunResult = struct {495pub const RunResult = struct {
...@@ -476,7 +501,20 @@ pub const RunResult = struct {...@@ -476,7 +501,20 @@ pub const RunResult = struct {
476/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.501/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
477/// If it succeeds, the caller owns result.stdout and result.stderr memory.502/// If it succeeds, the caller owns result.stdout and result.stderr memory.
478pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult {503pub fn run(gpa: Allocator, io: Io, options: RunOptions) RunError!RunResult {
479 var child = try spawn(io, options.spawn_options);504 var child = try spawn(io, .{
505 .argv = options.argv,
506 .cwd = options.cwd,
507 .cwd_dir = options.cwd_dir,
508 .env_map = options.env_map,
509 .expand_arg0 = options.expand_arg0,
510 .progress_node = options.progress_node,
511 .create_no_window = options.create_no_window,
512 .disable_aslr = options.disable_aslr,
513
514 .stdin = .ignore,
515 .stdout = .pipe,
516 .stderr = .pipe,
517 });
480 defer child.kill(io);518 defer child.kill(io);
481519
482 var stdout: std.ArrayList(u8) = .empty;520 var stdout: std.ArrayList(u8) = .empty;
lib/std/zig/LibCInstallation.zig+24-28
...@@ -208,16 +208,16 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib...@@ -208,16 +208,16 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib
208 } else if (is_haiku) {208 } else if (is_haiku) {
209 try self.findNativeIncludeDirPosix(gpa, io, args);209 try self.findNativeIncludeDirPosix(gpa, io, args);
210 try self.findNativeGccDirHaiku(gpa, io, args);210 try self.findNativeGccDirHaiku(gpa, io, args);
211 self.crt_dir = try gpa.dupeZ(u8, "/system/develop/lib");211 self.crt_dir = try gpa.dupe(u8, "/system/develop/lib");
212 } else if (builtin.target.os.tag == .illumos) {212 } else if (builtin.target.os.tag == .illumos) {
213 // There is only one libc, and its headers/libraries are always in the same spot.213 // There is only one libc, and its headers/libraries are always in the same spot.
214 self.include_dir = try gpa.dupeZ(u8, "/usr/include");214 self.include_dir = try gpa.dupe(u8, "/usr/include");
215 self.sys_include_dir = try gpa.dupeZ(u8, "/usr/include");215 self.sys_include_dir = try gpa.dupe(u8, "/usr/include");
216 self.crt_dir = try gpa.dupeZ(u8, "/usr/lib/64");216 self.crt_dir = try gpa.dupe(u8, "/usr/lib/64");
217 } else if (std.process.can_spawn) {217 } else if (std.process.can_spawn) {
218 try self.findNativeIncludeDirPosix(gpa, io, args);218 try self.findNativeIncludeDirPosix(gpa, io, args);
219 switch (builtin.target.os.tag) {219 switch (builtin.target.os.tag) {
220 .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try gpa.dupeZ(u8, "/usr/lib"),220 .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try gpa.dupe(u8, "/usr/lib"),
221 .linux => try self.findNativeCrtDirPosix(gpa, io, args),221 .linux => try self.findNativeCrtDirPosix(gpa, io, args),
222 else => {},222 else => {},
223 }223 }
...@@ -269,15 +269,13 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar...@@ -269,15 +269,13 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar
269269
270 const run_res = std.process.run(gpa, io, .{270 const run_res = std.process.run(gpa, io, .{
271 .max_output_bytes = 1024 * 1024,271 .max_output_bytes = 1024 * 1024,
272 .spawn_options = .{272 .argv = argv.items,
273 .argv = argv.items,273 .env_map = &env_map,
274 .env_map = &env_map,274 // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
275 // Some C compilers, such as Clang, are known to rely on argv[0] to find the path275 // to their own executable, without even bothering to resolve PATH. This results in the message:
276 // to their own executable, without even bothering to resolve PATH. This results in the message:276 // error: unable to execute command: Executable "" doesn't exist!
277 // error: unable to execute command: Executable "" doesn't exist!277 // So we use the expandArg0 variant of ChildProcess to give them a helping hand.
278 // So we use the expandArg0 variant of ChildProcess to give them a helping hand.278 .expand_arg0 = .expand,
279 .expand_arg0 = .expand,
280 },
281 }) catch |err| switch (err) {279 }) catch |err| switch (err) {
282 error.OutOfMemory => return error.OutOfMemory,280 error.OutOfMemory => return error.OutOfMemory,
283 else => {281 else => {
...@@ -337,7 +335,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar...@@ -337,7 +335,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar
337335
338 if (self.include_dir == null) {336 if (self.include_dir == null) {
339 if (search_dir.access(io, include_dir_example_file, .{})) |_| {337 if (search_dir.access(io, include_dir_example_file, .{})) |_| {
340 self.include_dir = try gpa.dupeZ(u8, search_path);338 self.include_dir = try gpa.dupe(u8, search_path);
341 } else |err| switch (err) {339 } else |err| switch (err) {
342 error.FileNotFound => {},340 error.FileNotFound => {},
343 else => return error.FileSystem,341 else => return error.FileSystem,
...@@ -346,7 +344,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar...@@ -346,7 +344,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar
346344
347 if (self.sys_include_dir == null) {345 if (self.sys_include_dir == null) {
348 if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| {346 if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| {
349 self.sys_include_dir = try gpa.dupeZ(u8, search_path);347 self.sys_include_dir = try gpa.dupe(u8, search_path);
350 } else |err| switch (err) {348 } else |err| switch (err) {
351 error.FileNotFound => {},349 error.FileNotFound => {},
352 else => return error.FileSystem,350 else => return error.FileSystem,
...@@ -560,7 +558,7 @@ pub const CCPrintFileNameOptions = struct {...@@ -560,7 +558,7 @@ pub const CCPrintFileNameOptions = struct {
560};558};
561559
562/// caller owns returned memory560/// caller owns returned memory
563fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8 {561fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![]u8 {
564 // Detect infinite loops.562 // Detect infinite loops.
565 var env_map = try args.env_map.clone(gpa);563 var env_map = try args.env_map.clone(gpa);
566 defer env_map.deinit();564 defer env_map.deinit();
...@@ -587,15 +585,13 @@ fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8...@@ -587,15 +585,13 @@ fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8
587585
588 const run_res = std.process.run(gpa, io, .{586 const run_res = std.process.run(gpa, io, .{
589 .max_output_bytes = 1024 * 1024,587 .max_output_bytes = 1024 * 1024,
590 .spawn_options = .{588 .argv = argv.items,
591 .argv = argv.items,589 .env_map = &env_map,
592 .env_map = &env_map,590 // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
593 // Some C compilers, such as Clang, are known to rely on argv[0] to find the path591 // to their own executable, without even bothering to resolve PATH. This results in the message:
594 // to their own executable, without even bothering to resolve PATH. This results in the message:592 // error: unable to execute command: Executable "" doesn't exist!
595 // error: unable to execute command: Executable "" doesn't exist!593 // So we use the expandArg0 variant of ChildProcess to give them a helping hand.
596 // So we use the expandArg0 variant of ChildProcess to give them a helping hand.594 .expand_arg0 = .expand,
597 .expand_arg0 = .expand,
598 },
599 }) catch |err| switch (err) {595 }) catch |err| switch (err) {
600 error.OutOfMemory => return error.OutOfMemory,596 error.OutOfMemory => return error.OutOfMemory,
601 else => return error.UnableToSpawnCCompiler,597 else => return error.UnableToSpawnCCompiler,
...@@ -621,10 +617,10 @@ fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8...@@ -621,10 +617,10 @@ fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![:0]u8
621 // So we detect failure by checking if the output matches exactly the input.617 // So we detect failure by checking if the output matches exactly the input.
622 if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound;618 if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound;
623 switch (args.want_dirname) {619 switch (args.want_dirname) {
624 .full_path => return gpa.dupeZ(u8, line),620 .full_path => return gpa.dupe(u8, line),
625 .only_dir => {621 .only_dir => {
626 const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;622 const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
627 return gpa.dupeZ(u8, dirname);623 return gpa.dupe(u8, dirname);
628 },624 },
629 }625 }
630}626}
lib/std/zig/system/darwin.zig+3-3
...@@ -17,9 +17,9 @@ pub const macos = @import("darwin/macos.zig");...@@ -17,9 +17,9 @@ pub const macos = @import("darwin/macos.zig");
17///17///
18/// If error.OutOfMemory occurs in Allocator, this function returns null.18/// If error.OutOfMemory occurs in Allocator, this function returns null.
19pub fn isSdkInstalled(gpa: Allocator, io: Io) bool {19pub fn isSdkInstalled(gpa: Allocator, io: Io) bool {
20 const result = std.process.run(gpa, io, .{ .spawn_options = .{20 const result = std.process.run(gpa, io, .{
21 .argv = &.{ "xcode-select", "--print-path" },21 .argv = &.{ "xcode-select", "--print-path" },
22 } }) catch return false;22 }) catch return false;
23 defer {23 defer {
24 gpa.free(result.stderr);24 gpa.free(result.stderr);
25 gpa.free(result.stdout);25 gpa.free(result.stdout);
...@@ -47,7 +47,7 @@ pub fn getSdk(gpa: Allocator, io: Io, target: *const Target) ?[]const u8 {...@@ -47,7 +47,7 @@ pub fn getSdk(gpa: Allocator, io: Io, target: *const Target) ?[]const u8 {
47 else => return null,47 else => return null,
48 };48 };
49 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };49 const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };
50 const result = std.process.run(gpa, io, .{ .spawn_options = .{ .argv = argv } }) catch return null;50 const result = std.process.run(gpa, io, .{ .argv = argv }) catch return null;
51 defer {51 defer {
52 gpa.free(result.stderr);52 gpa.free(result.stderr);
53 gpa.free(result.stdout);53 gpa.free(result.stdout);
test/standalone/child_process/child.zig+8-16
...@@ -4,31 +4,23 @@ const Io = std.Io;...@@ -4,31 +4,23 @@ const Io = std.Io;
4// 42 is expected by parent; other values result in test failure4// 42 is expected by parent; other values result in test failure
5var exit_code: u8 = 42;5var exit_code: u8 = 42;
66
7pub fn main() !void {7pub fn main(init: std.process.Init) !void {
8 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);8 try run(init.arena.allocator(), init.io, init.minimal.args);
9 const arena = arena_state.allocator();
10
11 var threaded: std.Io.Threaded = .init(arena, .{});
12 defer threaded.deinit();
13 const io = threaded.io();
14
15 try run(arena, io);
16 arena_state.deinit();
17 std.process.exit(exit_code);9 std.process.exit(exit_code);
18}10}
1911
20fn run(allocator: std.mem.Allocator, io: Io) !void {12fn run(arena: std.mem.Allocator, io: Io, args: std.process.Args) !void {
21 var args = try std.process.argsWithAllocator(allocator);13 var it = try args.iterateAllocator(arena);
22 defer args.deinit();14 defer it.deinit();
23 _ = args.next() orelse unreachable; // skip binary name15 _ = it.next() orelse unreachable; // skip binary name
2416
25 // test cmd args17 // test cmd args
26 const hello_arg = "hello arg";18 const hello_arg = "hello arg";
27 const a1 = args.next() orelse unreachable;19 const a1 = it.next() orelse unreachable;
28 if (!std.mem.eql(u8, a1, hello_arg)) {20 if (!std.mem.eql(u8, a1, hello_arg)) {
29 testError(io, "first arg: '{s}'; want '{s}'", .{ a1, hello_arg });21 testError(io, "first arg: '{s}'; want '{s}'", .{ a1, hello_arg });
30 }22 }
31 if (args.next()) |a2| {23 if (it.next()) |a2| {
32 testError(io, "expected only one arg; got more: {s}", .{a2});24 testError(io, "expected only one arg; got more: {s}", .{a2});
33 }25 }
3426
test/standalone/install_headers/check_exists.zig+4-8
...@@ -2,17 +2,13 @@ const std = @import("std");...@@ -2,17 +2,13 @@ const std = @import("std");
22
3/// Checks the existence of files relative to cwd.3/// Checks the existence of files relative to cwd.
4/// A path starting with ! should not exist.4/// A path starting with ! should not exist.
5pub fn main() !void {5pub fn main(init: std.process.Init) !void {
6 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);6 const arena = init.arena.allocator();
7 defer arena_state.deinit();7 const io = init.io;
88
9 const arena = arena_state.allocator();9 var arg_it = try init.minimal.args.iterateAllocator(arena);
10
11 var arg_it = try std.process.argsWithAllocator(arena);
12 _ = arg_it.next();10 _ = arg_it.next();
1311
14 const io = std.Io.Threaded.global_single_threaded.ioBasic();
15
16 const cwd = std.Io.Dir.cwd();12 const cwd = std.Io.Dir.cwd();
17 const cwd_realpath = try cwd.realPathFileAlloc(io, ".", arena);13 const cwd_realpath = try cwd.realPathFileAlloc(io, ".", arena);
1814
test/standalone/libfuzzer/main.zig+4-9
...@@ -6,19 +6,14 @@ fn testOne(in: abi.Slice) callconv(.c) void {...@@ -6,19 +6,14 @@ fn testOne(in: abi.Slice) callconv(.c) void {
6 std.debug.assertReadable(in.toSlice());6 std.debug.assertReadable(in.toSlice());
7}7}
88
9pub fn main() !void {9pub fn main(init: std.process.Init) !void {
10 var debug_gpa_ctx: std.heap.DebugAllocator(.{}) = .init;10 const gpa = init.gpa;
11 defer _ = debug_gpa_ctx.deinit();11 const io = init.io;
12 const gpa = debug_gpa_ctx.allocator();
1312
14 var args = try std.process.argsWithAllocator(gpa);13 var args = try init.minimal.args.iterateAllocator(gpa);
15 defer args.deinit();14 defer args.deinit();
16 _ = args.skip(); // executable name15 _ = args.skip(); // executable name
1716
18 var threaded: std.Io.Threaded = .init(gpa, .{});
19 defer threaded.deinit();
20 const io = threaded.io();
21
22 const cache_dir_path = args.next() orelse @panic("expected cache directory path argument");17 const cache_dir_path = args.next() orelse @panic("expected cache directory path argument");
23 var cache_dir = try std.Io.Dir.cwd().openDir(io, cache_dir_path, .{});18 var cache_dir = try std.Io.Dir.cwd().openDir(io, cache_dir_path, .{});
24 defer cache_dir.close(io);19 defer cache_dir.close(io);
test/standalone/run_output_caching/main.zig+3-3
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn main() !void {3pub fn main(init: std.process.Init) !void {
4 const io = std.Io.Threaded.global_single_threaded.ioBasic();4 const io = init.io;
5 var args = try std.process.argsWithAllocator(std.heap.page_allocator);5 var args = try init.minimal.argsAllocator(init.arena.allocator());
6 _ = args.skip();6 _ = args.skip();
7 const filename = args.next().?;7 const filename = args.next().?;
8 const file = try std.Io.Dir.cwd().createFile(io, filename, .{});8 const file = try std.Io.Dir.cwd().createFile(io, filename, .{});
test/standalone/windows_bat_args/fuzz.zig+4-9
...@@ -4,16 +4,11 @@ const std = @import("std");...@@ -4,16 +4,11 @@ const std = @import("std");
4const Io = std.Io;4const Io = std.Io;
5const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
66
7pub fn main() anyerror!void {7pub fn main(init: std.process.Init) !void {
8 var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init;8 const gpa = init.gpa;
9 defer std.debug.assert(debug_alloc_inst.deinit() == .ok);9 const io = init.io;
10 const gpa = debug_alloc_inst.allocator();
1110
12 var threaded: Io.Threaded = .init(gpa, .{});11 var it = try init.minimal.argsAllocator(gpa);
13 defer threaded.deinit();
14 const io = threaded.io();
15
16 var it = try std.process.argsWithAllocator(gpa);
17 defer it.deinit();12 defer it.deinit();
18 _ = it.next() orelse unreachable; // skip binary name13 _ = it.next() orelse unreachable; // skip binary name
19 const child_exe_path_orig = it.next() orelse unreachable;14 const child_exe_path_orig = it.next() orelse unreachable;
test/standalone/windows_bat_args/test.zig+4-8
...@@ -2,15 +2,11 @@ const std = @import("std");...@@ -2,15 +2,11 @@ const std = @import("std");
2const Io = std.Io;2const Io = std.Io;
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
44
5pub fn main() anyerror!void {5pub fn main(init: std.process.Init) !void {
6 var debug_alloc_inst: std.heap.DebugAllocator(.{}) = .init;6 const gpa = init.gpa;
7 defer std.debug.assert(debug_alloc_inst.deinit() == .ok);7 const io = init.io;
8 const gpa = debug_alloc_inst.allocator();
98
10 var threaded: Io.Threaded = .init(gpa, .{});9 var it = try init.minimal.argsAllocator(gpa);
11 const io = threaded.io();
12
13 var it = try std.process.argsWithAllocator(gpa);
14 defer it.deinit();10 defer it.deinit();
15 _ = it.next() orelse unreachable; // skip binary name11 _ = it.next() orelse unreachable; // skip binary name
16 const child_exe_path_orig = it.next() orelse unreachable;12 const child_exe_path_orig = it.next() orelse unreachable;
test/standalone/windows_spawn/main.zig+4-9
...@@ -5,16 +5,11 @@ const Allocator = std.mem.Allocator;...@@ -5,16 +5,11 @@ const Allocator = std.mem.Allocator;
5const windows = std.os.windows;5const windows = std.os.windows;
6const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;6const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;
77
8pub fn main() anyerror!void {8pub fn main(init: std.process.Init) !void {
9 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;9 const gpa = init.gpa;
10 defer if (debug_allocator.deinit() == .leak) @panic("found memory leaks");10 const io = init.io;
11 const gpa = debug_allocator.allocator();
1211
13 var threaded: std.Io.Threaded = .init(gpa, .{});12 var it = try init.minimal.argsAllocator(gpa);
14 defer threaded.deinit();
15 const io = threaded.io();
16
17 var it = try std.process.argsWithAllocator(gpa);
18 defer it.deinit();13 defer it.deinit();
19 _ = it.next() orelse unreachable; // skip binary name14 _ = it.next() orelse unreachable; // skip binary name
20 const hello_exe_cache_path = it.next() orelse unreachable;15 const hello_exe_cache_path = it.next() orelse unreachable;
tools/docgen.zig+4-12
...@@ -28,21 +28,13 @@ const usage =...@@ -28,21 +28,13 @@ const usage =
28 \\28 \\
29;29;
3030
31pub fn main() !void {31pub fn main(init: std.process.Init) !void {
32 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);32 const arena = init.arena.allocator();
33 defer arena_instance.deinit();33 const io = init.io;
3434
35 const arena = arena_instance.allocator();35 var args_it = try init.minimal.args.iterateAllocator(arena);
36
37 var args_it = try process.argsWithAllocator(arena);
38 if (!args_it.skip()) @panic("expected self arg");36 if (!args_it.skip()) @panic("expected self arg");
3937
40 const gpa = arena;
41
42 var threaded: std.Io.Threaded = .init(gpa, .{});
43 defer threaded.deinit();
44 const io = threaded.io();
45
46 var opt_code_dir: ?[]const u8 = null;38 var opt_code_dir: ?[]const u8 = null;
47 var opt_input: ?[]const u8 = null;39 var opt_input: ?[]const u8 = null;
48 var opt_output: ?[]const u8 = null;40 var opt_output: ?[]const u8 = null;
tools/doctest.zig+4-12
...@@ -29,21 +29,13 @@ const usage =...@@ -29,21 +29,13 @@ const usage =
29 \\29 \\
30;30;
3131
32pub fn main() !void {32pub fn main(init: std.process.Init) !void {
33 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);33 const arena = init.arena.allocator();
34 defer arena_instance.deinit();34 const io = init.io;
3535
36 const arena = arena_instance.allocator();36 var args_it = try init.minimal.args.iterateAllocator(arena);
37
38 var args_it = try process.argsWithAllocator(arena);
39 if (!args_it.skip()) fatal("missing argv[0]", .{});37 if (!args_it.skip()) fatal("missing argv[0]", .{});
4038
41 const gpa = arena;
42
43 var threaded: std.Io.Threaded = .init(gpa, .{});
44 defer threaded.deinit();
45 const io = threaded.io();
46
47 var opt_input: ?[]const u8 = null;39 var opt_input: ?[]const u8 = null;
48 var opt_output: ?[]const u8 = null;40 var opt_output: ?[]const u8 = null;
49 var opt_zig: ?[]const u8 = null;41 var opt_zig: ?[]const u8 = null;
tools/incr-check.zig+1-1
...@@ -44,7 +44,7 @@ pub fn main(init: std.process.Init) !void {...@@ -44,7 +44,7 @@ pub fn main(init: std.process.Init) !void {
4444
45 var debug_log_args: std.ArrayList([]const u8) = .empty;45 var debug_log_args: std.ArrayList([]const u8) = .empty;
4646
47 var arg_it = try std.process.argsWithAllocator(arena);47 var arg_it = try init.minimal.argsIterator(arena);
48 _ = arg_it.skip();48 _ = arg_it.skip();
49 while (arg_it.next()) |arg| {49 while (arg_it.next()) |arg| {
50 if (arg.len > 0 and arg[0] == '-') {50 if (arg.len > 0 and arg[0] == '-') {
tools/update_cpu_features.zig+4-13
...@@ -1883,20 +1883,11 @@ const targets = [_]ArchTarget{...@@ -1883,20 +1883,11 @@ const targets = [_]ArchTarget{
1883 },1883 },
1884};1884};
18851885
1886pub fn main() anyerror!void {1886pub fn main(init: std.process.Init) !void {
1887 var debug_allocator: std.heap.DebugAllocator(.{}) = .init;1887 const arena = init.arena_allocator.allocator();
1888 defer _ = debug_allocator.deinit();1888 const io = init.io;
1889 const gpa = debug_allocator.allocator();
18901889
1891 var arena_state: std.heap.ArenaAllocator = .init(gpa);1890 var args = try init.minimal.args.iterateAllocator(arena);
1892 defer arena_state.deinit();
1893 const arena = arena_state.allocator();
1894
1895 var threaded: std.Io.Threaded = .init(gpa, .{});
1896 defer threaded.deinit();
1897 const io = threaded.io();
1898
1899 var args = try std.process.argsWithAllocator(arena);
1900 const args0 = args.next().?;1891 const args0 = args.next().?;
19011892
1902 const llvm_tblgen_exe = args.next() orelse1893 const llvm_tblgen_exe = args.next() orelse