diff options
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 95 |
1 files changed, 49 insertions, 46 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index fab0496b22..5a1c54aa9e 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -39,6 +39,8 @@ const Air = @import("Air.zig"); const Builtin = @import("Builtin.zig"); const LlvmObject = @import("codegen/llvm.zig").Object; const dev = @import("dev.zig"); +pub const Directory = Cache.Directory; +const Path = Cache.Path; pub const Config = @import("Compilation/Config.zig"); @@ -269,6 +271,11 @@ llvm_opt_bisect_limit: c_int, file_system_inputs: ?*std.ArrayListUnmanaged(u8), +/// This is the digest of the cache for the current compilation. +/// This digest will be known after update() is called. +digest: ?[Cache.bin_digest_len]u8 = null, + +/// TODO(robin): Remove because it is the same as Cache.Path pub const Emit = struct { /// Where the output will go. directory: Directory, @@ -868,8 +875,6 @@ pub const LldError = struct { } }; -pub const Directory = Cache.Directory; - pub const EmitLoc = struct { /// If this is `null` it means the file will be output to the cache directory. /// When provided, both the open file handle and the path name must outlive the `Compilation`. @@ -1672,7 +1677,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil // In the case of incremental cache mode, this `artifact_directory` // is computed based on a hash of non-linker inputs, and it is where all // build artifacts are stored (even while in-progress). + comp.digest = hash.peekBin(); const digest = hash.final(); + const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest; var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{}); errdefer artifact_dir.close(); @@ -2121,9 +2128,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { comp.last_update_was_cache_hit = true; log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name}); - const digest = man.final(); + const bin_digest = man.finalBin(); + const hex_digest = Cache.binToHex(bin_digest); - comp.wholeCacheModeSetBinFilePath(whole, &digest); + comp.digest = bin_digest; + comp.wholeCacheModeSetBinFilePath(whole, &hex_digest); assert(whole.lock == null); whole.lock = man.toOwnedLock(); @@ -2329,7 +2338,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); } - const digest = man.final(); + const bin_digest = man.finalBin(); + const hex_digest = Cache.binToHex(bin_digest); // Rename the temporary directory into place. // Close tmp dir and link.File to avoid open handle during rename. @@ -2341,7 +2351,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { const s = std.fs.path.sep_str; const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); - const o_sub_path = "o" ++ s ++ digest; + const o_sub_path = "o" ++ s ++ hex_digest; // Work around windows `AccessDenied` if any files within this // directory are open by closing and reopening the file handles. @@ -2376,7 +2386,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { }, ); }; - comp.wholeCacheModeSetBinFilePath(whole, &digest); + comp.digest = bin_digest; + comp.wholeCacheModeSetBinFilePath(whole, &hex_digest); // The linker flush functions need to know the final output path // for debug info purposes because executable debug info contains @@ -2393,9 +2404,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { } } - try flush(comp, arena, .main, main_progress_node); - - if (try comp.totalErrorCount() != 0) return; + try flush(comp, arena, .{ + .root_dir = comp.local_cache_directory, + .sub_path = o_sub_path, + }, .main, main_progress_node); // Failure here only means an unnecessary cache miss. man.writeManifest() catch |err| { @@ -2410,8 +2422,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { assert(whole.lock == null); whole.lock = man.toOwnedLock(); }, - .incremental => { - try flush(comp, arena, .main, main_progress_node); + .incremental => |incremental| { + try flush(comp, arena, .{ + .root_dir = incremental.artifact_directory, + }, .main, main_progress_node); }, } } @@ -2440,7 +2454,13 @@ pub fn appendFileSystemInput( std.debug.panic("missing prefix directory: {}, {s}", .{ root, sub_file_path }); } -fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { +fn flush( + comp: *Compilation, + arena: Allocator, + default_artifact_directory: Path, + tid: Zcu.PerThread.Id, + prog_node: std.Progress.Node, +) !void { if (comp.bin_file) |lf| { // This is needed before reading the error flags. lf.flush(arena, tid, prog_node) catch |err| switch (err) { @@ -2454,17 +2474,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: try link.File.C.flushEmitH(zcu); if (zcu.llvm_object) |llvm_object| { - const default_emit = switch (comp.cache_use) { - .whole => |whole| .{ - .directory = whole.tmp_artifact_directory.?, - .sub_path = "dummy", - }, - .incremental => |incremental| .{ - .directory = incremental.artifact_directory, - .sub_path = "dummy", - }, - }; - try emitLlvmObject(comp, arena, default_emit, null, llvm_object, prog_node); + try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node); } } } @@ -2745,7 +2755,7 @@ fn emitOthers(comp: *Compilation) void { pub fn emitLlvmObject( comp: *Compilation, arena: Allocator, - default_emit: Emit, + default_artifact_directory: Path, bin_emit_loc: ?EmitLoc, llvm_object: LlvmObject.Ptr, prog_node: std.Progress.Node, @@ -2756,10 +2766,10 @@ pub fn emitLlvmObject( try llvm_object.emit(.{ .pre_ir_path = comp.verbose_llvm_ir, .pre_bc_path = comp.verbose_llvm_bc, - .bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc), - .asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm), - .post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir), - .post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc), + .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc), + .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm), + .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir), + .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc), .is_debug = comp.root_mod.optimize_mode == .Debug, .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, @@ -2772,14 +2782,14 @@ pub fn emitLlvmObject( fn resolveEmitLoc( arena: Allocator, - default_emit: Emit, + default_artifact_directory: Path, opt_loc: ?EmitLoc, ) Allocator.Error!?[*:0]const u8 { const loc = opt_loc orelse return null; const slice = if (loc.directory) |directory| try directory.joinZ(arena, &.{loc.basename}) else - try default_emit.basenamePath(arena, loc.basename); + try default_artifact_directory.joinStringZ(arena, loc.basename); return slice.ptr; } @@ -4403,7 +4413,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest } pub const CImportResult = struct { - out_zig_path: []u8, + digest: [Cache.bin_digest_len]u8, cache_hit: bool, errors: std.zig.ErrorBundle, @@ -4413,8 +4423,6 @@ pub const CImportResult = struct { }; /// Caller owns returned memory. -/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked -/// a bit when we want to start using it from self-hosted. pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { dev.check(.translate_c_command); @@ -4503,7 +4511,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module error.OutOfMemory => return error.OutOfMemory, error.SemanticAnalyzeFail => { return CImportResult{ - .out_zig_path = "", + .digest = undefined, .cache_hit = actual_hit, .errors = errors, }; @@ -4528,8 +4536,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module .incremental => {}, } - const digest = man.final(); - const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); + const bin_digest = man.finalBin(); + const hex_digest = Cache.binToHex(bin_digest); + const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest; var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); defer o_dir.close(); @@ -4541,8 +4550,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module try out_zig_file.writeAll(formatted); - break :digest digest; - } else man.final(); + break :digest bin_digest; + } else man.finalBin(); if (man.have_exclusive_lock) { // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is @@ -4554,14 +4563,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module }; } - const out_zig_path = try comp.local_cache_directory.join(comp.arena, &.{ - "o", &digest, cimport_zig_basename, - }); - if (comp.verbose_cimport) { - log.info("C import output: {s}", .{out_zig_path}); - } return CImportResult{ - .out_zig_path = out_zig_path, + .digest = digest, .cache_hit = actual_hit, .errors = std.zig.ErrorBundle.empty, }; |
