authorgravatar for motiejus@jakstys.ltMotiejus Jakštys <motiejus@jakstys.lt> 2023-05-19 10:12:47+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-03-14 09:32:56-07:00
log400145ee3bb0740cc274a75b7c612d799811b5fe
tree01a4303a0d32299630f8a876ecc4d8978f59f408
parentbc5b09469509fae80e989adc511e2f31aca05dc0

reduce garbage for repeated `zig cc -` calls

Context: user provides `-` to read from stdin instead of a file. Before: it would create a file in $ZIG_LOCAL_CACHE_DIR/tmp/ for each invocation and leave it there. After: it hashes the file contents and renames the file to the hash. Result: repeated invocations of `zig cc` do not cause so much trash to be created.

1 files changed, 26 insertions(+), 9 deletions(-)

src/main.zig+26-9
...@@ -3129,19 +3129,36 @@ fn buildOutputType(...@@ -3129,19 +3129,36 @@ fn buildOutputType(
31293129
3130 // "-" is stdin. Dump it to a real file.3130 // "-" is stdin. Dump it to a real file.
3131 const sep = fs.path.sep_str;3131 const sep = fs.path.sep_str;
3132 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{3132 const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{
3133 std.crypto.random.int(u64), ext.canonicalName(target),3133 std.crypto.random.int(u64), ext.canonicalName(target),
3134 });3134 });
3135 try local_cache_directory.handle.makePath("tmp");3135 try local_cache_directory.handle.makePath("tmp");
3136 // Note that in one of the happy paths, execve() is used to switch3136
3137 // to clang in which case any cleanup logic that exists for this3137 // Note that in one of the happy paths, execve() is used to switch to
3138 // temporary file will not run and this temp file will be leaked.3138 // clang in which case any cleanup logic that exists for this temporary
3139 // Oh well. It's a minor punishment for using `-x c` which nobody3139 // file will not run and this temp file will be leaked. The filename
3140 // should be doing. Therefore, we make no effort to clean up. Using3140 // will be a hash of its contents — so multiple invocations of
3141 // `-` for stdin as a source file always leaks a temp file.3141 // `zig cc -` will result in the same temp file name.
3142 var f = try local_cache_directory.handle.createFile(sub_path, .{});3142 var f = try local_cache_directory.handle.createFile(dump_path, .{});
3143 defer f.close();3143 defer f.close();
3144 try f.writeFileAll(io.getStdIn(), .{});3144
3145 // Re-using the hasher from Cache, since the functional requirements
3146 // for the hashing algorithm here and in the cache are the same.
3147 // We are providing our own cache key, because this file has nothing
3148 // to do with the cache manifest.
3149 var hasher = Cache.Hasher.init("0123456789abcdef");
3150 var w = io.multiWriter(.{ f.writer(), hasher.writer() });
3151 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init();
3152 try fifo.pump(io.getStdIn().reader(), w.writer());
3153
3154 var bin_digest: Cache.BinDigest = undefined;
3155 hasher.final(&bin_digest);
3156
3157 const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{
3158 std.fmt.fmtSliceHexLower(&bin_digest),
3159 ext.canonicalName(target),
3160 });
3161 try local_cache_directory.handle.rename(dump_path, sub_path);
31453162
3146 // Convert `sub_path` to be relative to current working directory.3163 // Convert `sub_path` to be relative to current working directory.
3147 src.src_path = try local_cache_directory.join(arena, &.{sub_path});3164 src.src_path = try local_cache_directory.join(arena, &.{sub_path});