| ... | @@ -2498,6 +2498,7 @@ fn updateStage1Module(comp: *Compilation) !void { | ... | @@ -2498,6 +2498,7 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2498 | const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"}); | 2498 | const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"}); |
| 2499 | const target = comp.getTarget(); | 2499 | const target = comp.getTarget(); |
| 2500 | const id_symlink_basename = "stage1.id"; | 2500 | const id_symlink_basename = "stage1.id"; |
| | 2501 | const libs_txt_basename = "libs.txt"; |
| 2501 | | 2502 | |
| 2502 | // We are about to obtain this lock, so here we give other processes a chance first. | 2503 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 2503 | comp.releaseStage1Lock(); | 2504 | comp.releaseStage1Lock(); |
| ... | @@ -2538,18 +2539,32 @@ fn updateStage1Module(comp: *Compilation) !void { | ... | @@ -2538,18 +2539,32 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2538 | // Handle this as a cache miss. | 2539 | // Handle this as a cache miss. |
| 2539 | break :blk prev_digest_buf[0..0]; | 2540 | break :blk prev_digest_buf[0..0]; |
| 2540 | }; | 2541 | }; |
| 2541 | if (prev_digest.len >= digest.len + 2) { | 2542 | if (prev_digest.len >= digest.len + 2) hit: { |
| 2542 | if (mem.eql(u8, prev_digest[0..digest.len], &digest)) { | 2543 | if (!mem.eql(u8, prev_digest[0..digest.len], &digest)) |
| 2543 | log.debug("stage1 {} digest={} match - skipping invocation", .{ mod.root_pkg.root_src_path, digest }); | 2544 | break :hit; |
| 2544 | var flags_bytes: [1]u8 = undefined; | 2545 | |
| 2545 | if (std.fmt.hexToBytes(&flags_bytes, prev_digest[digest.len..])) |_| { | 2546 | log.debug("stage1 {} digest={} match - skipping invocation", .{ mod.root_pkg.root_src_path, digest }); |
| 2546 | comp.stage1_lock = man.toOwnedLock(); | 2547 | var flags_bytes: [1]u8 = undefined; |
| 2547 | mod.stage1_flags = @bitCast(@TypeOf(mod.stage1_flags), flags_bytes[0]); | 2548 | _ = std.fmt.hexToBytes(&flags_bytes, prev_digest[digest.len..]) catch { |
| 2548 | return; | 2549 | log.warn("bad cache stage1 digest: '{s}'", .{prev_digest}); |
| 2549 | } else |err| { | 2550 | break :hit; |
| 2550 | log.warn("bad cache stage1 digest: '{s}'", .{prev_digest}); | 2551 | }; |
| | 2552 | |
| | 2553 | if (directory.handle.readFileAlloc(comp.gpa, libs_txt_basename, 10 * 1024 * 1024)) |libs_txt| { |
| | 2554 | var it = mem.tokenize(libs_txt, "\n"); |
| | 2555 | while (it.next()) |lib_name| { |
| | 2556 | try comp.stage1AddLinkLib(lib_name); |
| 2551 | } | 2557 | } |
| | 2558 | } else |err| switch (err) { |
| | 2559 | error.FileNotFound => {}, // That's OK, it just means 0 libs. |
| | 2560 | else => { |
| | 2561 | log.warn("unable to read cached list of link libs: {s}", .{@errorName(err)}); |
| | 2562 | break :hit; |
| | 2563 | }, |
| 2552 | } | 2564 | } |
| | 2565 | comp.stage1_lock = man.toOwnedLock(); |
| | 2566 | mod.stage1_flags = @bitCast(@TypeOf(mod.stage1_flags), flags_bytes[0]); |
| | 2567 | return; |
| 2553 | } | 2568 | } |
| 2554 | log.debug("stage1 {} prev_digest={} new_digest={}", .{ mod.root_pkg.root_src_path, prev_digest, digest }); | 2569 | log.debug("stage1 {} prev_digest={} new_digest={}", .{ mod.root_pkg.root_src_path, prev_digest, digest }); |
| 2555 | man.unhit(prev_hash_state, input_file_count); | 2570 | man.unhit(prev_hash_state, input_file_count); |
| ... | @@ -2668,8 +2683,20 @@ fn updateStage1Module(comp: *Compilation) !void { | ... | @@ -2668,8 +2683,20 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2668 | .have_wwinmain_crt_startup = false, | 2683 | .have_wwinmain_crt_startup = false, |
| 2669 | .have_dllmain_crt_startup = false, | 2684 | .have_dllmain_crt_startup = false, |
| 2670 | }; | 2685 | }; |
| | 2686 | |
| | 2687 | const inferred_lib_start_index = comp.bin_file.options.system_libs.count(); |
| 2671 | stage1_module.build_object(); | 2688 | stage1_module.build_object(); |
| 2672 | | 2689 | |
| | 2690 | if (comp.bin_file.options.system_libs.count() > inferred_lib_start_index) { |
| | 2691 | // We need to save the inferred link libs to the cache, otherwise if we get a cache hit |
| | 2692 | // next time we will be missing these libs. |
| | 2693 | var libs_txt = std.ArrayList(u8).init(arena); |
| | 2694 | for (comp.bin_file.options.system_libs.items()[inferred_lib_start_index..]) |entry| { |
| | 2695 | try libs_txt.writer().print("{s}\n", .{entry.key}); |
| | 2696 | } |
| | 2697 | try directory.handle.writeFile(libs_txt_basename, libs_txt.items); |
| | 2698 | } |
| | 2699 | |
| 2673 | mod.stage1_flags = .{ | 2700 | mod.stage1_flags = .{ |
| 2674 | .have_c_main = stage1_module.have_c_main, | 2701 | .have_c_main = stage1_module.have_c_main, |
| 2675 | .have_winmain = stage1_module.have_winmain, | 2702 | .have_winmain = stage1_module.have_winmain, |
| ... | @@ -2814,3 +2841,15 @@ pub fn build_crt_file( | ... | @@ -2814,3 +2841,15 @@ pub fn build_crt_file( |
| 2814 | .lock = sub_compilation.bin_file.toOwnedLock(), | 2841 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 2815 | }); | 2842 | }); |
| 2816 | } | 2843 | } |
| | 2844 | |
| | 2845 | pub fn stage1AddLinkLib(comp: *Compilation, lib_name: []const u8) !void { |
| | 2846 | // This happens when an `extern "foo"` function is referenced by the stage1 backend. |
| | 2847 | // If we haven't seen this library yet and we're targeting Windows, we need to queue up |
| | 2848 | // a work item to produce the DLL import library for this. |
| | 2849 | const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name); |
| | 2850 | if (!gop.found_existing and comp.getTarget().os.tag == .windows) { |
| | 2851 | try comp.work_queue.writeItem(.{ |
| | 2852 | .windows_import_lib = comp.bin_file.options.system_libs.count() - 1, |
| | 2853 | }); |
| | 2854 | } |
| | 2855 | } |