| ... | ... | @@ -365,7 +365,6 @@ const usage_build_generic = |
| 365 | 365 | \\ |
| 366 | 366 | \\General Options: |
| 367 | 367 | \\ -h, --help Print this help and exit |
| 368 | | \\ --watch Enable compiler REPL |
| 369 | 368 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 370 | 369 | \\ -femit-bin[=path] (default) Output machine code |
| 371 | 370 | \\ -fno-emit-bin Do not output machine code |
| ... | ... | @@ -700,7 +699,6 @@ fn buildOutputType( |
| 700 | 699 | var formatted_panics: ?bool = null; |
| 701 | 700 | var function_sections = false; |
| 702 | 701 | var no_builtin = false; |
| 703 | | var watch = false; |
| 704 | 702 | var listen: Listen = .none; |
| 705 | 703 | var debug_compile_errors = false; |
| 706 | 704 | var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK"); |
| ... | ... | @@ -1163,7 +1161,6 @@ fn buildOutputType( |
| 1163 | 1161 | const next_arg = args_iter.nextOrFatal(); |
| 1164 | 1162 | if (mem.eql(u8, next_arg, "-")) { |
| 1165 | 1163 | listen = .stdio; |
| 1166 | | watch = true; |
| 1167 | 1164 | } else { |
| 1168 | 1165 | if (build_options.omit_pkg_fetching_code) unreachable; |
| 1169 | 1166 | // example: --listen 127.0.0.1:9000 |
| ... | ... | @@ -1174,11 +1171,9 @@ fn buildOutputType( |
| 1174 | 1171 | fatal("invalid port number: '{s}': {s}", .{ port_text, @errorName(err) }); |
| 1175 | 1172 | listen = .{ .ip4 = std.net.Ip4Address.parse(host, port) catch |err| |
| 1176 | 1173 | fatal("invalid host: '{s}': {s}", .{ host, @errorName(err) }) }; |
| 1177 | | watch = true; |
| 1178 | 1174 | } |
| 1179 | 1175 | } else if (mem.eql(u8, arg, "--listen=-")) { |
| 1180 | 1176 | listen = .stdio; |
| 1181 | | watch = true; |
| 1182 | 1177 | } else if (mem.eql(u8, arg, "--debug-link-snapshot")) { |
| 1183 | 1178 | if (!build_options.enable_link_snapshots) { |
| 1184 | 1179 | std.log.warn("Zig was compiled without linker snapshots enabled (-Dlink-snapshot). --debug-link-snapshot has no effect.", .{}); |
| ... | ... | @@ -1207,8 +1202,6 @@ fn buildOutputType( |
| 1207 | 1202 | test_evented_io = true; |
| 1208 | 1203 | } else if (mem.eql(u8, arg, "--test-no-exec")) { |
| 1209 | 1204 | test_no_exec = true; |
| 1210 | | } else if (mem.eql(u8, arg, "--watch")) { |
| 1211 | | watch = true; |
| 1212 | 1205 | } else if (mem.eql(u8, arg, "-ftime-report")) { |
| 1213 | 1206 | time_report = true; |
| 1214 | 1207 | } else if (mem.eql(u8, arg, "-fstack-report")) { |
| ... | ... | @@ -3355,7 +3348,7 @@ fn buildOutputType( |
| 3355 | 3348 | }; |
| 3356 | 3349 | |
| 3357 | 3350 | updateModule(gpa, comp, hook) catch |err| switch (err) { |
| 3358 | | error.SemanticAnalyzeFail => if (!watch) process.exit(1), |
| 3351 | error.SemanticAnalyzeFail => if (listen == .none) process.exit(1), |
| 3359 | 3352 | else => |e| return e, |
| 3360 | 3353 | }; |
| 3361 | 3354 | if (build_options.only_c) return cleanExit(); |
| ... | ... | @@ -3411,7 +3404,6 @@ fn buildOutputType( |
| 3411 | 3404 | self_exe_path.?, |
| 3412 | 3405 | arg_mode, |
| 3413 | 3406 | target_info, |
| 3414 | | watch, |
| 3415 | 3407 | &comp_destroyed, |
| 3416 | 3408 | all_args, |
| 3417 | 3409 | runtime_args_start, |
| ... | ... | @@ -3419,113 +3411,6 @@ fn buildOutputType( |
| 3419 | 3411 | ); |
| 3420 | 3412 | } |
| 3421 | 3413 | |
| 3422 | | // TODO move this REPL implementation to the standard library / build |
| 3423 | | // system and have it be a CLI abstraction layer on top of the real, actual |
| 3424 | | // binary protocol of the compiler. Make it actually interface through the |
| 3425 | | // server protocol. This way the REPL does not have any special powers that |
| 3426 | | // an IDE couldn't also have. |
| 3427 | | |
| 3428 | | const stdin = std.io.getStdIn().reader(); |
| 3429 | | const stderr = std.io.getStdErr().writer(); |
| 3430 | | var repl_buf: [1024]u8 = undefined; |
| 3431 | | |
| 3432 | | const ReplCmd = enum { |
| 3433 | | update, |
| 3434 | | help, |
| 3435 | | run, |
| 3436 | | update_and_run, |
| 3437 | | }; |
| 3438 | | |
| 3439 | | var last_cmd: ReplCmd = .help; |
| 3440 | | |
| 3441 | | while (watch) { |
| 3442 | | try stderr.print("(zig) ", .{}); |
| 3443 | | try comp.makeBinFileExecutable(); |
| 3444 | | if (stdin.readUntilDelimiterOrEof(&repl_buf, '\n') catch |err| { |
| 3445 | | try stderr.print("\nUnable to parse command: {s}\n", .{@errorName(err)}); |
| 3446 | | continue; |
| 3447 | | }) |line| { |
| 3448 | | const actual_line = mem.trimRight(u8, line, "\r\n "); |
| 3449 | | const cmd: ReplCmd = blk: { |
| 3450 | | if (mem.eql(u8, actual_line, "update")) { |
| 3451 | | break :blk .update; |
| 3452 | | } else if (mem.eql(u8, actual_line, "exit")) { |
| 3453 | | break; |
| 3454 | | } else if (mem.eql(u8, actual_line, "help")) { |
| 3455 | | break :blk .help; |
| 3456 | | } else if (mem.eql(u8, actual_line, "run")) { |
| 3457 | | break :blk .run; |
| 3458 | | } else if (mem.eql(u8, actual_line, "update-and-run")) { |
| 3459 | | break :blk .update_and_run; |
| 3460 | | } else if (actual_line.len == 0) { |
| 3461 | | break :blk last_cmd; |
| 3462 | | } else { |
| 3463 | | try stderr.print("unknown command: {s}\n", .{actual_line}); |
| 3464 | | continue; |
| 3465 | | } |
| 3466 | | }; |
| 3467 | | last_cmd = cmd; |
| 3468 | | switch (cmd) { |
| 3469 | | .update => { |
| 3470 | | tracy.frameMark(); |
| 3471 | | if (output_mode == .Exe) { |
| 3472 | | try comp.makeBinFileWritable(); |
| 3473 | | } |
| 3474 | | updateModule(gpa, comp, hook) catch |err| switch (err) { |
| 3475 | | error.SemanticAnalyzeFail => continue, |
| 3476 | | else => |e| return e, |
| 3477 | | }; |
| 3478 | | }, |
| 3479 | | .help => { |
| 3480 | | try stderr.writeAll(repl_help); |
| 3481 | | }, |
| 3482 | | .run => { |
| 3483 | | tracy.frameMark(); |
| 3484 | | try runOrTest( |
| 3485 | | comp, |
| 3486 | | gpa, |
| 3487 | | arena, |
| 3488 | | test_exec_args.items, |
| 3489 | | self_exe_path.?, |
| 3490 | | arg_mode, |
| 3491 | | target_info, |
| 3492 | | watch, |
| 3493 | | &comp_destroyed, |
| 3494 | | all_args, |
| 3495 | | runtime_args_start, |
| 3496 | | link_libc, |
| 3497 | | ); |
| 3498 | | }, |
| 3499 | | .update_and_run => { |
| 3500 | | tracy.frameMark(); |
| 3501 | | if (output_mode == .Exe) { |
| 3502 | | try comp.makeBinFileWritable(); |
| 3503 | | } |
| 3504 | | updateModule(gpa, comp, hook) catch |err| switch (err) { |
| 3505 | | error.SemanticAnalyzeFail => continue, |
| 3506 | | else => |e| return e, |
| 3507 | | }; |
| 3508 | | try comp.makeBinFileExecutable(); |
| 3509 | | try runOrTest( |
| 3510 | | comp, |
| 3511 | | gpa, |
| 3512 | | arena, |
| 3513 | | test_exec_args.items, |
| 3514 | | self_exe_path.?, |
| 3515 | | arg_mode, |
| 3516 | | target_info, |
| 3517 | | watch, |
| 3518 | | &comp_destroyed, |
| 3519 | | all_args, |
| 3520 | | runtime_args_start, |
| 3521 | | link_libc, |
| 3522 | | ); |
| 3523 | | }, |
| 3524 | | } |
| 3525 | | } else { |
| 3526 | | break; |
| 3527 | | } |
| 3528 | | } |
| 3529 | 3414 | // Skip resource deallocation in release builds; let the OS do it. |
| 3530 | 3415 | return cleanExit(); |
| 3531 | 3416 | } |
| ... | ... | @@ -3822,7 +3707,6 @@ fn runOrTest( |
| 3822 | 3707 | self_exe_path: []const u8, |
| 3823 | 3708 | arg_mode: ArgMode, |
| 3824 | 3709 | target_info: std.zig.system.NativeTargetInfo, |
| 3825 | | watch: bool, |
| 3826 | 3710 | comp_destroyed: *bool, |
| 3827 | 3711 | all_args: []const []const u8, |
| 3828 | 3712 | runtime_args_start: ?usize, |
| ... | ... | @@ -3853,7 +3737,7 @@ fn runOrTest( |
| 3853 | 3737 | |
| 3854 | 3738 | // We do not execve for tests because if the test fails we want to print |
| 3855 | 3739 | // the error message and invocation below. |
| 3856 | | if (std.process.can_execv and arg_mode == .run and !watch) { |
| 3740 | if (std.process.can_execv and arg_mode == .run) { |
| 3857 | 3741 | // execv releases the locks; no need to destroy the Compilation here. |
| 3858 | 3742 | const err = std.process.execve(gpa, argv.items, &env_map); |
| 3859 | 3743 | try warnAboutForeignBinaries(arena, arg_mode, target_info, link_libc); |
| ... | ... | @@ -3866,12 +3750,10 @@ fn runOrTest( |
| 3866 | 3750 | child.stdout_behavior = .Inherit; |
| 3867 | 3751 | child.stderr_behavior = .Inherit; |
| 3868 | 3752 | |
| 3869 | | if (!watch) { |
| 3870 | | // Here we release all the locks associated with the Compilation so |
| 3871 | | // that whatever this child process wants to do won't deadlock. |
| 3872 | | comp.destroy(); |
| 3873 | | comp_destroyed.* = true; |
| 3874 | | } |
| 3753 | // Here we release all the locks associated with the Compilation so |
| 3754 | // that whatever this child process wants to do won't deadlock. |
| 3755 | comp.destroy(); |
| 3756 | comp_destroyed.* = true; |
| 3875 | 3757 | |
| 3876 | 3758 | const term = child.spawnAndWait() catch |err| { |
| 3877 | 3759 | try warnAboutForeignBinaries(arena, arg_mode, target_info, link_libc); |
| ... | ... | @@ -3883,19 +3765,13 @@ fn runOrTest( |
| 3883 | 3765 | switch (term) { |
| 3884 | 3766 | .Exited => |code| { |
| 3885 | 3767 | if (code == 0) { |
| 3886 | | if (!watch) return cleanExit(); |
| 3887 | | } else if (watch) { |
| 3888 | | warn("process exited with code {d}", .{code}); |
| 3768 | return cleanExit(); |
| 3889 | 3769 | } else { |
| 3890 | 3770 | process.exit(code); |
| 3891 | 3771 | } |
| 3892 | 3772 | }, |
| 3893 | 3773 | else => { |
| 3894 | | if (watch) { |
| 3895 | | warn("process aborted abnormally", .{}); |
| 3896 | | } else { |
| 3897 | | process.exit(1); |
| 3898 | | } |
| 3774 | process.exit(1); |
| 3899 | 3775 | }, |
| 3900 | 3776 | } |
| 3901 | 3777 | }, |
| ... | ... | @@ -3903,7 +3779,7 @@ fn runOrTest( |
| 3903 | 3779 | switch (term) { |
| 3904 | 3780 | .Exited => |code| { |
| 3905 | 3781 | if (code == 0) { |
| 3906 | | if (!watch) return cleanExit(); |
| 3782 | return cleanExit(); |
| 3907 | 3783 | } else { |
| 3908 | 3784 | const cmd = try std.mem.join(arena, " ", argv.items); |
| 3909 | 3785 | fatal("the following test command failed with exit code {d}:\n{s}", .{ code, cmd }); |