mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
Configuration: type safety for extended pattern
This commit is contained in:
@@ -40,8 +40,7 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
|
||||
try deps_field.end();
|
||||
}
|
||||
try step_field.field("max_rss", step.max_rss.toBytes(), .{});
|
||||
const type_erased_flags: Configuration.Step.Flags = @bitCast(c.extra[step.extra_index]);
|
||||
switch (type_erased_flags.tag) {
|
||||
switch (step.extended.get(c.extra)) {
|
||||
.check_file => try step_field.field("check_file", .TODO, .{}),
|
||||
.check_object => try step_field.field("check_object", .TODO, .{}),
|
||||
.compile => try step_field.field("compile", .TODO, .{}),
|
||||
@@ -55,8 +54,7 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void {
|
||||
.options => try step_field.field("options", .TODO, .{}),
|
||||
.remove_dir => try step_field.field("remove_dir", .TODO, .{}),
|
||||
.run => try step_field.field("run", .TODO, .{}),
|
||||
.top_level => {
|
||||
const top_level = c.extraData(Configuration.Step.TopLevel, step.extra_index);
|
||||
.top_level => |top_level| {
|
||||
var sf = try step_field.beginStructField("top_level", .{});
|
||||
try sf.field("description", top_level.description.slice(c), .{});
|
||||
try sf.end();
|
||||
@@ -82,7 +80,7 @@ pub fn printSteps(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void {
|
||||
try std.fmt.allocPrint(arena, "{s} (default)", .{name})
|
||||
else
|
||||
name;
|
||||
const top_level = c.extraData(Configuration.Step.TopLevel, step.extra_index);
|
||||
const top_level = step.extended.get(c.extra).top_level;
|
||||
const description = top_level.description.slice(c);
|
||||
try w.print(" {s:<28} {s}\n", .{ decorated_name, description });
|
||||
}
|
||||
|
||||
@@ -331,12 +331,12 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
|
||||
.owner = try s.builderToPackage(step.owner),
|
||||
.deps = deps,
|
||||
.max_rss = .fromBytes(step.max_rss),
|
||||
.extra_index = switch (step.tag) {
|
||||
.extended = switch (step.tag) {
|
||||
.top_level => e: {
|
||||
const top_level: *Step.TopLevel = @fieldParentPtr("step", step);
|
||||
break :e try wc.addExtra(@as(Configuration.Step.TopLevel, .{
|
||||
break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.TopLevel, .{
|
||||
.description = try wc.addString(top_level.description),
|
||||
}));
|
||||
})));
|
||||
},
|
||||
.compile => e: {
|
||||
const c: *Step.Compile = @fieldParentPtr("step", step);
|
||||
@@ -462,11 +462,11 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
|
||||
|
||||
log.err("TODO serialize the trailing Compile step data", .{});
|
||||
|
||||
break :e extra_index;
|
||||
break :e @enumFromInt(extra_index);
|
||||
},
|
||||
.install_artifact => e: {
|
||||
const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
|
||||
break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
|
||||
break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
|
||||
.flags = .{
|
||||
.dylib_symlinks = ia.dylib_symlinks != null,
|
||||
},
|
||||
@@ -480,7 +480,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
|
||||
.h_dir = try addInstallDir(wc, ia.h_dir),
|
||||
.emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h),
|
||||
.artifact = stepIndex(&step_map, &ia.artifact.step),
|
||||
}));
|
||||
})));
|
||||
},
|
||||
.install_file => @panic("TODO"),
|
||||
.install_dir => @panic("TODO"),
|
||||
@@ -536,7 +536,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
|
||||
|
||||
log.err("TODO serialize the trailing Run step data", .{});
|
||||
|
||||
break :e extra_index;
|
||||
break :e @enumFromInt(extra_index);
|
||||
},
|
||||
.check_file => @panic("TODO"),
|
||||
.check_object => @panic("TODO"),
|
||||
@@ -639,7 +639,7 @@ fn addOptionalResolvedTarget(
|
||||
})));
|
||||
}
|
||||
|
||||
fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDir {
|
||||
fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDestDir {
|
||||
switch (install_dir orelse return .none) {
|
||||
.prefix => return .prefix,
|
||||
.lib => return .lib,
|
||||
|
||||
+176
-13
@@ -397,9 +397,25 @@ pub const Step = extern struct {
|
||||
owner: Package.Index,
|
||||
deps: Deps,
|
||||
max_rss: MaxRss,
|
||||
/// Points into `extra` for step-specific data. First element has flags
|
||||
/// with `Tag`.
|
||||
extra_index: u32,
|
||||
extended: Storage.ExtendedIndex(Flags, union(Tag) {
|
||||
check_file: CheckFile,
|
||||
check_object: CheckObject,
|
||||
compile: Compile,
|
||||
config_header: ConfigHeader,
|
||||
fail: Fail,
|
||||
fmt: Fmt,
|
||||
install_artifact: InstallArtifact,
|
||||
install_dir: InstallDir,
|
||||
install_file: InstallFile,
|
||||
objcopy: Objcopy,
|
||||
options: Options,
|
||||
remove_dir: RemoveDir,
|
||||
run: Run,
|
||||
top_level: TopLevel,
|
||||
translate_c: TranslateC,
|
||||
update_source_files: UpdateSourceFiles,
|
||||
write_file: WriteFile,
|
||||
}),
|
||||
|
||||
/// Points into `steps`.
|
||||
pub const Index = enum(u32) {
|
||||
@@ -449,17 +465,17 @@ pub const Step = extern struct {
|
||||
pub const InstallArtifact = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
dest_dir: InstallDir,
|
||||
dest_dir: InstallDestDir,
|
||||
dest_sub_path: String,
|
||||
emitted_bin: OptionalLazyPath,
|
||||
|
||||
implib_dir: InstallDir,
|
||||
implib_dir: InstallDestDir,
|
||||
emitted_implib: OptionalLazyPath,
|
||||
|
||||
pdb_dir: InstallDir,
|
||||
pdb_dir: InstallDestDir,
|
||||
emitted_pdb: OptionalLazyPath,
|
||||
|
||||
h_dir: InstallDir,
|
||||
h_dir: InstallDestDir,
|
||||
emitted_h: OptionalLazyPath,
|
||||
|
||||
/// Always a compile step.
|
||||
@@ -789,8 +805,125 @@ pub const Step = extern struct {
|
||||
};
|
||||
};
|
||||
|
||||
pub const CheckFile = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .check_file,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const CheckObject = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .check_object,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const ConfigHeader = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .config_header,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Fail = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .fail,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Fmt = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .fmt,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const InstallDir = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .install_dir,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const InstallFile = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .install_file,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Objcopy = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .objcopy,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Options = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .options,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const RemoveDir = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .remove_dir,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const TranslateC = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .translate_c,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const UpdateSourceFiles = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .update_source_files,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const WriteFile = struct {
|
||||
flags: @This().Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .write_file,
|
||||
_: u27 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn flags(s: *const Step, c: *const Configuration) Flags {
|
||||
return @bitCast(c.extra[s.extra_index]);
|
||||
return @bitCast(c.extra[@intFromEnum(s.extended)]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1081,7 +1214,7 @@ pub const Path = extern struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const InstallDir = enum(u32) {
|
||||
pub const InstallDestDir = enum(u32) {
|
||||
none = maxInt(u32) - 4,
|
||||
prefix = maxInt(u32) - 3,
|
||||
lib = maxInt(u32) - 2,
|
||||
@@ -1090,8 +1223,8 @@ pub const InstallDir = enum(u32) {
|
||||
/// A `String` path relative to the prefix.
|
||||
_,
|
||||
|
||||
pub fn initCustom(sub_path: String) InstallDir {
|
||||
assert(@intFromEnum(sub_path) < @intFromEnum(InstallDir.none));
|
||||
pub fn initCustom(sub_path: String) InstallDestDir {
|
||||
assert(@intFromEnum(sub_path) < @intFromEnum(InstallDestDir.none));
|
||||
return @enumFromInt(@intFromEnum(sub_path));
|
||||
}
|
||||
};
|
||||
@@ -1496,7 +1629,10 @@ pub const TargetQuery = struct {
|
||||
|
||||
pub const Storage = enum {
|
||||
flag_optional,
|
||||
extended,
|
||||
|
||||
/// The presence of the field is determined by a boolean within a packed
|
||||
/// struct.
|
||||
pub fn FlagOptional(
|
||||
comptime flags_arg: @EnumLiteral(),
|
||||
comptime flag_arg: @EnumLiteral(),
|
||||
@@ -1512,6 +1648,31 @@ pub const Storage = enum {
|
||||
};
|
||||
}
|
||||
|
||||
/// The field indexes into an auxilary buffer, with the first element being
|
||||
/// a packed struct that contains the tag.
|
||||
pub fn Extended(comptime U: type) type {
|
||||
return struct {
|
||||
value: U,
|
||||
|
||||
pub const storage: Storage = .extended;
|
||||
};
|
||||
}
|
||||
|
||||
/// Equivalent to `Extended` but works in an `extern struct`.
|
||||
pub fn ExtendedIndex(comptime BaseFlags: type, comptime U: type) type {
|
||||
return enum(u32) {
|
||||
_,
|
||||
|
||||
pub fn get(this: @This(), buffer: []const u32) U {
|
||||
var i: usize = @intFromEnum(this);
|
||||
const base_flags: BaseFlags = @bitCast(buffer[i]);
|
||||
return switch (base_flags.tag) {
|
||||
inline else => |tag| @unionInit(U, @tagName(tag), data(buffer, &i, @FieldType(U, @tagName(tag)))),
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn dataLength(buffer: []const u32, i: usize, comptime S: type) usize {
|
||||
var end = i;
|
||||
_ = data(buffer, &end, S);
|
||||
@@ -1536,7 +1697,7 @@ pub const Storage = enum {
|
||||
},
|
||||
64 => {
|
||||
defer i.* += 2;
|
||||
return buffer[i.*..][0..2].*;
|
||||
return @bitCast(buffer[i.*..][0..2].*);
|
||||
},
|
||||
else => comptime unreachable,
|
||||
},
|
||||
@@ -1573,6 +1734,7 @@ pub const Storage = enum {
|
||||
.value = if (flag) dataField(buffer, i, container, Field.Value) else null,
|
||||
};
|
||||
},
|
||||
.extended => @compileError("TODO"),
|
||||
},
|
||||
},
|
||||
.@"extern" => comptime unreachable,
|
||||
@@ -1639,6 +1801,7 @@ pub const Storage = enum {
|
||||
.flag_optional => {
|
||||
return if (value.value) |v| setExtraField(buffer, i, Field.Value, v) else 0;
|
||||
},
|
||||
.extended => @compileError("TODO"),
|
||||
},
|
||||
},
|
||||
.@"extern" => comptime unreachable,
|
||||
@@ -1662,7 +1825,7 @@ pub const Storage = enum {
|
||||
else => comptime unreachable,
|
||||
},
|
||||
.auto => switch (Field.storage) {
|
||||
.flag_optional => 1,
|
||||
.flag_optional, .extended => 1,
|
||||
},
|
||||
.@"extern" => comptime unreachable,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user