authorgravatar for stephen@hexops.comStephen Gutekanst <stephen@hexops.com> 2022-02-19 23:28:54-07:00
committergravatar for stephen@hexops.comStephen Gutekanst <stephen@hexops.com> 2022-02-20 13:47:41-07:00
log0778f644b519a83e95848d05d5a9e6241f8f41f3
tree44a16593fc2db28226d29ecda285ee76b3a1a035
parent2c8541bdde0b5ffd291600639b6123e512496923

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 <stephen@hexops.com>

1 files changed, 143 insertions(+), 146 deletions(-)

src/main.zig+143-146
......@@ -765,10 +765,16 @@ fn buildOutputType(
765765 }
766766
767767 soname = .yes_default_value;
768 const args = all_args[2..];
769 var i: usize = 0;
770 args_loop: while (i < args.len) : (i += 1) {
771 const arg = args[i];
768 var process_args_iter = try process.argsWithAllocator(arena);
769 _ = process_args_iter.skip(); // "zig"
770 _ = process_args_iter.skip(); // e.g. "build-lib"
771
772 args_loop: while (process_args_iter.next()) |arg| {
773 var args_index = process_args_iter.inner.index;
774 if (resp_file_args_iter) |iter| {
775 args_index = iter.index;
776 }
777
772778 if (mem.startsWith(u8, arg, "-")) {
773779 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
774780 try io.getStdOut().writeAll(usage_build_generic);
......@@ -777,73 +783,68 @@ fn buildOutputType(
777783 if (arg_mode == .run) {
778784 // The index refers to all_args so skip `zig` `run`
779785 // and `--`
780 runtime_args_start = i + 3;
786 runtime_args_start = args_index + 3;
781787 break :args_loop;
782788 } else {
783789 fatal("unexpected end-of-parameter mark: --", .{});
784790 }
785791 } else if (mem.eql(u8, arg, "--pkg-begin")) {
786 if (i + 2 >= args.len) fatal("Expected 2 arguments after {s}", .{arg});
787 i += 1;
788 const pkg_name = args[i];
789 i += 1;
790 const pkg_path = args[i];
792 const pkg_name = process_args_iter.next();
793 const pkg_path = process_args_iter.next();
794 if (pkg_name == null or pkg_path == null) fatal("Expected 2 arguments after {s}", .{arg});
791795
792796 const new_cur_pkg = Package.create(
793797 gpa,
794 fs.path.dirname(pkg_path),
795 fs.path.basename(pkg_path),
798 fs.path.dirname(pkg_path.?),
799 fs.path.basename(pkg_path.?),
796800 ) catch |err| {
797 fatal("Failed to add package at path {s}: {s}", .{ pkg_path, @errorName(err) });
801 fatal("Failed to add package at path {s}: {s}", .{ pkg_path.?, @errorName(err) });
798802 };
799 try cur_pkg.addAndAdopt(gpa, pkg_name, new_cur_pkg);
803 try cur_pkg.addAndAdopt(gpa, pkg_name.?, new_cur_pkg);
800804 cur_pkg = new_cur_pkg;
801805 } else if (mem.eql(u8, arg, "--pkg-end")) {
802806 cur_pkg = cur_pkg.parent orelse
803807 fatal("encountered --pkg-end with no matching --pkg-begin", .{});
804808 } else if (mem.eql(u8, arg, "--main-pkg-path")) {
805 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
806 i += 1;
807 main_pkg_path = args[i];
809 const next_arg = process_args_iter.next();
810 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
811 main_pkg_path = next_arg.?;
808812 } else if (mem.eql(u8, arg, "-cflags")) {
809813 extra_cflags.shrinkRetainingCapacity(0);
810814 while (true) {
811 i += 1;
812 if (i >= args.len) fatal("expected -- after -cflags", .{});
813 if (mem.eql(u8, args[i], "--")) break;
814 try extra_cflags.append(args[i]);
815 const next_arg = process_args_iter.next();
816 if (next_arg == null) fatal("expected -- after -cflags", .{});
817 if (mem.eql(u8, next_arg.?, "--")) break;
818 try extra_cflags.append(next_arg.?);
815819 }
816820 } else if (mem.eql(u8, arg, "--color")) {
817 if (i + 1 >= args.len) {
818 fatal("expected [auto|on|off] after --color", .{});
819 }
820 i += 1;
821 const next_arg = args[i];
822 color = std.meta.stringToEnum(Color, next_arg) orelse {
823 fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
821 const next_arg = process_args_iter.next();
822 if (next_arg == null) fatal("expected [auto|on|off] after --color", .{});
823 color = std.meta.stringToEnum(Color, next_arg.?) orelse {
824 fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg.?});
824825 };
825826 } else if (mem.eql(u8, arg, "--subsystem")) {
826 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
827 i += 1;
828 if (mem.eql(u8, args[i], "console")) {
827 const next_arg = process_args_iter.next();
828 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
829 if (mem.eql(u8, next_arg.?, "console")) {
829830 subsystem = .Console;
830 } else if (mem.eql(u8, args[i], "windows")) {
831 } else if (mem.eql(u8, next_arg.?, "windows")) {
831832 subsystem = .Windows;
832 } else if (mem.eql(u8, args[i], "posix")) {
833 } else if (mem.eql(u8, next_arg.?, "posix")) {
833834 subsystem = .Posix;
834 } else if (mem.eql(u8, args[i], "native")) {
835 } else if (mem.eql(u8, next_arg.?, "native")) {
835836 subsystem = .Native;
836 } else if (mem.eql(u8, args[i], "efi_application")) {
837 } else if (mem.eql(u8, next_arg.?, "efi_application")) {
837838 subsystem = .EfiApplication;
838 } else if (mem.eql(u8, args[i], "efi_boot_service_driver")) {
839 } else if (mem.eql(u8, next_arg.?, "efi_boot_service_driver")) {
839840 subsystem = .EfiBootServiceDriver;
840 } else if (mem.eql(u8, args[i], "efi_rom")) {
841 } else if (mem.eql(u8, next_arg.?, "efi_rom")) {
841842 subsystem = .EfiRom;
842 } else if (mem.eql(u8, args[i], "efi_runtime_driver")) {
843 } else if (mem.eql(u8, next_arg.?, "efi_runtime_driver")) {
843844 subsystem = .EfiRuntimeDriver;
844845 } else {
845846 fatal("invalid: --subsystem: '{s}'. Options are:\n{s}", .{
846 args[i],
847 next_arg.?,
847848 \\ console
848849 \\ windows
849850 \\ posix
......@@ -856,67 +857,67 @@ fn buildOutputType(
856857 });
857858 }
858859 } else if (mem.eql(u8, arg, "-O")) {
859 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
860 i += 1;
861 optimize_mode_string = args[i];
860 const next_arg = process_args_iter.next();
861 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
862 optimize_mode_string = next_arg.?;
862863 } else if (mem.eql(u8, arg, "--entry")) {
863 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
864 i += 1;
865 entry = args[i];
864 const next_arg = process_args_iter.next();
865 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
866 entry = next_arg.?;
866867 } else if (mem.eql(u8, arg, "--stack")) {
867 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
868 i += 1;
869 stack_size_override = std.fmt.parseUnsigned(u64, args[i], 0) catch |err| {
868 const next_arg = process_args_iter.next();
869 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
870 stack_size_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| {
870871 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
871872 };
872873 } else if (mem.eql(u8, arg, "--image-base")) {
873 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
874 i += 1;
875 image_base_override = std.fmt.parseUnsigned(u64, args[i], 0) catch |err| {
874 const next_arg = process_args_iter.next();
875 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
876 image_base_override = std.fmt.parseUnsigned(u64, next_arg.?, 0) catch |err| {
876877 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
877878 };
878879 } else if (mem.eql(u8, arg, "--name")) {
879 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
880 i += 1;
881 provided_name = args[i];
880 const next_arg = process_args_iter.next();
881 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
882 provided_name = next_arg.?;
882883 } else if (mem.eql(u8, arg, "-rpath")) {
883 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
884 i += 1;
885 try rpath_list.append(args[i]);
884 const next_arg = process_args_iter.next();
885 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
886 try rpath_list.append(next_arg.?);
886887 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {
887 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
888 i += 1;
889 try lib_dirs.append(args[i]);
888 const next_arg = process_args_iter.next();
889 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
890 try lib_dirs.append(next_arg.?);
890891 } else if (mem.eql(u8, arg, "-F")) {
891 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
892 i += 1;
893 try framework_dirs.append(args[i]);
892 const next_arg = process_args_iter.next();
893 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
894 try framework_dirs.append(next_arg.?);
894895 } else if (mem.eql(u8, arg, "-framework")) {
895 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
896 i += 1;
897 try frameworks.append(args[i]);
896 const next_arg = process_args_iter.next();
897 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
898 try frameworks.append(next_arg.?);
898899 } else if (mem.eql(u8, arg, "-install_name")) {
899 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
900 i += 1;
901 install_name = args[i];
900 const next_arg = process_args_iter.next();
901 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
902 install_name = next_arg.?;
902903 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
903 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
904 i += 1;
905 linker_script = args[i];
904 const next_arg = process_args_iter.next();
905 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
906 linker_script = next_arg.?;
906907 } else if (mem.eql(u8, arg, "--version-script")) {
907 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
908 i += 1;
909 version_script = args[i];
908 const next_arg = process_args_iter.next();
909 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
910 version_script = next_arg.?;
910911 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
911 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
912 const next_arg = process_args_iter.next();
913 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
912914 // We don't know whether this library is part of libc or libc++ until
913915 // we resolve the target, so we simply append to the list for now.
914 i += 1;
915 try system_libs.put(args[i], .{ .needed = false });
916 try system_libs.put(next_arg.?, .{ .needed = false });
916917 } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l")) {
917 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
918 i += 1;
919 try system_libs.put(args[i], .{ .needed = true });
918 const next_arg = process_args_iter.next();
919 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
920 try system_libs.put(next_arg.?, .{ .needed = true });
920921 } else if (mem.eql(u8, arg, "-D") or
921922 mem.eql(u8, arg, "-isystem") or
922923 mem.eql(u8, arg, "-I") or
......@@ -925,31 +926,29 @@ fn buildOutputType(
925926 mem.eql(u8, arg, "-iframework") or
926927 mem.eql(u8, arg, "-iframeworkwithsysroot"))
927928 {
928 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
929 i += 1;
929 const next_arg = process_args_iter.next();
930 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
930931 try clang_argv.append(arg);
931 try clang_argv.append(args[i]);
932 try clang_argv.append(next_arg.?);
932933 } else if (mem.eql(u8, arg, "--version")) {
933 if (i + 1 >= args.len) {
934 fatal("expected parameter after --version", .{});
935 }
936 i += 1;
937 version = std.builtin.Version.parse(args[i]) catch |err| {
938 fatal("unable to parse --version '{s}': {s}", .{ args[i], @errorName(err) });
934 const next_arg = process_args_iter.next();
935 if (next_arg == null) fatal("expected parameter after --version", .{});
936 version = std.builtin.Version.parse(next_arg.?) catch |err| {
937 fatal("unable to parse --version '{s}': {s}", .{ next_arg.?, @errorName(err) });
939938 };
940939 have_version = true;
941940 } else if (mem.eql(u8, arg, "-target")) {
942 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
943 i += 1;
944 target_arch_os_abi = args[i];
941 const next_arg = process_args_iter.next();
942 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
943 target_arch_os_abi = next_arg.?;
945944 } else if (mem.eql(u8, arg, "-mcpu")) {
946 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
947 i += 1;
948 target_mcpu = args[i];
945 const next_arg = process_args_iter.next();
946 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
947 target_mcpu = next_arg.?;
949948 } else if (mem.eql(u8, arg, "-mcmodel")) {
950 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
951 i += 1;
952 machine_code_model = parseCodeModel(args[i]);
949 const next_arg = process_args_iter.next();
950 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
951 machine_code_model = parseCodeModel(next_arg.?);
953952 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
954953 target_ofmt = arg["-ofmt=".len..];
955954 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
......@@ -959,50 +958,50 @@ fn buildOutputType(
959958 } else if (mem.startsWith(u8, arg, "-O")) {
960959 optimize_mode_string = arg["-O".len..];
961960 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
962 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
963 i += 1;
964 target_dynamic_linker = args[i];
961 const next_arg = process_args_iter.next();
962 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
963 target_dynamic_linker = next_arg.?;
965964 } else if (mem.eql(u8, arg, "--sysroot")) {
966 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
967 i += 1;
968 sysroot = args[i];
965 const next_arg = process_args_iter.next();
966 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
967 sysroot = next_arg.?;
969968 try clang_argv.append("-isysroot");
970 try clang_argv.append(args[i]);
969 try clang_argv.append(next_arg.?);
971970 } else if (mem.eql(u8, arg, "--libc")) {
972 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
973 i += 1;
974 libc_paths_file = args[i];
971 const next_arg = process_args_iter.next();
972 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
973 libc_paths_file = next_arg.?;
975974 } else if (mem.eql(u8, arg, "--test-filter")) {
976 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
977 i += 1;
978 test_filter = args[i];
975 const next_arg = process_args_iter.next();
976 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
977 test_filter = next_arg.?;
979978 } else if (mem.eql(u8, arg, "--test-name-prefix")) {
980 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
981 i += 1;
982 test_name_prefix = args[i];
979 const next_arg = process_args_iter.next();
980 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
981 test_name_prefix = next_arg.?;
983982 } else if (mem.eql(u8, arg, "--test-cmd")) {
984 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
985 i += 1;
986 try test_exec_args.append(args[i]);
983 const next_arg = process_args_iter.next();
984 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
985 try test_exec_args.append(next_arg.?);
987986 } else if (mem.eql(u8, arg, "--cache-dir")) {
988 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
989 i += 1;
990 override_local_cache_dir = args[i];
987 const next_arg = process_args_iter.next();
988 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
989 override_local_cache_dir = next_arg.?;
991990 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
992 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
993 i += 1;
994 override_global_cache_dir = args[i];
991 const next_arg = process_args_iter.next();
992 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
993 override_global_cache_dir = next_arg.?;
995994 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
996 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
997 i += 1;
998 override_lib_dir = args[i];
995 const next_arg = process_args_iter.next();
996 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
997 override_lib_dir = next_arg.?;
999998 } else if (mem.eql(u8, arg, "--debug-log")) {
1000 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
1001 i += 1;
999 const next_arg = process_args_iter.next();
1000 if (next_arg == null) fatal("expected parameter after {s}", .{arg});
10021001 if (!build_options.enable_logging) {
10031002 std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
10041003 } else {
1005 try log_scopes.append(gpa, args[i]);
1004 try log_scopes.append(gpa, next_arg.?);
10061005 }
10071006 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {
10081007 if (!build_options.enable_link_snapshots) {
......@@ -1175,11 +1174,9 @@ fn buildOutputType(
11751174 } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) {
11761175 linker_allow_shlib_undefined = false;
11771176 } else if (mem.eql(u8, arg, "-z")) {
1178 i += 1;
1179 if (i >= args.len) {
1180 fatal("expected linker extension flag after '{s}'", .{arg});
1181 }
1182 const z_arg = args[i];
1177 const next_arg = process_args_iter.next();
1178 if (next_arg == null) fatal("expected linker extension flag after '{s}'", .{arg});
1179 const z_arg = next_arg.?;
11831180 if (mem.eql(u8, z_arg, "nodelete")) {
11841181 linker_z_nodelete = true;
11851182 } else if (mem.eql(u8, z_arg, "notext")) {
......@@ -4265,6 +4262,17 @@ pub fn lldMain(
42654262 return @bitCast(u8, @truncate(i8, exit_code));
42664263}
42674264
4265const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, .single_quotes = true });
4266
4267/// Initialize the arguments from a Response File. "*.rsp"
4268fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile {
4269 const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit
4270 var cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes);
4271 errdefer allocator.free(cmd_line);
4272
4273 return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line);
4274}
4275
42684276const clang_args = @import("clang_options.zig").list;
42694277
42704278pub const ClangArgIterator = struct {
......@@ -4354,17 +4362,6 @@ pub const ClangArgIterator = struct {
43544362 };
43554363 }
43564364
4357 const ArgIteratorResponseFile = process.ArgIteratorGeneral(.{ .comments = true, .single_quotes = true });
4358
4359 /// Initialize the arguments from a Response File. "*.rsp"
4360 fn initArgIteratorResponseFile(allocator: Allocator, resp_file_path: []const u8) !ArgIteratorResponseFile {
4361 const max_bytes = 10 * 1024 * 1024; // 10 MiB of command line arguments is a reasonable limit
4362 var cmd_line = try fs.cwd().readFileAlloc(allocator, resp_file_path, max_bytes);
4363 errdefer allocator.free(cmd_line);
4364
4365 return ArgIteratorResponseFile.initTakeOwnership(allocator, cmd_line);
4366 }
4367
43684365 fn next(self: *ClangArgIterator) !void {
43694366 assert(self.has_next);
43704367 assert(self.next_index < self.argv.len);