aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Build.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/Build.zig')
-rw-r--r--lib/std/Build.zig227
1 files changed, 151 insertions, 76 deletions
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index e65a71e12b..d6b0e68f5d 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -408,104 +408,179 @@ fn createChildOnly(
return child;
}
-fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOptionsMap {
- var user_input_options = UserInputOptionsMap.init(allocator);
+fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap {
+ var map = UserInputOptionsMap.init(arena);
inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {
- const v = @field(args, field.name);
- const T = @TypeOf(v);
- switch (T) {
- Target.Query => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
- user_input_options.put("cpu", .{
- .name = "cpu",
- .value = .{ .scalar = v.serializeCpuAlloc(allocator) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
- },
- ResolvedTarget => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = v.query.zigTriple(allocator) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
- user_input_options.put("cpu", .{
- .name = "cpu",
- .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
- },
- LazyPath => {
- user_input_options.put(field.name, .{
+ if (field.type == @Type(.null)) continue;
+ addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name));
+ }
+ return map;
+}
+
+fn addUserInputOptionFromArg(
+ arena: Allocator,
+ map: *UserInputOptionsMap,
+ field: std.builtin.Type.StructField,
+ comptime T: type,
+ /// If null, the value won't be added, but `T` will still be type-checked.
+ maybe_value: ?T,
+) void {
+ switch (T) {
+ Target.Query => return if (maybe_value) |v| {
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .scalar = v.zigTriple(arena) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ map.put("cpu", .{
+ .name = "cpu",
+ .value = .{ .scalar = v.serializeCpuAlloc(arena) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ ResolvedTarget => return if (maybe_value) |v| {
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .scalar = v.query.zigTriple(arena) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ map.put("cpu", .{
+ .name = "cpu",
+ .value = .{ .scalar = v.query.serializeCpuAlloc(arena) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ std.zig.BuildId => return if (maybe_value) |v| {
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .scalar = std.fmt.allocPrint(arena, "{f}", .{v}) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ LazyPath => return if (maybe_value) |v| {
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .lazy_path = v.dupeInner(arena) },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ []const LazyPath => return if (maybe_value) |v| {
+ var list = ArrayList(LazyPath).initCapacity(arena, v.len) catch @panic("OOM");
+ for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(arena));
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .lazy_path_list = list },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ []const u8 => return if (maybe_value) |v| {
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .scalar = arena.dupe(u8, v) catch @panic("OOM") },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ []const []const u8 => return if (maybe_value) |v| {
+ var list = ArrayList([]const u8).initCapacity(arena, v.len) catch @panic("OOM");
+ for (v) |s| list.appendAssumeCapacity(arena.dupe(u8, s) catch @panic("OOM"));
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .list = list },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ else => switch (@typeInfo(T)) {
+ .bool => return if (maybe_value) |v| {
+ map.put(field.name, .{
.name = field.name,
- .value = .{ .lazy_path = v.dupeInner(allocator) },
+ .value = .{ .scalar = if (v) "true" else "false" },
.used = false,
}) catch @panic("OOM");
},
- []const LazyPath => {
- var list = ArrayList(LazyPath).initCapacity(allocator, v.len) catch @panic("OOM");
- for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(allocator));
- user_input_options.put(field.name, .{
+ .@"enum", .enum_literal => return if (maybe_value) |v| {
+ map.put(field.name, .{
.name = field.name,
- .value = .{ .lazy_path_list = list },
+ .value = .{ .scalar = @tagName(v) },
.used = false,
}) catch @panic("OOM");
},
- []const u8 => {
- user_input_options.put(field.name, .{
+ .comptime_int, .int => return if (maybe_value) |v| {
+ map.put(field.name, .{
.name = field.name,
- .value = .{ .scalar = v },
+ .value = .{ .scalar = std.fmt.allocPrint(arena, "{d}", .{v}) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
},
- []const []const u8 => {
- var list = ArrayList([]const u8).initCapacity(allocator, v.len) catch @panic("OOM");
- list.appendSliceAssumeCapacity(v);
-
- user_input_options.put(field.name, .{
+ .comptime_float, .float => return if (maybe_value) |v| {
+ map.put(field.name, .{
.name = field.name,
- .value = .{ .list = list },
+ .value = .{ .scalar = std.fmt.allocPrint(arena, "{x}", .{v}) catch @panic("OOM") },
.used = false,
}) catch @panic("OOM");
},
- else => switch (@typeInfo(T)) {
- .bool => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = if (v) "true" else "false" },
- .used = false,
- }) catch @panic("OOM");
- },
- .@"enum", .enum_literal => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = @tagName(v) },
- .used = false,
- }) catch @panic("OOM");
+ .pointer => |ptr_info| switch (ptr_info.size) {
+ .one => switch (@typeInfo(ptr_info.child)) {
+ .array => |array_info| {
+ comptime var slice_info = ptr_info;
+ slice_info.size = .slice;
+ slice_info.is_const = true;
+ slice_info.child = array_info.child;
+ slice_info.sentinel_ptr = null;
+ addUserInputOptionFromArg(
+ arena,
+ map,
+ field,
+ @Type(.{ .pointer = slice_info }),
+ maybe_value orelse null,
+ );
+ return;
+ },
+ else => {},
},
- .comptime_int, .int => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = std.fmt.allocPrint(allocator, "{d}", .{v}) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
+ .slice => switch (@typeInfo(ptr_info.child)) {
+ .@"enum" => return if (maybe_value) |v| {
+ var list = ArrayList([]const u8).initCapacity(arena, v.len) catch @panic("OOM");
+ for (v) |tag| list.appendAssumeCapacity(@tagName(tag));
+ map.put(field.name, .{
+ .name = field.name,
+ .value = .{ .list = list },
+ .used = false,
+ }) catch @panic("OOM");
+ },
+ else => {
+ comptime var slice_info = ptr_info;
+ slice_info.is_const = true;
+ slice_info.sentinel_ptr = null;
+ addUserInputOptionFromArg(
+ arena,
+ map,
+ field,
+ @Type(.{ .pointer = slice_info }),
+ maybe_value orelse null,
+ );
+ return;
+ },
},
- .comptime_float, .float => {
- user_input_options.put(field.name, .{
- .name = field.name,
- .value = .{ .scalar = std.fmt.allocPrint(allocator, "{e}", .{v}) catch @panic("OOM") },
- .used = false,
- }) catch @panic("OOM");
+ else => {},
+ },
+ .null => unreachable,
+ .optional => |info| switch (@typeInfo(info.child)) {
+ .optional => {},
+ else => {
+ addUserInputOptionFromArg(
+ arena,
+ map,
+ field,
+ info.child,
+ maybe_value orelse null,
+ );
+ return;
},
- else => @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(T)),
},
- }
+ else => {},
+ },
}
-
- return user_input_options;
+ @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(field.type));
}
const OrderedUserValue = union(enum) {