mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Compilation: re-implement cImport
This commit is contained in:
parent
ea169e6ccf
commit
9e979e5a9d
@ -5655,12 +5655,89 @@ pub const CImportResult = struct {
|
||||
};
|
||||
|
||||
/// Caller owns returned memory.
|
||||
pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {
|
||||
pub fn cImport(
|
||||
comp: *Compilation,
|
||||
c_src: []const u8,
|
||||
owner_mod: *Package.Module,
|
||||
prog_node: std.Progress.Node,
|
||||
) !CImportResult {
|
||||
dev.check(.translate_c_command);
|
||||
_ = comp;
|
||||
_ = c_src;
|
||||
_ = owner_mod;
|
||||
@panic("TODO execute 'zig translate-c' as a sub process and use the results");
|
||||
|
||||
const cimport_basename = "cimport.h";
|
||||
const translated_basename = "cimport.zig";
|
||||
|
||||
var man = comp.obtainCObjectCacheManifest(owner_mod);
|
||||
defer man.deinit();
|
||||
|
||||
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects
|
||||
man.hash.addBytes(c_src);
|
||||
|
||||
const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const tmp_basename = std.fmt.hex(std.crypto.random.int(u64));
|
||||
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename;
|
||||
const cache_dir = comp.dirs.local_cache.handle;
|
||||
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
|
||||
|
||||
try cache_dir.makePath(tmp_sub_path);
|
||||
|
||||
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path});
|
||||
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename });
|
||||
const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path});
|
||||
|
||||
if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path});
|
||||
try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src });
|
||||
|
||||
var argv = std.array_list.Managed([]const u8).init(comp.gpa);
|
||||
defer argv.deinit();
|
||||
try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod);
|
||||
try argv.appendSlice(&.{ out_h_path, "-o", translated_path });
|
||||
|
||||
if (comp.verbose_cc) dump_argv(argv.items);
|
||||
var stdout: []u8 = undefined;
|
||||
try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout);
|
||||
if (comp.verbose_cimport and stdout.len != 0) log.info("unexpected stdout: {s}", .{stdout});
|
||||
|
||||
const dep_sub_path = out_h_sub_path ++ ".d";
|
||||
if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_sub_path});
|
||||
try man.addDepFilePost(cache_dir, dep_sub_path);
|
||||
switch (comp.cache_use) {
|
||||
.whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
|
||||
whole.cache_manifest_mutex.lock();
|
||||
defer whole.cache_manifest_mutex.unlock();
|
||||
try whole_cache_manifest.addDepFilePost(cache_dir, dep_sub_path);
|
||||
},
|
||||
.incremental, .none => {},
|
||||
}
|
||||
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
|
||||
|
||||
if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path });
|
||||
try fs.rename(cache_dir, tmp_sub_path, cache_dir, o_sub_path);
|
||||
|
||||
break :digest .{ bin_digest, false };
|
||||
};
|
||||
|
||||
if (man.have_exclusive_lock) {
|
||||
// Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is
|
||||
// possible we had a hit and the manifest is dirty, for example if the file mtime changed but
|
||||
// the contents were the same, we hit the cache but the manifest is dirty and we need to update
|
||||
// it to prevent doing a full file content comparison the next time around.
|
||||
man.writeManifest() catch |err| {
|
||||
log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)});
|
||||
};
|
||||
}
|
||||
|
||||
return .{
|
||||
.digest = digest,
|
||||
.cache_hit = is_hit,
|
||||
.errors = std.zig.ErrorBundle.empty,
|
||||
};
|
||||
}
|
||||
|
||||
fn workerUpdateCObject(
|
||||
@ -6964,7 +7041,7 @@ fn addCommonCCArgs(
|
||||
pub fn addCCArgs(
|
||||
comp: *const Compilation,
|
||||
arena: Allocator,
|
||||
argv: *std.ArrayList([]const u8),
|
||||
argv: *std.array_list.Managed([]const u8),
|
||||
ext: FileExt,
|
||||
out_dep_path: ?[]const u8,
|
||||
mod: *Package.Module,
|
||||
|
||||
11
src/Sema.zig
11
src/Sema.zig
@ -5713,10 +5713,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
|
||||
const body = sema.code.bodySlice(extra.end, extra.data.body_len);
|
||||
|
||||
// we check this here to avoid undefined symbols
|
||||
if (!build_options.have_llvm)
|
||||
return sema.fail(parent_block, src, "C import unavailable; Zig compiler built without LLVM extensions", .{});
|
||||
|
||||
var c_import_buf = std.array_list.Managed(u8).init(gpa);
|
||||
defer c_import_buf.deinit();
|
||||
|
||||
@ -5741,8 +5737,11 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
|
||||
_ = try sema.analyzeInlineBody(&child_block, body, inst);
|
||||
|
||||
var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|
|
||||
return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
|
||||
const prog_node = zcu.cur_sema_prog_node.start("@cImport", 0);
|
||||
defer prog_node.end();
|
||||
|
||||
var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule(), prog_node) catch |err|
|
||||
return sema.fail(&child_block, src, "C import failed: {t}", .{err});
|
||||
defer c_import_res.deinit(gpa);
|
||||
|
||||
if (c_import_res.errors.errorMessageCount() != 0) {
|
||||
|
||||
23
src/main.zig
23
src/main.zig
@ -4559,12 +4559,7 @@ fn cmdTranslateC(
|
||||
try argv.append(c_source_file.src_path);
|
||||
if (comp.verbose_cc) Compilation.dump_argv(argv.items);
|
||||
|
||||
try jitCmd(comp.gpa, arena, argv.items, .{
|
||||
.cmd_name = "translate-c",
|
||||
.root_src_path = "translate-c/main.zig",
|
||||
.depend_on_aro = true,
|
||||
.progress_node = prog_node,
|
||||
});
|
||||
try translateC(comp.gpa, arena, argv.items, prog_node, null);
|
||||
|
||||
if (out_dep_path) |dep_file_path| {
|
||||
const dep_basename = fs.path.basename(dep_file_path);
|
||||
@ -4585,6 +4580,22 @@ fn cmdTranslateC(
|
||||
return cleanExit();
|
||||
}
|
||||
|
||||
pub fn translateC(
|
||||
gpa: Allocator,
|
||||
arena: Allocator,
|
||||
argv: []const []const u8,
|
||||
prog_node: std.Progress.Node,
|
||||
capture: ?*[]u8,
|
||||
) !void {
|
||||
try jitCmd(gpa, arena, argv, .{
|
||||
.cmd_name = "translate-c",
|
||||
.root_src_path = "translate-c/main.zig",
|
||||
.depend_on_aro = true,
|
||||
.progress_node = prog_node,
|
||||
.capture = capture,
|
||||
});
|
||||
}
|
||||
|
||||
const usage_init =
|
||||
\\Usage: zig init
|
||||
\\
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user