| ... | @@ -2216,39 +2216,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2216,39 +2216,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2216 | // -femit-llvm-bc, and -femit-asm, in the case of C objects. | 2216 | // -femit-llvm-bc, and -femit-asm, in the case of C objects. |
| 2217 | comp.emitOthers(); | 2217 | comp.emitOthers(); |
| 2218 | | 2218 | |
| 2219 | { | | |
| 2220 | if (comp.bin_file) |lf| { | | |
| 2221 | // This is needed before reading the error flags. | | |
| 2222 | lf.flush(comp, main_progress_node) catch |err| switch (err) { | | |
| 2223 | error.FlushFailure => {}, // error reported through link_error_flags | | |
| 2224 | error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr | | |
| 2225 | else => |e| return e, | | |
| 2226 | }; | | |
| 2227 | } | | |
| 2228 | | | |
| 2229 | if (comp.module) |zcu| { | | |
| 2230 | try link.File.C.flushEmitH(zcu); | | |
| 2231 | | | |
| 2232 | if (zcu.llvm_object) |llvm_object| { | | |
| 2233 | if (build_options.only_c) unreachable; | | |
| 2234 | const default_emit = switch (comp.cache_use) { | | |
| 2235 | .whole => |whole| .{ | | |
| 2236 | .directory = whole.tmp_artifact_directory.?, | | |
| 2237 | .sub_path = "dummy", | | |
| 2238 | }, | | |
| 2239 | .incremental => |incremental| .{ | | |
| 2240 | .directory = incremental.artifact_directory, | | |
| 2241 | .sub_path = "dummy", | | |
| 2242 | }, | | |
| 2243 | }; | | |
| 2244 | try emitLlvmObject(comp, arena, default_emit, null, llvm_object, main_progress_node); | | |
| 2245 | } | | |
| 2246 | } | | |
| 2247 | } | | |
| 2248 | | | |
| 2249 | if (comp.totalErrorCount() != 0) return; | | |
| 2250 | try maybeGenerateAutodocs(comp, main_progress_node); | | |
| 2251 | | | |
| 2252 | switch (comp.cache_use) { | 2219 | switch (comp.cache_use) { |
| 2253 | .whole => |whole| { | 2220 | .whole => |whole| { |
| 2254 | const digest = man.final(); | 2221 | const digest = man.final(); |
| ... | @@ -2261,15 +2228,32 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2261,15 +2228,32 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2261 | whole.tmp_artifact_directory = null; | 2228 | whole.tmp_artifact_directory = null; |
| 2262 | } else unreachable; | 2229 | } else unreachable; |
| 2263 | | 2230 | |
| 2264 | if (comp.bin_file) |lf| { | | |
| 2265 | lf.destroy(); | | |
| 2266 | comp.bin_file = null; | | |
| 2267 | } | | |
| 2268 | | | |
| 2269 | const s = std.fs.path.sep_str; | 2231 | const s = std.fs.path.sep_str; |
| 2270 | const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); | 2232 | const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int); |
| 2271 | const o_sub_path = "o" ++ s ++ digest; | 2233 | const o_sub_path = "o" ++ s ++ digest; |
| 2272 | | 2234 | |
| | 2235 | // Work around windows `AccessDenied` if any files within this |
| | 2236 | // directory are open by closing and reopening the file handles. |
| | 2237 | const need_writable_dance = w: { |
| | 2238 | if (builtin.os.tag == .windows) { |
| | 2239 | if (comp.bin_file) |lf| { |
| | 2240 | // We cannot just call `makeExecutable` as it makes a false |
| | 2241 | // assumption that we have a file handle open only when linking |
| | 2242 | // an executable file. This used to be true when our linkers |
| | 2243 | // were incapable of emitting relocatables and static archive. |
| | 2244 | // Now that they are capable, we need to unconditionally close |
| | 2245 | // the file handle and re-open it in the follow up call to |
| | 2246 | // `makeWritable`. |
| | 2247 | if (lf.file) |f| { |
| | 2248 | f.close(); |
| | 2249 | lf.file = null; |
| | 2250 | break :w true; |
| | 2251 | } |
| | 2252 | } |
| | 2253 | } |
| | 2254 | break :w false; |
| | 2255 | }; |
| | 2256 | |
| 2273 | renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path) catch |err| { | 2257 | renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path) catch |err| { |
| 2274 | return comp.setMiscFailure( | 2258 | return comp.setMiscFailure( |
| 2275 | .rename_results, | 2259 | .rename_results, |
| ... | @@ -2283,15 +2267,75 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2283,15 +2267,75 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2283 | }; | 2267 | }; |
| 2284 | comp.wholeCacheModeSetBinFilePath(whole, &digest); | 2268 | comp.wholeCacheModeSetBinFilePath(whole, &digest); |
| 2285 | | 2269 | |
| | 2270 | // The linker flush functions need to know the final output path |
| | 2271 | // for debug info purposes because executable debug info contains |
| | 2272 | // references object file paths. |
| | 2273 | if (comp.bin_file) |lf| { |
| | 2274 | lf.emit = .{ |
| | 2275 | .directory = comp.local_cache_directory, |
| | 2276 | .sub_path = whole.bin_sub_path.?, |
| | 2277 | }; |
| | 2278 | |
| | 2279 | // Has to be after the `wholeCacheModeSetBinFilePath` above. |
| | 2280 | if (need_writable_dance) { |
| | 2281 | try lf.makeWritable(); |
| | 2282 | } |
| | 2283 | } |
| | 2284 | |
| | 2285 | try flush(comp, arena, main_progress_node); |
| | 2286 | if (comp.totalErrorCount() != 0) return; |
| | 2287 | |
| 2286 | // Failure here only means an unnecessary cache miss. | 2288 | // Failure here only means an unnecessary cache miss. |
| 2287 | man.writeManifest() catch |err| { | 2289 | man.writeManifest() catch |err| { |
| 2288 | log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); | 2290 | log.warn("failed to write cache manifest: {s}", .{@errorName(err)}); |
| 2289 | }; | 2291 | }; |
| 2290 | | 2292 | |
| | 2293 | if (comp.bin_file) |lf| { |
| | 2294 | lf.destroy(); |
| | 2295 | comp.bin_file = null; |
| | 2296 | } |
| | 2297 | |
| 2291 | assert(whole.lock == null); | 2298 | assert(whole.lock == null); |
| 2292 | whole.lock = man.toOwnedLock(); | 2299 | whole.lock = man.toOwnedLock(); |
| 2293 | }, | 2300 | }, |
| 2294 | .incremental => {}, | 2301 | .incremental => { |
| | 2302 | try flush(comp, arena, main_progress_node); |
| | 2303 | if (comp.totalErrorCount() != 0) return; |
| | 2304 | }, |
| | 2305 | } |
| | 2306 | } |
| | 2307 | |
| | 2308 | fn flush(comp: *Compilation, arena: Allocator, prog_node: *std.Progress.Node) !void { |
| | 2309 | if (comp.bin_file) |lf| { |
| | 2310 | // This is needed before reading the error flags. |
| | 2311 | lf.flush(comp, prog_node) catch |err| switch (err) { |
| | 2312 | error.FlushFailure => {}, // error reported through link_error_flags |
| | 2313 | error.LLDReportedFailure => {}, // error reported via lockAndParseLldStderr |
| | 2314 | else => |e| return e, |
| | 2315 | }; |
| | 2316 | } |
| | 2317 | |
| | 2318 | if (comp.module) |zcu| { |
| | 2319 | try link.File.C.flushEmitH(zcu); |
| | 2320 | |
| | 2321 | if (zcu.llvm_object) |llvm_object| { |
| | 2322 | if (build_options.only_c) unreachable; |
| | 2323 | const default_emit = switch (comp.cache_use) { |
| | 2324 | .whole => |whole| .{ |
| | 2325 | .directory = whole.tmp_artifact_directory.?, |
| | 2326 | .sub_path = "dummy", |
| | 2327 | }, |
| | 2328 | .incremental => |incremental| .{ |
| | 2329 | .directory = incremental.artifact_directory, |
| | 2330 | .sub_path = "dummy", |
| | 2331 | }, |
| | 2332 | }; |
| | 2333 | try emitLlvmObject(comp, arena, default_emit, null, llvm_object, prog_node); |
| | 2334 | } |
| | 2335 | } |
| | 2336 | |
| | 2337 | if (comp.totalErrorCount() == 0) { |
| | 2338 | try maybeGenerateAutodocs(comp, prog_node); |
| 2295 | } | 2339 | } |
| 2296 | } | 2340 | } |
| 2297 | | 2341 | |