| ... | ... | @@ -1248,100 +1248,88 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { |
| 1248 | 1248 | defer arena_allocator.deinit(); |
| 1249 | 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. |
| 1252 | | // This block is so that the defers for closing the tmp directory handle can run before |
| 1253 | | // we try to delete the directory after the block. |
| 1254 | | const result: struct { tmp_dir_sub_path: []const u8, digest: [Cache.hex_digest_len]u8 } = blk: { |
| 1255 | | const tmp_digest = man.hash.peek(); |
| 1256 | | const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest }); |
| 1257 | | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); |
| 1258 | | defer zig_cache_tmp_dir.close(); |
| 1259 | | const cimport_c_basename = "cimport.c"; |
| 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 | | } |
| 1251 | const tmp_digest = man.hash.peek(); |
| 1252 | const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest }); |
| 1253 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{}); |
| 1254 | defer zig_cache_tmp_dir.close(); |
| 1255 | const cimport_c_basename = "cimport.c"; |
| 1256 | const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{ |
| 1257 | tmp_dir_sub_path, cimport_c_basename, |
| 1258 | }); |
| 1259 | const out_dep_path = try std.fmt.allocPrint(arena, "{}.d", .{out_h_path}); |
| 1269 | 1260 | |
| 1270 | | var argv = std.ArrayList([]const u8).init(comp.gpa); |
| 1271 | | defer argv.deinit(); |
| 1261 | try zig_cache_tmp_dir.writeFile(cimport_c_basename, c_src); |
| 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) { |
| 1278 | | dump_argv(argv.items); |
| 1279 | | } |
| 1271 | try argv.append(out_h_path); |
| 1280 | 1272 | |
| 1281 | | // Convert to null terminated args. |
| 1282 | | const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); |
| 1283 | | new_argv_with_sentinel[argv.items.len] = null; |
| 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 | | } |
| 1273 | if (comp.verbose_cc) { |
| 1274 | dump_argv(argv.items); |
| 1275 | } |
| 1288 | 1276 | |
| 1289 | | const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"}); |
| 1290 | | const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path); |
| 1291 | | var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{}; |
| 1292 | | const tree = translate_c.translate( |
| 1293 | | comp.gpa, |
| 1294 | | new_argv.ptr, |
| 1295 | | new_argv.ptr + new_argv.len, |
| 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(); |
| 1277 | // Convert to null terminated args. |
| 1278 | const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); |
| 1279 | new_argv_with_sentinel[argv.items.len] = null; |
| 1280 | const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; |
| 1281 | for (argv.items) |arg, i| { |
| 1282 | new_argv[i] = try arena.dupeZ(u8, arg); |
| 1283 | } |
| 1312 | 1284 | |
| 1313 | | if (comp.verbose_cimport) { |
| 1314 | | log.info("C import .d file: {}", .{out_dep_path}); |
| 1315 | | } |
| 1285 | const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"}); |
| 1286 | const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path); |
| 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); |
| 1318 | | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 1309 | if (comp.verbose_cimport) { |
| 1310 | log.info("C import .d file: {}", .{out_dep_path}); |
| 1311 | } |
| 1319 | 1312 | |
| 1320 | | const digest = man.final(); |
| 1321 | | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); |
| 1322 | | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); |
| 1323 | | defer o_dir.close(); |
| 1313 | const dep_basename = std.fs.path.basename(out_dep_path); |
| 1314 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 1324 | 1315 | |
| 1325 | | var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); |
| 1326 | | defer out_zig_file.close(); |
| 1316 | const digest = man.final(); |
| 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()); |
| 1329 | | _ = try std.zig.render(comp.gpa, bos.writer(), tree); |
| 1330 | | try bos.flush(); |
| 1321 | var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); |
| 1322 | defer out_zig_file.close(); |
| 1331 | 1323 | |
| 1332 | | man.writeManifest() catch |err| { |
| 1333 | | log.warn("failed to write cache manifest for C import: {}", .{@errorName(err)}); |
| 1334 | | }; |
| 1324 | var bos = std.io.bufferedOutStream(out_zig_file.writer()); |
| 1325 | _ = try std.zig.render(comp.gpa, bos.writer(), tree); |
| 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) { |
| 1339 | | // Remove the tmp dir and files to save space because we don't need them again. |
| 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; |
| 1331 | |
| 1332 | break :digest digest; |
| 1345 | 1333 | } else man.final(); |
| 1346 | 1334 | |
| 1347 | 1335 | const out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ |