Skip to content

Commit 0096c08

Browse files
committed
Compilation: retain ZCU object when emitting unstripped Mach-O binary
On macOS, when using the LLVM backend, the output binary retains a reference to this object file's debug info (as opposed to self-hosted backends which instead emit a dSYM bundle). As such, we need to retain this object file in such cases. This object does unfortunately "leak", in that it won't be reused and will just sit in the cache forever (or until GC'd in the future). But that's no worse than the cache behavior prior to the rework that caused this, and it will become less of a problem over time as the self-hosted backend gains usability for debug builds and eventually becomes the default. Resolves: #24369
1 parent 4fcdb08 commit 0096c08

1 file changed

Lines changed: 15 additions & 3 deletions

File tree

src/Compilation.zig

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,7 +1549,8 @@ pub const SystemLib = link.SystemLib;
15491549
pub const CacheMode = enum {
15501550
/// The results of this compilation are not cached. The compilation is always performed, and the
15511551
/// results are emitted directly to their output locations. Temporary files will be placed in a
1552-
/// temporary directory in the cache, but deleted after the compilation is done.
1552+
/// temporary directory in the cache, but deleted after the compilation is done, unless they are
1553+
/// needed for the output binary to work correctly.
15531554
///
15541555
/// This mode is typically used for direct CLI invocations like `zig build-exe`, because such
15551556
/// processes are typically low-level usages which would not make efficient use of the cache.
@@ -1593,8 +1594,8 @@ const CacheUse = union(CacheMode) {
15931594
const None = struct {
15941595
/// User-requested artifacts are written directly to their output path in this cache mode.
15951596
/// However, if we need to emit any temporary files, they are placed in this directory.
1596-
/// We will recursively delete this directory at the end of this update. This field is
1597-
/// non-`null` only inside `update`.
1597+
/// We will recursively delete this directory at the end of this update if possible. This
1598+
/// field is non-`null` only inside `update`.
15981599
tmp_artifact_directory: ?Cache.Directory,
15991600
};
16001601

@@ -2807,6 +2808,17 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
28072808
// temporary directories; it doesn't have a real cache directory anyway.
28082809
return;
28092810
}
2811+
// Usually, we want to delete the temporary directory. However, if we are emitting
2812+
// an unstripped Mach-O binary with the LLVM backend, then the temporary directory
2813+
// contains the ZCU object file emitted by LLVM, which contains debug symbols not
2814+
// replicated in the output binary (the output instead contains a reference to that
2815+
// file which debug tooling can look through). So, in that particular case, we need
2816+
// to keep this directory around so that the output binary can be debugged.
2817+
if (comp.bin_file != null and comp.getTarget().ofmt == .macho and comp.config.debug_format != .strip) {
2818+
// We are emitting an unstripped Mach-O binary with the LLVM backend: the ZCU
2819+
// object file must remain on-disk for its debug info.
2820+
return;
2821+
}
28102822
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
28112823
comp.dirs.local_cache.handle.deleteTree(tmp_dir_sub_path) catch |err| {
28122824
log.warn("failed to delete temporary directory '{s}{c}{s}': {s}", .{

0 commit comments

Comments
 (0)