diff --git a/BRANCH_TODO b/BRANCH_TODO index d65507f95d0a184fdbd5a8d9500460e1703cfab0..b54140d4a0fee66c9fc59a3dca66b906cf3f3d53 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -76,3 +76,4 @@ closes #31397 ### std.Build API * `b.build_root` (Directory) -> `b.root` (Path) +* `ConfigHeader.Options`: `include_guard_override` -> `include_guard` diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig index a7ef5429ff26a3ed8323209257333e2d8bf827a9..b8a0f6097133c3f6178e52f37246084840e15b5a 100644 --- a/lib/compiler/configurer.zig +++ b/lib/compiler/configurer.zig @@ -1064,7 +1064,63 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { .max_bytes = .{ .value = cf.max_bytes }, }))); }, - .config_header => @panic("TODO"), + .config_header => e: { + const ch: *Step.ConfigHeader = @fieldParentPtr("step", step); + const lazy_path: ?std.Build.LazyPath = ch.style.getPath(); + const pairs = try arena.alloc(Configuration.Step.ConfigHeader.Value.Pair, ch.values.count()); + for (pairs, ch.values.keys(), ch.values.values()) |*pair, key, value| pair.* = .{ + .key = try wc.addString(key), + .index = switch (value) { + .undef => .undef, + .defined => .defined, + .boolean => |x| switch (x) { + false => .bool_false, + true => .bool_true, + }, + .int => |x| switch (x) { + 0 => .int_0, + 1 => .int_1, + else => @enumFromInt(try wc.addExtra( + Configuration.Step.ConfigHeader.Value.initSigned(x), + )), + }, + .ident => |x| @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader.Value, .{ + .flags = .{ + .tag = .ident, + .small = 0, + }, + .i64 = .{ .value = null }, + .u64 = .{ .value = null }, + .ident = .{ .value = try wc.addString(x) }, + .string = .{ .value = null }, + }))), + .string => |x| @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader.Value, .{ + .flags = .{ + .tag = .string, + .small = 0, + }, + .i64 = .{ .value = null }, + .u64 = .{ .value = null }, + .ident = .{ .value = null }, + .string = .{ .value = try wc.addString(x) }, + }))), + }, + }; + break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.ConfigHeader, .{ + .flags = .{ + .template_file = lazy_path != null, + .style = .init(ch.style), + .input_size_limit = ch.input_size_limit != null, + .include_guard = ch.include_guard != .none, + }, + .template_file = .{ .value = try s.addOptionalLazyPath(lazy_path) }, + .generated_dir = ch.generated_dir, + .input_size_limit = .{ .value = ch.input_size_limit }, + .include_path = try wc.addString(ch.include_path), + .include_guard = .{ .value = ch.include_guard.unwrap() }, + .values = .{ .slice = pairs }, + }))); + }, .obj_copy => e: { const oc: *Step.ObjCopy = @fieldParentPtr("step", step); diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig index 15986804057d8350d0e1ef8f652c5c7129704c3c..2a15f3362d36a8b917d65b4d670c3bfa9685c477 100644 --- a/lib/std/Build/Configuration.zig +++ b/lib/std/Build/Configuration.zig @@ -1029,10 +1029,112 @@ pub const Step = extern struct { pub const ConfigHeader = struct { flags: @This().Flags, + template_file: Storage.FlagOptional(.flags, .template_file, LazyPath.Index), + generated_dir: GeneratedFileIndex, + input_size_limit: Storage.FlagOptional(.flags, .input_size_limit, u64), + include_path: String, + include_guard: Storage.FlagOptional(.flags, .include_guard, String), + values: Storage.LengthPrefixedList(Value.Pair), + + pub const Style = enum(u3) { + autoconf_undef, + autoconf_at, + cmake, + blank, + nasm, + + pub fn init(s: std.Build.Step.ConfigHeader.Style) Style { + return switch (s) { + .autoconf_undef => .autoconf_undef, + .autoconf_at => .autoconf_at, + .cmake => .cmake, + .blank => .blank, + .nasm => .nasm, + }; + } + }; + + pub const Value = struct { + flags: @This().Flags, + i64: Storage.EnumOptional(.flags, .tag, .i64, i64), + u64: Storage.EnumOptional(.flags, .tag, .u64, u64), + ident: Storage.EnumOptional(.flags, .tag, .ident, String), + string: Storage.EnumOptional(.flags, .tag, .string, String), + + pub const Flags = packed struct(u32) { + tag: Value.Tag, + small: u29, + }; + + pub const Tag = enum(u3) { + ident, + string, + small_unsigned, + small_signed, + i64, + u64, + }; + + pub const Pair = extern struct { + key: String, + index: Value.Index, + }; + + pub const Index = enum(u32) { + int_0 = max_u32 - 5, + int_1 = max_u32 - 4, + bool_false = max_u32 - 3, + bool_true = max_u32 - 2, + undef = max_u32 - 1, + defined = max_u32, + _, + }; + + pub fn initSigned(x: i64) @This() { + return switch (x) { + 0 => unreachable, // should have been an Index + 1 => unreachable, // should have been an Index + 2...std.math.maxInt(u29) => .{ + .flags = .{ + .tag = .small_unsigned, + .small = @intCast(x), + }, + .i64 = .{ .value = null }, + .u64 = .{ .value = null }, + .ident = .{ .value = null }, + .string = .{ .value = null }, + }, + std.math.minInt(i29)...-1 => .{ + .flags = .{ + .tag = .small_signed, + .small = @bitCast(@as(i29, @intCast(x))), + }, + .i64 = .{ .value = null }, + .u64 = .{ .value = null }, + .ident = .{ .value = null }, + .string = .{ .value = null }, + }, + else => .{ + .flags = .{ + .tag = .i64, + .small = 0, + }, + .i64 = .{ .value = x }, + .u64 = .{ .value = null }, + .ident = .{ .value = null }, + .string = .{ .value = null }, + }, + }; + } + }; pub const Flags = packed struct(u32) { tag: Tag = .config_header, - _: u27 = 0, + template_file: bool, + style: Style, + input_size_limit: bool, + include_guard: bool, + _: u21 = 0, }; }; diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 026496fe4a08378cbe89b1b8f2dda947b5108747..55b9a617f2e1670e3c32140b43f2aba3c450000a 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -5,16 +5,17 @@ const Io = std.Io; const Step = std.Build.Step; const Allocator = std.mem.Allocator; const Configuration = std.Build.Configuration; +const allocPrint = std.fmt.allocPrint; step: Step, -values: std.array_hash_map.String(Value), +values: std.array_hash_map.String(Value) = .empty, /// This directory contains the generated file under the name `include_path`. generated_dir: Configuration.GeneratedFileIndex, style: Style, -max_bytes: usize, +input_size_limit: ?u64, include_path: []const u8, -include_guard_override: ?[]const u8, +include_guard: Configuration.OptionalString, pub const base_tag: Step.Tag = .config_header; @@ -51,42 +52,45 @@ pub const Value = union(enum) { pub const Options = struct { style: Style = .blank, - max_bytes: usize = 2 * 1024 * 1024, + max_bytes: ?u64 = null, include_path: ?[]const u8 = null, + include_guard: ?[]const u8 = null, first_ret_addr: ?usize = null, - include_guard_override: ?[]const u8 = null, }; pub fn create(owner: *std.Build, options: Options) *ConfigHeader { const graph = owner.graph; const arena = graph.arena; - const config_header = arena.create(ConfigHeader) catch @panic("OOM"); + const wc = &graph.wip_configuration; + const config_header = graph.create(ConfigHeader); - var include_path: []const u8 = "config.h"; + const include_path: []const u8 = p: { + if (options.include_path) |p| + break :p graph.dupeString(p); - if (options.style.getPath()) |s| default_include_path: { - const wc = &graph.wip_configuration; - const sub_path = switch (s) { - .src_path => |sp| sp.sub_path, - .generated => break :default_include_path, - .cwd_relative => |sub_path| sub_path, - .relative => |r| wc.stringSlice(r.sub_path), - .dependency => |dependency| dependency.sub_path, - }; - const basename = std.fs.path.basename(sub_path); - if (std.mem.endsWith(u8, basename, ".h.in")) { - include_path = basename[0 .. basename.len - 3]; + if (options.style.getPath()) |s| default: { + const sub_path = switch (s) { + .src_path => |sp| sp.sub_path, + .generated => break :default, + .cwd_relative => |sub_path| sub_path, + .relative => |r| wc.stringSlice(r.sub_path), + .dependency => |dependency| dependency.sub_path, + }; + const basename = Io.Dir.path.basename(sub_path); + if (std.mem.endsWith(u8, basename, ".h.in")) + break :p graph.dupeString(basename[0 .. basename.len - 3]); } - } - - if (options.include_path) |p| { - include_path = p; - } + break :p "config.h"; + }; const name = if (options.style.getPath()) |s| - owner.fmt("configure {t} header {f} to {s}", .{ options.style, s.fmt(graph), include_path }) + allocPrint(arena, "configure {t} header {f} to {s}", .{ + options.style, s.fmt(graph), include_path, + }) catch @panic("OOM") else - owner.fmt("configure {t} header to {s}", .{ options.style, include_path }); + allocPrint(arena, "configure {t} header to {s}", .{ + options.style, include_path, + }) catch @panic("OOM"); config_header.* = .{ .step = .init(.{ @@ -96,11 +100,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { .first_ret_addr = options.first_ret_addr orelse @returnAddress(), }), .style = options.style, - .values = .empty, - - .max_bytes = options.max_bytes, - .include_path = graph.dupeString(include_path), - .include_guard_override = options.include_guard_override, + .input_size_limit = options.max_bytes, + .include_path = include_path, + .include_guard = if (options.include_guard) |s| .init(wc.addString(s) catch @panic("OOM")) else .none, .generated_dir = graph.addGeneratedFile(&config_header.step), }; @@ -179,6 +181,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void { pub fn getOutputDir(ch: *ConfigHeader) std.Build.LazyPath { return .{ .generated = .{ .index = ch.generated_dir } }; } + pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath { return ch.getOutputDir().path(ch.step.owner, ch.include_path); }