| author | |
| committer | |
| log | 26f2f9bf1c774caf246317b3fc032449e982a150 |
| tree | 43bc4d4b19cea9a245d87f105841d075ab75f5ab |
| parent | 9b83112a1f6af758a1a995ea8838a2319d2fbc1e |
we are now passing the cli tests12 files changed, 137 insertions(+), 102 deletions(-)
BRANCH_TODO-1| ... | @@ -1,4 +1,3 @@ | ... | @@ -1,4 +1,3 @@ |
| 1 | * support -fno-emit-bin for godbolt | ||
| 2 | * restore the legacy -femit-h feature using the stage1 backend | 1 | * restore the legacy -femit-h feature using the stage1 backend |
| 3 | * figure out why test-translate-c is failing | 2 | * figure out why test-translate-c is failing |
| 4 | * tests passing with -Dskip-non-native | 3 | * tests passing with -Dskip-non-native |
src/Compilation.zig+73-56| ... | @@ -500,8 +500,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -500,8 +500,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 500 | break :pic explicit; | 500 | break :pic explicit; |
| 501 | } else must_pic; | 501 | } else must_pic; |
| 502 | 502 | ||
| 503 | const emit_bin = options.emit_bin orelse fatal("-fno-emit-bin not supported yet", .{}); // TODO | ||
| 504 | |||
| 505 | // Make a decision on whether to use Clang for translate-c and compiling C files. | 503 | // Make a decision on whether to use Clang for translate-c and compiling C files. |
| 506 | const use_clang = if (options.use_clang) |explicit| explicit else blk: { | 504 | const use_clang = if (options.use_clang) |explicit| explicit else blk: { |
| 507 | if (build_options.have_llvm) { | 505 | if (build_options.have_llvm) { |
| ... | @@ -667,13 +665,29 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -667,13 +665,29 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 667 | } else null; | 665 | } else null; |
| 668 | errdefer if (module) |zm| zm.deinit(); | 666 | errdefer if (module) |zm| zm.deinit(); |
| 669 | 667 | ||
| 668 | const error_return_tracing = !options.strip and switch (options.optimize_mode) { | ||
| 669 | .Debug, .ReleaseSafe => true, | ||
| 670 | .ReleaseFast, .ReleaseSmall => false, | ||
| 671 | }; | ||
| 672 | |||
| 670 | // For resource management purposes. | 673 | // For resource management purposes. |
| 671 | var owned_link_dir: ?std.fs.Dir = null; | 674 | var owned_link_dir: ?std.fs.Dir = null; |
| 672 | errdefer if (owned_link_dir) |*dir| dir.close(); | 675 | errdefer if (owned_link_dir) |*dir| dir.close(); |
| 673 | 676 | ||
| 674 | const bin_directory = emit_bin.directory orelse blk: { | 677 | const bin_file_emit: ?link.Emit = blk: { |
| 675 | if (module) |zm| break :blk zm.zig_cache_artifact_directory; | 678 | const emit_bin = options.emit_bin orelse break :blk null; |
| 676 | 679 | if (emit_bin.directory) |directory| { | |
| 680 | break :blk link.Emit{ | ||
| 681 | .directory = directory, | ||
| 682 | .sub_path = emit_bin.basename, | ||
| 683 | }; | ||
| 684 | } | ||
| 685 | if (module) |zm| { | ||
| 686 | break :blk link.Emit{ | ||
| 687 | .directory = zm.zig_cache_artifact_directory, | ||
| 688 | .sub_path = emit_bin.basename, | ||
| 689 | }; | ||
| 690 | } | ||
| 677 | // We could use the cache hash as is no problem, however, we increase | 691 | // We could use the cache hash as is no problem, however, we increase |
| 678 | // the likelihood of cache hits by adding the first C source file | 692 | // the likelihood of cache hits by adding the first C source file |
| 679 | // path name (not contents) to the hash. This way if the user is compiling | 693 | // path name (not contents) to the hash. This way if the user is compiling |
| ... | @@ -694,17 +708,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -694,17 +708,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 694 | .handle = artifact_dir, | 708 | .handle = artifact_dir, |
| 695 | .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), | 709 | .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), |
| 696 | }; | 710 | }; |
| 697 | break :blk link_artifact_directory; | 711 | break :blk link.Emit{ |
| 698 | }; | 712 | .directory = link_artifact_directory, |
| 699 | 713 | .sub_path = emit_bin.basename, | |
| 700 | const error_return_tracing = !options.strip and switch (options.optimize_mode) { | 714 | }; |
| 701 | .Debug, .ReleaseSafe => true, | ||
| 702 | .ReleaseFast, .ReleaseSmall => false, | ||
| 703 | }; | 715 | }; |
| 704 | 716 | ||
| 705 | const bin_file = try link.File.openPath(gpa, .{ | 717 | const bin_file = try link.File.openPath(gpa, .{ |
| 706 | .directory = bin_directory, | 718 | .emit = bin_file_emit, |
| 707 | .sub_path = emit_bin.basename, | ||
| 708 | .root_name = root_name, | 719 | .root_name = root_name, |
| 709 | .module = module, | 720 | .module = module, |
| 710 | .target = options.target, | 721 | .target = options.target, |
| ... | @@ -815,43 +826,46 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -815,43 +826,46 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 815 | comp.c_object_table.putAssumeCapacityNoClobber(c_object, {}); | 826 | comp.c_object_table.putAssumeCapacityNoClobber(c_object, {}); |
| 816 | } | 827 | } |
| 817 | 828 | ||
| 818 | // If we need to build glibc for the target, add work items for it. | 829 | if (comp.bin_file.options.emit != null) { |
| 819 | // We go through the work queue so that building can be done in parallel. | 830 | // If we need to build glibc for the target, add work items for it. |
| 820 | if (comp.wantBuildGLibCFromSource()) { | 831 | // We go through the work queue so that building can be done in parallel. |
| 821 | try comp.addBuildingGLibCJobs(); | 832 | if (comp.wantBuildGLibCFromSource()) { |
| 822 | } | 833 | try comp.addBuildingGLibCJobs(); |
| 823 | if (comp.wantBuildMuslFromSource()) { | 834 | } |
| 824 | try comp.work_queue.write(&[_]Job{ | 835 | if (comp.wantBuildMuslFromSource()) { |
| 825 | .{ .musl_crt_file = .crti_o }, | 836 | try comp.work_queue.write(&[_]Job{ |
| 826 | .{ .musl_crt_file = .crtn_o }, | 837 | .{ .musl_crt_file = .crti_o }, |
| 827 | .{ .musl_crt_file = .crt1_o }, | 838 | .{ .musl_crt_file = .crtn_o }, |
| 828 | .{ .musl_crt_file = .scrt1_o }, | 839 | .{ .musl_crt_file = .crt1_o }, |
| 829 | .{ .musl_crt_file = .libc_a }, | 840 | .{ .musl_crt_file = .scrt1_o }, |
| 830 | }); | 841 | .{ .musl_crt_file = .libc_a }, |
| 831 | } | 842 | }); |
| 832 | if (comp.wantBuildMinGWW64FromSource()) { | 843 | } |
| 833 | @panic("TODO"); | 844 | if (comp.wantBuildMinGWW64FromSource()) { |
| 834 | } | 845 | @panic("TODO"); |
| 835 | if (comp.wantBuildLibUnwindFromSource()) { | 846 | } |
| 836 | try comp.work_queue.writeItem(.{ .libunwind = {} }); | 847 | if (comp.wantBuildLibUnwindFromSource()) { |
| 837 | } | 848 | try comp.work_queue.writeItem(.{ .libunwind = {} }); |
| 838 | if (build_options.have_llvm and comp.bin_file.options.output_mode != .Obj and | 849 | } |
| 839 | comp.bin_file.options.link_libcpp) | 850 | if (build_options.have_llvm and comp.bin_file.options.output_mode != .Obj and |
| 840 | { | 851 | comp.bin_file.options.link_libcpp) |
| 841 | try comp.work_queue.writeItem(.libcxx); | 852 | { |
| 842 | try comp.work_queue.writeItem(.libcxxabi); | 853 | try comp.work_queue.writeItem(.libcxx); |
| 854 | try comp.work_queue.writeItem(.libcxxabi); | ||
| 855 | } | ||
| 856 | if (is_exe_or_dyn_lib and !comp.bin_file.options.is_compiler_rt_or_libc and | ||
| 857 | build_options.is_stage1) | ||
| 858 | { | ||
| 859 | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); | ||
| 860 | if (!comp.bin_file.options.link_libc) { | ||
| 861 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | ||
| 862 | } | ||
| 863 | } | ||
| 843 | } | 864 | } |
| 865 | |||
| 844 | if (build_options.is_stage1 and comp.bin_file.options.use_llvm) { | 866 | if (build_options.is_stage1 and comp.bin_file.options.use_llvm) { |
| 845 | try comp.work_queue.writeItem(.{ .stage1_module = {} }); | 867 | try comp.work_queue.writeItem(.{ .stage1_module = {} }); |
| 846 | } | 868 | } |
| 847 | if (is_exe_or_dyn_lib and !comp.bin_file.options.is_compiler_rt_or_libc and | ||
| 848 | build_options.is_stage1) | ||
| 849 | { | ||
| 850 | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); | ||
| 851 | if (!comp.bin_file.options.link_libc) { | ||
| 852 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | ||
| 853 | } | ||
| 854 | } | ||
| 855 | 869 | ||
| 856 | return comp; | 870 | return comp; |
| 857 | } | 871 | } |
| ... | @@ -2408,8 +2422,8 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR | ... | @@ -2408,8 +2422,8 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2408 | 2422 | ||
| 2409 | assert(out.* == null); | 2423 | assert(out.* == null); |
| 2410 | out.* = Compilation.CRTFile{ | 2424 | out.* = Compilation.CRTFile{ |
| 2411 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{ | 2425 | .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ |
| 2412 | sub_compilation.bin_file.options.sub_path, | 2426 | sub_compilation.bin_file.options.emit.?.sub_path, |
| 2413 | }), | 2427 | }), |
| 2414 | .lock = sub_compilation.bin_file.toOwnedLock(), | 2428 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 2415 | }; | 2429 | }; |
| ... | @@ -2452,6 +2466,7 @@ fn updateStage1Module(comp: *Compilation) !void { | ... | @@ -2452,6 +2466,7 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2452 | man.hash.add(comp.bin_file.options.dll_export_fns); | 2466 | man.hash.add(comp.bin_file.options.dll_export_fns); |
| 2453 | man.hash.add(comp.bin_file.options.function_sections); | 2467 | man.hash.add(comp.bin_file.options.function_sections); |
| 2454 | man.hash.add(comp.is_test); | 2468 | man.hash.add(comp.is_test); |
| 2469 | man.hash.add(comp.bin_file.options.emit != null); | ||
| 2455 | man.hash.add(comp.emit_h != null); | 2470 | man.hash.add(comp.emit_h != null); |
| 2456 | man.hash.add(comp.emit_asm != null); | 2471 | man.hash.add(comp.emit_asm != null); |
| 2457 | man.hash.add(comp.emit_llvm_ir != null); | 2472 | man.hash.add(comp.emit_llvm_ir != null); |
| ... | @@ -2517,12 +2532,14 @@ fn updateStage1Module(comp: *Compilation) !void { | ... | @@ -2517,12 +2532,14 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2517 | comp.is_test, | 2532 | comp.is_test, |
| 2518 | ) orelse return error.OutOfMemory; | 2533 | ) orelse return error.OutOfMemory; |
| 2519 | 2534 | ||
| 2520 | const bin_basename = try std.zig.binNameAlloc(arena, .{ | 2535 | const emit_bin_path = if (comp.bin_file.options.emit != null) blk: { |
| 2521 | .root_name = comp.bin_file.options.root_name, | 2536 | const bin_basename = try std.zig.binNameAlloc(arena, .{ |
| 2522 | .target = target, | 2537 | .root_name = comp.bin_file.options.root_name, |
| 2523 | .output_mode = .Obj, | 2538 | .target = target, |
| 2524 | }); | 2539 | .output_mode = .Obj, |
| 2525 | const emit_bin_path = try directory.join(arena, &[_][]const u8{bin_basename}); | 2540 | }); |
| 2541 | break :blk try directory.join(arena, &[_][]const u8{bin_basename}); | ||
| 2542 | } else ""; | ||
| 2526 | const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory); | 2543 | const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory); |
| 2527 | const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory); | 2544 | const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory); |
| 2528 | const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory); | 2545 | const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory); |
| ... | @@ -2697,8 +2714,8 @@ pub fn build_crt_file( | ... | @@ -2697,8 +2714,8 @@ pub fn build_crt_file( |
| 2697 | try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); | 2714 | try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); |
| 2698 | 2715 | ||
| 2699 | comp.crt_files.putAssumeCapacityNoClobber(basename, .{ | 2716 | comp.crt_files.putAssumeCapacityNoClobber(basename, .{ |
| 2700 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{ | 2717 | .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{ |
| 2701 | sub_compilation.bin_file.options.sub_path, | 2718 | sub_compilation.bin_file.options.emit.?.sub_path, |
| 2702 | }), | 2719 | }), |
| 2703 | .lock = sub_compilation.bin_file.toOwnedLock(), | 2720 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 2704 | }); | 2721 | }); |
src/libcxx.zig+8-2| ... | @@ -189,7 +189,10 @@ pub fn buildLibCXX(comp: *Compilation) !void { | ... | @@ -189,7 +189,10 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 189 | 189 | ||
| 190 | assert(comp.libcxx_static_lib == null); | 190 | assert(comp.libcxx_static_lib == null); |
| 191 | comp.libcxx_static_lib = Compilation.CRTFile{ | 191 | comp.libcxx_static_lib = Compilation.CRTFile{ |
| 192 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), | 192 | .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join( |
| 193 | comp.gpa, | ||
| 194 | &[_][]const u8{basename}, | ||
| 195 | ), | ||
| 193 | .lock = sub_compilation.bin_file.toOwnedLock(), | 196 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 194 | }; | 197 | }; |
| 195 | } | 198 | } |
| ... | @@ -303,7 +306,10 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { | ... | @@ -303,7 +306,10 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 303 | 306 | ||
| 304 | assert(comp.libcxxabi_static_lib == null); | 307 | assert(comp.libcxxabi_static_lib == null); |
| 305 | comp.libcxxabi_static_lib = Compilation.CRTFile{ | 308 | comp.libcxxabi_static_lib = Compilation.CRTFile{ |
| 306 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), | 309 | .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join( |
| 310 | comp.gpa, | ||
| 311 | &[_][]const u8{basename}, | ||
| 312 | ), | ||
| 307 | .lock = sub_compilation.bin_file.toOwnedLock(), | 313 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 308 | }; | 314 | }; |
| 309 | } | 315 | } |
src/libunwind.zig+4-1| ... | @@ -126,7 +126,10 @@ pub fn buildStaticLib(comp: *Compilation) !void { | ... | @@ -126,7 +126,10 @@ pub fn buildStaticLib(comp: *Compilation) !void { |
| 126 | 126 | ||
| 127 | assert(comp.libunwind_static_lib == null); | 127 | assert(comp.libunwind_static_lib == null); |
| 128 | comp.libunwind_static_lib = Compilation.CRTFile{ | 128 | comp.libunwind_static_lib = Compilation.CRTFile{ |
| 129 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), | 129 | .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join( |
| 130 | comp.gpa, | ||
| 131 | &[_][]const u8{basename}, | ||
| 132 | ), | ||
| 130 | .lock = sub_compilation.bin_file.toOwnedLock(), | 133 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 131 | }; | 134 | }; |
| 132 | } | 135 | } |
src/link.zig+18-13| ... | @@ -16,11 +16,17 @@ const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ... | @@ -16,11 +16,17 @@ const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| 16 | 16 | ||
| 17 | pub const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; | 17 | pub const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; |
| 18 | 18 | ||
| 19 | pub const Options = struct { | 19 | pub const Emit = struct { |
| 20 | /// Where the output will go. | 20 | /// Where the output will go. |
| 21 | directory: Compilation.Directory, | 21 | directory: Compilation.Directory, |
| 22 | /// Path to the output file, relative to `directory`. | 22 | /// Path to the output file, relative to `directory`. |
| 23 | sub_path: []const u8, | 23 | sub_path: []const u8, |
| 24 | }; | ||
| 25 | |||
| 26 | pub const Options = struct { | ||
| 27 | /// This is `null` when -fno-emit-bin is used. When `openPath` or `flush` is called, | ||
| 28 | /// it will have already been null-checked. | ||
| 29 | emit: ?Emit, | ||
| 24 | target: std.Target, | 30 | target: std.Target, |
| 25 | output_mode: std.builtin.OutputMode, | 31 | output_mode: std.builtin.OutputMode, |
| 26 | link_mode: std.builtin.LinkMode, | 32 | link_mode: std.builtin.LinkMode, |
| ... | @@ -141,7 +147,7 @@ pub const File = struct { | ... | @@ -141,7 +147,7 @@ pub const File = struct { |
| 141 | /// and does not cause Illegal Behavior. This operation is not atomic. | 147 | /// and does not cause Illegal Behavior. This operation is not atomic. |
| 142 | pub fn openPath(allocator: *Allocator, options: Options) !*File { | 148 | pub fn openPath(allocator: *Allocator, options: Options) !*File { |
| 143 | const use_stage1 = build_options.is_stage1 and options.use_llvm; | 149 | const use_stage1 = build_options.is_stage1 and options.use_llvm; |
| 144 | if (use_stage1) { | 150 | if (use_stage1 or options.emit == null) { |
| 145 | return switch (options.object_format) { | 151 | return switch (options.object_format) { |
| 146 | .coff, .pe => &(try Coff.createEmpty(allocator, options)).base, | 152 | .coff, .pe => &(try Coff.createEmpty(allocator, options)).base, |
| 147 | .elf => &(try Elf.createEmpty(allocator, options)).base, | 153 | .elf => &(try Elf.createEmpty(allocator, options)).base, |
| ... | @@ -152,6 +158,7 @@ pub const File = struct { | ... | @@ -152,6 +158,7 @@ pub const File = struct { |
| 152 | .raw => return error.RawObjectFormatUnimplemented, | 158 | .raw => return error.RawObjectFormatUnimplemented, |
| 153 | }; | 159 | }; |
| 154 | } | 160 | } |
| 161 | const emit = options.emit.?; | ||
| 155 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm | 162 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm |
| 156 | const sub_path = if (use_lld) blk: { | 163 | const sub_path = if (use_lld) blk: { |
| 157 | if (options.module == null) { | 164 | if (options.module == null) { |
| ... | @@ -167,8 +174,8 @@ pub const File = struct { | ... | @@ -167,8 +174,8 @@ pub const File = struct { |
| 167 | }; | 174 | }; |
| 168 | } | 175 | } |
| 169 | // Open a temporary object file, not the final output file because we want to link with LLD. | 176 | // Open a temporary object file, not the final output file because we want to link with LLD. |
| 170 | break :blk try std.fmt.allocPrint(allocator, "{}{}", .{ options.sub_path, options.target.oFileExt() }); | 177 | break :blk try std.fmt.allocPrint(allocator, "{}{}", .{ emit.sub_path, options.target.oFileExt() }); |
| 171 | } else options.sub_path; | 178 | } else emit.sub_path; |
| 172 | errdefer if (use_lld) allocator.free(sub_path); | 179 | errdefer if (use_lld) allocator.free(sub_path); |
| 173 | 180 | ||
| 174 | const file: *File = switch (options.object_format) { | 181 | const file: *File = switch (options.object_format) { |
| ... | @@ -199,7 +206,8 @@ pub const File = struct { | ... | @@ -199,7 +206,8 @@ pub const File = struct { |
| 199 | switch (base.tag) { | 206 | switch (base.tag) { |
| 200 | .coff, .elf, .macho => { | 207 | .coff, .elf, .macho => { |
| 201 | if (base.file != null) return; | 208 | if (base.file != null) return; |
| 202 | base.file = try base.options.directory.handle.createFile(base.options.sub_path, .{ | 209 | const emit = base.options.emit orelse return; |
| 210 | base.file = try emit.directory.handle.createFile(emit.sub_path, .{ | ||
| 203 | .truncate = false, | 211 | .truncate = false, |
| 204 | .read = true, | 212 | .read = true, |
| 205 | .mode = determineMode(base.options), | 213 | .mode = determineMode(base.options), |
| ... | @@ -305,14 +313,14 @@ pub const File = struct { | ... | @@ -305,14 +313,14 @@ pub const File = struct { |
| 305 | /// Commit pending changes and write headers. Takes into account final output mode | 313 | /// Commit pending changes and write headers. Takes into account final output mode |
| 306 | /// and `use_lld`, not only `effectiveOutputMode`. | 314 | /// and `use_lld`, not only `effectiveOutputMode`. |
| 307 | pub fn flush(base: *File, comp: *Compilation) !void { | 315 | pub fn flush(base: *File, comp: *Compilation) !void { |
| 316 | const emit = base.options.emit orelse return; // -fno-emit-bin | ||
| 317 | |||
| 308 | if (comp.clang_preprocessor_mode == .yes) { | 318 | if (comp.clang_preprocessor_mode == .yes) { |
| 309 | // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) | 319 | // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case) |
| 310 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same | 320 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same |
| 311 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file | 321 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file |
| 312 | // to the final location. | 322 | // to the final location. |
| 313 | const full_out_path = try base.options.directory.join(comp.gpa, &[_][]const u8{ | 323 | const full_out_path = try emit.directory.join(comp.gpa, &[_][]const u8{emit.sub_path}); |
| 314 | base.options.sub_path, | ||
| 315 | }); | ||
| 316 | defer comp.gpa.free(full_out_path); | 324 | defer comp.gpa.free(full_out_path); |
| 317 | assert(comp.c_object_table.count() == 1); | 325 | assert(comp.c_object_table.count() == 1); |
| 318 | const the_entry = comp.c_object_table.items()[0]; | 326 | const the_entry = comp.c_object_table.items()[0]; |
| ... | @@ -402,7 +410,7 @@ pub const File = struct { | ... | @@ -402,7 +410,7 @@ pub const File = struct { |
| 402 | defer arena_allocator.deinit(); | 410 | defer arena_allocator.deinit(); |
| 403 | const arena = &arena_allocator.allocator; | 411 | const arena = &arena_allocator.allocator; |
| 404 | 412 | ||
| 405 | const directory = base.options.directory; // Just an alias to make it shorter to type. | 413 | const directory = base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 406 | 414 | ||
| 407 | // If there is no Zig code to compile, then we should skip flushing the output file because it | 415 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 408 | // will not be part of the linker line anyway. | 416 | // will not be part of the linker line anyway. |
| ... | @@ -471,10 +479,7 @@ pub const File = struct { | ... | @@ -471,10 +479,7 @@ pub const File = struct { |
| 471 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | 479 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 472 | } | 480 | } |
| 473 | 481 | ||
| 474 | const full_out_path = if (directory.path) |dir_path| | 482 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); |
| 475 | try std.fs.path.join(arena, &[_][]const u8{ dir_path, base.options.sub_path }) | ||
| 476 | else | ||
| 477 | base.options.sub_path; | ||
| 478 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); | 483 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); |
| 479 | 484 | ||
| 480 | if (base.options.verbose_link) { | 485 | if (base.options.verbose_link) { |
src/link/C.zig+1-1| ... | @@ -30,7 +30,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -30,7 +30,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 30 | if (options.use_llvm) return error.LLVMHasNoCBackend; | 30 | if (options.use_llvm) return error.LLVMHasNoCBackend; |
| 31 | if (options.use_lld) return error.LLDHasNoCBackend; | 31 | if (options.use_lld) return error.LLDHasNoCBackend; |
| 32 | 32 | ||
| 33 | const file = try options.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); | 33 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); |
| 34 | errdefer file.close(); | 34 | errdefer file.close(); |
| 35 | 35 | ||
| 36 | var c_file = try allocator.create(C); | 36 | var c_file = try allocator.create(C); |
src/link/Coff.zig+1-1| ... | @@ -120,7 +120,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -120,7 +120,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 120 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | 120 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO |
| 121 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO | 121 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO |
| 122 | 122 | ||
| 123 | const file = try options.directory.handle.createFile(sub_path, .{ | 123 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 124 | .truncate = false, | 124 | .truncate = false, |
| 125 | .read = true, | 125 | .read = true, |
| 126 | .mode = link.determineMode(options), | 126 | .mode = link.determineMode(options), |
src/link/Elf.zig+3-3| ... | @@ -229,7 +229,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -229,7 +229,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 229 | 229 | ||
| 230 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO | 230 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO |
| 231 | 231 | ||
| 232 | const file = try options.directory.handle.createFile(sub_path, .{ | 232 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 233 | .truncate = false, | 233 | .truncate = false, |
| 234 | .read = true, | 234 | .read = true, |
| 235 | .mode = link.determineMode(options), | 235 | .mode = link.determineMode(options), |
| ... | @@ -1218,7 +1218,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1218,7 +1218,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1218 | defer arena_allocator.deinit(); | 1218 | defer arena_allocator.deinit(); |
| 1219 | const arena = &arena_allocator.allocator; | 1219 | const arena = &arena_allocator.allocator; |
| 1220 | 1220 | ||
| 1221 | const directory = self.base.options.directory; // Just an alias to make it shorter to type. | 1221 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 1222 | 1222 | ||
| 1223 | // If there is no Zig code to compile, then we should skip flushing the output file because it | 1223 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 1224 | // will not be part of the linker line anyway. | 1224 | // will not be part of the linker line anyway. |
| ... | @@ -1401,7 +1401,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1401,7 +1401,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1401 | try argv.append("-pie"); | 1401 | try argv.append("-pie"); |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.sub_path}); | 1404 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| 1405 | try argv.append("-o"); | 1405 | try argv.append("-o"); |
| 1406 | try argv.append(full_out_path); | 1406 | try argv.append(full_out_path); |
| 1407 | 1407 |
src/link/MachO.zig+1-1| ... | @@ -142,7 +142,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -142,7 +142,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 142 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO | 142 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO |
| 143 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForMachO; // TODO | 143 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForMachO; // TODO |
| 144 | 144 | ||
| 145 | const file = try options.directory.handle.createFile(sub_path, .{ | 145 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 146 | .truncate = false, | 146 | .truncate = false, |
| 147 | .read = true, | 147 | .read = true, |
| 148 | .mode = link.determineMode(options), | 148 | .mode = link.determineMode(options), |
src/link/Wasm.zig+1-1| ... | @@ -59,7 +59,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -59,7 +59,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 59 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForWasm; // TODO | 59 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForWasm; // TODO |
| 60 | 60 | ||
| 61 | // TODO: read the file and keep vaild parts instead of truncating | 61 | // TODO: read the file and keep vaild parts instead of truncating |
| 62 | const file = try options.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true }); | 62 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true }); |
| 63 | errdefer file.close(); | 63 | errdefer file.close(); |
| 64 | 64 | ||
| 65 | const wasm = try createEmpty(allocator, options); | 65 | const wasm = try createEmpty(allocator, options); |
src/main.zig+11-6| ... | @@ -1307,7 +1307,9 @@ fn buildOutputType( | ... | @@ -1307,7 +1307,9 @@ fn buildOutputType( |
| 1307 | }; | 1307 | }; |
| 1308 | } | 1308 | } |
| 1309 | if (fs.path.dirname(full_path)) |dirname| { | 1309 | if (fs.path.dirname(full_path)) |dirname| { |
| 1310 | const handle = try fs.cwd().openDir(dirname, .{}); | 1310 | const handle = fs.cwd().openDir(dirname, .{}) catch |err| { |
| 1311 | fatal("unable to open output directory '{}': {}", .{ dirname, @errorName(err) }); | ||
| 1312 | }; | ||
| 1311 | cleanup_emit_bin_dir = handle; | 1313 | cleanup_emit_bin_dir = handle; |
| 1312 | break :b Compilation.EmitLoc{ | 1314 | break :b Compilation.EmitLoc{ |
| 1313 | .basename = basename, | 1315 | .basename = basename, |
| ... | @@ -1545,7 +1547,7 @@ fn buildOutputType( | ... | @@ -1545,7 +1547,7 @@ fn buildOutputType( |
| 1545 | switch (emit_bin) { | 1547 | switch (emit_bin) { |
| 1546 | .no => break :blk .none, | 1548 | .no => break :blk .none, |
| 1547 | .yes_default_path => break :blk .{ | 1549 | .yes_default_path => break :blk .{ |
| 1548 | .print = comp.bin_file.options.directory.path orelse ".", | 1550 | .print = comp.bin_file.options.emit.?.directory.path orelse ".", |
| 1549 | }, | 1551 | }, |
| 1550 | .yes => |full_path| break :blk .{ .update = full_path }, | 1552 | .yes => |full_path| break :blk .{ .update = full_path }, |
| 1551 | } | 1553 | } |
| ... | @@ -1560,7 +1562,7 @@ fn buildOutputType( | ... | @@ -1560,7 +1562,7 @@ fn buildOutputType( |
| 1560 | switch (arg_mode) { | 1562 | switch (arg_mode) { |
| 1561 | .run, .zig_test => run: { | 1563 | .run, .zig_test => run: { |
| 1562 | const exe_loc = emit_bin_loc orelse break :run; | 1564 | const exe_loc = emit_bin_loc orelse break :run; |
| 1563 | const exe_directory = exe_loc.directory orelse comp.bin_file.options.directory; | 1565 | const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory; |
| 1564 | const exe_path = try fs.path.join(arena, &[_][]const u8{ | 1566 | const exe_path = try fs.path.join(arena, &[_][]const u8{ |
| 1565 | exe_directory.path orelse ".", exe_loc.basename, | 1567 | exe_directory.path orelse ".", exe_loc.basename, |
| 1566 | }); | 1568 | }); |
| ... | @@ -1676,8 +1678,8 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8, | ... | @@ -1676,8 +1678,8 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8, |
| 1676 | } else switch (hook) { | 1678 | } else switch (hook) { |
| 1677 | .none => {}, | 1679 | .none => {}, |
| 1678 | .print => |bin_path| try io.getStdOut().writer().print("{s}\n", .{bin_path}), | 1680 | .print => |bin_path| try io.getStdOut().writer().print("{s}\n", .{bin_path}), |
| 1679 | .update => |full_path| _ = try comp.bin_file.options.directory.handle.updateFile( | 1681 | .update => |full_path| _ = try comp.bin_file.options.emit.?.directory.handle.updateFile( |
| 1680 | comp.bin_file.options.sub_path, | 1682 | comp.bin_file.options.emit.?.sub_path, |
| 1681 | fs.cwd(), | 1683 | fs.cwd(), |
| 1682 | full_path, | 1684 | full_path, |
| 1683 | .{}, | 1685 | .{}, |
| ... | @@ -2106,7 +2108,10 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2106,7 +2108,10 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2106 | 2108 | ||
| 2107 | try updateModule(gpa, comp, null, .none); | 2109 | try updateModule(gpa, comp, null, .none); |
| 2108 | 2110 | ||
| 2109 | child_argv.items[argv_index_exe] = try comp.bin_file.options.directory.join(arena, &[_][]const u8{exe_basename}); | 2111 | child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join( |
| 2112 | arena, | ||
| 2113 | &[_][]const u8{exe_basename}, | ||
| 2114 | ); | ||
| 2110 | 2115 | ||
| 2111 | break :lock_and_argv .{ | 2116 | break :lock_and_argv .{ |
| 2112 | .child_argv = child_argv.items, | 2117 | .child_argv = child_argv.items, |
test/cli.zig+16-16| ... | @@ -58,7 +58,7 @@ fn printCmd(cwd: []const u8, argv: []const []const u8) void { | ... | @@ -58,7 +58,7 @@ fn printCmd(cwd: []const u8, argv: []const []const u8) void { |
| 58 | std.debug.warn("\n", .{}); | 58 | std.debug.warn("\n", .{}); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult { | 61 | fn exec(cwd: []const u8, expect_0: bool, argv: []const []const u8) !ChildProcess.ExecResult { |
| 62 | const max_output_size = 100 * 1024; | 62 | const max_output_size = 100 * 1024; |
| 63 | const result = ChildProcess.exec(.{ | 63 | const result = ChildProcess.exec(.{ |
| 64 | .allocator = a, | 64 | .allocator = a, |
| ... | @@ -72,7 +72,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult { | ... | @@ -72,7 +72,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult { |
| 72 | }; | 72 | }; |
| 73 | switch (result.term) { | 73 | switch (result.term) { |
| 74 | .Exited => |code| { | 74 | .Exited => |code| { |
| 75 | if (code != 0) { | 75 | if ((code != 0) == expect_0) { |
| 76 | std.debug.warn("The following command exited with error code {}:\n", .{code}); | 76 | std.debug.warn("The following command exited with error code {}:\n", .{code}); |
| 77 | printCmd(cwd, argv); | 77 | printCmd(cwd, argv); |
| 78 | std.debug.warn("stderr:\n{}\n", .{result.stderr}); | 78 | std.debug.warn("stderr:\n{}\n", .{result.stderr}); |
| ... | @@ -90,14 +90,14 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult { | ... | @@ -90,14 +90,14 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult { |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void { | 92 | fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void { |
| 93 | _ = try exec(dir_path, &[_][]const u8{ zig_exe, "init-lib" }); | 93 | _ = try exec(dir_path, true, &[_][]const u8{ zig_exe, "init-lib" }); |
| 94 | const test_result = try exec(dir_path, &[_][]const u8{ zig_exe, "build", "test" }); | 94 | const test_result = try exec(dir_path, true, &[_][]const u8{ zig_exe, "build", "test" }); |
| 95 | testing.expect(std.mem.endsWith(u8, test_result.stderr, "All 1 tests passed.\n")); | 95 | testing.expect(std.mem.endsWith(u8, test_result.stderr, "All 1 tests passed.\n")); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void { | 98 | fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void { |
| 99 | _ = try exec(dir_path, &[_][]const u8{ zig_exe, "init-exe" }); | 99 | _ = try exec(dir_path, true, &[_][]const u8{ zig_exe, "init-exe" }); |
| 100 | const run_result = try exec(dir_path, &[_][]const u8{ zig_exe, "build", "run" }); | 100 | const run_result = try exec(dir_path, true, &[_][]const u8{ zig_exe, "build", "run" }); |
| 101 | testing.expect(std.mem.eql(u8, run_result.stderr, "info: All your codebase are belong to us.\n")); | 101 | testing.expect(std.mem.eql(u8, run_result.stderr, "info: All your codebase are belong to us.\n")); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| ... | @@ -131,7 +131,7 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { | ... | @@ -131,7 +131,7 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { |
| 131 | const emit_asm_arg = try std.fmt.allocPrint(a, "-femit-asm={s}", .{example_s_path}); | 131 | const emit_asm_arg = try std.fmt.allocPrint(a, "-femit-asm={s}", .{example_s_path}); |
| 132 | try args.append(emit_asm_arg); | 132 | try args.append(emit_asm_arg); |
| 133 | 133 | ||
| 134 | _ = try exec(dir_path, args.items); | 134 | _ = try exec(dir_path, true, args.items); |
| 135 | 135 | ||
| 136 | const out_asm = try std.fs.cwd().readFileAlloc(a, example_s_path, std.math.maxInt(usize)); | 136 | const out_asm = try std.fs.cwd().readFileAlloc(a, example_s_path, std.math.maxInt(usize)); |
| 137 | testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null); | 137 | testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null); |
| ... | @@ -140,23 +140,23 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { | ... | @@ -140,23 +140,23 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | fn testMissingOutputPath(zig_exe: []const u8, dir_path: []const u8) !void { | 142 | fn testMissingOutputPath(zig_exe: []const u8, dir_path: []const u8) !void { |
| 143 | _ = try exec(dir_path, &[_][]const u8{ zig_exe, "init-exe" }); | 143 | _ = try exec(dir_path, true, &[_][]const u8{ zig_exe, "init-exe" }); |
| 144 | const output_path = try fs.path.join(a, &[_][]const u8{ "does", "not", "exist" }); | 144 | const output_path = try fs.path.join(a, &[_][]const u8{ "does", "not", "exist", "foo.exe" }); |
| 145 | const output_arg = try std.fmt.allocPrint(a, "-femit-bin={s}", .{output_path}); | ||
| 145 | const source_path = try fs.path.join(a, &[_][]const u8{ "src", "main.zig" }); | 146 | const source_path = try fs.path.join(a, &[_][]const u8{ "src", "main.zig" }); |
| 146 | _ = try exec(dir_path, &[_][]const u8{ | 147 | const result = try exec(dir_path, false, &[_][]const u8{ zig_exe, "build-exe", source_path, output_arg }); |
| 147 | zig_exe, "build-exe", source_path, "--output-dir", output_path, | 148 | testing.expect(std.mem.eql(u8, result.stderr, "error: unable to open output directory 'does/not/exist': FileNotFound\n")); |
| 148 | }); | ||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | fn testZigFmt(zig_exe: []const u8, dir_path: []const u8) !void { | 151 | fn testZigFmt(zig_exe: []const u8, dir_path: []const u8) !void { |
| 152 | _ = try exec(dir_path, &[_][]const u8{ zig_exe, "init-exe" }); | 152 | _ = try exec(dir_path, true, &[_][]const u8{ zig_exe, "init-exe" }); |
| 153 | 153 | ||
| 154 | const unformatted_code = " // no reason for indent"; | 154 | const unformatted_code = " // no reason for indent"; |
| 155 | 155 | ||
| 156 | const fmt1_zig_path = try fs.path.join(a, &[_][]const u8{ dir_path, "fmt1.zig" }); | 156 | const fmt1_zig_path = try fs.path.join(a, &[_][]const u8{ dir_path, "fmt1.zig" }); |
| 157 | try fs.cwd().writeFile(fmt1_zig_path, unformatted_code); | 157 | try fs.cwd().writeFile(fmt1_zig_path, unformatted_code); |
| 158 | 158 | ||
| 159 | const run_result1 = try exec(dir_path, &[_][]const u8{ zig_exe, "fmt", fmt1_zig_path }); | 159 | const run_result1 = try exec(dir_path, true, &[_][]const u8{ zig_exe, "fmt", fmt1_zig_path }); |
| 160 | // stderr should be file path + \n | 160 | // stderr should be file path + \n |
| 161 | testing.expect(std.mem.startsWith(u8, run_result1.stderr, fmt1_zig_path)); | 161 | testing.expect(std.mem.startsWith(u8, run_result1.stderr, fmt1_zig_path)); |
| 162 | testing.expect(run_result1.stderr.len == fmt1_zig_path.len + 1 and run_result1.stderr[run_result1.stderr.len - 1] == '\n'); | 162 | testing.expect(run_result1.stderr.len == fmt1_zig_path.len + 1 and run_result1.stderr[run_result1.stderr.len - 1] == '\n'); |
| ... | @@ -164,12 +164,12 @@ fn testZigFmt(zig_exe: []const u8, dir_path: []const u8) !void { | ... | @@ -164,12 +164,12 @@ fn testZigFmt(zig_exe: []const u8, dir_path: []const u8) !void { |
| 164 | const fmt2_zig_path = try fs.path.join(a, &[_][]const u8{ dir_path, "fmt2.zig" }); | 164 | const fmt2_zig_path = try fs.path.join(a, &[_][]const u8{ dir_path, "fmt2.zig" }); |
| 165 | try fs.cwd().writeFile(fmt2_zig_path, unformatted_code); | 165 | try fs.cwd().writeFile(fmt2_zig_path, unformatted_code); |
| 166 | 166 | ||
| 167 | const run_result2 = try exec(dir_path, &[_][]const u8{ zig_exe, "fmt", dir_path }); | 167 | const run_result2 = try exec(dir_path, true, &[_][]const u8{ zig_exe, "fmt", dir_path }); |
| 168 | // running it on the dir, only the new file should be changed | 168 | // running it on the dir, only the new file should be changed |
| 169 | testing.expect(std.mem.startsWith(u8, run_result2.stderr, fmt2_zig_path)); | 169 | testing.expect(std.mem.startsWith(u8, run_result2.stderr, fmt2_zig_path)); |
| 170 | testing.expect(run_result2.stderr.len == fmt2_zig_path.len + 1 and run_result2.stderr[run_result2.stderr.len - 1] == '\n'); | 170 | testing.expect(run_result2.stderr.len == fmt2_zig_path.len + 1 and run_result2.stderr[run_result2.stderr.len - 1] == '\n'); |
| 171 | 171 | ||
| 172 | const run_result3 = try exec(dir_path, &[_][]const u8{ zig_exe, "fmt", dir_path }); | 172 | const run_result3 = try exec(dir_path, true, &[_][]const u8{ zig_exe, "fmt", dir_path }); |
| 173 | // both files have been formatted, nothing should change now | 173 | // both files have been formatted, nothing should change now |
| 174 | testing.expect(run_result3.stderr.len == 0); | 174 | testing.expect(run_result3.stderr.len == 0); |
| 175 | } | 175 | } |