| ... | ... | @@ -11,32 +11,31 @@ const warn = std.debug.warn; |
| 11 | 11 | const File = std.fs.File; |
| 12 | 12 | |
| 13 | 13 | pub fn main() !void { |
| 14 | | var arg_it = process.args(); |
| 15 | | |
| 16 | 14 | // Here we use an ArenaAllocator backed by a DirectAllocator because a build is a short-lived, |
| 17 | 15 | // one shot program. We don't need to waste time freeing memory and finding places to squish |
| 18 | 16 | // bytes into. So we free everything all at once at the very end. |
| 19 | | |
| 20 | 17 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 21 | 18 | defer arena.deinit(); |
| 22 | 19 | |
| 23 | 20 | const allocator = &arena.allocator; |
| 21 | var args = try process.argsAlloc(allocator); |
| 22 | defer process.argsFree(allocator, args); |
| 24 | 23 | |
| 25 | 24 | // skip my own exe name |
| 26 | | _ = arg_it.skip(); |
| 25 | var arg_idx: usize = 1; |
| 27 | 26 | |
| 28 | | const zig_exe = try unwrapArg(arg_it.next(allocator) orelse { |
| 27 | const zig_exe = nextArg(args, &arg_idx) orelse { |
| 29 | 28 | warn("Expected first argument to be path to zig compiler\n", .{}); |
| 30 | 29 | return error.InvalidArgs; |
| 31 | | }); |
| 32 | | const build_root = try unwrapArg(arg_it.next(allocator) orelse { |
| 30 | }; |
| 31 | const build_root = nextArg(args, &arg_idx) orelse { |
| 33 | 32 | warn("Expected second argument to be build root directory path\n", .{}); |
| 34 | 33 | return error.InvalidArgs; |
| 35 | | }); |
| 36 | | const cache_root = try unwrapArg(arg_it.next(allocator) orelse { |
| 34 | }; |
| 35 | const cache_root = nextArg(args, &arg_idx) orelse { |
| 37 | 36 | warn("Expected third argument to be cache root directory path\n", .{}); |
| 38 | 37 | return error.InvalidArgs; |
| 39 | | }); |
| 38 | }; |
| 40 | 39 | |
| 41 | 40 | const builder = try Builder.create(allocator, zig_exe, build_root, cache_root); |
| 42 | 41 | defer builder.destroy(); |
| ... | ... | @@ -46,8 +45,7 @@ pub fn main() !void { |
| 46 | 45 | const stderr_stream = &io.getStdErr().outStream().stream; |
| 47 | 46 | const stdout_stream = &io.getStdOut().outStream().stream; |
| 48 | 47 | |
| 49 | | while (arg_it.next(allocator)) |err_or_arg| { |
| 50 | | const arg = try unwrapArg(err_or_arg); |
| 48 | while (nextArg(args, &arg_idx)) |arg| { |
| 51 | 49 | if (mem.startsWith(u8, arg, "-D")) { |
| 52 | 50 | const option_contents = arg[2..]; |
| 53 | 51 | if (option_contents.len == 0) { |
| ... | ... | @@ -69,21 +67,21 @@ pub fn main() !void { |
| 69 | 67 | } else if (mem.eql(u8, arg, "--help")) { |
| 70 | 68 | return usage(builder, false, stdout_stream); |
| 71 | 69 | } else if (mem.eql(u8, arg, "--prefix")) { |
| 72 | | builder.install_prefix = try unwrapArg(arg_it.next(allocator) orelse { |
| 70 | builder.install_prefix = nextArg(args, &arg_idx) orelse { |
| 73 | 71 | warn("Expected argument after --prefix\n\n", .{}); |
| 74 | 72 | return usageAndErr(builder, false, stderr_stream); |
| 75 | | }); |
| 73 | }; |
| 76 | 74 | } else if (mem.eql(u8, arg, "--search-prefix")) { |
| 77 | | const search_prefix = try unwrapArg(arg_it.next(allocator) orelse { |
| 75 | const search_prefix = nextArg(args, &arg_idx) orelse { |
| 78 | 76 | warn("Expected argument after --search-prefix\n\n", .{}); |
| 79 | 77 | return usageAndErr(builder, false, stderr_stream); |
| 80 | | }); |
| 78 | }; |
| 81 | 79 | builder.addSearchPrefix(search_prefix); |
| 82 | 80 | } else if (mem.eql(u8, arg, "--override-lib-dir")) { |
| 83 | | builder.override_lib_dir = try unwrapArg(arg_it.next(allocator) orelse { |
| 81 | builder.override_lib_dir = nextArg(args, &arg_idx) orelse { |
| 84 | 82 | warn("Expected argument after --override-lib-dir\n\n", .{}); |
| 85 | 83 | return usageAndErr(builder, false, stderr_stream); |
| 86 | | }); |
| 84 | }; |
| 87 | 85 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { |
| 88 | 86 | builder.verbose_tokenize = true; |
| 89 | 87 | } else if (mem.eql(u8, arg, "--verbose-ast")) { |
| ... | ... | @@ -98,6 +96,9 @@ pub fn main() !void { |
| 98 | 96 | builder.verbose_cimport = true; |
| 99 | 97 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 100 | 98 | builder.verbose_cc = true; |
| 99 | } else if (mem.eql(u8, arg, "--")) { |
| 100 | builder.args = argsRest(args, arg_idx); |
| 101 | break; |
| 101 | 102 | } else { |
| 102 | 103 | warn("Unrecognized argument: {}\n\n", .{arg}); |
| 103 | 104 | return usageAndErr(builder, false, stderr_stream); |
| ... | ... | @@ -203,11 +204,13 @@ fn usageAndErr(builder: *Builder, already_ran_build: bool, out_stream: var) void |
| 203 | 204 | process.exit(1); |
| 204 | 205 | } |
| 205 | 206 | |
| 206 | | const UnwrapArgError = error{OutOfMemory}; |
| 207 | fn nextArg(args: [][]const u8, idx: *usize) ?[]const u8 { |
| 208 | if (idx.* >= args.len) return null; |
| 209 | defer idx.* += 1; |
| 210 | return args[idx.*]; |
| 211 | } |
| 207 | 212 | |
| 208 | | fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 { |
| 209 | | return arg catch |err| { |
| 210 | | warn("Unable to parse command line: {}\n", .{err}); |
| 211 | | return err; |
| 212 | | }; |
| 213 | fn argsRest(args: [][]const u8, idx: usize) ?[][]const u8 { |
| 214 | if (idx >= args.len) return null; |
| 215 | return args[idx..]; |
| 213 | 216 | } |