authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-24 21:10:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-24 21:13:01-07:00
log4f0850fe285937e37a7e9260c399867d3f61a487
tree5ce8d9d2ecda1f428e423da500bf9067e2a20d20
parent054fafd7d9a5226f21e7be1737c6d352fe39f795

don't delete C import .c source from zig-cache

preventing CacheUnavailable error when doing `@cImport`

2 files changed, 69 insertions(+), 80 deletions(-)

src/Compilation.zig+68-80
...@@ -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;
12501250
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 before1252 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 }
12691260
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 }
12721265
1273 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);1266 var argv = std.ArrayList([]const u8).init(comp.gpa);
1267 defer argv.deinit();
12741268
1275 try argv.append(out_h_path);1269 try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);
12761270
1277 if (comp.verbose_cc) {1271 try argv.append(out_h_path);
1278 dump_argv(argv.items);
1279 }
12801272
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 }
12881276
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();
13121284
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();
13161308
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 }
13191312
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();
13241315
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();
13271320
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();
13311323
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();
13351327
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();
13461334
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{
src/stage1.zig+1
...@@ -347,6 +347,7 @@ export fn stage2_cimport(...@@ -347,6 +347,7 @@ export fn stage2_cimport(
347 error.Unexpected => return .Unexpected,347 error.Unexpected => return .Unexpected,
348 error.InputOutput => return .FileSystem,348 error.InputOutput => return .FileSystem,
349 error.ASTUnitFailure => return .ASTUnitFailure,349 error.ASTUnitFailure => return .ASTUnitFailure,
350 error.CacheUnavailable => return .CacheUnavailable,
350 else => return .Unexpected,351 else => return .Unexpected,
351 };352 };
352 out_zig_path_ptr.* = result.out_zig_path.ptr;353 out_zig_path_ptr.* = result.out_zig_path.ptr;