| author | |
| committer | |
| log | dffc8c44f9a01aa05ea364ffdc71509d15bc2601 |
| tree | b9b610ac10bb537b8b0dfba500f6599c5e4b2e15 |
| parent | 7071d1b3c2ed908bb8f1170673b50568ed56da7b |
| parent | 80999391d9b0db0303f59942cb52542a6e4da331 |
| signature |
compilation and build system fixes33 files changed, 363 insertions(+), 345 deletions(-)
lib/compiler/objcopy.zig+4-3| ... | ... | @@ -201,9 +201,10 @@ fn cmdObjCopy( |
| 201 | 201 | if (seen_update) fatal("zig objcopy only supports 1 update for now", .{}); |
| 202 | 202 | seen_update = true; |
| 203 | 203 | |
| 204 | try server.serveEmitBinPath(output, .{ | |
| 205 | .flags = .{ .cache_hit = false }, | |
| 206 | }); | |
| 204 | // The build system already knows what the output is at this point, we | |
| 205 | // only need to communicate that the process has finished. | |
| 206 | // Use the empty error bundle to indicate that the update is done. | |
| 207 | try server.serveErrorBundle(std.zig.ErrorBundle.empty); | |
| 207 | 208 | }, |
| 208 | 209 | else => fatal("unsupported message: {s}", .{@tagName(hdr.tag)}), |
| 209 | 210 | } |
lib/std/Build.zig+1-1| ... | ... | @@ -2373,7 +2373,7 @@ pub const LazyPath = union(enum) { |
| 2373 | 2373 | // basis for not traversing up too many directories. |
| 2374 | 2374 | |
| 2375 | 2375 | var file_path: Cache.Path = .{ |
| 2376 | .root_dir = gen.file.step.owner.build_root, | |
| 2376 | .root_dir = Cache.Directory.cwd(), | |
| 2377 | 2377 | .sub_path = gen.file.path orelse { |
| 2378 | 2378 | std.debug.lockStdErr(); |
| 2379 | 2379 | const stderr = std.io.getStdErr(); |
lib/std/Build/Cache.zig+7-2| ... | ... | @@ -896,8 +896,8 @@ pub const Manifest = struct { |
| 896 | 896 | } |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | /// Returns a hex encoded hash of the inputs. | |
| 900 | pub fn final(self: *Manifest) HexDigest { | |
| 899 | /// Returns a binary hash of the inputs. | |
| 900 | pub fn finalBin(self: *Manifest) BinDigest { | |
| 901 | 901 | assert(self.manifest_file != null); |
| 902 | 902 | |
| 903 | 903 | // We don't close the manifest file yet, because we want to |
| ... | ... | @@ -908,7 +908,12 @@ pub const Manifest = struct { |
| 908 | 908 | |
| 909 | 909 | var bin_digest: BinDigest = undefined; |
| 910 | 910 | self.hash.hasher.final(&bin_digest); |
| 911 | return bin_digest; | |
| 912 | } | |
| 911 | 913 | |
| 914 | /// Returns a hex encoded hash of the inputs. | |
| 915 | pub fn final(self: *Manifest) HexDigest { | |
| 916 | const bin_digest = self.finalBin(); | |
| 912 | 917 | return binToHex(bin_digest); |
| 913 | 918 | } |
| 914 | 919 |
lib/std/Build/Fuzz.zig+11-7| ... | ... | @@ -100,6 +100,15 @@ pub fn start( |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) void { |
| 103 | rebuildTestsWorkerRunFallible(run, ttyconf, parent_prog_node) catch |err| { | |
| 104 | const compile = run.producer.?; | |
| 105 | log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{ | |
| 106 | compile.step.name, @errorName(err), | |
| 107 | }); | |
| 108 | }; | |
| 109 | } | |
| 110 | ||
| 111 | fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void { | |
| 103 | 112 | const gpa = run.step.owner.allocator; |
| 104 | 113 | const stderr = std.io.getStdErr(); |
| 105 | 114 | |
| ... | ... | @@ -121,14 +130,9 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog |
| 121 | 130 | |
| 122 | 131 | const rebuilt_bin_path = result catch |err| switch (err) { |
| 123 | 132 | error.MakeFailed => return, |
| 124 | else => { | |
| 125 | log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{ | |
| 126 | compile.step.name, @errorName(err), | |
| 127 | }); | |
| 128 | return; | |
| 129 | }, | |
| 133 | else => |other| return other, | |
| 130 | 134 | }; |
| 131 | run.rebuilt_executable = rebuilt_bin_path; | |
| 135 | run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename); | |
| 132 | 136 | } |
| 133 | 137 | |
| 134 | 138 | fn fuzzWorkerRun( |
lib/std/Build/Fuzz/WebServer.zig+30-14| ... | ... | @@ -8,6 +8,8 @@ const Coverage = std.debug.Coverage; |
| 8 | 8 | const abi = std.Build.Fuzz.abi; |
| 9 | 9 | const log = std.log; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | const Cache = std.Build.Cache; | |
| 12 | const Path = Cache.Path; | |
| 11 | 13 | |
| 12 | 14 | const WebServer = @This(); |
| 13 | 15 | |
| ... | ... | @@ -31,6 +33,10 @@ coverage_mutex: std.Thread.Mutex, |
| 31 | 33 | /// Signaled when `coverage_files` changes. |
| 32 | 34 | coverage_condition: std.Thread.Condition, |
| 33 | 35 | |
| 36 | const fuzzer_bin_name = "fuzzer"; | |
| 37 | const fuzzer_arch_os_abi = "wasm32-freestanding"; | |
| 38 | const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext"; | |
| 39 | ||
| 34 | 40 | const CoverageMap = struct { |
| 35 | 41 | mapped_memory: []align(std.mem.page_size) const u8, |
| 36 | 42 | coverage: Coverage, |
| ... | ... | @@ -181,9 +187,18 @@ fn serveWasm( |
| 181 | 187 | |
| 182 | 188 | // Do the compilation every request, so that the user can edit the files |
| 183 | 189 | // and see the changes without restarting the server. |
| 184 | const wasm_binary_path = try buildWasmBinary(ws, arena, optimize_mode); | |
| 190 | const wasm_base_path = try buildWasmBinary(ws, arena, optimize_mode); | |
| 191 | const bin_name = try std.zig.binNameAlloc(arena, .{ | |
| 192 | .root_name = fuzzer_bin_name, | |
| 193 | .target = std.zig.system.resolveTargetQuery(std.Build.parseTargetQuery(.{ | |
| 194 | .arch_os_abi = fuzzer_arch_os_abi, | |
| 195 | .cpu_features = fuzzer_cpu_features, | |
| 196 | }) catch unreachable) catch unreachable, | |
| 197 | .output_mode = .Exe, | |
| 198 | }); | |
| 185 | 199 | // std.http.Server does not have a sendfile API yet. |
| 186 | const file_contents = try std.fs.cwd().readFileAlloc(gpa, wasm_binary_path, 10 * 1024 * 1024); | |
| 200 | const bin_path = try wasm_base_path.join(arena, bin_name); | |
| 201 | const file_contents = try bin_path.root_dir.handle.readFileAlloc(gpa, bin_path.sub_path, 10 * 1024 * 1024); | |
| 187 | 202 | defer gpa.free(file_contents); |
| 188 | 203 | try request.respond(file_contents, .{ |
| 189 | 204 | .extra_headers = &.{ |
| ... | ... | @@ -197,7 +212,7 @@ fn buildWasmBinary( |
| 197 | 212 | ws: *WebServer, |
| 198 | 213 | arena: Allocator, |
| 199 | 214 | optimize_mode: std.builtin.OptimizeMode, |
| 200 | ) ![]const u8 { | |
| 215 | ) !Path { | |
| 201 | 216 | const gpa = ws.gpa; |
| 202 | 217 | |
| 203 | 218 | const main_src_path: Build.Cache.Path = .{ |
| ... | ... | @@ -219,11 +234,11 @@ fn buildWasmBinary( |
| 219 | 234 | ws.zig_exe_path, "build-exe", // |
| 220 | 235 | "-fno-entry", // |
| 221 | 236 | "-O", @tagName(optimize_mode), // |
| 222 | "-target", "wasm32-freestanding", // | |
| 223 | "-mcpu", "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext", // | |
| 237 | "-target", fuzzer_arch_os_abi, // | |
| 238 | "-mcpu", fuzzer_cpu_features, // | |
| 224 | 239 | "--cache-dir", ws.global_cache_directory.path orelse ".", // |
| 225 | 240 | "--global-cache-dir", ws.global_cache_directory.path orelse ".", // |
| 226 | "--name", "fuzzer", // | |
| 241 | "--name", fuzzer_bin_name, // | |
| 227 | 242 | "-rdynamic", // |
| 228 | 243 | "-fsingle-threaded", // |
| 229 | 244 | "--dep", "Walk", // |
| ... | ... | @@ -251,7 +266,7 @@ fn buildWasmBinary( |
| 251 | 266 | try sendMessage(child.stdin.?, .exit); |
| 252 | 267 | |
| 253 | 268 | const Header = std.zig.Server.Message.Header; |
| 254 | var result: ?[]const u8 = null; | |
| 269 | var result: ?Path = null; | |
| 255 | 270 | var result_error_bundle = std.zig.ErrorBundle.empty; |
| 256 | 271 | |
| 257 | 272 | const stdout = poller.fifo(.stdout); |
| ... | ... | @@ -288,13 +303,17 @@ fn buildWasmBinary( |
| 288 | 303 | .extra = extra_array, |
| 289 | 304 | }; |
| 290 | 305 | }, |
| 291 | .emit_bin_path => { | |
| 292 | const EbpHdr = std.zig.Server.Message.EmitBinPath; | |
| 306 | .emit_digest => { | |
| 307 | const EbpHdr = std.zig.Server.Message.EmitDigest; | |
| 293 | 308 | const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body)); |
| 294 | 309 | if (!ebp_hdr.flags.cache_hit) { |
| 295 | 310 | log.info("source changes detected; rebuilt wasm component", .{}); |
| 296 | 311 | } |
| 297 | result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]); | |
| 312 | const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len]; | |
| 313 | result = Path{ | |
| 314 | .root_dir = ws.global_cache_directory, | |
| 315 | .sub_path = try arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*)), | |
| 316 | }; | |
| 298 | 317 | }, |
| 299 | 318 | else => {}, // ignore other messages |
| 300 | 319 | } |
| ... | ... | @@ -568,10 +587,7 @@ fn prepareTables( |
| 568 | 587 | }; |
| 569 | 588 | errdefer gop.value_ptr.coverage.deinit(gpa); |
| 570 | 589 | |
| 571 | const rebuilt_exe_path: Build.Cache.Path = .{ | |
| 572 | .root_dir = Build.Cache.Directory.cwd(), | |
| 573 | .sub_path = run_step.rebuilt_executable.?, | |
| 574 | }; | |
| 590 | const rebuilt_exe_path = run_step.rebuilt_executable.?; | |
| 575 | 591 | var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| { |
| 576 | 592 | log.err("step '{s}': failed to load debug information for '{}': {s}", .{ |
| 577 | 593 | run_step.step.name, rebuilt_exe_path, @errorName(err), |
lib/std/Build/Step.zig+12-11| ... | ... | @@ -317,6 +317,8 @@ const Build = std.Build; |
| 317 | 317 | const Allocator = std.mem.Allocator; |
| 318 | 318 | const assert = std.debug.assert; |
| 319 | 319 | const builtin = @import("builtin"); |
| 320 | const Cache = Build.Cache; | |
| 321 | const Path = Cache.Path; | |
| 320 | 322 | |
| 321 | 323 | pub fn evalChildProcess(s: *Step, argv: []const []const u8) ![]u8 { |
| 322 | 324 | const run_result = try captureChildProcess(s, std.Progress.Node.none, argv); |
| ... | ... | @@ -373,7 +375,7 @@ pub fn evalZigProcess( |
| 373 | 375 | argv: []const []const u8, |
| 374 | 376 | prog_node: std.Progress.Node, |
| 375 | 377 | watch: bool, |
| 376 | ) !?[]const u8 { | |
| 378 | ) !?Path { | |
| 377 | 379 | if (s.getZigProcess()) |zp| update: { |
| 378 | 380 | assert(watch); |
| 379 | 381 | if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd); |
| ... | ... | @@ -477,7 +479,7 @@ pub fn evalZigProcess( |
| 477 | 479 | return result; |
| 478 | 480 | } |
| 479 | 481 | |
| 480 | fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 { | |
| 482 | fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path { | |
| 481 | 483 | const b = s.owner; |
| 482 | 484 | const arena = b.allocator; |
| 483 | 485 | |
| ... | ... | @@ -487,7 +489,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 { |
| 487 | 489 | if (!watch) try sendMessage(zp.child.stdin.?, .exit); |
| 488 | 490 | |
| 489 | 491 | const Header = std.zig.Server.Message.Header; |
| 490 | var result: ?[]const u8 = null; | |
| 492 | var result: ?Path = null; | |
| 491 | 493 | |
| 492 | 494 | const stdout = zp.poller.fifo(.stdout); |
| 493 | 495 | |
| ... | ... | @@ -531,16 +533,15 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 { |
| 531 | 533 | break; |
| 532 | 534 | } |
| 533 | 535 | }, |
| 534 | .emit_bin_path => { | |
| 535 | const EbpHdr = std.zig.Server.Message.EmitBinPath; | |
| 536 | .emit_digest => { | |
| 537 | const EbpHdr = std.zig.Server.Message.EmitDigest; | |
| 536 | 538 | const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body)); |
| 537 | 539 | s.result_cached = ebp_hdr.flags.cache_hit; |
| 538 | result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]); | |
| 539 | if (watch) { | |
| 540 | // This message indicates the end of the update. | |
| 541 | stdout.discard(body.len); | |
| 542 | break; | |
| 543 | } | |
| 540 | const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len]; | |
| 541 | result = Path{ | |
| 542 | .root_dir = b.cache_root, | |
| 543 | .sub_path = try arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*)), | |
| 544 | }; | |
| 544 | 545 | }, |
| 545 | 546 | .file_system_inputs => { |
| 546 | 547 | s.clearWatchInputs(); |
lib/std/Build/Step/Compile.zig+14-15| ... | ... | @@ -17,6 +17,7 @@ const Module = std.Build.Module; |
| 17 | 17 | const InstallDir = std.Build.InstallDir; |
| 18 | 18 | const GeneratedFile = std.Build.GeneratedFile; |
| 19 | 19 | const Compile = @This(); |
| 20 | const Path = std.Build.Cache.Path; | |
| 20 | 21 | |
| 21 | 22 | pub const base_id: Step.Id = .compile; |
| 22 | 23 | |
| ... | ... | @@ -1765,7 +1766,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1765 | 1766 | |
| 1766 | 1767 | const zig_args = try getZigArgs(compile, false); |
| 1767 | 1768 | |
| 1768 | const maybe_output_bin_path = step.evalZigProcess( | |
| 1769 | const maybe_output_dir = step.evalZigProcess( | |
| 1769 | 1770 | zig_args, |
| 1770 | 1771 | options.progress_node, |
| 1771 | 1772 | (b.graph.incremental == true) and options.watch, |
| ... | ... | @@ -1779,53 +1780,51 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1779 | 1780 | }; |
| 1780 | 1781 | |
| 1781 | 1782 | // Update generated files |
| 1782 | if (maybe_output_bin_path) |output_bin_path| { | |
| 1783 | const output_dir = fs.path.dirname(output_bin_path).?; | |
| 1784 | ||
| 1783 | if (maybe_output_dir) |output_dir| { | |
| 1785 | 1784 | if (compile.emit_directory) |lp| { |
| 1786 | lp.path = output_dir; | |
| 1785 | lp.path = b.fmt("{}", .{output_dir}); | |
| 1787 | 1786 | } |
| 1788 | 1787 | |
| 1789 | 1788 | // -femit-bin[=path] (default) Output machine code |
| 1790 | 1789 | if (compile.generated_bin) |bin| { |
| 1791 | bin.path = b.pathJoin(&.{ output_dir, compile.out_filename }); | |
| 1790 | bin.path = output_dir.joinString(b.allocator, compile.out_filename) catch @panic("OOM"); | |
| 1792 | 1791 | } |
| 1793 | 1792 | |
| 1794 | const sep = std.fs.path.sep; | |
| 1793 | const sep = std.fs.path.sep_str; | |
| 1795 | 1794 | |
| 1796 | 1795 | // output PDB if someone requested it |
| 1797 | 1796 | if (compile.generated_pdb) |pdb| { |
| 1798 | pdb.path = b.fmt("{s}{c}{s}.pdb", .{ output_dir, sep, compile.name }); | |
| 1797 | pdb.path = b.fmt("{}" ++ sep ++ "{s}.pdb", .{ output_dir, compile.name }); | |
| 1799 | 1798 | } |
| 1800 | 1799 | |
| 1801 | 1800 | // -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL |
| 1802 | 1801 | if (compile.generated_implib) |implib| { |
| 1803 | implib.path = b.fmt("{s}{c}{s}.lib", .{ output_dir, sep, compile.name }); | |
| 1802 | implib.path = b.fmt("{}" ++ sep ++ "{s}.lib", .{ output_dir, compile.name }); | |
| 1804 | 1803 | } |
| 1805 | 1804 | |
| 1806 | 1805 | // -femit-h[=path] Generate a C header file (.h) |
| 1807 | 1806 | if (compile.generated_h) |lp| { |
| 1808 | lp.path = b.fmt("{s}{c}{s}.h", .{ output_dir, sep, compile.name }); | |
| 1807 | lp.path = b.fmt("{}" ++ sep ++ "{s}.h", .{ output_dir, compile.name }); | |
| 1809 | 1808 | } |
| 1810 | 1809 | |
| 1811 | 1810 | // -femit-docs[=path] Create a docs/ dir with html documentation |
| 1812 | 1811 | if (compile.generated_docs) |generated_docs| { |
| 1813 | generated_docs.path = b.pathJoin(&.{ output_dir, "docs" }); | |
| 1812 | generated_docs.path = output_dir.joinString(b.allocator, "docs") catch @panic("OOM"); | |
| 1814 | 1813 | } |
| 1815 | 1814 | |
| 1816 | 1815 | // -femit-asm[=path] Output .s (assembly code) |
| 1817 | 1816 | if (compile.generated_asm) |lp| { |
| 1818 | lp.path = b.fmt("{s}{c}{s}.s", .{ output_dir, sep, compile.name }); | |
| 1817 | lp.path = b.fmt("{}" ++ sep ++ "{s}.s", .{ output_dir, compile.name }); | |
| 1819 | 1818 | } |
| 1820 | 1819 | |
| 1821 | 1820 | // -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions) |
| 1822 | 1821 | if (compile.generated_llvm_ir) |lp| { |
| 1823 | lp.path = b.fmt("{s}{c}{s}.ll", .{ output_dir, sep, compile.name }); | |
| 1822 | lp.path = b.fmt("{}" ++ sep ++ "{s}.ll", .{ output_dir, compile.name }); | |
| 1824 | 1823 | } |
| 1825 | 1824 | |
| 1826 | 1825 | // -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions) |
| 1827 | 1826 | if (compile.generated_llvm_bc) |lp| { |
| 1828 | lp.path = b.fmt("{s}{c}{s}.bc", .{ output_dir, sep, compile.name }); | |
| 1827 | lp.path = b.fmt("{}" ++ sep ++ "{s}.bc", .{ output_dir, compile.name }); | |
| 1829 | 1828 | } |
| 1830 | 1829 | } |
| 1831 | 1830 | |
| ... | ... | @@ -1841,7 +1840,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1841 | 1840 | } |
| 1842 | 1841 | } |
| 1843 | 1842 | |
| 1844 | pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) ![]const u8 { | |
| 1843 | pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) !Path { | |
| 1845 | 1844 | const gpa = c.step.owner.allocator; |
| 1846 | 1845 | |
| 1847 | 1846 | c.step.result_error_msgs.clearRetainingCapacity(); |
lib/std/Build/Step/InstallArtifact.zig+25-24| ... | ... | @@ -125,10 +125,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 125 | 125 | |
| 126 | 126 | if (install_artifact.dest_dir) |dest_dir| { |
| 127 | 127 | const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path); |
| 128 | const full_src_path = install_artifact.emitted_bin.?.getPath2(b, step); | |
| 129 | const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_dest_path, .{}) catch |err| { | |
| 128 | const src_path = install_artifact.emitted_bin.?.getPath3(b, step); | |
| 129 | const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_dest_path, .{}) catch |err| { | |
| 130 | 130 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 131 | full_src_path, full_dest_path, @errorName(err), | |
| 131 | src_path.sub_path, full_dest_path, @errorName(err), | |
| 132 | 132 | }); |
| 133 | 133 | }; |
| 134 | 134 | all_cached = all_cached and p == .fresh; |
| ... | ... | @@ -141,22 +141,22 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | if (install_artifact.implib_dir) |implib_dir| { |
| 144 | const full_src_path = install_artifact.emitted_implib.?.getPath2(b, step); | |
| 145 | const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(full_src_path)); | |
| 146 | const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_implib_path, .{}) catch |err| { | |
| 144 | const src_path = install_artifact.emitted_implib.?.getPath3(b, step); | |
| 145 | const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(src_path.sub_path)); | |
| 146 | const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_implib_path, .{}) catch |err| { | |
| 147 | 147 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 148 | full_src_path, full_implib_path, @errorName(err), | |
| 148 | src_path.sub_path, full_implib_path, @errorName(err), | |
| 149 | 149 | }); |
| 150 | 150 | }; |
| 151 | 151 | all_cached = all_cached and p == .fresh; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | if (install_artifact.pdb_dir) |pdb_dir| { |
| 155 | const full_src_path = install_artifact.emitted_pdb.?.getPath2(b, step); | |
| 156 | const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(full_src_path)); | |
| 157 | const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_pdb_path, .{}) catch |err| { | |
| 155 | const src_path = install_artifact.emitted_pdb.?.getPath3(b, step); | |
| 156 | const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(src_path.sub_path)); | |
| 157 | const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_pdb_path, .{}) catch |err| { | |
| 158 | 158 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 159 | full_src_path, full_pdb_path, @errorName(err), | |
| 159 | src_path.sub_path, full_pdb_path, @errorName(err), | |
| 160 | 160 | }); |
| 161 | 161 | }; |
| 162 | 162 | all_cached = all_cached and p == .fresh; |
| ... | ... | @@ -164,11 +164,11 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 164 | 164 | |
| 165 | 165 | if (install_artifact.h_dir) |h_dir| { |
| 166 | 166 | if (install_artifact.emitted_h) |emitted_h| { |
| 167 | const full_src_path = emitted_h.getPath2(b, step); | |
| 168 | const full_h_path = b.getInstallPath(h_dir, fs.path.basename(full_src_path)); | |
| 169 | const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_h_path, .{}) catch |err| { | |
| 167 | const src_path = emitted_h.getPath3(b, step); | |
| 168 | const full_h_path = b.getInstallPath(h_dir, fs.path.basename(src_path.sub_path)); | |
| 169 | const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| { | |
| 170 | 170 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 171 | full_src_path, full_h_path, @errorName(err), | |
| 171 | src_path.sub_path, full_h_path, @errorName(err), | |
| 172 | 172 | }); |
| 173 | 173 | }; |
| 174 | 174 | all_cached = all_cached and p == .fresh; |
| ... | ... | @@ -176,22 +176,22 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 176 | 176 | |
| 177 | 177 | for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) { |
| 178 | 178 | .file => |file| { |
| 179 | const full_src_path = file.source.getPath2(b, step); | |
| 179 | const src_path = file.source.getPath3(b, step); | |
| 180 | 180 | const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path); |
| 181 | const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_h_path, .{}) catch |err| { | |
| 181 | const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| { | |
| 182 | 182 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 183 | full_src_path, full_h_path, @errorName(err), | |
| 183 | src_path.sub_path, full_h_path, @errorName(err), | |
| 184 | 184 | }); |
| 185 | 185 | }; |
| 186 | 186 | all_cached = all_cached and p == .fresh; |
| 187 | 187 | }, |
| 188 | 188 | .directory => |dir| { |
| 189 | const full_src_dir_path = dir.source.getPath2(b, step); | |
| 189 | const src_dir_path = dir.source.getPath3(b, step); | |
| 190 | 190 | const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path); |
| 191 | 191 | |
| 192 | var src_dir = b.build_root.handle.openDir(full_src_dir_path, .{ .iterate = true }) catch |err| { | |
| 192 | var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.sub_path, .{ .iterate = true }) catch |err| { | |
| 193 | 193 | return step.fail("unable to open source directory '{s}': {s}", .{ |
| 194 | full_src_dir_path, @errorName(err), | |
| 194 | src_dir_path.sub_path, @errorName(err), | |
| 195 | 195 | }); |
| 196 | 196 | }; |
| 197 | 197 | defer src_dir.close(); |
| ... | ... | @@ -208,14 +208,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 208 | 208 | continue :next_entry; |
| 209 | 209 | } |
| 210 | 210 | } |
| 211 | const full_src_entry_path = b.pathJoin(&.{ full_src_dir_path, entry.path }); | |
| 211 | ||
| 212 | const src_entry_path = src_dir_path.join(b.allocator, entry.path) catch @panic("OOM"); | |
| 212 | 213 | const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path }); |
| 213 | 214 | switch (entry.kind) { |
| 214 | 215 | .directory => try cwd.makePath(full_dest_path), |
| 215 | 216 | .file => { |
| 216 | const p = fs.Dir.updateFile(cwd, full_src_entry_path, cwd, full_dest_path, .{}) catch |err| { | |
| 217 | const p = fs.Dir.updateFile(src_entry_path.root_dir.handle, src_entry_path.sub_path, cwd, full_dest_path, .{}) catch |err| { | |
| 217 | 218 | return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ |
| 218 | full_src_entry_path, full_dest_path, @errorName(err), | |
| 219 | src_entry_path.sub_path, full_dest_path, @errorName(err), | |
| 219 | 220 | }); |
| 220 | 221 | }; |
| 221 | 222 | all_cached = all_cached and p == .fresh; |
lib/std/Build/Step/Run.zig+3-2| ... | ... | @@ -7,6 +7,7 @@ const mem = std.mem; |
| 7 | 7 | const process = std.process; |
| 8 | 8 | const EnvMap = process.EnvMap; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | const Path = Build.Cache.Path; | |
| 10 | 11 | |
| 11 | 12 | const Run = @This(); |
| 12 | 13 | |
| ... | ... | @@ -93,7 +94,7 @@ cached_test_metadata: ?CachedTestMetadata = null, |
| 93 | 94 | |
| 94 | 95 | /// Populated during the fuzz phase if this run step corresponds to a unit test |
| 95 | 96 | /// executable that contains fuzz tests. |
| 96 | rebuilt_executable: ?[]const u8, | |
| 97 | rebuilt_executable: ?Path, | |
| 97 | 98 | |
| 98 | 99 | /// If this Run step was produced by a Compile step, it is tracked here. |
| 99 | 100 | producer: ?*Step.Compile, |
| ... | ... | @@ -872,7 +873,7 @@ pub fn rerunInFuzzMode( |
| 872 | 873 | .artifact => |pa| { |
| 873 | 874 | const artifact = pa.artifact; |
| 874 | 875 | const file_path = if (artifact == run.producer.?) |
| 875 | run.rebuilt_executable.? | |
| 876 | b.fmt("{}", .{run.rebuilt_executable.?}) | |
| 876 | 877 | else |
| 877 | 878 | (artifact.installed_path orelse artifact.generated_bin.?.path.?); |
| 878 | 879 | try argv_list.append(arena, b.fmt("{s}{s}", .{ pa.prefix, file_path })); |
lib/std/Build/Step/TranslateC.zig+6-6| ... | ... | @@ -153,12 +153,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 153 | 153 | try argv_list.append(c_macro); |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | try argv_list.append(translate_c.source.getPath2(b, step)); | |
| 156 | const c_source_path = translate_c.source.getPath2(b, step); | |
| 157 | try argv_list.append(c_source_path); | |
| 157 | 158 | |
| 158 | const output_path = try step.evalZigProcess(argv_list.items, prog_node, false); | |
| 159 | const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false); | |
| 159 | 160 | |
| 160 | translate_c.out_basename = fs.path.basename(output_path.?); | |
| 161 | const output_dir = fs.path.dirname(output_path.?).?; | |
| 162 | ||
| 163 | translate_c.output_file.path = b.pathJoin(&.{ output_dir, translate_c.out_basename }); | |
| 161 | const basename = std.fs.path.stem(std.fs.path.basename(c_source_path)); | |
| 162 | translate_c.out_basename = b.fmt("{s}.zig", .{basename}); | |
| 163 | translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM"); | |
| 164 | 164 | } |
lib/std/zig/Server.zig+11-10| ... | ... | @@ -14,8 +14,8 @@ pub const Message = struct { |
| 14 | 14 | zig_version, |
| 15 | 15 | /// Body is an ErrorBundle. |
| 16 | 16 | error_bundle, |
| 17 | /// Body is a EmitBinPath. | |
| 18 | emit_bin_path, | |
| 17 | /// Body is a EmitDigest. | |
| 18 | emit_digest, | |
| 19 | 19 | /// Body is a TestMetadata |
| 20 | 20 | test_metadata, |
| 21 | 21 | /// Body is a TestResults |
| ... | ... | @@ -82,8 +82,8 @@ pub const Message = struct { |
| 82 | 82 | }; |
| 83 | 83 | |
| 84 | 84 | /// Trailing: |
| 85 | /// * file system path where the emitted binary can be found | |
| 86 | pub const EmitBinPath = extern struct { | |
| 85 | /// * the hex digest of the cache directory within the /o/ subdirectory. | |
| 86 | pub const EmitDigest = extern struct { | |
| 87 | 87 | flags: Flags, |
| 88 | 88 | |
| 89 | 89 | pub const Flags = packed struct(u8) { |
| ... | ... | @@ -196,17 +196,17 @@ pub fn serveU64Message(s: *Server, tag: OutMessage.Tag, int: u64) !void { |
| 196 | 196 | }, &.{std.mem.asBytes(&msg_le)}); |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | pub fn serveEmitBinPath( | |
| 199 | pub fn serveEmitDigest( | |
| 200 | 200 | s: *Server, |
| 201 | fs_path: []const u8, | |
| 202 | header: OutMessage.EmitBinPath, | |
| 201 | digest: *const [Cache.bin_digest_len]u8, | |
| 202 | header: OutMessage.EmitDigest, | |
| 203 | 203 | ) !void { |
| 204 | 204 | try s.serveMessage(.{ |
| 205 | .tag = .emit_bin_path, | |
| 206 | .bytes_len = @intCast(fs_path.len + @sizeOf(OutMessage.EmitBinPath)), | |
| 205 | .tag = .emit_digest, | |
| 206 | .bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)), | |
| 207 | 207 | }, &.{ |
| 208 | 208 | std.mem.asBytes(&header), |
| 209 | fs_path, | |
| 209 | digest, | |
| 210 | 210 | }); |
| 211 | 211 | } |
| 212 | 212 | |
| ... | ... | @@ -328,3 +328,4 @@ const Allocator = std.mem.Allocator; |
| 328 | 328 | const assert = std.debug.assert; |
| 329 | 329 | const native_endian = builtin.target.cpu.arch.endian(); |
| 330 | 330 | const need_bswap = native_endian != .little; |
| 331 | const Cache = std.Build.Cache; |
src/Compilation.zig+68-88| ... | ... | @@ -39,6 +39,8 @@ const Air = @import("Air.zig"); |
| 39 | 39 | const Builtin = @import("Builtin.zig"); |
| 40 | 40 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 41 | 41 | const dev = @import("dev.zig"); |
| 42 | pub const Directory = Cache.Directory; | |
| 43 | const Path = Cache.Path; | |
| 42 | 44 | |
| 43 | 45 | pub const Config = @import("Compilation/Config.zig"); |
| 44 | 46 | |
| ... | ... | @@ -70,9 +72,9 @@ bin_file: ?*link.File, |
| 70 | 72 | /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) |
| 71 | 73 | sysroot: ?[]const u8, |
| 72 | 74 | /// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used. |
| 73 | implib_emit: ?Emit, | |
| 75 | implib_emit: ?Path, | |
| 74 | 76 | /// This is non-null when `-femit-docs` is provided. |
| 75 | docs_emit: ?Emit, | |
| 77 | docs_emit: ?Path, | |
| 76 | 78 | root_name: [:0]const u8, |
| 77 | 79 | include_compiler_rt: bool, |
| 78 | 80 | objects: []Compilation.LinkObject, |
| ... | ... | @@ -269,27 +271,9 @@ llvm_opt_bisect_limit: c_int, |
| 269 | 271 | |
| 270 | 272 | file_system_inputs: ?*std.ArrayListUnmanaged(u8), |
| 271 | 273 | |
| 272 | pub const Emit = struct { | |
| 273 | /// Where the output will go. | |
| 274 | directory: Directory, | |
| 275 | /// Path to the output file, relative to `directory`. | |
| 276 | sub_path: []const u8, | |
| 277 | ||
| 278 | /// Returns the full path to `basename` if it were in the same directory as the | |
| 279 | /// `Emit` sub_path. | |
| 280 | pub fn basenamePath(emit: Emit, arena: Allocator, basename: []const u8) ![:0]const u8 { | |
| 281 | const full_path = if (emit.directory.path) |p| | |
| 282 | try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path }) | |
| 283 | else | |
| 284 | emit.sub_path; | |
| 285 | ||
| 286 | if (std.fs.path.dirname(full_path)) |dirname| { | |
| 287 | return try std.fs.path.joinZ(arena, &.{ dirname, basename }); | |
| 288 | } else { | |
| 289 | return try arena.dupeZ(u8, basename); | |
| 290 | } | |
| 291 | } | |
| 292 | }; | |
| 274 | /// This is the digest of the cache for the current compilation. | |
| 275 | /// This digest will be known after update() is called. | |
| 276 | digest: ?[Cache.bin_digest_len]u8 = null, | |
| 293 | 277 | |
| 294 | 278 | pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size; |
| 295 | 279 | pub const SemaError = Zcu.SemaError; |
| ... | ... | @@ -868,8 +852,6 @@ pub const LldError = struct { |
| 868 | 852 | } |
| 869 | 853 | }; |
| 870 | 854 | |
| 871 | pub const Directory = Cache.Directory; | |
| 872 | ||
| 873 | 855 | pub const EmitLoc = struct { |
| 874 | 856 | /// If this is `null` it means the file will be output to the cache directory. |
| 875 | 857 | /// When provided, both the open file handle and the path name must outlive the `Compilation`. |
| ... | ... | @@ -1672,7 +1654,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1672 | 1654 | // In the case of incremental cache mode, this `artifact_directory` |
| 1673 | 1655 | // is computed based on a hash of non-linker inputs, and it is where all |
| 1674 | 1656 | // build artifacts are stored (even while in-progress). |
| 1657 | comp.digest = hash.peekBin(); | |
| 1675 | 1658 | const digest = hash.final(); |
| 1659 | ||
| 1676 | 1660 | const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest; |
| 1677 | 1661 | var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); |
| 1678 | 1662 | errdefer artifact_dir.close(); |
| ... | ... | @@ -1688,8 +1672,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1688 | 1672 | comp.cache_use = .{ .incremental = incremental }; |
| 1689 | 1673 | |
| 1690 | 1674 | if (options.emit_bin) |emit_bin| { |
| 1691 | const emit: Emit = .{ | |
| 1692 | .directory = emit_bin.directory orelse artifact_directory, | |
| 1675 | const emit: Path = .{ | |
| 1676 | .root_dir = emit_bin.directory orelse artifact_directory, | |
| 1693 | 1677 | .sub_path = emit_bin.basename, |
| 1694 | 1678 | }; |
| 1695 | 1679 | comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts); |
| ... | ... | @@ -1697,14 +1681,14 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1697 | 1681 | |
| 1698 | 1682 | if (options.emit_implib) |emit_implib| { |
| 1699 | 1683 | comp.implib_emit = .{ |
| 1700 | .directory = emit_implib.directory orelse artifact_directory, | |
| 1684 | .root_dir = emit_implib.directory orelse artifact_directory, | |
| 1701 | 1685 | .sub_path = emit_implib.basename, |
| 1702 | 1686 | }; |
| 1703 | 1687 | } |
| 1704 | 1688 | |
| 1705 | 1689 | if (options.emit_docs) |emit_docs| { |
| 1706 | 1690 | comp.docs_emit = .{ |
| 1707 | .directory = emit_docs.directory orelse artifact_directory, | |
| 1691 | .root_dir = emit_docs.directory orelse artifact_directory, | |
| 1708 | 1692 | .sub_path = emit_docs.basename, |
| 1709 | 1693 | }; |
| 1710 | 1694 | } |
| ... | ... | @@ -2121,9 +2105,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2121 | 2105 | |
| 2122 | 2106 | comp.last_update_was_cache_hit = true; |
| 2123 | 2107 | log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); |
| 2124 | const digest = man.final(); | |
| 2108 | const bin_digest = man.finalBin(); | |
| 2109 | const hex_digest = Cache.binToHex(bin_digest); | |
| 2125 | 2110 | |
| 2126 | comp.wholeCacheModeSetBinFilePath(whole, &digest); | |
| 2111 | comp.digest = bin_digest; | |
| 2112 | comp.wholeCacheModeSetBinFilePath(whole, &hex_digest); | |
| 2127 | 2113 | |
| 2128 | 2114 | assert(whole.lock == null); |
| 2129 | 2115 | whole.lock = man.toOwnedLock(); |
| ... | ... | @@ -2155,21 +2141,21 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2155 | 2141 | |
| 2156 | 2142 | if (whole.implib_sub_path) |sub_path| { |
| 2157 | 2143 | comp.implib_emit = .{ |
| 2158 | .directory = tmp_artifact_directory, | |
| 2144 | .root_dir = tmp_artifact_directory, | |
| 2159 | 2145 | .sub_path = std.fs.path.basename(sub_path), |
| 2160 | 2146 | }; |
| 2161 | 2147 | } |
| 2162 | 2148 | |
| 2163 | 2149 | if (whole.docs_sub_path) |sub_path| { |
| 2164 | 2150 | comp.docs_emit = .{ |
| 2165 | .directory = tmp_artifact_directory, | |
| 2151 | .root_dir = tmp_artifact_directory, | |
| 2166 | 2152 | .sub_path = std.fs.path.basename(sub_path), |
| 2167 | 2153 | }; |
| 2168 | 2154 | } |
| 2169 | 2155 | |
| 2170 | 2156 | if (whole.bin_sub_path) |sub_path| { |
| 2171 | const emit: Emit = .{ | |
| 2172 | .directory = tmp_artifact_directory, | |
| 2157 | const emit: Path = .{ | |
| 2158 | .root_dir = tmp_artifact_directory, | |
| 2173 | 2159 | .sub_path = std.fs.path.basename(sub_path), |
| 2174 | 2160 | }; |
| 2175 | 2161 | comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts); |
| ... | ... | @@ -2329,7 +2315,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2329 | 2315 | try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); |
| 2330 | 2316 | } |
| 2331 | 2317 | |
| 2332 | const digest = man.final(); | |
| 2318 | const bin_digest = man.finalBin(); | |
| 2319 | const hex_digest = Cache.binToHex(bin_digest); | |
| 2333 | 2320 | |
| 2334 | 2321 | // Rename the temporary directory into place. |
| 2335 | 2322 | // Close tmp dir and link.File to avoid open handle during rename. |
| ... | ... | @@ -2341,7 +2328,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2341 | 2328 | |
| 2342 | 2329 | const s = std.fs.path.sep_str; |
| 2343 | 2330 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); |
| 2344 | const o_sub_path = "o" ++ s ++ digest; | |
| 2331 | const o_sub_path = "o" ++ s ++ hex_digest; | |
| 2345 | 2332 | |
| 2346 | 2333 | // Work around windows `AccessDenied` if any files within this |
| 2347 | 2334 | // directory are open by closing and reopening the file handles. |
| ... | ... | @@ -2376,14 +2363,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2376 | 2363 | }, |
| 2377 | 2364 | ); |
| 2378 | 2365 | }; |
| 2379 | comp.wholeCacheModeSetBinFilePath(whole, &digest); | |
| 2366 | comp.digest = bin_digest; | |
| 2367 | comp.wholeCacheModeSetBinFilePath(whole, &hex_digest); | |
| 2380 | 2368 | |
| 2381 | 2369 | // The linker flush functions need to know the final output path |
| 2382 | 2370 | // for debug info purposes because executable debug info contains |
| 2383 | 2371 | // references object file paths. |
| 2384 | 2372 | if (comp.bin_file) |lf| { |
| 2385 | 2373 | lf.emit = .{ |
| 2386 | .directory = comp.local_cache_directory, | |
| 2374 | .root_dir = comp.local_cache_directory, | |
| 2387 | 2375 | .sub_path = whole.bin_sub_path.?, |
| 2388 | 2376 | }; |
| 2389 | 2377 | |
| ... | ... | @@ -2393,9 +2381,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2393 | 2381 | } |
| 2394 | 2382 | } |
| 2395 | 2383 | |
| 2396 | try flush(comp, arena, .main, main_progress_node); | |
| 2397 | ||
| 2398 | if (try comp.totalErrorCount() != 0) return; | |
| 2384 | try flush(comp, arena, .{ | |
| 2385 | .root_dir = comp.local_cache_directory, | |
| 2386 | .sub_path = o_sub_path, | |
| 2387 | }, .main, main_progress_node); | |
| 2399 | 2388 | |
| 2400 | 2389 | // Failure here only means an unnecessary cache miss. |
| 2401 | 2390 | man.writeManifest() catch |err| { |
| ... | ... | @@ -2410,8 +2399,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2410 | 2399 | assert(whole.lock == null); |
| 2411 | 2400 | whole.lock = man.toOwnedLock(); |
| 2412 | 2401 | }, |
| 2413 | .incremental => { | |
| 2414 | try flush(comp, arena, .main, main_progress_node); | |
| 2402 | .incremental => |incremental| { | |
| 2403 | try flush(comp, arena, .{ | |
| 2404 | .root_dir = incremental.artifact_directory, | |
| 2405 | }, .main, main_progress_node); | |
| 2415 | 2406 | }, |
| 2416 | 2407 | } |
| 2417 | 2408 | } |
| ... | ... | @@ -2440,7 +2431,13 @@ pub fn appendFileSystemInput( |
| 2440 | 2431 | std.debug.panic("missing prefix directory: {}, {s}", .{ root, sub_file_path }); |
| 2441 | 2432 | } |
| 2442 | 2433 | |
| 2443 | fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { | |
| 2434 | fn flush( | |
| 2435 | comp: *Compilation, | |
| 2436 | arena: Allocator, | |
| 2437 | default_artifact_directory: Path, | |
| 2438 | tid: Zcu.PerThread.Id, | |
| 2439 | prog_node: std.Progress.Node, | |
| 2440 | ) !void { | |
| 2444 | 2441 | if (comp.bin_file) |lf| { |
| 2445 | 2442 | // This is needed before reading the error flags. |
| 2446 | 2443 | lf.flush(arena, tid, prog_node) catch |err| switch (err) { |
| ... | ... | @@ -2454,17 +2451,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 2454 | 2451 | try link.File.C.flushEmitH(zcu); |
| 2455 | 2452 | |
| 2456 | 2453 | if (zcu.llvm_object) |llvm_object| { |
| 2457 | const default_emit = switch (comp.cache_use) { | |
| 2458 | .whole => |whole| .{ | |
| 2459 | .directory = whole.tmp_artifact_directory.?, | |
| 2460 | .sub_path = "dummy", | |
| 2461 | }, | |
| 2462 | .incremental => |incremental| .{ | |
| 2463 | .directory = incremental.artifact_directory, | |
| 2464 | .sub_path = "dummy", | |
| 2465 | }, | |
| 2466 | }; | |
| 2467 | try emitLlvmObject(comp, arena, default_emit, null, llvm_object, prog_node); | |
| 2454 | try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node); | |
| 2468 | 2455 | } |
| 2469 | 2456 | } |
| 2470 | 2457 | } |
| ... | ... | @@ -2533,7 +2520,7 @@ fn wholeCacheModeSetBinFilePath( |
| 2533 | 2520 | @memcpy(sub_path[digest_start..][0..digest.len], digest); |
| 2534 | 2521 | |
| 2535 | 2522 | comp.implib_emit = .{ |
| 2536 | .directory = comp.local_cache_directory, | |
| 2523 | .root_dir = comp.local_cache_directory, | |
| 2537 | 2524 | .sub_path = sub_path, |
| 2538 | 2525 | }; |
| 2539 | 2526 | } |
| ... | ... | @@ -2542,7 +2529,7 @@ fn wholeCacheModeSetBinFilePath( |
| 2542 | 2529 | @memcpy(sub_path[digest_start..][0..digest.len], digest); |
| 2543 | 2530 | |
| 2544 | 2531 | comp.docs_emit = .{ |
| 2545 | .directory = comp.local_cache_directory, | |
| 2532 | .root_dir = comp.local_cache_directory, | |
| 2546 | 2533 | .sub_path = sub_path, |
| 2547 | 2534 | }; |
| 2548 | 2535 | } |
| ... | ... | @@ -2745,7 +2732,7 @@ fn emitOthers(comp: *Compilation) void { |
| 2745 | 2732 | pub fn emitLlvmObject( |
| 2746 | 2733 | comp: *Compilation, |
| 2747 | 2734 | arena: Allocator, |
| 2748 | default_emit: Emit, | |
| 2735 | default_artifact_directory: Path, | |
| 2749 | 2736 | bin_emit_loc: ?EmitLoc, |
| 2750 | 2737 | llvm_object: LlvmObject.Ptr, |
| 2751 | 2738 | prog_node: std.Progress.Node, |
| ... | ... | @@ -2756,10 +2743,10 @@ pub fn emitLlvmObject( |
| 2756 | 2743 | try llvm_object.emit(.{ |
| 2757 | 2744 | .pre_ir_path = comp.verbose_llvm_ir, |
| 2758 | 2745 | .pre_bc_path = comp.verbose_llvm_bc, |
| 2759 | .bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc), | |
| 2760 | .asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm), | |
| 2761 | .post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir), | |
| 2762 | .post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc), | |
| 2746 | .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc), | |
| 2747 | .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm), | |
| 2748 | .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir), | |
| 2749 | .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc), | |
| 2763 | 2750 | |
| 2764 | 2751 | .is_debug = comp.root_mod.optimize_mode == .Debug, |
| 2765 | 2752 | .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, |
| ... | ... | @@ -2772,14 +2759,14 @@ pub fn emitLlvmObject( |
| 2772 | 2759 | |
| 2773 | 2760 | fn resolveEmitLoc( |
| 2774 | 2761 | arena: Allocator, |
| 2775 | default_emit: Emit, | |
| 2762 | default_artifact_directory: Path, | |
| 2776 | 2763 | opt_loc: ?EmitLoc, |
| 2777 | 2764 | ) Allocator.Error!?[*:0]const u8 { |
| 2778 | 2765 | const loc = opt_loc orelse return null; |
| 2779 | 2766 | const slice = if (loc.directory) |directory| |
| 2780 | 2767 | try directory.joinZ(arena, &.{loc.basename}) |
| 2781 | 2768 | else |
| 2782 | try default_emit.basenamePath(arena, loc.basename); | |
| 2769 | try default_artifact_directory.joinStringZ(arena, loc.basename); | |
| 2783 | 2770 | return slice.ptr; |
| 2784 | 2771 | } |
| 2785 | 2772 | |
| ... | ... | @@ -3035,7 +3022,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 3035 | 3022 | |
| 3036 | 3023 | // Using an atomic file prevents a crash or power failure from corrupting |
| 3037 | 3024 | // the previous incremental compilation state. |
| 3038 | var af = try lf.emit.directory.handle.atomicFile(basename, .{}); | |
| 3025 | var af = try lf.emit.root_dir.handle.atomicFile(basename, .{}); | |
| 3039 | 3026 | defer af.deinit(); |
| 3040 | 3027 | try af.file.pwritevAll(bufs.items, 0); |
| 3041 | 3028 | try af.finish(); |
| ... | ... | @@ -4000,11 +3987,11 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { |
| 4000 | 3987 | return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{}); |
| 4001 | 3988 | |
| 4002 | 3989 | const emit = comp.docs_emit.?; |
| 4003 | var out_dir = emit.directory.handle.makeOpenPath(emit.sub_path, .{}) catch |err| { | |
| 3990 | var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| { | |
| 4004 | 3991 | return comp.lockAndSetMiscFailure( |
| 4005 | 3992 | .docs_copy, |
| 4006 | 3993 | "unable to create output directory '{}{s}': {s}", |
| 4007 | .{ emit.directory, emit.sub_path, @errorName(err) }, | |
| 3994 | .{ emit.root_dir, emit.sub_path, @errorName(err) }, | |
| 4008 | 3995 | ); |
| 4009 | 3996 | }; |
| 4010 | 3997 | defer out_dir.close(); |
| ... | ... | @@ -4024,7 +4011,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void { |
| 4024 | 4011 | return comp.lockAndSetMiscFailure( |
| 4025 | 4012 | .docs_copy, |
| 4026 | 4013 | "unable to create '{}{s}/sources.tar': {s}", |
| 4027 | .{ emit.directory, emit.sub_path, @errorName(err) }, | |
| 4014 | .{ emit.root_dir, emit.sub_path, @errorName(err) }, | |
| 4028 | 4015 | ); |
| 4029 | 4016 | }; |
| 4030 | 4017 | defer tar_file.close(); |
| ... | ... | @@ -4223,11 +4210,11 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 4223 | 4210 | try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node); |
| 4224 | 4211 | |
| 4225 | 4212 | const emit = comp.docs_emit.?; |
| 4226 | var out_dir = emit.directory.handle.makeOpenPath(emit.sub_path, .{}) catch |err| { | |
| 4213 | var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| { | |
| 4227 | 4214 | return comp.lockAndSetMiscFailure( |
| 4228 | 4215 | .docs_copy, |
| 4229 | 4216 | "unable to create output directory '{}{s}': {s}", |
| 4230 | .{ emit.directory, emit.sub_path, @errorName(err) }, | |
| 4217 | .{ emit.root_dir, emit.sub_path, @errorName(err) }, | |
| 4231 | 4218 | ); |
| 4232 | 4219 | }; |
| 4233 | 4220 | defer out_dir.close(); |
| ... | ... | @@ -4241,7 +4228,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 4241 | 4228 | return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{ |
| 4242 | 4229 | sub_compilation.local_cache_directory, |
| 4243 | 4230 | sub_compilation.cache_use.whole.bin_sub_path.?, |
| 4244 | emit.directory, | |
| 4231 | emit.root_dir, | |
| 4245 | 4232 | emit.sub_path, |
| 4246 | 4233 | @errorName(err), |
| 4247 | 4234 | }); |
| ... | ... | @@ -4403,7 +4390,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest |
| 4403 | 4390 | } |
| 4404 | 4391 | |
| 4405 | 4392 | pub const CImportResult = struct { |
| 4406 | out_zig_path: []u8, | |
| 4393 | digest: [Cache.bin_digest_len]u8, | |
| 4407 | 4394 | cache_hit: bool, |
| 4408 | 4395 | errors: std.zig.ErrorBundle, |
| 4409 | 4396 | |
| ... | ... | @@ -4413,8 +4400,6 @@ pub const CImportResult = struct { |
| 4413 | 4400 | }; |
| 4414 | 4401 | |
| 4415 | 4402 | /// Caller owns returned memory. |
| 4416 | /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked | |
| 4417 | /// a bit when we want to start using it from self-hosted. | |
| 4418 | 4403 | pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { |
| 4419 | 4404 | dev.check(.translate_c_command); |
| 4420 | 4405 | |
| ... | ... | @@ -4503,7 +4488,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module |
| 4503 | 4488 | error.OutOfMemory => return error.OutOfMemory, |
| 4504 | 4489 | error.SemanticAnalyzeFail => { |
| 4505 | 4490 | return CImportResult{ |
| 4506 | .out_zig_path = "", | |
| 4491 | .digest = undefined, | |
| 4507 | 4492 | .cache_hit = actual_hit, |
| 4508 | 4493 | .errors = errors, |
| 4509 | 4494 | }; |
| ... | ... | @@ -4528,8 +4513,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module |
| 4528 | 4513 | .incremental => {}, |
| 4529 | 4514 | } |
| 4530 | 4515 | |
| 4531 | const digest = man.final(); | |
| 4532 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); | |
| 4516 | const bin_digest = man.finalBin(); | |
| 4517 | const hex_digest = Cache.binToHex(bin_digest); | |
| 4518 | const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest; | |
| 4533 | 4519 | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); |
| 4534 | 4520 | defer o_dir.close(); |
| 4535 | 4521 | |
| ... | ... | @@ -4541,8 +4527,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module |
| 4541 | 4527 | |
| 4542 | 4528 | try out_zig_file.writeAll(formatted); |
| 4543 | 4529 | |
| 4544 | break :digest digest; | |
| 4545 | } else man.final(); | |
| 4530 | break :digest bin_digest; | |
| 4531 | } else man.finalBin(); | |
| 4546 | 4532 | |
| 4547 | 4533 | if (man.have_exclusive_lock) { |
| 4548 | 4534 | // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is |
| ... | ... | @@ -4554,14 +4540,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module |
| 4554 | 4540 | }; |
| 4555 | 4541 | } |
| 4556 | 4542 | |
| 4557 | const out_zig_path = try comp.local_cache_directory.join(comp.arena, &.{ | |
| 4558 | "o", &digest, cimport_zig_basename, | |
| 4559 | }); | |
| 4560 | if (comp.verbose_cimport) { | |
| 4561 | log.info("C import output: {s}", .{out_zig_path}); | |
| 4562 | } | |
| 4563 | 4543 | return CImportResult{ |
| 4564 | .out_zig_path = out_zig_path, | |
| 4544 | .digest = digest, | |
| 4565 | 4545 | .cache_hit = actual_hit, |
| 4566 | 4546 | .errors = std.zig.ErrorBundle.empty, |
| 4567 | 4547 | }; |
| ... | ... | @@ -4800,7 +4780,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4800 | 4780 | try argv.appendSlice(c_object.src.cache_exempt_flags); |
| 4801 | 4781 | |
| 4802 | 4782 | const out_obj_path = if (comp.bin_file) |lf| |
| 4803 | try lf.emit.directory.join(arena, &.{lf.emit.sub_path}) | |
| 4783 | try lf.emit.root_dir.join(arena, &.{lf.emit.sub_path}) | |
| 4804 | 4784 | else |
| 4805 | 4785 | "/dev/null"; |
| 4806 | 4786 |
src/Sema.zig+7-4| ... | ... | @@ -183,6 +183,7 @@ const InternPool = @import("InternPool.zig"); |
| 183 | 183 | const Alignment = InternPool.Alignment; |
| 184 | 184 | const AnalUnit = InternPool.AnalUnit; |
| 185 | 185 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; |
| 186 | const Cache = std.Build.Cache; | |
| 186 | 187 | |
| 187 | 188 | pub const default_branch_quota = 1000; |
| 188 | 189 | pub const default_reference_trace_len = 2; |
| ... | ... | @@ -5871,16 +5872,18 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5871 | 5872 | return sema.failWithOwnedErrorMsg(&child_block, msg); |
| 5872 | 5873 | } |
| 5873 | 5874 | const parent_mod = parent_block.ownerModule(); |
| 5875 | const digest = Cache.binToHex(c_import_res.digest); | |
| 5876 | const c_import_zig_path = try comp.arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ digest); | |
| 5874 | 5877 | const c_import_mod = Package.Module.create(comp.arena, .{ |
| 5875 | 5878 | .global_cache_directory = comp.global_cache_directory, |
| 5876 | 5879 | .paths = .{ |
| 5877 | 5880 | .root = .{ |
| 5878 | .root_dir = Compilation.Directory.cwd(), | |
| 5879 | .sub_path = std.fs.path.dirname(c_import_res.out_zig_path) orelse "", | |
| 5881 | .root_dir = comp.local_cache_directory, | |
| 5882 | .sub_path = c_import_zig_path, | |
| 5880 | 5883 | }, |
| 5881 | .root_src_path = std.fs.path.basename(c_import_res.out_zig_path), | |
| 5884 | .root_src_path = "cimport.zig", | |
| 5882 | 5885 | }, |
| 5883 | .fully_qualified_name = c_import_res.out_zig_path, | |
| 5886 | .fully_qualified_name = c_import_zig_path, | |
| 5884 | 5887 | .cc_argv = parent_mod.cc_argv, |
| 5885 | 5888 | .inherited = .{}, |
| 5886 | 5889 | .global = comp.config, |
src/link.zig+13-9| ... | ... | @@ -11,6 +11,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 11 | 11 | const Air = @import("Air.zig"); |
| 12 | 12 | const Allocator = std.mem.Allocator; |
| 13 | 13 | const Cache = std.Build.Cache; |
| 14 | const Path = Cache.Path; | |
| 14 | 15 | const Compilation = @import("Compilation.zig"); |
| 15 | 16 | const LibCInstallation = std.zig.LibCInstallation; |
| 16 | 17 | const Liveness = @import("Liveness.zig"); |
| ... | ... | @@ -56,7 +57,7 @@ pub const File = struct { |
| 56 | 57 | |
| 57 | 58 | /// The owner of this output File. |
| 58 | 59 | comp: *Compilation, |
| 59 | emit: Compilation.Emit, | |
| 60 | emit: Path, | |
| 60 | 61 | |
| 61 | 62 | file: ?fs.File, |
| 62 | 63 | /// When linking with LLD, this linker code will output an object file only at |
| ... | ... | @@ -189,7 +190,7 @@ pub const File = struct { |
| 189 | 190 | pub fn open( |
| 190 | 191 | arena: Allocator, |
| 191 | 192 | comp: *Compilation, |
| 192 | emit: Compilation.Emit, | |
| 193 | emit: Path, | |
| 193 | 194 | options: OpenOptions, |
| 194 | 195 | ) !*File { |
| 195 | 196 | switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { |
| ... | ... | @@ -204,7 +205,7 @@ pub const File = struct { |
| 204 | 205 | pub fn createEmpty( |
| 205 | 206 | arena: Allocator, |
| 206 | 207 | comp: *Compilation, |
| 207 | emit: Compilation.Emit, | |
| 208 | emit: Path, | |
| 208 | 209 | options: OpenOptions, |
| 209 | 210 | ) !*File { |
| 210 | 211 | switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { |
| ... | ... | @@ -243,8 +244,8 @@ pub const File = struct { |
| 243 | 244 | emit.sub_path, std.crypto.random.int(u32), |
| 244 | 245 | }); |
| 245 | 246 | defer gpa.free(tmp_sub_path); |
| 246 | try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{}); | |
| 247 | try emit.directory.handle.rename(tmp_sub_path, emit.sub_path); | |
| 247 | try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, .{}); | |
| 248 | try emit.root_dir.handle.rename(tmp_sub_path, emit.sub_path); | |
| 248 | 249 | switch (builtin.os.tag) { |
| 249 | 250 | .linux => std.posix.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0) catch |err| { |
| 250 | 251 | log.warn("ptrace failure: {s}", .{@errorName(err)}); |
| ... | ... | @@ -260,7 +261,7 @@ pub const File = struct { |
| 260 | 261 | const use_lld = build_options.have_llvm and comp.config.use_lld; |
| 261 | 262 | const output_mode = comp.config.output_mode; |
| 262 | 263 | const link_mode = comp.config.link_mode; |
| 263 | base.file = try emit.directory.handle.createFile(emit.sub_path, .{ | |
| 264 | base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ | |
| 264 | 265 | .truncate = false, |
| 265 | 266 | .read = true, |
| 266 | 267 | .mode = determineMode(use_lld, output_mode, link_mode), |
| ... | ... | @@ -603,7 +604,7 @@ pub const File = struct { |
| 603 | 604 | // Until then, we do `lld -r -o output.o input.o` even though the output is the same |
| 604 | 605 | // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file |
| 605 | 606 | // to the final location. See also the corresponding TODO in Coff linking. |
| 606 | const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path}); | |
| 607 | const full_out_path = try emit.root_dir.join(gpa, &[_][]const u8{emit.sub_path}); | |
| 607 | 608 | defer gpa.free(full_out_path); |
| 608 | 609 | assert(comp.c_object_table.count() == 1); |
| 609 | 610 | const the_key = comp.c_object_table.keys()[0]; |
| ... | ... | @@ -751,7 +752,7 @@ pub const File = struct { |
| 751 | 752 | const comp = base.comp; |
| 752 | 753 | const gpa = comp.gpa; |
| 753 | 754 | |
| 754 | const directory = base.emit.directory; // Just an alias to make it shorter to type. | |
| 755 | const directory = base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 755 | 756 | const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path}); |
| 756 | 757 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); |
| 757 | 758 | const opt_zcu = comp.module; |
| ... | ... | @@ -1029,7 +1030,10 @@ pub const File = struct { |
| 1029 | 1030 | llvm_object: LlvmObject.Ptr, |
| 1030 | 1031 | prog_node: std.Progress.Node, |
| 1031 | 1032 | ) !void { |
| 1032 | return base.comp.emitLlvmObject(arena, base.emit, .{ | |
| 1033 | return base.comp.emitLlvmObject(arena, .{ | |
| 1034 | .root_dir = base.emit.root_dir, | |
| 1035 | .sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "", | |
| 1036 | }, .{ | |
| 1033 | 1037 | .directory = null, |
| 1034 | 1038 | .basename = base.zcu_object_sub_path.?, |
| 1035 | 1039 | }, llvm_object, prog_node); |
src/link/C.zig+4-3| ... | ... | @@ -3,6 +3,7 @@ const mem = std.mem; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | 5 | const fs = std.fs; |
| 6 | const Path = std.Build.Cache.Path; | |
| 6 | 7 | |
| 7 | 8 | const C = @This(); |
| 8 | 9 | const build_options = @import("build_options"); |
| ... | ... | @@ -104,7 +105,7 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { |
| 104 | 105 | pub fn open( |
| 105 | 106 | arena: Allocator, |
| 106 | 107 | comp: *Compilation, |
| 107 | emit: Compilation.Emit, | |
| 108 | emit: Path, | |
| 108 | 109 | options: link.File.OpenOptions, |
| 109 | 110 | ) !*C { |
| 110 | 111 | return createEmpty(arena, comp, emit, options); |
| ... | ... | @@ -113,7 +114,7 @@ pub fn open( |
| 113 | 114 | pub fn createEmpty( |
| 114 | 115 | arena: Allocator, |
| 115 | 116 | comp: *Compilation, |
| 116 | emit: Compilation.Emit, | |
| 117 | emit: Path, | |
| 117 | 118 | options: link.File.OpenOptions, |
| 118 | 119 | ) !*C { |
| 119 | 120 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -127,7 +128,7 @@ pub fn createEmpty( |
| 127 | 128 | assert(!use_lld); |
| 128 | 129 | assert(!use_llvm); |
| 129 | 130 | |
| 130 | const file = try emit.directory.handle.createFile(emit.sub_path, .{ | |
| 131 | const file = try emit.root_dir.handle.createFile(emit.sub_path, .{ | |
| 131 | 132 | // Truncation is done on `flush`. |
| 132 | 133 | .truncate = false, |
| 133 | 134 | }); |
src/link/Coff.zig+4-3| ... | ... | @@ -219,7 +219,7 @@ pub const min_text_capacity = padToIdeal(minimum_text_block_size); |
| 219 | 219 | pub fn createEmpty( |
| 220 | 220 | arena: Allocator, |
| 221 | 221 | comp: *Compilation, |
| 222 | emit: Compilation.Emit, | |
| 222 | emit: Path, | |
| 223 | 223 | options: link.File.OpenOptions, |
| 224 | 224 | ) !*Coff { |
| 225 | 225 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -315,7 +315,7 @@ pub fn createEmpty( |
| 315 | 315 | // If using LLD to link, this code should produce an object file so that it |
| 316 | 316 | // can be passed to LLD. |
| 317 | 317 | const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; |
| 318 | self.base.file = try emit.directory.handle.createFile(sub_path, .{ | |
| 318 | self.base.file = try emit.root_dir.handle.createFile(sub_path, .{ | |
| 319 | 319 | .truncate = true, |
| 320 | 320 | .read = true, |
| 321 | 321 | .mode = link.File.determineMode(use_lld, output_mode, link_mode), |
| ... | ... | @@ -416,7 +416,7 @@ pub fn createEmpty( |
| 416 | 416 | pub fn open( |
| 417 | 417 | arena: Allocator, |
| 418 | 418 | comp: *Compilation, |
| 419 | emit: Compilation.Emit, | |
| 419 | emit: Path, | |
| 420 | 420 | options: link.File.OpenOptions, |
| 421 | 421 | ) !*Coff { |
| 422 | 422 | // TODO: restore saved linker state, don't truncate the file, and |
| ... | ... | @@ -2714,6 +2714,7 @@ const math = std.math; |
| 2714 | 2714 | const mem = std.mem; |
| 2715 | 2715 | |
| 2716 | 2716 | const Allocator = std.mem.Allocator; |
| 2717 | const Path = std.Build.Cache.Path; | |
| 2717 | 2718 | |
| 2718 | 2719 | const codegen = @import("../codegen.zig"); |
| 2719 | 2720 | const link = @import("../link.zig"); |
src/link/Coff/lld.zig+2-2| ... | ... | @@ -27,7 +27,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 27 | 27 | const comp = self.base.comp; |
| 28 | 28 | const gpa = comp.gpa; |
| 29 | 29 | |
| 30 | const directory = self.base.emit.directory; // Just an alias to make it shorter to type. | |
| 30 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 31 | 31 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 32 | 32 | |
| 33 | 33 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| ... | ... | @@ -248,7 +248,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 248 | 248 | try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); |
| 249 | 249 | |
| 250 | 250 | if (comp.implib_emit) |emit| { |
| 251 | const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path}); | |
| 251 | const implib_out_path = try emit.root_dir.join(arena, &[_][]const u8{emit.sub_path}); | |
| 252 | 252 | try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path})); |
| 253 | 253 | } |
| 254 | 254 |
src/link/Elf.zig+7-6| ... | ... | @@ -204,7 +204,7 @@ pub const SortSection = enum { name, alignment }; |
| 204 | 204 | pub fn createEmpty( |
| 205 | 205 | arena: Allocator, |
| 206 | 206 | comp: *Compilation, |
| 207 | emit: Compilation.Emit, | |
| 207 | emit: Path, | |
| 208 | 208 | options: link.File.OpenOptions, |
| 209 | 209 | ) !*Elf { |
| 210 | 210 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -321,7 +321,7 @@ pub fn createEmpty( |
| 321 | 321 | // If using LLD to link, this code should produce an object file so that it |
| 322 | 322 | // can be passed to LLD. |
| 323 | 323 | const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; |
| 324 | self.base.file = try emit.directory.handle.createFile(sub_path, .{ | |
| 324 | self.base.file = try emit.root_dir.handle.createFile(sub_path, .{ | |
| 325 | 325 | .truncate = true, |
| 326 | 326 | .read = true, |
| 327 | 327 | .mode = link.File.determineMode(use_lld, output_mode, link_mode), |
| ... | ... | @@ -401,7 +401,7 @@ pub fn createEmpty( |
| 401 | 401 | pub fn open( |
| 402 | 402 | arena: Allocator, |
| 403 | 403 | comp: *Compilation, |
| 404 | emit: Compilation.Emit, | |
| 404 | emit: Path, | |
| 405 | 405 | options: link.File.OpenOptions, |
| 406 | 406 | ) !*Elf { |
| 407 | 407 | // TODO: restore saved linker state, don't truncate the file, and |
| ... | ... | @@ -999,7 +999,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 999 | 999 | |
| 1000 | 1000 | const target = comp.root_mod.resolved_target.result; |
| 1001 | 1001 | const link_mode = comp.config.link_mode; |
| 1002 | const directory = self.base.emit.directory; // Just an alias to make it shorter to type. | |
| 1002 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 1003 | 1003 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 1004 | 1004 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| 1005 | 1005 | if (fs.path.dirname(full_out_path)) |dirname| { |
| ... | ... | @@ -1356,7 +1356,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1356 | 1356 | |
| 1357 | 1357 | const target = self.base.comp.root_mod.resolved_target.result; |
| 1358 | 1358 | const link_mode = self.base.comp.config.link_mode; |
| 1359 | const directory = self.base.emit.directory; // Just an alias to make it shorter to type. | |
| 1359 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 1360 | 1360 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 1361 | 1361 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| 1362 | 1362 | if (fs.path.dirname(full_out_path)) |dirname| { |
| ... | ... | @@ -2054,7 +2054,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2054 | 2054 | const comp = self.base.comp; |
| 2055 | 2055 | const gpa = comp.gpa; |
| 2056 | 2056 | |
| 2057 | const directory = self.base.emit.directory; // Just an alias to make it shorter to type. | |
| 2057 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 2058 | 2058 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 2059 | 2059 | |
| 2060 | 2060 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| ... | ... | @@ -6016,6 +6016,7 @@ const Allocator = std.mem.Allocator; |
| 6016 | 6016 | const Archive = @import("Elf/Archive.zig"); |
| 6017 | 6017 | pub const Atom = @import("Elf/Atom.zig"); |
| 6018 | 6018 | const Cache = std.Build.Cache; |
| 6019 | const Path = Cache.Path; | |
| 6019 | 6020 | const Compilation = @import("../Compilation.zig"); |
| 6020 | 6021 | const ComdatGroupSection = synthetic_sections.ComdatGroupSection; |
| 6021 | 6022 | const CopyRelSection = synthetic_sections.CopyRelSection; |
src/link/MachO.zig+9-8| ... | ... | @@ -156,7 +156,7 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void { |
| 156 | 156 | pub fn createEmpty( |
| 157 | 157 | arena: Allocator, |
| 158 | 158 | comp: *Compilation, |
| 159 | emit: Compilation.Emit, | |
| 159 | emit: Path, | |
| 160 | 160 | options: link.File.OpenOptions, |
| 161 | 161 | ) !*MachO { |
| 162 | 162 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -221,7 +221,7 @@ pub fn createEmpty( |
| 221 | 221 | } |
| 222 | 222 | errdefer self.base.destroy(); |
| 223 | 223 | |
| 224 | self.base.file = try emit.directory.handle.createFile(emit.sub_path, .{ | |
| 224 | self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ | |
| 225 | 225 | .truncate = true, |
| 226 | 226 | .read = true, |
| 227 | 227 | .mode = link.File.determineMode(false, output_mode, link_mode), |
| ... | ... | @@ -260,7 +260,7 @@ pub fn createEmpty( |
| 260 | 260 | pub fn open( |
| 261 | 261 | arena: Allocator, |
| 262 | 262 | comp: *Compilation, |
| 263 | emit: Compilation.Emit, | |
| 263 | emit: Path, | |
| 264 | 264 | options: link.File.OpenOptions, |
| 265 | 265 | ) !*MachO { |
| 266 | 266 | // TODO: restore saved linker state, don't truncate the file, and |
| ... | ... | @@ -353,7 +353,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 353 | 353 | const sub_prog_node = prog_node.start("MachO Flush", 0); |
| 354 | 354 | defer sub_prog_node.end(); |
| 355 | 355 | |
| 356 | const directory = self.base.emit.directory; | |
| 356 | const directory = self.base.emit.root_dir; | |
| 357 | 357 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 358 | 358 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| 359 | 359 | if (fs.path.dirname(full_out_path)) |dirname| { |
| ... | ... | @@ -586,7 +586,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n |
| 586 | 586 | if (codesig) |*csig| { |
| 587 | 587 | try self.writeCodeSignature(csig); // code signing always comes last |
| 588 | 588 | const emit = self.base.emit; |
| 589 | try invalidateKernelCache(emit.directory.handle, emit.sub_path); | |
| 589 | try invalidateKernelCache(emit.root_dir.handle, emit.sub_path); | |
| 590 | 590 | } |
| 591 | 591 | } |
| 592 | 592 | |
| ... | ... | @@ -597,7 +597,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 597 | 597 | defer arena_allocator.deinit(); |
| 598 | 598 | const arena = arena_allocator.allocator(); |
| 599 | 599 | |
| 600 | const directory = self.base.emit.directory; | |
| 600 | const directory = self.base.emit.root_dir; | |
| 601 | 601 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 602 | 602 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| 603 | 603 | if (fs.path.dirname(full_out_path)) |dirname| { |
| ... | ... | @@ -3199,7 +3199,7 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64 |
| 3199 | 3199 | } |
| 3200 | 3200 | |
| 3201 | 3201 | const InitMetadataOptions = struct { |
| 3202 | emit: Compilation.Emit, | |
| 3202 | emit: Path, | |
| 3203 | 3203 | zo: *ZigObject, |
| 3204 | 3204 | symbol_count_hint: u64, |
| 3205 | 3205 | program_code_size_hint: u64, |
| ... | ... | @@ -3271,7 +3271,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3271 | 3271 | ); |
| 3272 | 3272 | defer gpa.free(d_sym_path); |
| 3273 | 3273 | |
| 3274 | var d_sym_bundle = try options.emit.directory.handle.makeOpenPath(d_sym_path, .{}); | |
| 3274 | var d_sym_bundle = try options.emit.root_dir.handle.makeOpenPath(d_sym_path, .{}); | |
| 3275 | 3275 | defer d_sym_bundle.close(); |
| 3276 | 3276 | |
| 3277 | 3277 | const d_sym_file = try d_sym_bundle.createFile(options.emit.sub_path, .{ |
| ... | ... | @@ -4603,6 +4603,7 @@ pub const Atom = @import("MachO/Atom.zig"); |
| 4603 | 4603 | const AtomicBool = std.atomic.Value(bool); |
| 4604 | 4604 | const Bind = bind.Bind; |
| 4605 | 4605 | const Cache = std.Build.Cache; |
| 4606 | const Path = Cache.Path; | |
| 4606 | 4607 | const CodeSignature = @import("MachO/CodeSignature.zig"); |
| 4607 | 4608 | const Compilation = @import("../Compilation.zig"); |
| 4608 | 4609 | const DataInCode = synthetic.DataInCode; |
src/link/MachO/load_commands.zig+2-2| ... | ... | @@ -53,7 +53,7 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 |
| 53 | 53 | if (macho_file.base.isDynLib()) { |
| 54 | 54 | const emit = macho_file.base.emit; |
| 55 | 55 | const install_name = macho_file.install_name orelse |
| 56 | try emit.directory.join(gpa, &.{emit.sub_path}); | |
| 56 | try emit.root_dir.join(gpa, &.{emit.sub_path}); | |
| 57 | 57 | defer if (macho_file.install_name == null) gpa.free(install_name); |
| 58 | 58 | sizeofcmds += calcInstallNameLen( |
| 59 | 59 | @sizeOf(macho.dylib_command), |
| ... | ... | @@ -237,7 +237,7 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { |
| 237 | 237 | assert(comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); |
| 238 | 238 | const emit = macho_file.base.emit; |
| 239 | 239 | const install_name = macho_file.install_name orelse |
| 240 | try emit.directory.join(gpa, &.{emit.sub_path}); | |
| 240 | try emit.root_dir.join(gpa, &.{emit.sub_path}); | |
| 241 | 241 | defer if (macho_file.install_name == null) gpa.free(install_name); |
| 242 | 242 | const curr = comp.version orelse std.SemanticVersion{ |
| 243 | 243 | .major = 1, |
src/link/NvPtx.zig+3-2| ... | ... | @@ -11,6 +11,7 @@ const builtin = @import("builtin"); |
| 11 | 11 | const Allocator = std.mem.Allocator; |
| 12 | 12 | const assert = std.debug.assert; |
| 13 | 13 | const log = std.log.scoped(.link); |
| 14 | const Path = std.Build.Cache.Path; | |
| 14 | 15 | |
| 15 | 16 | const Zcu = @import("../Zcu.zig"); |
| 16 | 17 | const InternPool = @import("../InternPool.zig"); |
| ... | ... | @@ -28,7 +29,7 @@ llvm_object: LlvmObject.Ptr, |
| 28 | 29 | pub fn createEmpty( |
| 29 | 30 | arena: Allocator, |
| 30 | 31 | comp: *Compilation, |
| 31 | emit: Compilation.Emit, | |
| 32 | emit: Path, | |
| 32 | 33 | options: link.File.OpenOptions, |
| 33 | 34 | ) !*NvPtx { |
| 34 | 35 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -70,7 +71,7 @@ pub fn createEmpty( |
| 70 | 71 | pub fn open( |
| 71 | 72 | arena: Allocator, |
| 72 | 73 | comp: *Compilation, |
| 73 | emit: Compilation.Emit, | |
| 74 | emit: Path, | |
| 74 | 75 | options: link.File.OpenOptions, |
| 75 | 76 | ) !*NvPtx { |
| 76 | 77 | const target = comp.root_mod.resolved_target.result; |
src/link/Plan9.zig+4-3| ... | ... | @@ -23,6 +23,7 @@ const mem = std.mem; |
| 23 | 23 | const Allocator = std.mem.Allocator; |
| 24 | 24 | const log = std.log.scoped(.link); |
| 25 | 25 | const assert = std.debug.assert; |
| 26 | const Path = std.Build.Cache.Path; | |
| 26 | 27 | |
| 27 | 28 | base: link.File, |
| 28 | 29 | sixtyfour_bit: bool, |
| ... | ... | @@ -275,7 +276,7 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { |
| 275 | 276 | pub fn createEmpty( |
| 276 | 277 | arena: Allocator, |
| 277 | 278 | comp: *Compilation, |
| 278 | emit: Compilation.Emit, | |
| 279 | emit: Path, | |
| 279 | 280 | options: link.File.OpenOptions, |
| 280 | 281 | ) !*Plan9 { |
| 281 | 282 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -1199,7 +1200,7 @@ pub fn deinit(self: *Plan9) void { |
| 1199 | 1200 | pub fn open( |
| 1200 | 1201 | arena: Allocator, |
| 1201 | 1202 | comp: *Compilation, |
| 1202 | emit: Compilation.Emit, | |
| 1203 | emit: Path, | |
| 1203 | 1204 | options: link.File.OpenOptions, |
| 1204 | 1205 | ) !*Plan9 { |
| 1205 | 1206 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -1213,7 +1214,7 @@ pub fn open( |
| 1213 | 1214 | const self = try createEmpty(arena, comp, emit, options); |
| 1214 | 1215 | errdefer self.base.destroy(); |
| 1215 | 1216 | |
| 1216 | const file = try emit.directory.handle.createFile(emit.sub_path, .{ | |
| 1217 | const file = try emit.root_dir.handle.createFile(emit.sub_path, .{ | |
| 1217 | 1218 | .read = true, |
| 1218 | 1219 | .mode = link.File.determineMode( |
| 1219 | 1220 | use_lld, |
src/link/SpirV.zig+4-3| ... | ... | @@ -26,6 +26,7 @@ const std = @import("std"); |
| 26 | 26 | const Allocator = std.mem.Allocator; |
| 27 | 27 | const assert = std.debug.assert; |
| 28 | 28 | const log = std.log.scoped(.link); |
| 29 | const Path = std.Build.Cache.Path; | |
| 29 | 30 | |
| 30 | 31 | const Zcu = @import("../Zcu.zig"); |
| 31 | 32 | const InternPool = @import("../InternPool.zig"); |
| ... | ... | @@ -54,7 +55,7 @@ object: codegen.Object, |
| 54 | 55 | pub fn createEmpty( |
| 55 | 56 | arena: Allocator, |
| 56 | 57 | comp: *Compilation, |
| 57 | emit: Compilation.Emit, | |
| 58 | emit: Path, | |
| 58 | 59 | options: link.File.OpenOptions, |
| 59 | 60 | ) !*SpirV { |
| 60 | 61 | const gpa = comp.gpa; |
| ... | ... | @@ -95,7 +96,7 @@ pub fn createEmpty( |
| 95 | 96 | pub fn open( |
| 96 | 97 | arena: Allocator, |
| 97 | 98 | comp: *Compilation, |
| 98 | emit: Compilation.Emit, | |
| 99 | emit: Path, | |
| 99 | 100 | options: link.File.OpenOptions, |
| 100 | 101 | ) !*SpirV { |
| 101 | 102 | const target = comp.root_mod.resolved_target.result; |
| ... | ... | @@ -110,7 +111,7 @@ pub fn open( |
| 110 | 111 | errdefer spirv.base.destroy(); |
| 111 | 112 | |
| 112 | 113 | // TODO: read the file and keep valid parts instead of truncating |
| 113 | const file = try emit.directory.handle.createFile(emit.sub_path, .{ | |
| 114 | const file = try emit.root_dir.handle.createFile(emit.sub_path, .{ | |
| 114 | 115 | .truncate = true, |
| 115 | 116 | .read = true, |
| 116 | 117 | }); |
src/link/Wasm.zig+6-5| ... | ... | @@ -22,6 +22,7 @@ const Air = @import("../Air.zig"); |
| 22 | 22 | const Allocator = std.mem.Allocator; |
| 23 | 23 | const Archive = @import("Wasm/Archive.zig"); |
| 24 | 24 | const Cache = std.Build.Cache; |
| 25 | const Path = Cache.Path; | |
| 25 | 26 | const CodeGen = @import("../arch/wasm/CodeGen.zig"); |
| 26 | 27 | const Compilation = @import("../Compilation.zig"); |
| 27 | 28 | const Dwarf = @import("Dwarf.zig"); |
| ... | ... | @@ -346,7 +347,7 @@ pub const StringTable = struct { |
| 346 | 347 | pub fn open( |
| 347 | 348 | arena: Allocator, |
| 348 | 349 | comp: *Compilation, |
| 349 | emit: Compilation.Emit, | |
| 350 | emit: Path, | |
| 350 | 351 | options: link.File.OpenOptions, |
| 351 | 352 | ) !*Wasm { |
| 352 | 353 | // TODO: restore saved linker state, don't truncate the file, and |
| ... | ... | @@ -357,7 +358,7 @@ pub fn open( |
| 357 | 358 | pub fn createEmpty( |
| 358 | 359 | arena: Allocator, |
| 359 | 360 | comp: *Compilation, |
| 360 | emit: Compilation.Emit, | |
| 361 | emit: Path, | |
| 361 | 362 | options: link.File.OpenOptions, |
| 362 | 363 | ) !*Wasm { |
| 363 | 364 | const gpa = comp.gpa; |
| ... | ... | @@ -430,7 +431,7 @@ pub fn createEmpty( |
| 430 | 431 | // can be passed to LLD. |
| 431 | 432 | const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path; |
| 432 | 433 | |
| 433 | wasm.base.file = try emit.directory.handle.createFile(sub_path, .{ | |
| 434 | wasm.base.file = try emit.root_dir.handle.createFile(sub_path, .{ | |
| 434 | 435 | .truncate = true, |
| 435 | 436 | .read = true, |
| 436 | 437 | .mode = if (fs.has_executable_bit) |
| ... | ... | @@ -2496,7 +2497,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no |
| 2496 | 2497 | const sub_prog_node = prog_node.start("Wasm Flush", 0); |
| 2497 | 2498 | defer sub_prog_node.end(); |
| 2498 | 2499 | |
| 2499 | const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. | |
| 2500 | const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 2500 | 2501 | const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); |
| 2501 | 2502 | const module_obj_path: ?[]const u8 = if (wasm.base.zcu_object_sub_path) |path| blk: { |
| 2502 | 2503 | if (fs.path.dirname(full_out_path)) |dirname| { |
| ... | ... | @@ -3346,7 +3347,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: |
| 3346 | 3347 | |
| 3347 | 3348 | const gpa = comp.gpa; |
| 3348 | 3349 | |
| 3349 | const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. | |
| 3350 | const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type. | |
| 3350 | 3351 | const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); |
| 3351 | 3352 | |
| 3352 | 3353 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
src/main.zig+18-68| ... | ... | @@ -3519,7 +3519,7 @@ fn buildOutputType( |
| 3519 | 3519 | if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: { |
| 3520 | 3520 | // Default to using `zig run` to execute the produced .c code from `zig test`. |
| 3521 | 3521 | const c_code_loc = emit_bin_loc orelse break :default_exec_args; |
| 3522 | const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.directory; | |
| 3522 | const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.root_dir; | |
| 3523 | 3523 | const c_code_path = try fs.path.join(arena, &[_][]const u8{ |
| 3524 | 3524 | c_code_directory.path orelse ".", c_code_loc.basename, |
| 3525 | 3525 | }); |
| ... | ... | @@ -4142,7 +4142,7 @@ fn serve( |
| 4142 | 4142 | if (output.errors.errorMessageCount() != 0) { |
| 4143 | 4143 | try server.serveErrorBundle(output.errors); |
| 4144 | 4144 | } else { |
| 4145 | try server.serveEmitBinPath(output.out_zig_path, .{ | |
| 4145 | try server.serveEmitDigest(&output.digest, .{ | |
| 4146 | 4146 | .flags = .{ .cache_hit = output.cache_hit }, |
| 4147 | 4147 | }); |
| 4148 | 4148 | } |
| ... | ... | @@ -4229,62 +4229,10 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void { |
| 4229 | 4229 | return; |
| 4230 | 4230 | } |
| 4231 | 4231 | |
| 4232 | // This logic is counter-intuitive because the protocol accounts for each | |
| 4233 | // emitted artifact possibly being in a different location, which correctly | |
| 4234 | // matches the behavior of the compiler, however, the build system | |
| 4235 | // currently always passes flags that makes all build artifacts output to | |
| 4236 | // the same local cache directory, and relies on them all being in the same | |
| 4237 | // directory. | |
| 4238 | // | |
| 4239 | // So, until the build system and protocol are changed to reflect this, | |
| 4240 | // this logic must ensure that emit_bin_path is emitted for at least one | |
| 4241 | // thing, if there are any artifacts. | |
| 4242 | ||
| 4243 | switch (comp.cache_use) { | |
| 4244 | .incremental => if (comp.bin_file) |lf| { | |
| 4245 | const full_path = try lf.emit.directory.join(gpa, &.{lf.emit.sub_path}); | |
| 4246 | defer gpa.free(full_path); | |
| 4247 | try s.serveEmitBinPath(full_path, .{ | |
| 4248 | .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, | |
| 4249 | }); | |
| 4250 | return; | |
| 4251 | }, | |
| 4252 | .whole => |whole| if (whole.bin_sub_path) |sub_path| { | |
| 4253 | const full_path = try comp.local_cache_directory.join(gpa, &.{sub_path}); | |
| 4254 | defer gpa.free(full_path); | |
| 4255 | try s.serveEmitBinPath(full_path, .{ | |
| 4256 | .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, | |
| 4257 | }); | |
| 4258 | return; | |
| 4259 | }, | |
| 4260 | } | |
| 4261 | ||
| 4262 | for ([_]?Compilation.Emit{ | |
| 4263 | comp.docs_emit, | |
| 4264 | comp.implib_emit, | |
| 4265 | }) |opt_emit| { | |
| 4266 | const emit = opt_emit orelse continue; | |
| 4267 | const full_path = try emit.directory.join(gpa, &.{emit.sub_path}); | |
| 4268 | defer gpa.free(full_path); | |
| 4269 | try s.serveEmitBinPath(full_path, .{ | |
| 4232 | if (comp.digest) |digest| { | |
| 4233 | try s.serveEmitDigest(&digest, .{ | |
| 4270 | 4234 | .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, |
| 4271 | 4235 | }); |
| 4272 | return; | |
| 4273 | } | |
| 4274 | ||
| 4275 | for ([_]?Compilation.EmitLoc{ | |
| 4276 | comp.emit_asm, | |
| 4277 | comp.emit_llvm_ir, | |
| 4278 | comp.emit_llvm_bc, | |
| 4279 | }) |opt_emit_loc| { | |
| 4280 | const emit_loc = opt_emit_loc orelse continue; | |
| 4281 | const directory = emit_loc.directory orelse continue; | |
| 4282 | const full_path = try directory.join(gpa, &.{emit_loc.basename}); | |
| 4283 | defer gpa.free(full_path); | |
| 4284 | try s.serveEmitBinPath(full_path, .{ | |
| 4285 | .flags = .{ .cache_hit = comp.last_update_was_cache_hit }, | |
| 4286 | }); | |
| 4287 | return; | |
| 4288 | 4236 | } |
| 4289 | 4237 | |
| 4290 | 4238 | // Serve empty error bundle to indicate the update is done. |
| ... | ... | @@ -4308,7 +4256,7 @@ fn runOrTest( |
| 4308 | 4256 | // A naive `directory.join` here will indeed get the correct path to the binary, |
| 4309 | 4257 | // however, in the case of cwd, we actually want `./foo` so that the path can be executed. |
| 4310 | 4258 | const exe_path = try fs.path.join(arena, &[_][]const u8{ |
| 4311 | lf.emit.directory.path orelse ".", lf.emit.sub_path, | |
| 4259 | lf.emit.root_dir.path orelse ".", lf.emit.sub_path, | |
| 4312 | 4260 | }); |
| 4313 | 4261 | |
| 4314 | 4262 | var argv = std.ArrayList([]const u8).init(gpa); |
| ... | ... | @@ -4420,7 +4368,7 @@ fn runOrTestHotSwap( |
| 4420 | 4368 | // tmp zig-cache and use it to spawn the child process. This way we are free to update |
| 4421 | 4369 | // the binary with each requested hot update. |
| 4422 | 4370 | .windows => blk: { |
| 4423 | try lf.emit.directory.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{}); | |
| 4371 | try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{}); | |
| 4424 | 4372 | break :blk try fs.path.join(gpa, &[_][]const u8{ |
| 4425 | 4373 | comp.local_cache_directory.path orelse ".", lf.emit.sub_path, |
| 4426 | 4374 | }); |
| ... | ... | @@ -4429,7 +4377,7 @@ fn runOrTestHotSwap( |
| 4429 | 4377 | // A naive `directory.join` here will indeed get the correct path to the binary, |
| 4430 | 4378 | // however, in the case of cwd, we actually want `./foo` so that the path can be executed. |
| 4431 | 4379 | else => try fs.path.join(gpa, &[_][]const u8{ |
| 4432 | lf.emit.directory.path orelse ".", lf.emit.sub_path, | |
| 4380 | lf.emit.root_dir.path orelse ".", lf.emit.sub_path, | |
| 4433 | 4381 | }), |
| 4434 | 4382 | }; |
| 4435 | 4383 | defer gpa.free(exe_path); |
| ... | ... | @@ -4539,9 +4487,11 @@ fn cmdTranslateC( |
| 4539 | 4487 | }; |
| 4540 | 4488 | |
| 4541 | 4489 | if (fancy_output) |p| p.cache_hit = true; |
| 4542 | const digest = if (try man.hit()) digest: { | |
| 4490 | const bin_digest, const hex_digest = if (try man.hit()) digest: { | |
| 4543 | 4491 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| 4544 | break :digest man.final(); | |
| 4492 | const bin_digest = man.finalBin(); | |
| 4493 | const hex_digest = Cache.binToHex(bin_digest); | |
| 4494 | break :digest .{ bin_digest, hex_digest }; | |
| 4545 | 4495 | } else digest: { |
| 4546 | 4496 | if (fancy_output) |p| p.cache_hit = false; |
| 4547 | 4497 | var argv = std.ArrayList([]const u8).init(arena); |
| ... | ... | @@ -4639,8 +4589,10 @@ fn cmdTranslateC( |
| 4639 | 4589 | }; |
| 4640 | 4590 | } |
| 4641 | 4591 | |
| 4642 | const digest = man.final(); | |
| 4643 | const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest }); | |
| 4592 | const bin_digest = man.finalBin(); | |
| 4593 | const hex_digest = Cache.binToHex(bin_digest); | |
| 4594 | ||
| 4595 | const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest }); | |
| 4644 | 4596 | |
| 4645 | 4597 | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); |
| 4646 | 4598 | defer o_dir.close(); |
| ... | ... | @@ -4656,16 +4608,14 @@ fn cmdTranslateC( |
| 4656 | 4608 | |
| 4657 | 4609 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| 4658 | 4610 | |
| 4659 | break :digest digest; | |
| 4611 | break :digest .{ bin_digest, hex_digest }; | |
| 4660 | 4612 | }; |
| 4661 | 4613 | |
| 4662 | 4614 | if (fancy_output) |p| { |
| 4663 | p.out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ | |
| 4664 | "o", &digest, translated_zig_basename, | |
| 4665 | }); | |
| 4615 | p.digest = bin_digest; | |
| 4666 | 4616 | p.errors = std.zig.ErrorBundle.empty; |
| 4667 | 4617 | } else { |
| 4668 | const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename }); | |
| 4618 | const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest, translated_zig_basename }); | |
| 4669 | 4619 | const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| { |
| 4670 | 4620 | const path = comp.local_cache_directory.path orelse "."; |
| 4671 | 4621 | fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) }); |
test/standalone/build.zig.zon+9-8| ... | ... | @@ -51,14 +51,15 @@ |
| 51 | 51 | .install_raw_hex = .{ |
| 52 | 52 | .path = "install_raw_hex", |
| 53 | 53 | }, |
| 54 | // https://github.com/ziglang/zig/issues/17484 | |
| 55 | //.emit_asm_and_bin = .{ | |
| 56 | // .path = "emit_asm_and_bin", | |
| 57 | //}, | |
| 58 | // https://github.com/ziglang/zig/issues/17484 | |
| 59 | //.issue_12588 = .{ | |
| 60 | // .path = "issue_12588", | |
| 61 | //}, | |
| 54 | .emit_asm_and_bin = .{ | |
| 55 | .path = "emit_asm_and_bin", | |
| 56 | }, | |
| 57 | .emit_llvm_no_bin = .{ | |
| 58 | .path = "emit_llvm_no_bin", | |
| 59 | }, | |
| 60 | .emit_asm_no_bin = .{ | |
| 61 | .path = "emit_asm_no_bin", | |
| 62 | }, | |
| 62 | 63 | .child_process = .{ |
| 63 | 64 | .path = "child_process", |
| 64 | 65 | }, |
test/standalone/emit_asm_no_bin/build.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn build(b: *std.Build) void { | |
| 4 | const test_step = b.step("test", "Test it"); | |
| 5 | b.default_step = test_step; | |
| 6 | ||
| 7 | const optimize: std.builtin.OptimizeMode = .Debug; | |
| 8 | ||
| 9 | const obj = b.addObject(.{ | |
| 10 | .name = "main", | |
| 11 | .root_source_file = b.path("main.zig"), | |
| 12 | .optimize = optimize, | |
| 13 | .target = b.graph.host, | |
| 14 | }); | |
| 15 | _ = obj.getEmittedAsm(); | |
| 16 | b.default_step.dependOn(&obj.step); | |
| 17 | ||
| 18 | test_step.dependOn(&obj.step); | |
| 19 | } |
test/standalone/emit_asm_no_bin/main.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | pub fn main() void {} |
test/standalone/emit_llvm_no_bin/build.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn build(b: *std.Build) void { | |
| 4 | const test_step = b.step("test", "Test it"); | |
| 5 | b.default_step = test_step; | |
| 6 | ||
| 7 | const optimize: std.builtin.OptimizeMode = .Debug; | |
| 8 | ||
| 9 | const obj = b.addObject(.{ | |
| 10 | .name = "main", | |
| 11 | .root_source_file = b.path("main.zig"), | |
| 12 | .optimize = optimize, | |
| 13 | .target = b.graph.host, | |
| 14 | }); | |
| 15 | _ = obj.getEmittedLlvmIr(); | |
| 16 | _ = obj.getEmittedLlvmBc(); | |
| 17 | b.default_step.dependOn(&obj.step); | |
| 18 | ||
| 19 | test_step.dependOn(&obj.step); | |
| 20 | } |
test/standalone/emit_llvm_no_bin/main.zig created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | export fn strFromFloatHelp(float: f64) void { | |
| 4 | var buf: [400]u8 = undefined; | |
| 5 | _ = std.fmt.bufPrint(&buf, "{d}", .{float}) catch unreachable; | |
| 6 | } |
test/standalone/issue_12588/build.zig deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn build(b: *std.Build) void { | |
| 4 | const test_step = b.step("test", "Test it"); | |
| 5 | b.default_step = test_step; | |
| 6 | ||
| 7 | const optimize: std.builtin.OptimizeMode = .Debug; | |
| 8 | ||
| 9 | const obj = b.addObject(.{ | |
| 10 | .name = "main", | |
| 11 | .root_source_file = b.path("main.zig"), | |
| 12 | .optimize = optimize, | |
| 13 | .target = b.graph.host, | |
| 14 | }); | |
| 15 | _ = obj.getEmittedLlvmIr(); | |
| 16 | _ = obj.getEmittedLlvmBc(); | |
| 17 | b.default_step.dependOn(&obj.step); | |
| 18 | ||
| 19 | test_step.dependOn(&obj.step); | |
| 20 | } |
test/standalone/issue_12588/main.zig deleted-6| ... | ... | @@ -1,6 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | export fn strFromFloatHelp(float: f64) void { | |
| 4 | var buf: [400]u8 = undefined; | |
| 5 | _ = std.fmt.bufPrint(&buf, "{d}", .{float}) catch unreachable; | |
| 6 | } |
tools/incr-check.zig+33-10| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const fatal = std.process.fatal; |
| 3 | 3 | const Allocator = std.mem.Allocator; |
| 4 | const Cache = std.Build.Cache; | |
| 4 | 5 | |
| 5 | 6 | const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--emit none|bin|c] [--zig-cc-binary /path/to/zig]"; |
| 6 | 7 | |
| ... | ... | @@ -233,30 +234,52 @@ const Eval = struct { |
| 233 | 234 | fatal("error_bundle included unexpected stderr:\n{s}", .{stderr_data}); |
| 234 | 235 | } |
| 235 | 236 | } |
| 236 | if (result_error_bundle.errorMessageCount() == 0) { | |
| 237 | // Empty bundle indicates successful update in a `-fno-emit-bin` build. | |
| 238 | try eval.checkSuccessOutcome(update, null, prog_node); | |
| 239 | } else { | |
| 237 | if (result_error_bundle.errorMessageCount() != 0) { | |
| 240 | 238 | try eval.checkErrorOutcome(update, result_error_bundle); |
| 241 | 239 | } |
| 242 | 240 | // This message indicates the end of the update. |
| 243 | 241 | stdout.discard(body.len); |
| 244 | 242 | return; |
| 245 | 243 | }, |
| 246 | .emit_bin_path => { | |
| 247 | const EbpHdr = std.zig.Server.Message.EmitBinPath; | |
| 244 | .emit_digest => { | |
| 245 | const EbpHdr = std.zig.Server.Message.EmitDigest; | |
| 248 | 246 | const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body)); |
| 249 | 247 | _ = ebp_hdr; |
| 250 | const result_binary = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]); | |
| 251 | 248 | if (stderr.readableLength() > 0) { |
| 252 | 249 | const stderr_data = try stderr.toOwnedSlice(); |
| 253 | 250 | if (eval.allow_stderr) { |
| 254 | std.log.info("emit_bin_path included stderr:\n{s}", .{stderr_data}); | |
| 251 | std.log.info("emit_digest included stderr:\n{s}", .{stderr_data}); | |
| 255 | 252 | } else { |
| 256 | fatal("emit_bin_path included unexpected stderr:\n{s}", .{stderr_data}); | |
| 253 | fatal("emit_digest included unexpected stderr:\n{s}", .{stderr_data}); | |
| 257 | 254 | } |
| 258 | 255 | } |
| 259 | try eval.checkSuccessOutcome(update, result_binary, prog_node); | |
| 256 | ||
| 257 | if (eval.emit == .none) { | |
| 258 | try eval.checkSuccessOutcome(update, null, prog_node); | |
| 259 | // This message indicates the end of the update. | |
| 260 | stdout.discard(body.len); | |
| 261 | return; | |
| 262 | } | |
| 263 | ||
| 264 | const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len]; | |
| 265 | const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*); | |
| 266 | ||
| 267 | const name = std.fs.path.stem(std.fs.path.basename(eval.case.root_source_file)); | |
| 268 | const bin_name = try std.zig.binNameAlloc(arena, .{ | |
| 269 | .root_name = name, | |
| 270 | .target = try std.zig.system.resolveTargetQuery(try std.Build.parseTargetQuery(.{ | |
| 271 | .arch_os_abi = eval.case.target_query, | |
| 272 | .object_format = switch (eval.emit) { | |
| 273 | .none => unreachable, | |
| 274 | .bin => null, | |
| 275 | .c => "c", | |
| 276 | }, | |
| 277 | })), | |
| 278 | .output_mode = .Exe, | |
| 279 | }); | |
| 280 | const bin_path = try std.fs.path.join(arena, &.{ result_dir, bin_name }); | |
| 281 | ||
| 282 | try eval.checkSuccessOutcome(update, bin_path, prog_node); | |
| 260 | 283 | // This message indicates the end of the update. |
| 261 | 284 | stdout.discard(body.len); |
| 262 | 285 | return; |