| ... | @@ -1248,100 +1248,88 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { | ... | @@ -1248,100 +1248,88 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { |
| 1248 | defer arena_allocator.deinit(); | 1248 | defer arena_allocator.deinit(); |
| 1249 | const arena = &arena_allocator.allocator; | 1249 | const arena = &arena_allocator.allocator; |
| 1250 | | 1250 | |
| 1251 | // We need a place to leave the .h file so we can can log it in case of verbose_cimport. | 1251 | const tmp_digest = man.hash.peek(); |
| 1252 | // This block is so that the defers for closing the tmp directory handle can run before | 1252 | const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest }); |
| 1253 | // we try to delete the directory after the block. | 1253 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); |
| 1254 | const result: struct { tmp_dir_sub_path: []const u8, digest: [Cache.hex_digest_len]u8 } = blk: { | 1254 | defer zig_cache_tmp_dir.close(); |
| 1255 | const tmp_digest = man.hash.peek(); | 1255 | const cimport_c_basename = "cimport.c"; |
| 1256 | const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest }); | 1256 | const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{ |
| 1257 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); | 1257 | tmp_dir_sub_path, cimport_c_basename, |
| 1258 | defer zig_cache_tmp_dir.close(); | 1258 | }); |
| 1259 | const cimport_c_basename = "cimport.c"; | 1259 | const out_dep_path = try std.fmt.allocPrint(arena, "{}.d", .{out_h_path}); |
| 1260 | const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{ | | |
| 1261 | tmp_dir_sub_path, cimport_c_basename, | | |
| 1262 | }); | | |
| 1263 | const out_dep_path = try std.fmt.allocPrint(arena, "{}.d", .{out_h_path}); | | |
| 1264 | | | |
| 1265 | try zig_cache_tmp_dir.writeFile(cimport_c_basename, c_src); | | |
| 1266 | if (comp.verbose_cimport) { | | |
| 1267 | log.info("C import source: {}", .{out_h_path}); | | |
| 1268 | } | | |
| 1269 | | 1260 | |
| 1270 | var argv = std.ArrayList([]const u8).init(comp.gpa); | 1261 | try zig_cache_tmp_dir.writeFile(cimport_c_basename, c_src); |
| 1271 | defer argv.deinit(); | 1262 | if (comp.verbose_cimport) { |
| | 1263 | log.info("C import source: {}", .{out_h_path}); |
| | 1264 | } |
| 1272 | | 1265 | |
| 1273 | try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path); | 1266 | var argv = std.ArrayList([]const u8).init(comp.gpa); |
| | 1267 | defer argv.deinit(); |
| 1274 | | 1268 | |
| 1275 | try argv.append(out_h_path); | 1269 | try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path); |
| 1276 | | 1270 | |
| 1277 | if (comp.verbose_cc) { | 1271 | try argv.append(out_h_path); |
| 1278 | dump_argv(argv.items); | | |
| 1279 | } | | |
| 1280 | | 1272 | |
| 1281 | // Convert to null terminated args. | 1273 | if (comp.verbose_cc) { |
| 1282 | const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); | 1274 | dump_argv(argv.items); |
| 1283 | new_argv_with_sentinel[argv.items.len] = null; | 1275 | } |
| 1284 | const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; | | |
| 1285 | for (argv.items) |arg, i| { | | |
| 1286 | new_argv[i] = try arena.dupeZ(u8, arg); | | |
| 1287 | } | | |
| 1288 | | 1276 | |
| 1289 | const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"}); | 1277 | // Convert to null terminated args. |
| 1290 | const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path); | 1278 | const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); |
| 1291 | var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{}; | 1279 | new_argv_with_sentinel[argv.items.len] = null; |
| 1292 | const tree = translate_c.translate( | 1280 | const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; |
| 1293 | comp.gpa, | 1281 | for (argv.items) |arg, i| { |
| 1294 | new_argv.ptr, | 1282 | new_argv[i] = try arena.dupeZ(u8, arg); |
| 1295 | new_argv.ptr + new_argv.len, | 1283 | } |
| 1296 | &clang_errors, | | |
| 1297 | c_headers_dir_path_z, | | |
| 1298 | ) catch |err| switch (err) { | | |
| 1299 | error.OutOfMemory => return error.OutOfMemory, | | |
| 1300 | error.ASTUnitFailure => { | | |
| 1301 | log.warn("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}); | | |
| 1302 | return error.ASTUnitFailure; | | |
| 1303 | }, | | |
| 1304 | error.SemanticAnalyzeFail => { | | |
| 1305 | return CImportResult{ | | |
| 1306 | .out_zig_path = "", | | |
| 1307 | .errors = clang_errors, | | |
| 1308 | }; | | |
| 1309 | }, | | |
| 1310 | }; | | |
| 1311 | defer tree.deinit(); | | |
| 1312 | | 1284 | |
| 1313 | if (comp.verbose_cimport) { | 1285 | const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"}); |
| 1314 | log.info("C import .d file: {}", .{out_dep_path}); | 1286 | const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path); |
| 1315 | } | 1287 | var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{}; |
| | 1288 | const tree = translate_c.translate( |
| | 1289 | comp.gpa, |
| | 1290 | new_argv.ptr, |
| | 1291 | new_argv.ptr + new_argv.len, |
| | 1292 | &clang_errors, |
| | 1293 | c_headers_dir_path_z, |
| | 1294 | ) catch |err| switch (err) { |
| | 1295 | error.OutOfMemory => return error.OutOfMemory, |
| | 1296 | error.ASTUnitFailure => { |
| | 1297 | log.warn("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}); |
| | 1298 | return error.ASTUnitFailure; |
| | 1299 | }, |
| | 1300 | error.SemanticAnalyzeFail => { |
| | 1301 | return CImportResult{ |
| | 1302 | .out_zig_path = "", |
| | 1303 | .errors = clang_errors, |
| | 1304 | }; |
| | 1305 | }, |
| | 1306 | }; |
| | 1307 | defer tree.deinit(); |
| 1316 | | 1308 | |
| 1317 | const dep_basename = std.fs.path.basename(out_dep_path); | 1309 | if (comp.verbose_cimport) { |
| 1318 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); | 1310 | log.info("C import .d file: {}", .{out_dep_path}); |
| | 1311 | } |
| 1319 | | 1312 | |
| 1320 | const digest = man.final(); | 1313 | const dep_basename = std.fs.path.basename(out_dep_path); |
| 1321 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); | 1314 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 1322 | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); | | |
| 1323 | defer o_dir.close(); | | |
| 1324 | | 1315 | |
| 1325 | var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); | 1316 | const digest = man.final(); |
| 1326 | defer out_zig_file.close(); | 1317 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); |
| | 1318 | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); |
| | 1319 | defer o_dir.close(); |
| 1327 | | 1320 | |
| 1328 | var bos = std.io.bufferedOutStream(out_zig_file.writer()); | 1321 | var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); |
| 1329 | _ = try std.zig.render(comp.gpa, bos.writer(), tree); | 1322 | defer out_zig_file.close(); |
| 1330 | try bos.flush(); | | |
| 1331 | | 1323 | |
| 1332 | man.writeManifest() catch |err| { | 1324 | var bos = std.io.bufferedOutStream(out_zig_file.writer()); |
| 1333 | log.warn("failed to write cache manifest for C import: {}", .{@errorName(err)}); | 1325 | _ = try std.zig.render(comp.gpa, bos.writer(), tree); |
| 1334 | }; | 1326 | try bos.flush(); |
| 1335 | | 1327 | |
| 1336 | break :blk .{ .tmp_dir_sub_path = tmp_dir_sub_path, .digest = digest }; | 1328 | man.writeManifest() catch |err| { |
| | 1329 | log.warn("failed to write cache manifest for C import: {}", .{@errorName(err)}); |
| 1337 | }; | 1330 | }; |
| 1338 | if (!comp.verbose_cimport) { | 1331 | |
| 1339 | // Remove the tmp dir and files to save space because we don't need them again. | 1332 | break :digest digest; |
| 1340 | comp.local_cache_directory.handle.deleteTree(result.tmp_dir_sub_path) catch |err| { | | |
| 1341 | log.warn("failed to delete tmp files for C import: {}", .{@errorName(err)}); | | |
| 1342 | }; | | |
| 1343 | } | | |
| 1344 | break :digest result.digest; | | |
| 1345 | } else man.final(); | 1333 | } else man.final(); |
| 1346 | | 1334 | |
| 1347 | const out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ | 1335 | const out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ |