mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
- Rework common translate-c and cImport logic into Compilation.translateC
- Add std.zig.Server.allocErrorBundle, replace duplicates
This commit is contained in:
parent
447280d0d9
commit
8b6cdc3d82
7 changed files with 212 additions and 264 deletions
|
|
@ -345,20 +345,7 @@ fn buildWasmBinary(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.error_bundle => {
|
.error_bundle => {
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
// TODO: use @ptrCast when the compiler supports it
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
result_error_bundle = .{
|
|
||||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
.emit_digest => {
|
.emit_digest => {
|
||||||
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
||||||
|
|
|
||||||
|
|
@ -524,22 +524,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build.
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.error_bundle => {
|
.error_bundle => {
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
s.result_error_bundle = try std.zig.Server.allocErrorBundle(gpa, body);
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
// TODO: use @ptrCast when the compiler supports it
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
{
|
|
||||||
s.result_error_bundle = .{ .string_bytes = &.{}, .extra = &.{} };
|
|
||||||
errdefer s.result_error_bundle.deinit(gpa);
|
|
||||||
s.result_error_bundle.string_bytes = try gpa.dupe(u8, string_bytes);
|
|
||||||
const extra = try gpa.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra, unaligned_extra);
|
|
||||||
s.result_error_bundle.extra = extra;
|
|
||||||
}
|
|
||||||
// This message indicates the end of the update.
|
// This message indicates the end of the update.
|
||||||
if (watch) break :poll;
|
if (watch) break :poll;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -595,19 +595,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.error_bundle => {
|
.error_bundle => {
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes);
|
|
||||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
result_error_bundle = .{
|
|
||||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
.emit_digest => {
|
.emit_digest => {
|
||||||
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,28 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
|
||||||
try s.out.flush();
|
try s.out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allocErrorBundle(allocator: std.mem.Allocator, body: []const u8) !std.zig.ErrorBundle {
|
||||||
|
const eb_hdr = @as(*align(1) const OutMessage.ErrorBundle, @ptrCast(body));
|
||||||
|
const extra_bytes =
|
||||||
|
body[@sizeOf(OutMessage.ErrorBundle)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||||
|
const string_bytes =
|
||||||
|
body[@sizeOf(OutMessage.ErrorBundle) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||||
|
const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes);
|
||||||
|
|
||||||
|
var error_bundle: std.zig.ErrorBundle = .{
|
||||||
|
.string_bytes = &.{},
|
||||||
|
.extra = &.{},
|
||||||
|
};
|
||||||
|
errdefer error_bundle.deinit(allocator);
|
||||||
|
|
||||||
|
error_bundle.string_bytes = try allocator.dupe(u8, string_bytes);
|
||||||
|
const extra = try allocator.alloc(u32, unaligned_extra.len);
|
||||||
|
@memcpy(extra, unaligned_extra);
|
||||||
|
error_bundle.extra = extra;
|
||||||
|
|
||||||
|
return error_bundle;
|
||||||
|
}
|
||||||
|
|
||||||
pub const TestMetadata = struct {
|
pub const TestMetadata = struct {
|
||||||
names: []const u32,
|
names: []const u32,
|
||||||
expected_panic_msgs: []const u32,
|
expected_panic_msgs: []const u32,
|
||||||
|
|
|
||||||
|
|
@ -5640,6 +5640,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CImportResult = struct {
|
pub const CImportResult = struct {
|
||||||
|
// Only valid if `errors` is not empty
|
||||||
digest: [Cache.bin_digest_len]u8,
|
digest: [Cache.bin_digest_len]u8,
|
||||||
cache_hit: bool,
|
cache_hit: bool,
|
||||||
errors: std.zig.ErrorBundle,
|
errors: std.zig.ErrorBundle,
|
||||||
|
|
@ -5649,6 +5650,144 @@ pub const CImportResult = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn translateC(
|
||||||
|
comp: *Compilation,
|
||||||
|
arena: Allocator,
|
||||||
|
man: *Cache.Manifest,
|
||||||
|
ext: FileExt,
|
||||||
|
source: union(enum) {
|
||||||
|
path: []const u8,
|
||||||
|
c_src: []const u8,
|
||||||
|
},
|
||||||
|
translated_basename: []const u8,
|
||||||
|
owner_mod: *Package.Module,
|
||||||
|
prog_node: std.Progress.Node,
|
||||||
|
) !CImportResult {
|
||||||
|
dev.check(.translate_c_command);
|
||||||
|
|
||||||
|
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;
|
||||||
|
var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{});
|
||||||
|
defer cache_tmp_dir.close();
|
||||||
|
|
||||||
|
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename });
|
||||||
|
const source_path = switch (source) {
|
||||||
|
.c_src => |c_src| path: {
|
||||||
|
const cimport_basename = "cimport.h";
|
||||||
|
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
|
||||||
|
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_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 });
|
||||||
|
break :path out_h_path;
|
||||||
|
},
|
||||||
|
.path => |p| p,
|
||||||
|
};
|
||||||
|
|
||||||
|
const out_dep_path: ?[]const u8 = blk: {
|
||||||
|
if (comp.disable_c_depfile) break :blk null;
|
||||||
|
const c_src_basename = fs.path.basename(source_path);
|
||||||
|
const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
|
||||||
|
const out_dep_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, dep_basename });
|
||||||
|
break :blk out_dep_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
var argv = std.array_list.Managed([]const u8).init(arena);
|
||||||
|
{
|
||||||
|
const target = &owner_mod.resolved_target.result;
|
||||||
|
try argv.appendSlice(&.{ "--zig-integration", "-x", "c" });
|
||||||
|
|
||||||
|
const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" });
|
||||||
|
try argv.appendSlice(&.{ "-isystem", resource_path });
|
||||||
|
try comp.addCommonCCArgs(arena, &argv, ext, out_dep_path, owner_mod, .aro);
|
||||||
|
try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) });
|
||||||
|
|
||||||
|
const mcpu = mcpu: {
|
||||||
|
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
|
defer buf.deinit(comp.gpa);
|
||||||
|
|
||||||
|
try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name});
|
||||||
|
|
||||||
|
// TODO better serialization https://github.com/ziglang/zig/issues/4584
|
||||||
|
const all_features_list = target.cpu.arch.allFeaturesList();
|
||||||
|
try argv.ensureUnusedCapacity(all_features_list.len * 4);
|
||||||
|
for (all_features_list, 0..) |feature, index_usize| {
|
||||||
|
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
||||||
|
const is_enabled = target.cpu.features.isEnabled(index);
|
||||||
|
|
||||||
|
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
||||||
|
try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
||||||
|
}
|
||||||
|
break :mcpu try buf.toOwnedSlice(arena);
|
||||||
|
};
|
||||||
|
try argv.append(mcpu);
|
||||||
|
|
||||||
|
try argv.appendSlice(comp.global_cc_argv);
|
||||||
|
try argv.appendSlice(owner_mod.cc_argv);
|
||||||
|
try argv.appendSlice(&.{ source_path, "-o", translated_path });
|
||||||
|
if (comp.verbose_cimport) dump_argv(argv.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
var stdout: []u8 = undefined;
|
||||||
|
try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout);
|
||||||
|
|
||||||
|
if (out_dep_path) |dep_file_path| add_deps: {
|
||||||
|
if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_file_path});
|
||||||
|
|
||||||
|
const dep_basename = fs.path.basename(dep_file_path);
|
||||||
|
// Add the files depended on to the cache system, if a dep file was emitted
|
||||||
|
man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) {
|
||||||
|
error.FileNotFound => break :add_deps,
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
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_tmp_dir, dep_basename);
|
||||||
|
},
|
||||||
|
.incremental, .none => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just to save disk space, we delete the file because it is never needed again.
|
||||||
|
cache_tmp_dir.deleteFile(dep_basename) catch |err| {
|
||||||
|
log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdout.len > 0) {
|
||||||
|
var reader: std.Io.Reader = .fixed(stdout);
|
||||||
|
const MessageHeader = std.zig.Server.Message.Header;
|
||||||
|
const header = reader.takeStruct(MessageHeader, .little) catch unreachable;
|
||||||
|
const body = reader.take(header.bytes_len) catch unreachable;
|
||||||
|
switch (header.tag) {
|
||||||
|
.error_bundle => {
|
||||||
|
const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body);
|
||||||
|
return .{
|
||||||
|
.digest = undefined,
|
||||||
|
.cache_hit = false,
|
||||||
|
.errors = error_bundle,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => unreachable, // No other messagse are sent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.digest = bin_digest,
|
||||||
|
.cache_hit = false,
|
||||||
|
.errors = ErrorBundle.empty,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Caller owns returned memory.
|
/// Caller owns returned memory.
|
||||||
pub fn cImport(
|
pub fn cImport(
|
||||||
comp: *Compilation,
|
comp: *Compilation,
|
||||||
|
|
@ -5658,67 +5797,35 @@ pub fn cImport(
|
||||||
) !CImportResult {
|
) !CImportResult {
|
||||||
dev.check(.translate_c_command);
|
dev.check(.translate_c_command);
|
||||||
|
|
||||||
const cimport_basename = "cimport.h";
|
|
||||||
const translated_basename = "cimport.zig";
|
const translated_basename = "cimport.zig";
|
||||||
|
|
||||||
var man = comp.obtainCObjectCacheManifest(owner_mod);
|
var man = comp.obtainCObjectCacheManifest(owner_mod);
|
||||||
defer man.deinit();
|
defer man.deinit();
|
||||||
|
|
||||||
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects
|
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish c-import from compiling C objects
|
||||||
man.hash.addBytes(c_src);
|
man.hash.addBytes(c_src);
|
||||||
|
|
||||||
const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: {
|
const result: CImportResult = if (try man.hit()) .{
|
||||||
|
.digest = man.finalBin(),
|
||||||
|
.cache_hit = true,
|
||||||
|
.errors = ErrorBundle.empty,
|
||||||
|
} else result: {
|
||||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||||
defer arena_allocator.deinit();
|
defer arena_allocator.deinit();
|
||||||
const arena = arena_allocator.allocator();
|
const arena = arena_allocator.allocator();
|
||||||
|
|
||||||
const tmp_basename = std.fmt.hex(std.crypto.random.int(u64));
|
break :result try comp.translateC(
|
||||||
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename;
|
arena,
|
||||||
const cache_dir = comp.dirs.local_cache.handle;
|
&man,
|
||||||
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
|
.c,
|
||||||
|
.{ .c_src = c_src },
|
||||||
try cache_dir.makePath(tmp_sub_path);
|
translated_basename,
|
||||||
|
owner_mod,
|
||||||
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path});
|
prog_node,
|
||||||
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 renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path);
|
|
||||||
|
|
||||||
break :digest .{ bin_digest, false };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (man.have_exclusive_lock) {
|
if (result.errors.errorMessageCount() == 0 and man.have_exclusive_lock) {
|
||||||
// Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is
|
// 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
|
// 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
|
// the contents were the same, we hit the cache but the manifest is dirty and we need to update
|
||||||
|
|
@ -5728,11 +5835,7 @@ pub fn cImport(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
return result;
|
||||||
.digest = digest,
|
|
||||||
.cache_hit = is_hit,
|
|
||||||
.errors = std.zig.ErrorBundle.empty,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn workerUpdateCObject(
|
fn workerUpdateCObject(
|
||||||
|
|
@ -6622,19 +6725,7 @@ fn spawnZigRc(
|
||||||
// We expect exactly one ErrorBundle, and if any error_bundle header is
|
// We expect exactly one ErrorBundle, and if any error_bundle header is
|
||||||
// sent then it's a fatal error.
|
// sent then it's a fatal error.
|
||||||
.error_bundle => {
|
.error_bundle => {
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body);
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
const error_bundle = std.zig.ErrorBundle{
|
|
||||||
.string_bytes = try comp.gpa.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle);
|
return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle);
|
||||||
},
|
},
|
||||||
else => {}, // ignore other messages
|
else => {}, // ignore other messages
|
||||||
|
|
@ -6672,49 +6763,6 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addTranslateCCArgs(
|
|
||||||
comp: *Compilation,
|
|
||||||
arena: Allocator,
|
|
||||||
argv: *std.array_list.Managed([]const u8),
|
|
||||||
ext: FileExt,
|
|
||||||
out_dep_path: ?[]const u8,
|
|
||||||
owner_mod: *Package.Module,
|
|
||||||
) !void {
|
|
||||||
const target = &owner_mod.resolved_target.result;
|
|
||||||
|
|
||||||
try argv.appendSlice(&.{ "-x", "c" });
|
|
||||||
|
|
||||||
const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" });
|
|
||||||
try argv.appendSlice(&.{ "-isystem", resource_path });
|
|
||||||
|
|
||||||
try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro);
|
|
||||||
|
|
||||||
try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) });
|
|
||||||
|
|
||||||
const mcpu = mcpu: {
|
|
||||||
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
|
||||||
defer buf.deinit(comp.gpa);
|
|
||||||
|
|
||||||
try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name});
|
|
||||||
|
|
||||||
// TODO better serialization https://github.com/ziglang/zig/issues/4584
|
|
||||||
const all_features_list = target.cpu.arch.allFeaturesList();
|
|
||||||
try argv.ensureUnusedCapacity(all_features_list.len * 4);
|
|
||||||
for (all_features_list, 0..) |feature, index_usize| {
|
|
||||||
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
|
||||||
const is_enabled = target.cpu.features.isEnabled(index);
|
|
||||||
|
|
||||||
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
|
||||||
try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
|
||||||
}
|
|
||||||
break :mcpu try buf.toOwnedSlice(arena);
|
|
||||||
};
|
|
||||||
try argv.append(mcpu);
|
|
||||||
|
|
||||||
try argv.appendSlice(comp.global_cc_argv);
|
|
||||||
try argv.appendSlice(owner_mod.cc_argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add common C compiler args between translate-c and C object compilation.
|
/// Add common C compiler args between translate-c and C object compilation.
|
||||||
fn addCommonCCArgs(
|
fn addCommonCCArgs(
|
||||||
comp: *const Compilation,
|
comp: *const Compilation,
|
||||||
|
|
|
||||||
129
src/main.zig
129
src/main.zig
|
|
@ -4520,12 +4520,11 @@ fn cmdTranslateC(
|
||||||
prog_node: std.Progress.Node,
|
prog_node: std.Progress.Node,
|
||||||
) !void {
|
) !void {
|
||||||
dev.check(.translate_c_command);
|
dev.check(.translate_c_command);
|
||||||
const color: Color = .auto;
|
|
||||||
|
|
||||||
assert(comp.c_source_files.len == 1);
|
assert(comp.c_source_files.len == 1);
|
||||||
const c_source_file = comp.c_source_files[0];
|
const c_source_file = comp.c_source_files[0];
|
||||||
|
|
||||||
const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});
|
const translated_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});
|
||||||
|
|
||||||
var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod);
|
var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod);
|
||||||
man.want_shared_lock = false;
|
man.want_shared_lock = false;
|
||||||
|
|
@ -4537,111 +4536,43 @@ fn cmdTranslateC(
|
||||||
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
|
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fancy_output) |p| p.cache_hit = true;
|
const result: Compilation.CImportResult = if (try man.hit()) .{
|
||||||
const bin_digest, const hex_digest = if (try man.hit()) digest: {
|
.digest = man.finalBin(),
|
||||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
.cache_hit = true,
|
||||||
const bin_digest = man.finalBin();
|
.errors = std.zig.ErrorBundle.empty,
|
||||||
const hex_digest = Cache.binToHex(bin_digest);
|
} else result: {
|
||||||
break :digest .{ bin_digest, hex_digest };
|
const result = try comp.translateC(
|
||||||
} else digest: {
|
arena,
|
||||||
if (fancy_output) |p| p.cache_hit = false;
|
&man,
|
||||||
|
Compilation.classifyFileExt(c_source_file.src_path),
|
||||||
const tmp_basename = std.fmt.hex(std.crypto.random.int(u64));
|
.{ .path = c_source_file.src_path },
|
||||||
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename;
|
translated_basename,
|
||||||
const cache_dir = comp.dirs.local_cache.handle;
|
comp.root_mod,
|
||||||
var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{});
|
prog_node,
|
||||||
defer cache_tmp_dir.close();
|
|
||||||
|
|
||||||
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_zig_basename });
|
|
||||||
|
|
||||||
const ext = Compilation.classifyFileExt(c_source_file.src_path);
|
|
||||||
const out_dep_path: ?[]const u8 = blk: {
|
|
||||||
if (comp.disable_c_depfile) break :blk null;
|
|
||||||
const c_src_basename = fs.path.basename(c_source_file.src_path);
|
|
||||||
const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
|
|
||||||
const out_dep_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, dep_basename });
|
|
||||||
break :blk out_dep_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
var argv = std.array_list.Managed([]const u8).init(arena);
|
|
||||||
try argv.append("--zig-integration");
|
|
||||||
try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod);
|
|
||||||
try argv.appendSlice(&.{ c_source_file.src_path, "-o", translated_path });
|
|
||||||
if (comp.verbose_cc) Compilation.dump_argv(argv.items);
|
|
||||||
|
|
||||||
var stdout: []u8 = undefined;
|
|
||||||
try translateC(comp.gpa, arena, argv.items, prog_node, &stdout);
|
|
||||||
|
|
||||||
if (out_dep_path) |dep_file_path| add_deps: {
|
|
||||||
const dep_basename = fs.path.basename(dep_file_path);
|
|
||||||
// Add the files depended on to the cache system, if a dep file was emitted
|
|
||||||
man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => break :add_deps,
|
|
||||||
else => |e| return e,
|
|
||||||
};
|
|
||||||
// Just to save disk space, we delete the file because it is never needed again.
|
|
||||||
cache_tmp_dir.deleteFile(dep_basename) catch |err| {
|
|
||||||
warn("failed to delete '{s}': {t}", .{ dep_file_path, err });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stdout.len > 0) {
|
|
||||||
var reader: std.Io.Reader = .fixed(stdout);
|
|
||||||
const MessageHeader = std.zig.Server.Message.Header;
|
|
||||||
const header = reader.takeStruct(MessageHeader, .little) catch unreachable;
|
|
||||||
const body = reader.take(header.bytes_len) catch unreachable;
|
|
||||||
switch (header.tag) {
|
|
||||||
.error_bundle => {
|
|
||||||
// TODO: De-dupe this logic
|
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
const error_bundle: std.zig.ErrorBundle = .{
|
|
||||||
.string_bytes = try comp.gpa.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (fancy_output) |p| {
|
|
||||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
|
||||||
p.errors = error_bundle;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
error_bundle.renderToStdErr(color.renderOptions());
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => unreachable, // No other messagse are sent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bin_digest = man.finalBin();
|
|
||||||
const hex_digest = Cache.binToHex(bin_digest);
|
|
||||||
|
|
||||||
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
|
|
||||||
try Compilation.renameTmpIntoCache(
|
|
||||||
comp.dirs.local_cache,
|
|
||||||
tmp_sub_path,
|
|
||||||
o_sub_path,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err});
|
if (result.errors.errorMessageCount() != 0) {
|
||||||
|
if (fancy_output) |p| {
|
||||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||||
|
p.* = result;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const color: Color = .auto;
|
||||||
|
result.errors.renderToStdErr(color.renderOptions());
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break :digest .{ bin_digest, hex_digest };
|
man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err});
|
||||||
|
break :result result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||||
if (fancy_output) |p| {
|
if (fancy_output) |p| {
|
||||||
p.digest = bin_digest;
|
p.* = result;
|
||||||
p.errors = std.zig.ErrorBundle.empty;
|
|
||||||
} else {
|
} else {
|
||||||
const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_zig_basename });
|
const hex_digest = Cache.binToHex(result.digest);
|
||||||
|
const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_basename });
|
||||||
const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| {
|
const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| {
|
||||||
const path = comp.dirs.local_cache.path orelse ".";
|
const path = comp.dirs.local_cache.path orelse ".";
|
||||||
fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{
|
fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{
|
||||||
|
|
|
||||||
|
|
@ -259,20 +259,7 @@ const Eval = struct {
|
||||||
|
|
||||||
switch (header.tag) {
|
switch (header.tag) {
|
||||||
.error_bundle => {
|
.error_bundle => {
|
||||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
|
||||||
const extra_bytes =
|
|
||||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
|
||||||
const string_bytes =
|
|
||||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
|
||||||
// TODO: use @ptrCast when the compiler supports it
|
|
||||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
|
||||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
|
||||||
@memcpy(extra_array, unaligned_extra);
|
|
||||||
const result_error_bundle: std.zig.ErrorBundle = .{
|
|
||||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
|
||||||
.extra = extra_array,
|
|
||||||
};
|
|
||||||
if (stderr.bufferedLen() > 0) {
|
if (stderr.bufferedLen() > 0) {
|
||||||
const stderr_data = try poller.toOwnedSlice(.stderr);
|
const stderr_data = try poller.toOwnedSlice(.stderr);
|
||||||
if (eval.allow_stderr) {
|
if (eval.allow_stderr) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue