mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
incr-check: specify backend in manifest, allow multiple targets/backends
This commit is contained in:
parent
1714b74edf
commit
054dbb6798
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
pub fn main() void {}
|
pub fn main() void {}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const MyEnum = enum(u8) {
|
const MyEnum = enum(u8) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const SomeType = u32;
|
const SomeType = u32;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-linux-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -3,13 +3,7 @@ const fatal = std.process.fatal;
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Cache = std.Build.Cache;
|
const Cache = std.Build.Cache;
|
||||||
|
|
||||||
const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--debug-link] [--emit none|bin|c] [--zig-cc-binary /path/to/zig]";
|
const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--debug-link] [--zig-cc-binary /path/to/zig]";
|
||||||
|
|
||||||
const EmitMode = enum {
|
|
||||||
none,
|
|
||||||
bin,
|
|
||||||
c,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
@ -20,7 +14,6 @@ pub fn main() !void {
|
|||||||
var opt_input_file_name: ?[]const u8 = null;
|
var opt_input_file_name: ?[]const u8 = null;
|
||||||
var opt_lib_dir: ?[]const u8 = null;
|
var opt_lib_dir: ?[]const u8 = null;
|
||||||
var opt_cc_zig: ?[]const u8 = null;
|
var opt_cc_zig: ?[]const u8 = null;
|
||||||
var emit: EmitMode = .bin;
|
|
||||||
var debug_zcu = false;
|
var debug_zcu = false;
|
||||||
var debug_link = false;
|
var debug_link = false;
|
||||||
|
|
||||||
@ -28,11 +21,7 @@ pub fn main() !void {
|
|||||||
_ = arg_it.skip();
|
_ = arg_it.skip();
|
||||||
while (arg_it.next()) |arg| {
|
while (arg_it.next()) |arg| {
|
||||||
if (arg.len > 0 and arg[0] == '-') {
|
if (arg.len > 0 and arg[0] == '-') {
|
||||||
if (std.mem.eql(u8, arg, "--emit")) {
|
if (std.mem.eql(u8, arg, "--zig-lib-dir")) {
|
||||||
const emit_str = arg_it.next() orelse fatal("expected arg after '--emit'\n{s}", .{usage});
|
|
||||||
emit = std.meta.stringToEnum(EmitMode, emit_str) orelse
|
|
||||||
fatal("invalid emit mode '{s}'\n{s}", .{ emit_str, usage });
|
|
||||||
} else if (std.mem.eql(u8, arg, "--zig-lib-dir")) {
|
|
||||||
opt_lib_dir = arg_it.next() orelse fatal("expected arg after '--zig-lib-dir'\n{s}", .{usage});
|
opt_lib_dir = arg_it.next() orelse fatal("expected arg after '--zig-lib-dir'\n{s}", .{usage});
|
||||||
} else if (std.mem.eql(u8, arg, "--debug-zcu")) {
|
} else if (std.mem.eql(u8, arg, "--debug-zcu")) {
|
||||||
debug_zcu = true;
|
debug_zcu = true;
|
||||||
@ -76,6 +65,11 @@ pub fn main() !void {
|
|||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
|
||||||
|
const debug_log_verbose = debug_zcu or debug_link;
|
||||||
|
|
||||||
|
for (case.targets) |target| {
|
||||||
|
std.log.scoped(.status).info("target: '{s}-{s}'", .{ target.query, @tagName(target.backend) });
|
||||||
|
|
||||||
var child_args: std.ArrayListUnmanaged([]const u8) = .empty;
|
var child_args: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||||
try child_args.appendSlice(arena, &.{
|
try child_args.appendSlice(arena, &.{
|
||||||
resolved_zig_exe,
|
resolved_zig_exe,
|
||||||
@ -83,7 +77,7 @@ pub fn main() !void {
|
|||||||
case.root_source_file,
|
case.root_source_file,
|
||||||
"-fincremental",
|
"-fincremental",
|
||||||
"-target",
|
"-target",
|
||||||
case.target_query,
|
target.query,
|
||||||
"--cache-dir",
|
"--cache-dir",
|
||||||
".local-cache",
|
".local-cache",
|
||||||
"--global-cache-dir",
|
"--global-cache-dir",
|
||||||
@ -93,10 +87,11 @@ pub fn main() !void {
|
|||||||
if (opt_resolved_lib_dir) |resolved_lib_dir| {
|
if (opt_resolved_lib_dir) |resolved_lib_dir| {
|
||||||
try child_args.appendSlice(arena, &.{ "--zig-lib-dir", resolved_lib_dir });
|
try child_args.appendSlice(arena, &.{ "--zig-lib-dir", resolved_lib_dir });
|
||||||
}
|
}
|
||||||
switch (emit) {
|
switch (target.backend) {
|
||||||
.bin => try child_args.appendSlice(arena, &.{ "-fno-llvm", "-fno-lld" }),
|
.sema => try child_args.append(arena, "-fno-emit-bin"),
|
||||||
.none => try child_args.append(arena, "-fno-emit-bin"),
|
.selfhosted => try child_args.appendSlice(arena, &.{ "-fno-llvm", "-fno-lld" }),
|
||||||
.c => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }),
|
.llvm => try child_args.appendSlice(arena, &.{ "-fllvm", "-flld" }),
|
||||||
|
.cbe => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }),
|
||||||
}
|
}
|
||||||
if (debug_zcu) {
|
if (debug_zcu) {
|
||||||
try child_args.appendSlice(arena, &.{ "--debug-log", "zcu" });
|
try child_args.appendSlice(arena, &.{ "--debug-log", "zcu" });
|
||||||
@ -105,8 +100,6 @@ pub fn main() !void {
|
|||||||
try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" });
|
try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const debug_log_verbose = debug_zcu or debug_link;
|
|
||||||
|
|
||||||
var child = std.process.Child.init(child_args.items, arena);
|
var child = std.process.Child.init(child_args.items, arena);
|
||||||
child.stdin_behavior = .Pipe;
|
child.stdin_behavior = .Pipe;
|
||||||
child.stdout_behavior = .Pipe;
|
child.stdout_behavior = .Pipe;
|
||||||
@ -116,7 +109,7 @@ pub fn main() !void {
|
|||||||
child.cwd = tmp_dir_path;
|
child.cwd = tmp_dir_path;
|
||||||
|
|
||||||
var cc_child_args: std.ArrayListUnmanaged([]const u8) = .empty;
|
var cc_child_args: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||||
if (emit == .c) {
|
if (target.backend == .cbe) {
|
||||||
const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe|
|
const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe|
|
||||||
try std.fs.path.relative(arena, tmp_dir_path, cc_zig_exe)
|
try std.fs.path.relative(arena, tmp_dir_path, cc_zig_exe)
|
||||||
else
|
else
|
||||||
@ -126,9 +119,9 @@ pub fn main() !void {
|
|||||||
resolved_cc_zig_exe,
|
resolved_cc_zig_exe,
|
||||||
"cc",
|
"cc",
|
||||||
"-target",
|
"-target",
|
||||||
case.target_query,
|
target.query,
|
||||||
"-I",
|
"-I",
|
||||||
opt_resolved_lib_dir orelse fatal("'--zig-lib-dir' required when using '--emit c'", .{}),
|
opt_resolved_lib_dir orelse fatal("'--zig-lib-dir' required when using backend 'cbe'", .{}),
|
||||||
"-o",
|
"-o",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -136,11 +129,11 @@ pub fn main() !void {
|
|||||||
var eval: Eval = .{
|
var eval: Eval = .{
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
.case = case,
|
.case = case,
|
||||||
|
.target = target,
|
||||||
.tmp_dir = tmp_dir,
|
.tmp_dir = tmp_dir,
|
||||||
.tmp_dir_path = tmp_dir_path,
|
.tmp_dir_path = tmp_dir_path,
|
||||||
.child = &child,
|
.child = &child,
|
||||||
.allow_stderr = debug_log_verbose,
|
.allow_stderr = debug_log_verbose,
|
||||||
.emit = emit,
|
|
||||||
.cc_child_args = &cc_child_args,
|
.cc_child_args = &cc_child_args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -157,7 +150,7 @@ pub fn main() !void {
|
|||||||
defer update_node.end();
|
defer update_node.end();
|
||||||
|
|
||||||
if (debug_log_verbose) {
|
if (debug_log_verbose) {
|
||||||
std.log.info("=== START UPDATE '{s}' ===", .{update.name});
|
std.log.scoped(.status).info("update: '{s}'", .{update.name});
|
||||||
}
|
}
|
||||||
|
|
||||||
eval.write(update);
|
eval.write(update);
|
||||||
@ -169,16 +162,17 @@ pub fn main() !void {
|
|||||||
|
|
||||||
waitChild(&child);
|
waitChild(&child);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Eval = struct {
|
const Eval = struct {
|
||||||
arena: Allocator,
|
arena: Allocator,
|
||||||
case: Case,
|
case: Case,
|
||||||
|
target: Case.Target,
|
||||||
tmp_dir: std.fs.Dir,
|
tmp_dir: std.fs.Dir,
|
||||||
tmp_dir_path: []const u8,
|
tmp_dir_path: []const u8,
|
||||||
child: *std.process.Child,
|
child: *std.process.Child,
|
||||||
allow_stderr: bool,
|
allow_stderr: bool,
|
||||||
emit: EmitMode,
|
/// When `target.backend == .cbe`, this contains the first few arguments to `zig cc` to build the generated binary.
|
||||||
/// When `emit == .c`, this contains the first few arguments to `zig cc` to build the generated binary.
|
|
||||||
/// The arguments `out.c in.c` must be appended before spawning the subprocess.
|
/// The arguments `out.c in.c` must be appended before spawning the subprocess.
|
||||||
cc_child_args: *std.ArrayListUnmanaged([]const u8),
|
cc_child_args: *std.ArrayListUnmanaged([]const u8),
|
||||||
|
|
||||||
@ -262,7 +256,7 @@ const Eval = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eval.emit == .none) {
|
if (eval.target.backend == .sema) {
|
||||||
try eval.checkSuccessOutcome(update, null, prog_node);
|
try eval.checkSuccessOutcome(update, null, prog_node);
|
||||||
// This message indicates the end of the update.
|
// This message indicates the end of the update.
|
||||||
stdout.discard(body.len);
|
stdout.discard(body.len);
|
||||||
@ -275,11 +269,11 @@ const Eval = struct {
|
|||||||
const bin_name = try std.zig.binNameAlloc(arena, .{
|
const bin_name = try std.zig.binNameAlloc(arena, .{
|
||||||
.root_name = name,
|
.root_name = name,
|
||||||
.target = try std.zig.system.resolveTargetQuery(try std.Build.parseTargetQuery(.{
|
.target = try std.zig.system.resolveTargetQuery(try std.Build.parseTargetQuery(.{
|
||||||
.arch_os_abi = eval.case.target_query,
|
.arch_os_abi = eval.target.query,
|
||||||
.object_format = switch (eval.emit) {
|
.object_format = switch (eval.target.backend) {
|
||||||
.none => unreachable,
|
.sema => unreachable,
|
||||||
.bin => null,
|
.selfhosted, .llvm => null,
|
||||||
.c => "c",
|
.cbe => "c",
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
.output_mode = .Exe,
|
.output_mode = .Exe,
|
||||||
@ -335,14 +329,14 @@ const Eval = struct {
|
|||||||
.stdout, .exit_code => {},
|
.stdout, .exit_code => {},
|
||||||
}
|
}
|
||||||
const emitted_path = opt_emitted_path orelse {
|
const emitted_path = opt_emitted_path orelse {
|
||||||
std.debug.assert(eval.emit == .none);
|
std.debug.assert(eval.target.backend == .sema);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const binary_path = switch (eval.emit) {
|
const binary_path = switch (eval.target.backend) {
|
||||||
.none => unreachable,
|
.sema => unreachable,
|
||||||
.bin => emitted_path,
|
.selfhosted, .llvm => emitted_path,
|
||||||
.c => bin: {
|
.cbe => bin: {
|
||||||
const rand_int = std.crypto.random.int(u64);
|
const rand_int = std.crypto.random.int(u64);
|
||||||
const out_bin_name = "./out_" ++ std.fmt.hex(rand_int);
|
const out_bin_name = "./out_" ++ std.fmt.hex(rand_int);
|
||||||
try eval.buildCOutput(update, emitted_path, out_bin_name, prog_node);
|
try eval.buildCOutput(update, emitted_path, out_bin_name, prog_node);
|
||||||
@ -468,7 +462,26 @@ const Eval = struct {
|
|||||||
const Case = struct {
|
const Case = struct {
|
||||||
updates: []Update,
|
updates: []Update,
|
||||||
root_source_file: []const u8,
|
root_source_file: []const u8,
|
||||||
target_query: []const u8,
|
targets: []const Target,
|
||||||
|
|
||||||
|
const Target = struct {
|
||||||
|
query: []const u8,
|
||||||
|
backend: Backend,
|
||||||
|
const Backend = enum {
|
||||||
|
/// Run semantic analysis only. Runtime output will not be tested, but we still verify
|
||||||
|
/// that compilation succeeds. Corresponds to `-fno-emit-bin`.
|
||||||
|
sema,
|
||||||
|
/// Use the self-hosted code generation backend for this target.
|
||||||
|
/// Corresponds to `-fno-llvm -fno-lld`.
|
||||||
|
selfhosted,
|
||||||
|
/// Use the LLVM backend.
|
||||||
|
/// Corresponds to `-fllvm -flld`.
|
||||||
|
llvm,
|
||||||
|
/// Use the C backend. The output is compiled with `zig cc`.
|
||||||
|
/// Corresponds to `-ofmt=c`.
|
||||||
|
cbe,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const Update = struct {
|
const Update = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
@ -498,9 +511,9 @@ const Case = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn parse(arena: Allocator, bytes: []const u8) !Case {
|
fn parse(arena: Allocator, bytes: []const u8) !Case {
|
||||||
|
var targets: std.ArrayListUnmanaged(Target) = .empty;
|
||||||
var updates: std.ArrayListUnmanaged(Update) = .empty;
|
var updates: std.ArrayListUnmanaged(Update) = .empty;
|
||||||
var changes: std.ArrayListUnmanaged(FullContents) = .empty;
|
var changes: std.ArrayListUnmanaged(FullContents) = .empty;
|
||||||
var target_query: ?[]const u8 = null;
|
|
||||||
var it = std.mem.splitScalar(u8, bytes, '\n');
|
var it = std.mem.splitScalar(u8, bytes, '\n');
|
||||||
var line_n: usize = 1;
|
var line_n: usize = 1;
|
||||||
var root_source_file: ?[]const u8 = null;
|
var root_source_file: ?[]const u8 = null;
|
||||||
@ -512,8 +525,16 @@ const Case = struct {
|
|||||||
if (val.len == 0) {
|
if (val.len == 0) {
|
||||||
fatal("line {d}: missing value", .{line_n});
|
fatal("line {d}: missing value", .{line_n});
|
||||||
} else if (std.mem.eql(u8, key, "target")) {
|
} else if (std.mem.eql(u8, key, "target")) {
|
||||||
if (target_query != null) fatal("line {d}: duplicate target", .{line_n});
|
const split_idx = std.mem.lastIndexOfScalar(u8, val, '-') orelse
|
||||||
target_query = val;
|
fatal("line {d}: target does not include backend", .{line_n});
|
||||||
|
const query = val[0..split_idx];
|
||||||
|
const backend_str = val[split_idx + 1 ..];
|
||||||
|
const backend: Target.Backend = std.meta.stringToEnum(Target.Backend, backend_str) orelse
|
||||||
|
fatal("line {d}: invalid backend '{s}'", .{ line_n, backend_str });
|
||||||
|
try targets.append(arena, .{
|
||||||
|
.query = query,
|
||||||
|
.backend = backend,
|
||||||
|
});
|
||||||
} else if (std.mem.eql(u8, key, "update")) {
|
} else if (std.mem.eql(u8, key, "update")) {
|
||||||
if (updates.items.len > 0) {
|
if (updates.items.len > 0) {
|
||||||
const last_update = &updates.items[updates.items.len - 1];
|
const last_update = &updates.items[updates.items.len - 1];
|
||||||
@ -565,15 +586,19 @@ const Case = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targets.items.len == 0) {
|
||||||
|
fatal("missing target", .{});
|
||||||
|
}
|
||||||
|
|
||||||
if (changes.items.len > 0) {
|
if (changes.items.len > 0) {
|
||||||
const last_update = &updates.items[updates.items.len - 1];
|
const last_update = &updates.items[updates.items.len - 1];
|
||||||
last_update.changes = try changes.toOwnedSlice(arena);
|
last_update.changes = changes.items; // arena so no need for toOwnedSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.updates = updates.items,
|
.updates = updates.items,
|
||||||
.root_source_file = root_source_file orelse fatal("missing root source file", .{}),
|
.root_source_file = root_source_file orelse fatal("missing root source file", .{}),
|
||||||
.target_query = target_query orelse fatal("missing target", .{}),
|
.targets = targets.items, // arena so no need for toOwnedSlice
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user