authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-08 16:03:03-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
log315d6ee59b42c07ac0a4e31924ce229d7c5afc32
treef5a50bb5784ef21e4ee4de28bd0aa5db399668cc
parent7e6be7ee6ee4223a4ef2b247002358cbfc714854

configurer: serialize Step.ConfigHeader


4 files changed, 197 insertions(+), 35 deletions(-)

BRANCH_TODO+1
...@@ -76,3 +76,4 @@ closes #31397...@@ -76,3 +76,4 @@ closes #31397
76### std.Build API76### std.Build API
7777
78* `b.build_root` (Directory) -> `b.root` (Path)78* `b.build_root` (Directory) -> `b.root` (Path)
79* `ConfigHeader.Options`: `include_guard_override` -> `include_guard`
lib/compiler/configurer.zig+57-1
...@@ -1064,7 +1064,63 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {...@@ -1064,7 +1064,63 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
1064 .max_bytes = .{ .value = cf.max_bytes },1064 .max_bytes = .{ .value = cf.max_bytes },
1065 })));1065 })));
1066 },1066 },
1067 .config_header => @panic("TODO"),1067 .config_header => e: {
1068 const ch: *Step.ConfigHeader = @fieldParentPtr("step", step);
1069 const lazy_path: ?std.Build.LazyPath = ch.style.getPath();
1070 const pairs = try arena.alloc(Configuration.Step.ConfigHeader.Value.Pair, ch.values.count());
1071 for (pairs, ch.values.keys(), ch.values.values()) |*pair, key, value| pair.* = .{
1072 .key = try wc.addString(key),
1073 .index = switch (value) {
1074 .undef => .undef,
1075 .defined => .defined,
1076 .boolean => |x| switch (x) {
1077 false => .bool_false,
1078 true => .bool_true,
1079 },
1080 .int => |x| switch (x) {
1081 0 => .int_0,
1082 1 => .int_1,
1083 else => @enumFromInt(try wc.addExtra(
1084 Configuration.Step.ConfigHeader.Value.initSigned(x),
1085 )),
1086 },
1087 .ident => |x| @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader.Value, .{
1088 .flags = .{
1089 .tag = .ident,
1090 .small = 0,
1091 },
1092 .i64 = .{ .value = null },
1093 .u64 = .{ .value = null },
1094 .ident = .{ .value = try wc.addString(x) },
1095 .string = .{ .value = null },
1096 }))),
1097 .string => |x| @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader.Value, .{
1098 .flags = .{
1099 .tag = .string,
1100 .small = 0,
1101 },
1102 .i64 = .{ .value = null },
1103 .u64 = .{ .value = null },
1104 .ident = .{ .value = null },
1105 .string = .{ .value = try wc.addString(x) },
1106 }))),
1107 },
1108 };
1109 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader, .{
1110 .flags = .{
1111 .template_file = lazy_path != null,
1112 .style = .init(ch.style),
1113 .input_size_limit = ch.input_size_limit != null,
1114 .include_guard = ch.include_guard != .none,
1115 },
1116 .template_file = .{ .value = try s.addOptionalLazyPath(lazy_path) },
1117 .generated_dir = ch.generated_dir,
1118 .input_size_limit = .{ .value = ch.input_size_limit },
1119 .include_path = try wc.addString(ch.include_path),
1120 .include_guard = .{ .value = ch.include_guard.unwrap() },
1121 .values = .{ .slice = pairs },
1122 })));
1123 },
1068 .obj_copy => e: {1124 .obj_copy => e: {
1069 const oc: *Step.ObjCopy = @fieldParentPtr("step", step);1125 const oc: *Step.ObjCopy = @fieldParentPtr("step", step);
10701126
lib/std/Build/Configuration.zig+103-1
...@@ -1029,10 +1029,112 @@ pub const Step = extern struct {...@@ -1029,10 +1029,112 @@ pub const Step = extern struct {
10291029
1030 pub const ConfigHeader = struct {1030 pub const ConfigHeader = struct {
1031 flags: @This().Flags,1031 flags: @This().Flags,
1032 template_file: Storage.FlagOptional(.flags, .template_file, LazyPath.Index),
1033 generated_dir: GeneratedFileIndex,
1034 input_size_limit: Storage.FlagOptional(.flags, .input_size_limit, u64),
1035 include_path: String,
1036 include_guard: Storage.FlagOptional(.flags, .include_guard, String),
1037 values: Storage.LengthPrefixedList(Value.Pair),
1038
1039 pub const Style = enum(u3) {
1040 autoconf_undef,
1041 autoconf_at,
1042 cmake,
1043 blank,
1044 nasm,
1045
1046 pub fn init(s: std.Build.Step.ConfigHeader.Style) Style {
1047 return switch (s) {
1048 .autoconf_undef => .autoconf_undef,
1049 .autoconf_at => .autoconf_at,
1050 .cmake => .cmake,
1051 .blank => .blank,
1052 .nasm => .nasm,
1053 };
1054 }
1055 };
1056
1057 pub const Value = struct {
1058 flags: @This().Flags,
1059 i64: Storage.EnumOptional(.flags, .tag, .i64, i64),
1060 u64: Storage.EnumOptional(.flags, .tag, .u64, u64),
1061 ident: Storage.EnumOptional(.flags, .tag, .ident, String),
1062 string: Storage.EnumOptional(.flags, .tag, .string, String),
1063
1064 pub const Flags = packed struct(u32) {
1065 tag: Value.Tag,
1066 small: u29,
1067 };
1068
1069 pub const Tag = enum(u3) {
1070 ident,
1071 string,
1072 small_unsigned,
1073 small_signed,
1074 i64,
1075 u64,
1076 };
1077
1078 pub const Pair = extern struct {
1079 key: String,
1080 index: Value.Index,
1081 };
1082
1083 pub const Index = enum(u32) {
1084 int_0 = max_u32 - 5,
1085 int_1 = max_u32 - 4,
1086 bool_false = max_u32 - 3,
1087 bool_true = max_u32 - 2,
1088 undef = max_u32 - 1,
1089 defined = max_u32,
1090 _,
1091 };
1092
1093 pub fn initSigned(x: i64) @This() {
1094 return switch (x) {
1095 0 => unreachable, // should have been an Index
1096 1 => unreachable, // should have been an Index
1097 2...std.math.maxInt(u29) => .{
1098 .flags = .{
1099 .tag = .small_unsigned,
1100 .small = @intCast(x),
1101 },
1102 .i64 = .{ .value = null },
1103 .u64 = .{ .value = null },
1104 .ident = .{ .value = null },
1105 .string = .{ .value = null },
1106 },
1107 std.math.minInt(i29)...-1 => .{
1108 .flags = .{
1109 .tag = .small_signed,
1110 .small = @bitCast(@as(i29, @intCast(x))),
1111 },
1112 .i64 = .{ .value = null },
1113 .u64 = .{ .value = null },
1114 .ident = .{ .value = null },
1115 .string = .{ .value = null },
1116 },
1117 else => .{
1118 .flags = .{
1119 .tag = .i64,
1120 .small = 0,
1121 },
1122 .i64 = .{ .value = x },
1123 .u64 = .{ .value = null },
1124 .ident = .{ .value = null },
1125 .string = .{ .value = null },
1126 },
1127 };
1128 }
1129 };
10321130
1033 pub const Flags = packed struct(u32) {1131 pub const Flags = packed struct(u32) {
1034 tag: Tag = .config_header,1132 tag: Tag = .config_header,
1035 _: u27 = 0,1133 template_file: bool,
1134 style: Style,
1135 input_size_limit: bool,
1136 include_guard: bool,
1137 _: u21 = 0,
1036 };1138 };
1037 };1139 };
10381140
lib/std/Build/Step/ConfigHeader.zig+36-33
...@@ -5,16 +5,17 @@ const Io = std.Io;...@@ -5,16 +5,17 @@ const Io = std.Io;
5const Step = std.Build.Step;5const Step = std.Build.Step;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
7const Configuration = std.Build.Configuration;7const Configuration = std.Build.Configuration;
8const allocPrint = std.fmt.allocPrint;
89
9step: Step,10step: Step,
10values: std.array_hash_map.String(Value),11values: std.array_hash_map.String(Value) = .empty,
11/// This directory contains the generated file under the name `include_path`.12/// This directory contains the generated file under the name `include_path`.
12generated_dir: Configuration.GeneratedFileIndex,13generated_dir: Configuration.GeneratedFileIndex,
1314
14style: Style,15style: Style,
15max_bytes: usize,16input_size_limit: ?u64,
16include_path: []const u8,17include_path: []const u8,
17include_guard_override: ?[]const u8,18include_guard: Configuration.OptionalString,
1819
19pub const base_tag: Step.Tag = .config_header;20pub const base_tag: Step.Tag = .config_header;
2021
...@@ -51,42 +52,45 @@ pub const Value = union(enum) {...@@ -51,42 +52,45 @@ pub const Value = union(enum) {
5152
52pub const Options = struct {53pub const Options = struct {
53 style: Style = .blank,54 style: Style = .blank,
54 max_bytes: usize = 2 * 1024 * 1024,55 max_bytes: ?u64 = null,
55 include_path: ?[]const u8 = null,56 include_path: ?[]const u8 = null,
57 include_guard: ?[]const u8 = null,
56 first_ret_addr: ?usize = null,58 first_ret_addr: ?usize = null,
57 include_guard_override: ?[]const u8 = null,
58};59};
5960
60pub fn create(owner: *std.Build, options: Options) *ConfigHeader {61pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
61 const graph = owner.graph;62 const graph = owner.graph;
62 const arena = graph.arena;63 const arena = graph.arena;
63 const config_header = arena.create(ConfigHeader) catch @panic("OOM");64 const wc = &graph.wip_configuration;
6465 const config_header = graph.create(ConfigHeader);
65 var include_path: []const u8 = "config.h";66
6667 const include_path: []const u8 = p: {
67 if (options.style.getPath()) |s| default_include_path: {68 if (options.include_path) |p|
68 const wc = &graph.wip_configuration;69 break :p graph.dupeString(p);
69 const sub_path = switch (s) {70
70 .src_path => |sp| sp.sub_path,71 if (options.style.getPath()) |s| default: {
71 .generated => break :default_include_path,72 const sub_path = switch (s) {
72 .cwd_relative => |sub_path| sub_path,73 .src_path => |sp| sp.sub_path,
73 .relative => |r| wc.stringSlice(r.sub_path),74 .generated => break :default,
74 .dependency => |dependency| dependency.sub_path,75 .cwd_relative => |sub_path| sub_path,
75 };76 .relative => |r| wc.stringSlice(r.sub_path),
76 const basename = std.fs.path.basename(sub_path);77 .dependency => |dependency| dependency.sub_path,
77 if (std.mem.endsWith(u8, basename, ".h.in")) {78 };
78 include_path = basename[0 .. basename.len - 3];79 const basename = Io.Dir.path.basename(sub_path);
80 if (std.mem.endsWith(u8, basename, ".h.in"))
81 break :p graph.dupeString(basename[0 .. basename.len - 3]);
79 }82 }
80 }83 break :p "config.h";
8184 };
82 if (options.include_path) |p| {
83 include_path = p;
84 }
8585
86 const name = if (options.style.getPath()) |s|86 const name = if (options.style.getPath()) |s|
87 owner.fmt("configure {t} header {f} to {s}", .{ options.style, s.fmt(graph), include_path })87 allocPrint(arena, "configure {t} header {f} to {s}", .{
88 options.style, s.fmt(graph), include_path,
89 }) catch @panic("OOM")
88 else90 else
89 owner.fmt("configure {t} header to {s}", .{ options.style, include_path });91 allocPrint(arena, "configure {t} header to {s}", .{
92 options.style, include_path,
93 }) catch @panic("OOM");
9094
91 config_header.* = .{95 config_header.* = .{
92 .step = .init(.{96 .step = .init(.{
...@@ -96,11 +100,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {...@@ -96,11 +100,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
96 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),100 .first_ret_addr = options.first_ret_addr orelse @returnAddress(),
97 }),101 }),
98 .style = options.style,102 .style = options.style,
99 .values = .empty,103 .input_size_limit = options.max_bytes,
100104 .include_path = include_path,
101 .max_bytes = options.max_bytes,105 .include_guard = if (options.include_guard) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
102 .include_path = graph.dupeString(include_path),
103 .include_guard_override = options.include_guard_override,
104 .generated_dir = graph.addGeneratedFile(&config_header.step),106 .generated_dir = graph.addGeneratedFile(&config_header.step),
105 };107 };
106108
...@@ -179,6 +181,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void {...@@ -179,6 +181,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void {
179pub fn getOutputDir(ch: *ConfigHeader) std.Build.LazyPath {181pub fn getOutputDir(ch: *ConfigHeader) std.Build.LazyPath {
180 return .{ .generated = .{ .index = ch.generated_dir } };182 return .{ .generated = .{ .index = ch.generated_dir } };
181}183}
184
182pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {185pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {
183 return ch.getOutputDir().path(ch.step.owner, ch.include_path);186 return ch.getOutputDir().path(ch.step.owner, ch.include_path);
184}187}