From 0778f644b519a83e95848d05d5a9e6241f8f41f3 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sat, 19 Feb 2022 23:28:54 -0700 Subject: [PATCH 1/8] use process.argsWithAllocator iterator for command line handling This change refactors the `zig` argument handling (for `build-lib`, etc. commands) to use a `process.argsWithAllocator` iterator instead of directly accessing arguments via array indices. This supports the next commit which will enable us to use a response file argument iterator here seamlessly. Helps #10693 Signed-off-by: Stephen Gutekanst --- src/main.zig | 289 +++++++++++++++++++++++++-------------------------- 1 file changed, 143 insertions(+), 146 deletions(-) diff --git a/src/main.zig b/src/main.zig index 6a85c92537..f9ed1baeeb 100644 --- a/src/main.zig +++ b/src/main.zig @@ -765,10 +765,16 @@ fn buildOutputType( } soname = .yes_default_value; - const args = all_args[2..]; - var i: usize = 0; - args_loop: while (i < args.len) : (i += 1) { - const arg = args[i]; + var process_args_iter = try process.argsWithAllocator(arena); + _ = process_args_iter.skip(); // "zig" + _ = process_args_iter.skip(); // e.g. "build-lib" + + args_loop: while (process_args_iter.next()) |arg| { + var args_index = process_args_iter.inner.index; + if (resp_file_args_iter) |iter| { + args_index = iter.index; + } + if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { try io.getStdOut().writeAll(usage_build_generic); @@ -777,73 +783,68 @@ fn buildOutputType( if (arg_mode == .run) { // The index refers to all_args so skip `zig` `run` // and `--` - runtime_args_start = i + 3; + runtime_args_start = args_index + 3; break :args_loop; } else { fatal("unexpected end-of-parameter mark: --", .{}); } } else if (mem.eql(u8, arg, "--pkg-begin")) { - if (i + 2 >= args.len) fatal("Expected 2 arguments after {s}", .{arg}); - i += 1; - const pkg_name = args[i]; - i += 1; - const pkg_path = args[i]; + const pkg_name = process_args_iter.next(); + const pkg_path = process_args_iter.next(); + if (pkg_name == null or pkg_path == null) fatal("Expected 2 arguments after {s}", .{arg}); const new_cur_pkg = Package.create( gpa, - fs.path.dirname(pkg_path), - fs.path.basename(pkg_path), + fs.path.dirname(pkg_path.?), + fs.path.basename(pkg_path.?), ) catch |err| { - fatal("Failed to add package at path {s}: {s}", .{ pkg_path, @errorName(err) }); + fatal("Failed to add package at path {s}: {s}", .{ pkg_path.?, @errorName(err) }); }; - try cur_pkg.addAndAdopt(gpa, pkg_name, new_cur_pkg); + try cur_pkg.addAndAdopt(gpa, pkg_name.?, new_cur_pkg); cur_pkg = new_cur_pkg; } else if (mem.eql(u8, arg, "--pkg-end")) { cur_pkg = cur_pkg.parent orelse fatal("encountered --pkg-end with no matching --pkg-begin", .{}); } else if (mem.eql(u8, arg, "--main-pkg-path")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - main_pkg_path = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + main_pkg_path = next_arg.?; } else if (mem.eql(u8, arg, "-cflags")) { extra_cflags.shrinkRetainingCapacity(0); while (true) { - i += 1; - if (i >= args.len) fatal("expected -- after -cflags", .{}); - if (mem.eql(u8, args[i], "--")) break; - try extra_cflags.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected -- after -cflags", .{}); + if (mem.eql(u8, next_arg.?, "--")) break; + try extra_cflags.append(next_arg.?); } } else if (mem.eql(u8, arg, "--color")) { - if (i + 1 >= args.len) { - fatal("expected [auto|on|off] after --color", .{}); - } - i += 1; - const next_arg = args[i]; - color = std.meta.stringToEnum(Color, next_arg) orelse { - fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected [auto|on|off] after --color", .{}); + color = std.meta.stringToEnum(Color, next_arg.?) orelse { + fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg.?}); }; } else if (mem.eql(u8, arg, "--subsystem")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - if (mem.eql(u8, args[i], "console")) { + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + if (mem.eql(u8, next_arg.?, "console")) { subsystem = .Console; - } else if (mem.eql(u8, args[i], "windows")) { + } else if (mem.eql(u8, next_arg.?, "windows")) { subsystem = .Windows; - } else if (mem.eql(u8, args[i], "posix")) { + } else if (mem.eql(u8, next_arg.?, "posix")) { subsystem = .Posix; - } else if (mem.eql(u8, args[i], "native")) { + } else if (mem.eql(u8, next_arg.?, "native")) { subsystem = .Native; - } else if (mem.eql(u8, args[i], "efi_application")) { + } else if (mem.eql(u8, next_arg.?, "efi_application")) { subsystem = .EfiApplication; - } else if (mem.eql(u8, args[i], "efi_boot_service_driver")) { + } else if (mem.eql(u8, next_arg.?, "efi_boot_service_driver")) { subsystem = .EfiBootServiceDriver; - } else if (mem.eql(u8, args[i], "efi_rom")) { + } else if (mem.eql(u8, next_arg.?, "efi_rom")) { subsystem = .EfiRom; - } else if (mem.eql(u8, args[i], "efi_runtime_driver")) { + } else if (mem.eql(u8, next_arg.?, "efi_runtime_driver")) { subsystem = .EfiRuntimeDriver; } else { fatal("invalid: --subsystem: '{s}'. Options are:\n{s}", .{ - args[i], + next_arg.?, \\ console \\ windows \\ posix @@ -856,67 +857,67 @@ fn buildOutputType( }); } } else if (mem.eql(u8, arg, "-O")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - optimize_mode_string = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + optimize_mode_string = next_arg.?; } else if (mem.eql(u8, arg, "--entry")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - entry = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + entry = next_arg.?; } else if (mem.eql(u8, arg, "--stack")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - stack_size_override = std.fmt.parseUnsigned(u64, args[i], 0) catch |err| { + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + stack_size_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--image-base")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - image_base_override = std.fmt.parseUnsigned(u64, args[i], 0) catch |err| { + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + image_base_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--name")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - provided_name = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + provided_name = next_arg.?; } else if (mem.eql(u8, arg, "-rpath")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try rpath_list.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try rpath_list.append(next_arg.?); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try lib_dirs.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try lib_dirs.append(next_arg.?); } else if (mem.eql(u8, arg, "-F")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try framework_dirs.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try framework_dirs.append(next_arg.?); } else if (mem.eql(u8, arg, "-framework")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try frameworks.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try frameworks.append(next_arg.?); } else if (mem.eql(u8, arg, "-install_name")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - install_name = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + install_name = next_arg.?; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - linker_script = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + linker_script = next_arg.?; } else if (mem.eql(u8, arg, "--version-script")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - version_script = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + version_script = next_arg.?; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); // We don't know whether this library is part of libc or libc++ until // we resolve the target, so we simply append to the list for now. - i += 1; - try system_libs.put(args[i], .{ .needed = false }); + try system_libs.put(next_arg.?, .{ .needed = false }); } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try system_libs.put(args[i], .{ .needed = true }); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try system_libs.put(next_arg.?, .{ .needed = true }); } else if (mem.eql(u8, arg, "-D") or mem.eql(u8, arg, "-isystem") or mem.eql(u8, arg, "-I") or @@ -925,31 +926,29 @@ fn buildOutputType( mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try clang_argv.append(arg); - try clang_argv.append(args[i]); + try clang_argv.append(next_arg.?); } else if (mem.eql(u8, arg, "--version")) { - if (i + 1 >= args.len) { - fatal("expected parameter after --version", .{}); - } - i += 1; - version = std.builtin.Version.parse(args[i]) catch |err| { - fatal("unable to parse --version '{s}': {s}", .{ args[i], @errorName(err) }); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after --version", .{}); + version = std.builtin.Version.parse(next_arg.?) catch |err| { + fatal("unable to parse --version '{s}': {s}", .{ next_arg.?, @errorName(err) }); }; have_version = true; } else if (mem.eql(u8, arg, "-target")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - target_arch_os_abi = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + target_arch_os_abi = next_arg.?; } else if (mem.eql(u8, arg, "-mcpu")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - target_mcpu = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + target_mcpu = next_arg.?; } else if (mem.eql(u8, arg, "-mcmodel")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - machine_code_model = parseCodeModel(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + machine_code_model = parseCodeModel(next_arg.?); } else if (mem.startsWith(u8, arg, "-ofmt=")) { target_ofmt = arg["-ofmt=".len..]; } else if (mem.startsWith(u8, arg, "-mcpu=")) { @@ -959,50 +958,50 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - target_dynamic_linker = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + target_dynamic_linker = next_arg.?; } else if (mem.eql(u8, arg, "--sysroot")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - sysroot = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + sysroot = next_arg.?; try clang_argv.append("-isysroot"); - try clang_argv.append(args[i]); + try clang_argv.append(next_arg.?); } else if (mem.eql(u8, arg, "--libc")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - libc_paths_file = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + libc_paths_file = next_arg.?; } else if (mem.eql(u8, arg, "--test-filter")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - test_filter = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + test_filter = next_arg.?; } else if (mem.eql(u8, arg, "--test-name-prefix")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - test_name_prefix = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + test_name_prefix = next_arg.?; } else if (mem.eql(u8, arg, "--test-cmd")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - try test_exec_args.append(args[i]); + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + try test_exec_args.append(next_arg.?); } else if (mem.eql(u8, arg, "--cache-dir")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - override_local_cache_dir = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + override_local_cache_dir = next_arg.?; } else if (mem.eql(u8, arg, "--global-cache-dir")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - override_global_cache_dir = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + override_global_cache_dir = next_arg.?; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - override_lib_dir = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + override_lib_dir = next_arg.?; } else if (mem.eql(u8, arg, "--debug-log")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected parameter after {s}", .{arg}); if (!build_options.enable_logging) { std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); } else { - try log_scopes.append(gpa, args[i]); + try log_scopes.append(gpa, next_arg.?); } } else if (mem.eql(u8, arg, "--debug-link-snapshot")) { if (!build_options.enable_link_snapshots) { @@ -1175,11 +1174,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; } else if (mem.eql(u8, arg, "-z")) { - i += 1; - if (i >= args.len) { - fatal("expected linker extension flag after '{s}'", .{arg}); - } - const z_arg = args[i]; + const next_arg = process_args_iter.next(); + if (next_arg == null) fatal("expected linker extension flag after '{s}'", .{arg}); + const z_arg = next_arg.?; if (mem.eql(u8, z_arg, "nodelete")) { linker_z_nodelete = true; } else if (mem.eql(u8, z_arg, "notext")) { @@ -4265,6 +4262,17 @@ pub fn lldMain( return @bitCast(u8, @truncate(i8, exit_code)); } +const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, .single_quotes = true }); + +/// Initialize the arguments from a Response File. "*.rsp" +fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { + const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit + var cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes); + errdefer allocator.free(cmd_line); + + return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); +} + const clang_args = @import("clang_options.zig").list; pub const ClangArgIterator = struct { @@ -4354,17 +4362,6 @@ pub const ClangArgIterator = struct { }; } - const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, .single_quotes = true }); - - /// Initialize the arguments from a Response File. "*.rsp" - fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile { - const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit - var cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes); - errdefer allocator.free(cmd_line); - - return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line); - } - fn next(self: *ClangArgIterator) !void { assert(self.has_next); assert(self.next_index < self.argv.len); From e41d4df93cf78b7ecccd959472dc653dc089f8aa Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 20 Feb 2022 13:43:52 -0700 Subject: [PATCH 2/8] enable passing build-[lib|exe|obj] params via @args.rsp file This change enables `zig build-lib` and friends to take a response file of command line arguments, for example: ```sh zig build-lib @args.rsp ``` Which effectively does the same thing as this in Bash: ```sh zig build-lib $(cat args.rsp) ``` Being able to use a file for arguments is important as one can quickly exceed the 32 KiB limit that Windows imposes on arguments to a process. Helps #10693 Signed-off-by: Stephen Gutekanst --- src/main.zig | 92 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/src/main.zig b/src/main.zig index f9ed1baeeb..5e012ed067 100644 --- a/src/main.zig +++ b/src/main.zig @@ -768,14 +768,30 @@ fn buildOutputType( var process_args_iter = try process.argsWithAllocator(arena); _ = process_args_iter.skip(); // "zig" _ = process_args_iter.skip(); // e.g. "build-lib" + var resp_file_args_iter: ?ArgIteratorResponseFile = null; - args_loop: while (process_args_iter.next()) |arg| { + var getNextArg = (struct { + pub fn getNextArg(_process_args_iter: *process.ArgIterator, maybe_resp_file_args_iter: *?ArgIteratorResponseFile) ?[:0]const u8 { + if (_process_args_iter.next()) |proc_arg| return proc_arg; + if (maybe_resp_file_args_iter.*) |*iter| return iter.next(); + return null; + } + }).getNextArg; + + args_loop: while (getNextArg(&process_args_iter, &resp_file_args_iter)) |arg| { var args_index = process_args_iter.inner.index; if (resp_file_args_iter) |iter| { args_index = iter.index; } - if (mem.startsWith(u8, arg, "-")) { + if (mem.startsWith(u8, arg, "@")) { + // This is a "compiler response file". We must parse the file and treat its + // contents as command line parameters. + const resp_file_path = arg[1..]; + resp_file_args_iter = initArgIteratorResponseFile(arena, resp_file_path) catch |err| { + fatal("unable to read response file '{s}': {s}", .{ resp_file_path, @errorName(err) }); + }; + } else if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { try io.getStdOut().writeAll(usage_build_generic); return cleanExit(); @@ -789,8 +805,8 @@ fn buildOutputType( fatal("unexpected end-of-parameter mark: --", .{}); } } else if (mem.eql(u8, arg, "--pkg-begin")) { - const pkg_name = process_args_iter.next(); - const pkg_path = process_args_iter.next(); + const pkg_name = getNextArg(&process_args_iter, &resp_file_args_iter); + const pkg_path = getNextArg(&process_args_iter, &resp_file_args_iter); if (pkg_name == null or pkg_path == null) fatal("Expected 2 arguments after {s}", .{arg}); const new_cur_pkg = Package.create( @@ -806,25 +822,25 @@ fn buildOutputType( cur_pkg = cur_pkg.parent orelse fatal("encountered --pkg-end with no matching --pkg-begin", .{}); } else if (mem.eql(u8, arg, "--main-pkg-path")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); main_pkg_path = next_arg.?; } else if (mem.eql(u8, arg, "-cflags")) { extra_cflags.shrinkRetainingCapacity(0); while (true) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected -- after -cflags", .{}); if (mem.eql(u8, next_arg.?, "--")) break; try extra_cflags.append(next_arg.?); } } else if (mem.eql(u8, arg, "--color")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected [auto|on|off] after --color", .{}); color = std.meta.stringToEnum(Color, next_arg.?) orelse { fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg.?}); }; } else if (mem.eql(u8, arg, "--subsystem")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); if (mem.eql(u8, next_arg.?, "console")) { subsystem = .Console; @@ -857,65 +873,65 @@ fn buildOutputType( }); } } else if (mem.eql(u8, arg, "-O")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); optimize_mode_string = next_arg.?; } else if (mem.eql(u8, arg, "--entry")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); entry = next_arg.?; } else if (mem.eql(u8, arg, "--stack")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); stack_size_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--image-base")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); image_base_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--name")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); provided_name = next_arg.?; } else if (mem.eql(u8, arg, "-rpath")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try rpath_list.append(next_arg.?); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try lib_dirs.append(next_arg.?); } else if (mem.eql(u8, arg, "-F")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try framework_dirs.append(next_arg.?); } else if (mem.eql(u8, arg, "-framework")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try frameworks.append(next_arg.?); } else if (mem.eql(u8, arg, "-install_name")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); install_name = next_arg.?; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); linker_script = next_arg.?; } else if (mem.eql(u8, arg, "--version-script")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); version_script = next_arg.?; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); // We don't know whether this library is part of libc or libc++ until // we resolve the target, so we simply append to the list for now. try system_libs.put(next_arg.?, .{ .needed = false }); } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try system_libs.put(next_arg.?, .{ .needed = true }); } else if (mem.eql(u8, arg, "-D") or @@ -926,27 +942,27 @@ fn buildOutputType( mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try clang_argv.append(arg); try clang_argv.append(next_arg.?); } else if (mem.eql(u8, arg, "--version")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after --version", .{}); version = std.builtin.Version.parse(next_arg.?) catch |err| { fatal("unable to parse --version '{s}': {s}", .{ next_arg.?, @errorName(err) }); }; have_version = true; } else if (mem.eql(u8, arg, "-target")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); target_arch_os_abi = next_arg.?; } else if (mem.eql(u8, arg, "-mcpu")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); target_mcpu = next_arg.?; } else if (mem.eql(u8, arg, "-mcmodel")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); machine_code_model = parseCodeModel(next_arg.?); } else if (mem.startsWith(u8, arg, "-ofmt=")) { @@ -958,45 +974,45 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); target_dynamic_linker = next_arg.?; } else if (mem.eql(u8, arg, "--sysroot")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); sysroot = next_arg.?; try clang_argv.append("-isysroot"); try clang_argv.append(next_arg.?); } else if (mem.eql(u8, arg, "--libc")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); libc_paths_file = next_arg.?; } else if (mem.eql(u8, arg, "--test-filter")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); test_filter = next_arg.?; } else if (mem.eql(u8, arg, "--test-name-prefix")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); test_name_prefix = next_arg.?; } else if (mem.eql(u8, arg, "--test-cmd")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); try test_exec_args.append(next_arg.?); } else if (mem.eql(u8, arg, "--cache-dir")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); override_local_cache_dir = next_arg.?; } else if (mem.eql(u8, arg, "--global-cache-dir")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); override_global_cache_dir = next_arg.?; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); override_lib_dir = next_arg.?; } else if (mem.eql(u8, arg, "--debug-log")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected parameter after {s}", .{arg}); if (!build_options.enable_logging) { std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); @@ -1174,7 +1190,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; } else if (mem.eql(u8, arg, "-z")) { - const next_arg = process_args_iter.next(); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); if (next_arg == null) fatal("expected linker extension flag after '{s}'", .{arg}); const z_arg = next_arg.?; if (mem.eql(u8, z_arg, "nodelete")) { From 2bd10f4db98fd313c6743477ad36b139652a8dd5 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 20 Feb 2022 11:58:58 -0700 Subject: [PATCH 3/8] std: have Builder use response files if zig build args exceed OS limits In Mach engine we're seeing command line arguments to `zig build-lib` exceed the 32 KiB limit that Windows imposes, due to the number of sources and compiler flags we must pass in order to build gpu-dawn. This change fixes the issue by having `Builder` check if the arguments to a `zig build-*` command are >30 KiB and, if so, writes the arguments to a file `zig-cache/args/`. Then the command invocation merely becomes `zig build-lib @`. Fixes #10693 Fixes hexops/mach#167 Signed-off-by: Stephen Gutekanst --- lib/std/build.zig | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/lib/std/build.zig b/lib/std/build.zig index fcaa115ccb..6ac592cb7e 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -17,6 +17,7 @@ const fmt_lib = std.fmt; const File = std.fs.File; const CrossTarget = std.zig.CrossTarget; const NativeTargetInfo = std.zig.system.NativeTargetInfo; +const Sha256 = std.crypto.hash.sha2.Sha256; pub const FmtStep = @import("build/FmtStep.zig"); pub const TranslateCStep = @import("build/TranslateCStep.zig"); @@ -2888,6 +2889,48 @@ pub const LibExeObjStep = struct { try zig_args.append("--enable-cache"); + const is_build = switch (self.kind) { + .lib => true, + .exe => true, + .obj => true, + else => false, + }; + if (is_build) { + // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux + // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and + // pass that to zig, e.g. via 'zig build-lib @args.rsp' + var args_length: usize = 0; + for (zig_args.items) |arg| { + args_length += arg.len; + } + if (args_length >= 30 * 1024) { + const args_dir = try fs.path.join( + builder.allocator, + &[_][]const u8{ builder.pathFromRoot("zig-cache"), "args" }, + ); + try std.fs.cwd().makePath(args_dir); + + // Write the args to zig-cache/args/ to avoid conflicts with + // other zig build commands running in parallel. + const partially_quoted = try std.mem.join(builder.allocator, "\" \"", zig_args.items[2..]); + const args = try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); + + var args_hash: [Sha256.digest_length]u8 = undefined; + Sha256.hash(args, &args_hash, .{}); + var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; + _ = try std.fmt.bufPrint( + &args_hex_hash, + "{s}", + .{std.fmt.fmtSliceHexLower(&args_hash)}, + ); + + const args_file = try fs.path.join(builder.allocator, &[_][]const u8{ args_dir, args_hex_hash[0..] }); + try std.fs.cwd().writeFile(args_file, args); + + zig_args.shrinkRetainingCapacity(2); + try zig_args.append(try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "@", args_file })); + } + } const output_dir_nl = try builder.execFromStep(zig_args.items, &self.step); const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n"); From fb61db1ee40e08e939613dc8448ac619a05bf91d Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Mon, 21 Feb 2022 12:51:23 -0700 Subject: [PATCH 4/8] zig build: use orelse to fetch next argument Signed-off-by: Stephen Gutekanst --- src/main.zig | 264 +++++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 115 deletions(-) diff --git a/src/main.zig b/src/main.zig index 5e012ed067..fa9ce18c78 100644 --- a/src/main.zig +++ b/src/main.zig @@ -770,7 +770,7 @@ fn buildOutputType( _ = process_args_iter.skip(); // e.g. "build-lib" var resp_file_args_iter: ?ArgIteratorResponseFile = null; - var getNextArg = (struct { + const getNextArg = (struct { pub fn getNextArg(_process_args_iter: *process.ArgIterator, maybe_resp_file_args_iter: *?ArgIteratorResponseFile) ?[:0]const u8 { if (_process_args_iter.next()) |proc_arg| return proc_arg; if (maybe_resp_file_args_iter.*) |*iter| return iter.next(); @@ -822,45 +822,49 @@ fn buildOutputType( cur_pkg = cur_pkg.parent orelse fatal("encountered --pkg-end with no matching --pkg-begin", .{}); } else if (mem.eql(u8, arg, "--main-pkg-path")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - main_pkg_path = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + main_pkg_path = next_arg; } else if (mem.eql(u8, arg, "-cflags")) { extra_cflags.shrinkRetainingCapacity(0); while (true) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected -- after -cflags", .{}); - if (mem.eql(u8, next_arg.?, "--")) break; - try extra_cflags.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected -- after -cflags", .{}); + }; + if (mem.eql(u8, next_arg, "--")) break; + try extra_cflags.append(next_arg); } } else if (mem.eql(u8, arg, "--color")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected [auto|on|off] after --color", .{}); - color = std.meta.stringToEnum(Color, next_arg.?) orelse { - fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg.?}); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected [auto|on|off] after --color", .{}); + }; + color = std.meta.stringToEnum(Color, next_arg) orelse { + fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); }; } else if (mem.eql(u8, arg, "--subsystem")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - if (mem.eql(u8, next_arg.?, "console")) { + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + if (mem.eql(u8, next_arg, "console")) { subsystem = .Console; - } else if (mem.eql(u8, next_arg.?, "windows")) { + } else if (mem.eql(u8, next_arg, "windows")) { subsystem = .Windows; - } else if (mem.eql(u8, next_arg.?, "posix")) { + } else if (mem.eql(u8, next_arg, "posix")) { subsystem = .Posix; - } else if (mem.eql(u8, next_arg.?, "native")) { + } else if (mem.eql(u8, next_arg, "native")) { subsystem = .Native; - } else if (mem.eql(u8, next_arg.?, "efi_application")) { + } else if (mem.eql(u8, next_arg, "efi_application")) { subsystem = .EfiApplication; - } else if (mem.eql(u8, next_arg.?, "efi_boot_service_driver")) { + } else if (mem.eql(u8, next_arg, "efi_boot_service_driver")) { subsystem = .EfiBootServiceDriver; - } else if (mem.eql(u8, next_arg.?, "efi_rom")) { + } else if (mem.eql(u8, next_arg, "efi_rom")) { subsystem = .EfiRom; - } else if (mem.eql(u8, next_arg.?, "efi_runtime_driver")) { + } else if (mem.eql(u8, next_arg, "efi_runtime_driver")) { subsystem = .EfiRuntimeDriver; } else { fatal("invalid: --subsystem: '{s}'. Options are:\n{s}", .{ - next_arg.?, + next_arg, \\ console \\ windows \\ posix @@ -873,67 +877,81 @@ fn buildOutputType( }); } } else if (mem.eql(u8, arg, "-O")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - optimize_mode_string = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + optimize_mode_string = next_arg; } else if (mem.eql(u8, arg, "--entry")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - entry = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + entry = next_arg; } else if (mem.eql(u8, arg, "--stack")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - stack_size_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--image-base")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - image_base_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| { + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--name")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - provided_name = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + provided_name = next_arg; } else if (mem.eql(u8, arg, "-rpath")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try rpath_list.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try rpath_list.append(next_arg); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try lib_dirs.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try lib_dirs.append(next_arg); } else if (mem.eql(u8, arg, "-F")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try framework_dirs.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try framework_dirs.append(next_arg); } else if (mem.eql(u8, arg, "-framework")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try frameworks.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try frameworks.append(next_arg); } else if (mem.eql(u8, arg, "-install_name")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - install_name = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + install_name = next_arg; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - linker_script = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + linker_script = next_arg; } else if (mem.eql(u8, arg, "--version-script")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - version_script = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + version_script = next_arg; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; // We don't know whether this library is part of libc or libc++ until // we resolve the target, so we simply append to the list for now. - try system_libs.put(next_arg.?, .{ .needed = false }); + try system_libs.put(next_arg, .{ .needed = false }); } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try system_libs.put(next_arg.?, .{ .needed = true }); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try system_libs.put(next_arg, .{ .needed = true }); } else if (mem.eql(u8, arg, "-D") or mem.eql(u8, arg, "-isystem") or mem.eql(u8, arg, "-I") or @@ -942,29 +960,34 @@ fn buildOutputType( mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; try clang_argv.append(arg); - try clang_argv.append(next_arg.?); + try clang_argv.append(next_arg); } else if (mem.eql(u8, arg, "--version")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after --version", .{}); - version = std.builtin.Version.parse(next_arg.?) catch |err| { - fatal("unable to parse --version '{s}': {s}", .{ next_arg.?, @errorName(err) }); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + version = std.builtin.Version.parse(next_arg) catch |err| { + fatal("unable to parse --version '{s}': {s}", .{ next_arg, @errorName(err) }); }; have_version = true; } else if (mem.eql(u8, arg, "-target")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - target_arch_os_abi = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + target_arch_os_abi = next_arg; } else if (mem.eql(u8, arg, "-mcpu")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - target_mcpu = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + target_mcpu = next_arg; } else if (mem.eql(u8, arg, "-mcmodel")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - machine_code_model = parseCodeModel(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + machine_code_model = parseCodeModel(next_arg); } else if (mem.startsWith(u8, arg, "-ofmt=")) { target_ofmt = arg["-ofmt=".len..]; } else if (mem.startsWith(u8, arg, "-mcpu=")) { @@ -974,50 +997,60 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - target_dynamic_linker = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + target_dynamic_linker = next_arg; } else if (mem.eql(u8, arg, "--sysroot")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - sysroot = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + sysroot = next_arg; try clang_argv.append("-isysroot"); - try clang_argv.append(next_arg.?); + try clang_argv.append(next_arg); } else if (mem.eql(u8, arg, "--libc")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - libc_paths_file = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + libc_paths_file = next_arg; } else if (mem.eql(u8, arg, "--test-filter")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - test_filter = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + test_filter = next_arg; } else if (mem.eql(u8, arg, "--test-name-prefix")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - test_name_prefix = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + test_name_prefix = next_arg; } else if (mem.eql(u8, arg, "--test-cmd")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - try test_exec_args.append(next_arg.?); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + try test_exec_args.append(next_arg); } else if (mem.eql(u8, arg, "--cache-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - override_local_cache_dir = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + override_local_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--global-cache-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - override_global_cache_dir = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + override_global_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); - override_lib_dir = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + override_lib_dir = next_arg; } else if (mem.eql(u8, arg, "--debug-log")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected parameter after {s}", .{arg}); + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; if (!build_options.enable_logging) { std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); } else { - try log_scopes.append(gpa, next_arg.?); + try log_scopes.append(gpa, next_arg); } } else if (mem.eql(u8, arg, "--debug-link-snapshot")) { if (!build_options.enable_link_snapshots) { @@ -1190,9 +1223,10 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; } else if (mem.eql(u8, arg, "-z")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter); - if (next_arg == null) fatal("expected linker extension flag after '{s}'", .{arg}); - const z_arg = next_arg.?; + const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + fatal("expected parameter after {s}", .{arg}); + }; + const z_arg = next_arg; if (mem.eql(u8, z_arg, "nodelete")) { linker_z_nodelete = true; } else if (mem.eql(u8, z_arg, "notext")) { From 9c1c4747f46cbf2911d3383154acce41b3f532c4 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Mon, 21 Feb 2022 12:58:13 -0700 Subject: [PATCH 5/8] std: Builder: account for null term considering response files Signed-off-by: Stephen Gutekanst --- lib/std/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 6ac592cb7e..3e6b8cf0c8 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -2901,7 +2901,7 @@ pub const LibExeObjStep = struct { // pass that to zig, e.g. via 'zig build-lib @args.rsp' var args_length: usize = 0; for (zig_args.items) |arg| { - args_length += arg.len; + args_length += arg.len + 1; // +1 to account for null terminator } if (args_length >= 30 * 1024) { const args_dir = try fs.path.join( From efd473bbfc1417c5cc376f1b8ec44036752570bf Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Mon, 21 Feb 2022 13:06:23 -0700 Subject: [PATCH 6/8] std: Builder: use response files for zig test invocations too Signed-off-by: Stephen Gutekanst --- lib/std/build.zig | 75 +++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 3e6b8cf0c8..dc9e9e8312 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -2889,48 +2889,41 @@ pub const LibExeObjStep = struct { try zig_args.append("--enable-cache"); - const is_build = switch (self.kind) { - .lib => true, - .exe => true, - .obj => true, - else => false, - }; - if (is_build) { - // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux - // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and - // pass that to zig, e.g. via 'zig build-lib @args.rsp' - var args_length: usize = 0; - for (zig_args.items) |arg| { - args_length += arg.len + 1; // +1 to account for null terminator - } - if (args_length >= 30 * 1024) { - const args_dir = try fs.path.join( - builder.allocator, - &[_][]const u8{ builder.pathFromRoot("zig-cache"), "args" }, - ); - try std.fs.cwd().makePath(args_dir); - - // Write the args to zig-cache/args/ to avoid conflicts with - // other zig build commands running in parallel. - const partially_quoted = try std.mem.join(builder.allocator, "\" \"", zig_args.items[2..]); - const args = try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); - - var args_hash: [Sha256.digest_length]u8 = undefined; - Sha256.hash(args, &args_hash, .{}); - var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; - _ = try std.fmt.bufPrint( - &args_hex_hash, - "{s}", - .{std.fmt.fmtSliceHexLower(&args_hash)}, - ); - - const args_file = try fs.path.join(builder.allocator, &[_][]const u8{ args_dir, args_hex_hash[0..] }); - try std.fs.cwd().writeFile(args_file, args); - - zig_args.shrinkRetainingCapacity(2); - try zig_args.append(try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "@", args_file })); - } + // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux + // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and + // pass that to zig, e.g. via 'zig build-lib @args.rsp' + var args_length: usize = 0; + for (zig_args.items) |arg| { + args_length += arg.len + 1; // +1 to account for null terminator } + if (args_length >= 30 * 1024) { + const args_dir = try fs.path.join( + builder.allocator, + &[_][]const u8{ builder.pathFromRoot("zig-cache"), "args" }, + ); + try std.fs.cwd().makePath(args_dir); + + // Write the args to zig-cache/args/ to avoid conflicts with + // other zig build commands running in parallel. + const partially_quoted = try std.mem.join(builder.allocator, "\" \"", zig_args.items[2..]); + const args = try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); + + var args_hash: [Sha256.digest_length]u8 = undefined; + Sha256.hash(args, &args_hash, .{}); + var args_hex_hash: [Sha256.digest_length * 2]u8 = undefined; + _ = try std.fmt.bufPrint( + &args_hex_hash, + "{s}", + .{std.fmt.fmtSliceHexLower(&args_hash)}, + ); + + const args_file = try fs.path.join(builder.allocator, &[_][]const u8{ args_dir, args_hex_hash[0..] }); + try std.fs.cwd().writeFile(args_file, args); + + zig_args.shrinkRetainingCapacity(2); + try zig_args.append(try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "@", args_file })); + } + const output_dir_nl = try builder.execFromStep(zig_args.items, &self.step); const build_output_dir = mem.trimRight(u8, output_dir_nl, "\r\n"); From b341967da0fc0fe5dfc8fa914006fd6a7624297f Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Mon, 21 Feb 2022 14:18:15 -0700 Subject: [PATCH 7/8] zig build: use a custom iterator for merging args and response file Signed-off-by: Stephen Gutekanst --- src/main.zig | 108 +++++++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/main.zig b/src/main.zig index fa9ce18c78..7f7ba201d8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -765,30 +765,30 @@ fn buildOutputType( } soname = .yes_default_value; - var process_args_iter = try process.argsWithAllocator(arena); - _ = process_args_iter.skip(); // "zig" - _ = process_args_iter.skip(); // e.g. "build-lib" - var resp_file_args_iter: ?ArgIteratorResponseFile = null; - const getNextArg = (struct { - pub fn getNextArg(_process_args_iter: *process.ArgIterator, maybe_resp_file_args_iter: *?ArgIteratorResponseFile) ?[:0]const u8 { - if (_process_args_iter.next()) |proc_arg| return proc_arg; - if (maybe_resp_file_args_iter.*) |*iter| return iter.next(); - return null; - } - }).getNextArg; - - args_loop: while (getNextArg(&process_args_iter, &resp_file_args_iter)) |arg| { - var args_index = process_args_iter.inner.index; - if (resp_file_args_iter) |iter| { - args_index = iter.index; + const Iterator = struct { + resp_file: ?ArgIteratorResponseFile = null, + args: []const []const u8, + i: usize = 0, + fn next(it: *@This()) ?[]const u8 { + if (it.i >= it.args.len) { + if (it.resp_file) |*resp| return if (resp.next()) |sentinel| std.mem.span(sentinel) else null; + return null; + } + defer it.i += 1; + return it.args[it.i]; } + }; + var args_iter = Iterator{ + .args = all_args[2..], + }; + args_loop: while (args_iter.next()) |arg| { if (mem.startsWith(u8, arg, "@")) { // This is a "compiler response file". We must parse the file and treat its // contents as command line parameters. const resp_file_path = arg[1..]; - resp_file_args_iter = initArgIteratorResponseFile(arena, resp_file_path) catch |err| { + args_iter.resp_file = initArgIteratorResponseFile(arena, resp_file_path) catch |err| { fatal("unable to read response file '{s}': {s}", .{ resp_file_path, @errorName(err) }); }; } else if (mem.startsWith(u8, arg, "-")) { @@ -799,14 +799,14 @@ fn buildOutputType( if (arg_mode == .run) { // The index refers to all_args so skip `zig` `run` // and `--` - runtime_args_start = args_index + 3; + runtime_args_start = args_iter.i + 3; break :args_loop; } else { fatal("unexpected end-of-parameter mark: --", .{}); } } else if (mem.eql(u8, arg, "--pkg-begin")) { - const pkg_name = getNextArg(&process_args_iter, &resp_file_args_iter); - const pkg_path = getNextArg(&process_args_iter, &resp_file_args_iter); + const pkg_name = args_iter.next(); + const pkg_path = args_iter.next(); if (pkg_name == null or pkg_path == null) fatal("Expected 2 arguments after {s}", .{arg}); const new_cur_pkg = Package.create( @@ -822,28 +822,28 @@ fn buildOutputType( cur_pkg = cur_pkg.parent orelse fatal("encountered --pkg-end with no matching --pkg-begin", .{}); } else if (mem.eql(u8, arg, "--main-pkg-path")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; main_pkg_path = next_arg; } else if (mem.eql(u8, arg, "-cflags")) { extra_cflags.shrinkRetainingCapacity(0); while (true) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected -- after -cflags", .{}); }; if (mem.eql(u8, next_arg, "--")) break; try extra_cflags.append(next_arg); } } else if (mem.eql(u8, arg, "--color")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected [auto|on|off] after --color", .{}); }; color = std.meta.stringToEnum(Color, next_arg) orelse { fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); }; } else if (mem.eql(u8, arg, "--subsystem")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; if (mem.eql(u8, next_arg, "console")) { @@ -877,78 +877,78 @@ fn buildOutputType( }); } } else if (mem.eql(u8, arg, "-O")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; optimize_mode_string = next_arg; } else if (mem.eql(u8, arg, "--entry")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; entry = next_arg; } else if (mem.eql(u8, arg, "--stack")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--image-base")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--name")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; provided_name = next_arg; } else if (mem.eql(u8, arg, "-rpath")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try rpath_list.append(next_arg); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try lib_dirs.append(next_arg); } else if (mem.eql(u8, arg, "-F")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try framework_dirs.append(next_arg); } else if (mem.eql(u8, arg, "-framework")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try frameworks.append(next_arg); } else if (mem.eql(u8, arg, "-install_name")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; install_name = next_arg; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; linker_script = next_arg; } else if (mem.eql(u8, arg, "--version-script")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; version_script = next_arg; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; // We don't know whether this library is part of libc or libc++ until // we resolve the target, so we simply append to the list for now. try system_libs.put(next_arg, .{ .needed = false }); } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try system_libs.put(next_arg, .{ .needed = true }); @@ -960,13 +960,13 @@ fn buildOutputType( mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try clang_argv.append(arg); try clang_argv.append(next_arg); } else if (mem.eql(u8, arg, "--version")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; version = std.builtin.Version.parse(next_arg) catch |err| { @@ -974,17 +974,17 @@ fn buildOutputType( }; have_version = true; } else if (mem.eql(u8, arg, "-target")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; target_arch_os_abi = next_arg; } else if (mem.eql(u8, arg, "-mcpu")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; target_mcpu = next_arg; } else if (mem.eql(u8, arg, "-mcmodel")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; machine_code_model = parseCodeModel(next_arg); @@ -997,54 +997,54 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; target_dynamic_linker = next_arg; } else if (mem.eql(u8, arg, "--sysroot")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; sysroot = next_arg; try clang_argv.append("-isysroot"); try clang_argv.append(next_arg); } else if (mem.eql(u8, arg, "--libc")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; libc_paths_file = next_arg; } else if (mem.eql(u8, arg, "--test-filter")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; test_filter = next_arg; } else if (mem.eql(u8, arg, "--test-name-prefix")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; test_name_prefix = next_arg; } else if (mem.eql(u8, arg, "--test-cmd")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; try test_exec_args.append(next_arg); } else if (mem.eql(u8, arg, "--cache-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; override_local_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--global-cache-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; override_global_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; override_lib_dir = next_arg; } else if (mem.eql(u8, arg, "--debug-log")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; if (!build_options.enable_logging) { @@ -1223,7 +1223,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; } else if (mem.eql(u8, arg, "-z")) { - const next_arg = getNextArg(&process_args_iter, &resp_file_args_iter) orelse { + const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; const z_arg = next_arg; From c577926a7d3cea68f781cd68ad65a0606c4f7a54 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Tue, 22 Feb 2022 09:02:37 -0700 Subject: [PATCH 8/8] zig build: style: remove unnecessary constant bindings Signed-off-by: Stephen Gutekanst --- src/main.zig | 93 +++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 59 deletions(-) diff --git a/src/main.zig b/src/main.zig index 7f7ba201d8..581e17967d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -822,10 +822,9 @@ fn buildOutputType( cur_pkg = cur_pkg.parent orelse fatal("encountered --pkg-end with no matching --pkg-begin", .{}); } else if (mem.eql(u8, arg, "--main-pkg-path")) { - const next_arg = args_iter.next() orelse { + main_pkg_path = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - main_pkg_path = next_arg; } else if (mem.eql(u8, arg, "-cflags")) { extra_cflags.shrinkRetainingCapacity(0); while (true) { @@ -877,15 +876,13 @@ fn buildOutputType( }); } } else if (mem.eql(u8, arg, "-O")) { - const next_arg = args_iter.next() orelse { + optimize_mode_string = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - optimize_mode_string = next_arg; } else if (mem.eql(u8, arg, "--entry")) { - const next_arg = args_iter.next() orelse { + entry = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - entry = next_arg; } else if (mem.eql(u8, arg, "--stack")) { const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); @@ -901,45 +898,37 @@ fn buildOutputType( fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; } else if (mem.eql(u8, arg, "--name")) { - const next_arg = args_iter.next() orelse { + provided_name = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - provided_name = next_arg; } else if (mem.eql(u8, arg, "-rpath")) { - const next_arg = args_iter.next() orelse { + try rpath_list.append(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - try rpath_list.append(next_arg); + }); } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { - const next_arg = args_iter.next() orelse { + try lib_dirs.append(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - try lib_dirs.append(next_arg); + }); } else if (mem.eql(u8, arg, "-F")) { - const next_arg = args_iter.next() orelse { + try framework_dirs.append(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - try framework_dirs.append(next_arg); + }); } else if (mem.eql(u8, arg, "-framework")) { - const next_arg = args_iter.next() orelse { + try frameworks.append(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - try frameworks.append(next_arg); + }); } else if (mem.eql(u8, arg, "-install_name")) { - const next_arg = args_iter.next() orelse { + install_name = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - install_name = next_arg; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { - const next_arg = args_iter.next() orelse { + linker_script = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - linker_script = next_arg; } else if (mem.eql(u8, arg, "--version-script")) { - const next_arg = args_iter.next() orelse { + version_script = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - version_script = next_arg; } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); @@ -960,11 +949,10 @@ fn buildOutputType( mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) { - const next_arg = args_iter.next() orelse { - fatal("expected parameter after {s}", .{arg}); - }; try clang_argv.append(arg); - try clang_argv.append(next_arg); + try clang_argv.append(args_iter.next() orelse { + fatal("expected parameter after {s}", .{arg}); + }); } else if (mem.eql(u8, arg, "--version")) { const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); @@ -974,20 +962,17 @@ fn buildOutputType( }; have_version = true; } else if (mem.eql(u8, arg, "-target")) { - const next_arg = args_iter.next() orelse { + target_arch_os_abi = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - target_arch_os_abi = next_arg; } else if (mem.eql(u8, arg, "-mcpu")) { - const next_arg = args_iter.next() orelse { + target_mcpu = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - target_mcpu = next_arg; } else if (mem.eql(u8, arg, "-mcmodel")) { - const next_arg = args_iter.next() orelse { + machine_code_model = parseCodeModel(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - machine_code_model = parseCodeModel(next_arg); + }); } else if (mem.startsWith(u8, arg, "-ofmt=")) { target_ofmt = arg["-ofmt=".len..]; } else if (mem.startsWith(u8, arg, "-mcpu=")) { @@ -997,52 +982,43 @@ fn buildOutputType( } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { - const next_arg = args_iter.next() orelse { + target_dynamic_linker = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - target_dynamic_linker = next_arg; } else if (mem.eql(u8, arg, "--sysroot")) { - const next_arg = args_iter.next() orelse { + sysroot = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - sysroot = next_arg; try clang_argv.append("-isysroot"); - try clang_argv.append(next_arg); + try clang_argv.append(sysroot.?); } else if (mem.eql(u8, arg, "--libc")) { - const next_arg = args_iter.next() orelse { + libc_paths_file = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - libc_paths_file = next_arg; } else if (mem.eql(u8, arg, "--test-filter")) { - const next_arg = args_iter.next() orelse { + test_filter = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - test_filter = next_arg; } else if (mem.eql(u8, arg, "--test-name-prefix")) { - const next_arg = args_iter.next() orelse { + test_name_prefix = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - test_name_prefix = next_arg; } else if (mem.eql(u8, arg, "--test-cmd")) { - const next_arg = args_iter.next() orelse { + try test_exec_args.append(args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); - }; - try test_exec_args.append(next_arg); + }); } else if (mem.eql(u8, arg, "--cache-dir")) { - const next_arg = args_iter.next() orelse { + override_local_cache_dir = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - override_local_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--global-cache-dir")) { - const next_arg = args_iter.next() orelse { + override_global_cache_dir = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - override_global_cache_dir = next_arg; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - const next_arg = args_iter.next() orelse { + override_lib_dir = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - override_lib_dir = next_arg; } else if (mem.eql(u8, arg, "--debug-log")) { const next_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); @@ -1223,10 +1199,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; } else if (mem.eql(u8, arg, "-z")) { - const next_arg = args_iter.next() orelse { + const z_arg = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; - const z_arg = next_arg; if (mem.eql(u8, z_arg, "nodelete")) { linker_z_nodelete = true; } else if (mem.eql(u8, z_arg, "notext")) {