| ... | ... | @@ -5655,12 +5655,89 @@ pub const CImportResult = struct { |
| 5655 | 5655 | }; |
| 5656 | 5656 | |
| 5657 | 5657 | /// Caller owns returned memory. |
| 5658 | | pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { |
| 5658 | pub fn cImport( |
| 5659 | comp: *Compilation, |
| 5660 | c_src: []const u8, |
| 5661 | owner_mod: *Package.Module, |
| 5662 | prog_node: std.Progress.Node, |
| 5663 | ) !CImportResult { |
| 5659 | 5664 | dev.check(.translate_c_command); |
| 5660 | | _ = comp; |
| 5661 | | _ = c_src; |
| 5662 | | _ = owner_mod; |
| 5663 | | @panic("TODO execute 'zig translate-c' as a sub process and use the results"); |
| 5665 | |
| 5666 | const cimport_basename = "cimport.h"; |
| 5667 | const translated_basename = "cimport.zig"; |
| 5668 | |
| 5669 | var man = comp.obtainCObjectCacheManifest(owner_mod); |
| 5670 | defer man.deinit(); |
| 5671 | |
| 5672 | man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects |
| 5673 | man.hash.addBytes(c_src); |
| 5674 | |
| 5675 | const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: { |
| 5676 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); |
| 5677 | defer arena_allocator.deinit(); |
| 5678 | const arena = arena_allocator.allocator(); |
| 5679 | |
| 5680 | const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); |
| 5681 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; |
| 5682 | const cache_dir = comp.dirs.local_cache.handle; |
| 5683 | const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename; |
| 5684 | |
| 5685 | try cache_dir.makePath(tmp_sub_path); |
| 5686 | |
| 5687 | const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path}); |
| 5688 | const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); |
| 5689 | const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path}); |
| 5690 | |
| 5691 | if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path}); |
| 5692 | try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src }); |
| 5693 | |
| 5694 | var argv = std.array_list.Managed([]const u8).init(comp.gpa); |
| 5695 | defer argv.deinit(); |
| 5696 | try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod); |
| 5697 | try argv.appendSlice(&.{ out_h_path, "-o", translated_path }); |
| 5698 | |
| 5699 | if (comp.verbose_cc) dump_argv(argv.items); |
| 5700 | var stdout: []u8 = undefined; |
| 5701 | try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout); |
| 5702 | if (comp.verbose_cimport and stdout.len != 0) log.info("unexpected stdout: {s}", .{stdout}); |
| 5703 | |
| 5704 | const dep_sub_path = out_h_sub_path ++ ".d"; |
| 5705 | if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_sub_path}); |
| 5706 | try man.addDepFilePost(cache_dir, dep_sub_path); |
| 5707 | switch (comp.cache_use) { |
| 5708 | .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { |
| 5709 | whole.cache_manifest_mutex.lock(); |
| 5710 | defer whole.cache_manifest_mutex.unlock(); |
| 5711 | try whole_cache_manifest.addDepFilePost(cache_dir, dep_sub_path); |
| 5712 | }, |
| 5713 | .incremental, .none => {}, |
| 5714 | } |
| 5715 | |
| 5716 | const bin_digest = man.finalBin(); |
| 5717 | const hex_digest = Cache.binToHex(bin_digest); |
| 5718 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; |
| 5719 | |
| 5720 | if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); |
| 5721 | try fs.rename(cache_dir, tmp_sub_path, cache_dir, o_sub_path); |
| 5722 | |
| 5723 | break :digest .{ bin_digest, false }; |
| 5724 | }; |
| 5725 | |
| 5726 | if (man.have_exclusive_lock) { |
| 5727 | // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is |
| 5728 | // possible we had a hit and the manifest is dirty, for example if the file mtime changed but |
| 5729 | // the contents were the same, we hit the cache but the manifest is dirty and we need to update |
| 5730 | // it to prevent doing a full file content comparison the next time around. |
| 5731 | man.writeManifest() catch |err| { |
| 5732 | log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)}); |
| 5733 | }; |
| 5734 | } |
| 5735 | |
| 5736 | return .{ |
| 5737 | .digest = digest, |
| 5738 | .cache_hit = is_hit, |
| 5739 | .errors = std.zig.ErrorBundle.empty, |
| 5740 | }; |
| 5664 | 5741 | } |
| 5665 | 5742 | |
| 5666 | 5743 | fn workerUpdateCObject( |
| ... | ... | @@ -6964,7 +7041,7 @@ fn addCommonCCArgs( |
| 6964 | 7041 | pub fn addCCArgs( |
| 6965 | 7042 | comp: *const Compilation, |
| 6966 | 7043 | arena: Allocator, |
| 6967 | | argv: *std.ArrayList([]const u8), |
| 7044 | argv: *std.array_list.Managed([]const u8), |
| 6968 | 7045 | ext: FileExt, |
| 6969 | 7046 | out_dep_path: ?[]const u8, |
| 6970 | 7047 | mod: *Package.Module, |