| ... | ... | @@ -85,6 +85,7 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: |
| 85 | 85 | value.minor, |
| 86 | 86 | value.patch, |
| 87 | 87 | }) catch unreachable; |
| 88 | return; |
| 88 | 89 | }, |
| 89 | 90 | std.SemanticVersion => { |
| 90 | 91 | out.print( |
| ... | ... | @@ -118,10 +119,58 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: |
| 118 | 119 | out.print(" {},\n", .{std.zig.fmtId(field.name)}) catch unreachable; |
| 119 | 120 | } |
| 120 | 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 | 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 | 176 | /// The value is the path in the cache dir. |
| ... | ... | @@ -235,17 +284,62 @@ test "OptionsStep" { |
| 235 | 284 | |
| 236 | 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 | 297 | options.addOption(usize, "option1", 1); |
| 239 | 298 | options.addOption(?usize, "option2", null); |
| 299 | options.addOption(?usize, "option3", 3); |
| 240 | 300 | options.addOption([]const u8, "string", "zigisthebest"); |
| 241 | 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 | 306 | options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar")); |
| 243 | 307 | |
| 244 | 308 | try std.testing.expectEqualStrings( |
| 245 | 309 | \\pub const option1: usize = 1; |
| 246 | 310 | \\pub const option2: ?usize = null; |
| 311 | \\pub const option3: ?usize = 3; |
| 247 | 312 | \\pub const string: []const u8 = "zigisthebest"; |
| 248 | 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 | 343 | \\pub const semantic_version: @import("std").SemanticVersion = .{ |
| 250 | 344 | \\ .major = 0, |
| 251 | 345 | \\ .minor = 1, |
| ... | ... | @@ -255,4 +349,6 @@ test "OptionsStep" { |
| 255 | 349 | \\}; |
| 256 | 350 | \\ |
| 257 | 351 | , options.contents.items); |
| 352 | |
| 353 | _ = try std.zig.parse(&arena.allocator, try options.contents.toOwnedSliceSentinel(0)); |
| 258 | 354 | } |