| ... | @@ -85,6 +85,7 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: | ... | @@ -85,6 +85,7 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: |
| 85 | value.minor, | 85 | value.minor, |
| 86 | value.patch, | 86 | value.patch, |
| 87 | }) catch unreachable; | 87 | }) catch unreachable; |
| | 88 | return; |
| 88 | }, | 89 | }, |
| 89 | std.SemanticVersion => { | 90 | std.SemanticVersion => { |
| 90 | out.print( | 91 | out.print( |
| ... | @@ -118,10 +119,58 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: | ... | @@ -118,10 +119,58 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: |
| 118 | out.print(" {},\n", .{std.zig.fmtId(field.name)}) catch unreachable; | 119 | out.print(" {},\n", .{std.zig.fmtId(field.name)}) catch unreachable; |
| 119 | } | 120 | } |
| 120 | out.writeAll("};\n") catch unreachable; | 121 | out.writeAll("};\n") catch unreachable; |
| | 122 | out.print("pub const {}: {s} = {s}.{s};\n", .{ std.zig.fmtId(name), @typeName(T), @typeName(T), std.zig.fmtId(@tagName(value)) }) catch unreachable; |
| | 123 | return; |
| 121 | }, | 124 | }, |
| 122 | else => {}, | 125 | else => {}, |
| 123 | } | 126 | } |
| 124 | out.print("pub const {}: {s} = {};\n", .{ std.zig.fmtId(name), @typeName(T), value }) catch unreachable; | 127 | out.print("pub const {}: {s} = ", .{ std.zig.fmtId(name), @typeName(T) }) catch unreachable; |
| | 128 | printLiteral(out, value, 0) catch unreachable; |
| | 129 | out.writeAll(";\n") catch unreachable; |
| | 130 | } |
| | 131 | |
| | 132 | // TODO: non-recursive? |
| | 133 | fn printLiteral(out: anytype, val: anytype, indent: u8) !void { |
| | 134 | const T = @TypeOf(val); |
| | 135 | switch (@typeInfo(T)) { |
| | 136 | .Array => { |
| | 137 | try out.print("{s} {{\n", .{@typeName(T)}); |
| | 138 | for (val) |item| { |
| | 139 | try out.writeByteNTimes(' ', indent + 4); |
| | 140 | try printLiteral(out, item, indent + 4); |
| | 141 | try out.writeAll(",\n"); |
| | 142 | } |
| | 143 | try out.writeByteNTimes(' ', indent); |
| | 144 | try out.writeAll("}"); |
| | 145 | }, |
| | 146 | .Pointer => |p| { |
| | 147 | if (p.size != .Slice) { |
| | 148 | @compileError("Non-slice pointers are not yet supported in build options"); |
| | 149 | } |
| | 150 | try out.print("&[_]{s} {{\n", .{@typeName(p.child)}); |
| | 151 | for (val) |item| { |
| | 152 | try out.writeByteNTimes(' ', indent + 4); |
| | 153 | try printLiteral(out, item, indent + 4); |
| | 154 | try out.writeAll(",\n"); |
| | 155 | } |
| | 156 | try out.writeByteNTimes(' ', indent); |
| | 157 | try out.writeAll("}"); |
| | 158 | }, |
| | 159 | .Optional => { |
| | 160 | if (val) |inner| { |
| | 161 | return printLiteral(out, inner, indent); |
| | 162 | } else { |
| | 163 | return out.writeAll("null"); |
| | 164 | } |
| | 165 | }, |
| | 166 | .Void, |
| | 167 | .Bool, |
| | 168 | .Int, |
| | 169 | .Float, |
| | 170 | .Null, |
| | 171 | => try out.print("{any}", .{val}), |
| | 172 | else => @compileError(comptime std.fmt.comptimePrint("`{s}` are not yet supported as build options", .{@tagName(@typeInfo(T))})), |
| | 173 | } |
| 125 | } | 174 | } |
| 126 | | 175 | |
| 127 | /// The value is the path in the cache dir. | 176 | /// The value is the path in the cache dir. |
| ... | @@ -235,17 +284,62 @@ test "OptionsStep" { | ... | @@ -235,17 +284,62 @@ test "OptionsStep" { |
| 235 | | 284 | |
| 236 | const options = builder.addOptions(); | 285 | const options = builder.addOptions(); |
| 237 | | 286 | |
| | 287 | const KeywordEnum = enum { |
| | 288 | @"0.8.1", |
| | 289 | }; |
| | 290 | |
| | 291 | const nested_array = [2][2]u16{ |
| | 292 | [2]u16{ 300, 200 }, |
| | 293 | [2]u16{ 300, 200 }, |
| | 294 | }; |
| | 295 | const nested_slice: []const []const u16 = &[_][]const u16{ &nested_array[0], &nested_array[1] }; |
| | 296 | |
| 238 | options.addOption(usize, "option1", 1); | 297 | options.addOption(usize, "option1", 1); |
| 239 | options.addOption(?usize, "option2", null); | 298 | options.addOption(?usize, "option2", null); |
| | 299 | options.addOption(?usize, "option3", 3); |
| 240 | options.addOption([]const u8, "string", "zigisthebest"); | 300 | options.addOption([]const u8, "string", "zigisthebest"); |
| 241 | options.addOption(?[]const u8, "optional_string", null); | 301 | options.addOption(?[]const u8, "optional_string", null); |
| | 302 | options.addOption([2][2]u16, "nested_array", nested_array); |
| | 303 | options.addOption([]const []const u16, "nested_slice", nested_slice); |
| | 304 | options.addOption(KeywordEnum, "keyword_enum", .@"0.8.1"); |
| | 305 | options.addOption(std.builtin.Version, "version", try std.builtin.Version.parse("0.1.2")); |
| 242 | options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar")); | 306 | options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar")); |
| 243 | | 307 | |
| 244 | try std.testing.expectEqualStrings( | 308 | try std.testing.expectEqualStrings( |
| 245 | \\pub const option1: usize = 1; | 309 | \\pub const option1: usize = 1; |
| 246 | \\pub const option2: ?usize = null; | 310 | \\pub const option2: ?usize = null; |
| | 311 | \\pub const option3: ?usize = 3; |
| 247 | \\pub const string: []const u8 = "zigisthebest"; | 312 | \\pub const string: []const u8 = "zigisthebest"; |
| 248 | \\pub const optional_string: ?[]const u8 = null; | 313 | \\pub const optional_string: ?[]const u8 = null; |
| | 314 | \\pub const nested_array: [2][2]u16 = [2][2]u16 { |
| | 315 | \\ [2]u16 { |
| | 316 | \\ 300, |
| | 317 | \\ 200, |
| | 318 | \\ }, |
| | 319 | \\ [2]u16 { |
| | 320 | \\ 300, |
| | 321 | \\ 200, |
| | 322 | \\ }, |
| | 323 | \\}; |
| | 324 | \\pub const nested_slice: []const []const u16 = &[_][]const u16 { |
| | 325 | \\ &[_]u16 { |
| | 326 | \\ 300, |
| | 327 | \\ 200, |
| | 328 | \\ }, |
| | 329 | \\ &[_]u16 { |
| | 330 | \\ 300, |
| | 331 | \\ 200, |
| | 332 | \\ }, |
| | 333 | \\}; |
| | 334 | \\pub const KeywordEnum = enum { |
| | 335 | \\ @"0.8.1", |
| | 336 | \\}; |
| | 337 | \\pub const keyword_enum: KeywordEnum = KeywordEnum.@"0.8.1"; |
| | 338 | \\pub const version: @import("std").builtin.Version = .{ |
| | 339 | \\ .major = 0, |
| | 340 | \\ .minor = 1, |
| | 341 | \\ .patch = 2, |
| | 342 | \\}; |
| 249 | \\pub const semantic_version: @import("std").SemanticVersion = .{ | 343 | \\pub const semantic_version: @import("std").SemanticVersion = .{ |
| 250 | \\ .major = 0, | 344 | \\ .major = 0, |
| 251 | \\ .minor = 1, | 345 | \\ .minor = 1, |
| ... | @@ -255,4 +349,6 @@ test "OptionsStep" { | ... | @@ -255,4 +349,6 @@ test "OptionsStep" { |
| 255 | \\}; | 349 | \\}; |
| 256 | \\ | 350 | \\ |
| 257 | , options.contents.items); | 351 | , options.contents.items); |
| | 352 | |
| | 353 | _ = try std.zig.parse(&arena.allocator, try options.contents.toOwnedSliceSentinel(0)); |
| 258 | } | 354 | } |