From eb3f7d2f37cab1d3df7c4493b8239e802b83e521 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Tue, 23 Aug 2022 23:43:16 +0200 Subject: compilation: avoid pointless caching When the entire purpose of this compilation is to perform a single zig cc operation we could "tail call" clang by doing an execve, and any use of the caching system would actually be problematic since the user is presumably doing their own caching by using dep file flags. Fixes #12317 --- src/Compilation.zig | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 1bc9719e1b..1b424a4001 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3753,22 +3753,64 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P }; const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, out_ext }); + try argv.appendSlice(&[_][]const u8{ + self_exe_path, + "clang", + c_object.src.src_path, + }); + try argv.appendSlice(c_object.src.extra_flags); + + const ext = classifyFileExt(c_object.src.src_path); + + // When all these flags are true, it means that the entire purpose of + // this compilation is to perform a single zig cc operation. This means + // that we could "tail call" clang by doing an execve, and any use of + // the caching system would actually be problematic since the user is + // presumably doing their own caching by using dep file flags. + if (comp.disable_c_depfile and comp.clang_passthrough_mode and std.process.can_execv and direct_o) { + try comp.addCCArgs(arena, &argv, ext, null); + + const out_obj_path = if (comp.bin_file.options.emit) |emit| + try emit.directory.join(arena, &.{emit.sub_path}) + else + "/dev/null"; + + try argv.ensureUnusedCapacity(5); + switch (comp.clang_preprocessor_mode) { + .no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }), + .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }), + .stdout => argv.appendAssumeCapacity("-E"), + } + + if (comp.emit_asm != null) { + argv.appendAssumeCapacity("-S"); + } else if (comp.emit_llvm_ir != null) { + argv.appendSliceAssumeCapacity(&[_][]const u8{ "-emit-llvm", "-S" }); + } else if (comp.emit_llvm_bc != null) { + argv.appendAssumeCapacity("-emit-llvm"); + } + + if (comp.verbose_cc) { + dump_argv(argv.items); + } + + const err = std.process.execv(arena, argv.items); + fatal("unable to execv clang: {s}", .{@errorName(err)}); + } + // We can't know the digest until we do the C compiler invocation, // so we need a temporary filename. const out_obj_path = try comp.tmpFilePath(arena, o_basename); var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); defer zig_cache_tmp_dir.close(); - try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang" }); - - const ext = classifyFileExt(c_object.src.src_path); const out_dep_path: ?[]const u8 = if (comp.disable_c_depfile or !ext.clangSupportsDepFile()) null else try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path}); try comp.addCCArgs(arena, &argv, ext, out_dep_path); - try argv.ensureUnusedCapacity(6 + c_object.src.extra_flags.len); + try argv.ensureUnusedCapacity(5); switch (comp.clang_preprocessor_mode) { .no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }), .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }), @@ -3783,8 +3825,6 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P argv.appendAssumeCapacity("-emit-llvm"); } } - argv.appendAssumeCapacity(c_object.src.src_path); - argv.appendSliceAssumeCapacity(c_object.src.extra_flags); if (comp.verbose_cc) { dump_argv(argv.items); -- cgit v1.2.3