| author | |
| committer | |
| log | 9e11727c7c88289554251646166f844376dcbbe9 |
| tree | db80e9778647f1f53c1f5078bab944bd51abd1ff |
| parent | 869ef00602328f97ea8c88358310cbd34d4391ab |
| parent | ca57115da7c4603dbcefce1dc9395617e28a86f8 |
| signature |
Add support for passing null, string literals, enum lists and more to `b.dependency()`11 files changed, 411 insertions(+), 85 deletions(-)
lib/std/Build.zig+151-76| ... | @@ -408,104 +408,179 @@ fn createChildOnly( | ... | @@ -408,104 +408,179 @@ fn createChildOnly( |
| 408 | return child; | 408 | return child; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOptionsMap { | 411 | fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap { |
| 412 | var user_input_options = UserInputOptionsMap.init(allocator); | 412 | var map = UserInputOptionsMap.init(arena); |
| 413 | inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| { | 413 | inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| { |
| 414 | const v = @field(args, field.name); | 414 | if (field.type == @Type(.null)) continue; |
| 415 | const T = @TypeOf(v); | 415 | addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name)); |
| 416 | switch (T) { | 416 | } |
| 417 | Target.Query => { | 417 | return map; |
| 418 | user_input_options.put(field.name, .{ | 418 | } |
| 419 | .name = field.name, | 419 | |
| 420 | .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, | 420 | fn addUserInputOptionFromArg( |
| 421 | .used = false, | 421 | arena: Allocator, |
| 422 | }) catch @panic("OOM"); | 422 | map: *UserInputOptionsMap, |
| 423 | user_input_options.put("cpu", .{ | 423 | field: std.builtin.Type.StructField, |
| 424 | .name = "cpu", | 424 | comptime T: type, |
| 425 | .value = .{ .scalar = v.serializeCpuAlloc(allocator) catch @panic("OOM") }, | 425 | /// If null, the value won't be added, but `T` will still be type-checked. |
| 426 | .used = false, | 426 | maybe_value: ?T, |
| 427 | }) catch @panic("OOM"); | 427 | ) void { |
| 428 | }, | 428 | switch (T) { |
| 429 | ResolvedTarget => { | 429 | Target.Query => return if (maybe_value) |v| { |
| 430 | user_input_options.put(field.name, .{ | 430 | map.put(field.name, .{ |
| 431 | .name = field.name, | 431 | .name = field.name, |
| 432 | .value = .{ .scalar = v.query.zigTriple(allocator) catch @panic("OOM") }, | 432 | .value = .{ .scalar = v.zigTriple(arena) catch @panic("OOM") }, |
| 433 | .used = false, | 433 | .used = false, |
| 434 | }) catch @panic("OOM"); | 434 | }) catch @panic("OOM"); |
| 435 | user_input_options.put("cpu", .{ | 435 | map.put("cpu", .{ |
| 436 | .name = "cpu", | 436 | .name = "cpu", |
| 437 | .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") }, | 437 | .value = .{ .scalar = v.serializeCpuAlloc(arena) catch @panic("OOM") }, |
| 438 | .used = false, | 438 | .used = false, |
| 439 | }) catch @panic("OOM"); | 439 | }) catch @panic("OOM"); |
| 440 | }, | 440 | }, |
| 441 | LazyPath => { | 441 | ResolvedTarget => return if (maybe_value) |v| { |
| 442 | user_input_options.put(field.name, .{ | 442 | map.put(field.name, .{ |
| 443 | .name = field.name, | ||
| 444 | .value = .{ .scalar = v.query.zigTriple(arena) catch @panic("OOM") }, | ||
| 445 | .used = false, | ||
| 446 | }) catch @panic("OOM"); | ||
| 447 | map.put("cpu", .{ | ||
| 448 | .name = "cpu", | ||
| 449 | .value = .{ .scalar = v.query.serializeCpuAlloc(arena) catch @panic("OOM") }, | ||
| 450 | .used = false, | ||
| 451 | }) catch @panic("OOM"); | ||
| 452 | }, | ||
| 453 | std.zig.BuildId => return if (maybe_value) |v| { | ||
| 454 | map.put(field.name, .{ | ||
| 455 | .name = field.name, | ||
| 456 | .value = .{ .scalar = std.fmt.allocPrint(arena, "{f}", .{v}) catch @panic("OOM") }, | ||
| 457 | .used = false, | ||
| 458 | }) catch @panic("OOM"); | ||
| 459 | }, | ||
| 460 | LazyPath => return if (maybe_value) |v| { | ||
| 461 | map.put(field.name, .{ | ||
| 462 | .name = field.name, | ||
| 463 | .value = .{ .lazy_path = v.dupeInner(arena) }, | ||
| 464 | .used = false, | ||
| 465 | }) catch @panic("OOM"); | ||
| 466 | }, | ||
| 467 | []const LazyPath => return if (maybe_value) |v| { | ||
| 468 | var list = ArrayList(LazyPath).initCapacity(arena, v.len) catch @panic("OOM"); | ||
| 469 | for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(arena)); | ||
| 470 | map.put(field.name, .{ | ||
| 471 | .name = field.name, | ||
| 472 | .value = .{ .lazy_path_list = list }, | ||
| 473 | .used = false, | ||
| 474 | }) catch @panic("OOM"); | ||
| 475 | }, | ||
| 476 | []const u8 => return if (maybe_value) |v| { | ||
| 477 | map.put(field.name, .{ | ||
| 478 | .name = field.name, | ||
| 479 | .value = .{ .scalar = arena.dupe(u8, v) catch @panic("OOM") }, | ||
| 480 | .used = false, | ||
| 481 | }) catch @panic("OOM"); | ||
| 482 | }, | ||
| 483 | []const []const u8 => return if (maybe_value) |v| { | ||
| 484 | var list = ArrayList([]const u8).initCapacity(arena, v.len) catch @panic("OOM"); | ||
| 485 | for (v) |s| list.appendAssumeCapacity(arena.dupe(u8, s) catch @panic("OOM")); | ||
| 486 | map.put(field.name, .{ | ||
| 487 | .name = field.name, | ||
| 488 | .value = .{ .list = list }, | ||
| 489 | .used = false, | ||
| 490 | }) catch @panic("OOM"); | ||
| 491 | }, | ||
| 492 | else => switch (@typeInfo(T)) { | ||
| 493 | .bool => return if (maybe_value) |v| { | ||
| 494 | map.put(field.name, .{ | ||
| 443 | .name = field.name, | 495 | .name = field.name, |
| 444 | .value = .{ .lazy_path = v.dupeInner(allocator) }, | 496 | .value = .{ .scalar = if (v) "true" else "false" }, |
| 445 | .used = false, | 497 | .used = false, |
| 446 | }) catch @panic("OOM"); | 498 | }) catch @panic("OOM"); |
| 447 | }, | 499 | }, |
| 448 | []const LazyPath => { | 500 | .@"enum", .enum_literal => return if (maybe_value) |v| { |
| 449 | var list = ArrayList(LazyPath).initCapacity(allocator, v.len) catch @panic("OOM"); | 501 | map.put(field.name, .{ |
| 450 | for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(allocator)); | ||
| 451 | user_input_options.put(field.name, .{ | ||
| 452 | .name = field.name, | 502 | .name = field.name, |
| 453 | .value = .{ .lazy_path_list = list }, | 503 | .value = .{ .scalar = @tagName(v) }, |
| 454 | .used = false, | 504 | .used = false, |
| 455 | }) catch @panic("OOM"); | 505 | }) catch @panic("OOM"); |
| 456 | }, | 506 | }, |
| 457 | []const u8 => { | 507 | .comptime_int, .int => return if (maybe_value) |v| { |
| 458 | user_input_options.put(field.name, .{ | 508 | map.put(field.name, .{ |
| 459 | .name = field.name, | 509 | .name = field.name, |
| 460 | .value = .{ .scalar = v }, | 510 | .value = .{ .scalar = std.fmt.allocPrint(arena, "{d}", .{v}) catch @panic("OOM") }, |
| 461 | .used = false, | 511 | .used = false, |
| 462 | }) catch @panic("OOM"); | 512 | }) catch @panic("OOM"); |
| 463 | }, | 513 | }, |
| 464 | []const []const u8 => { | 514 | .comptime_float, .float => return if (maybe_value) |v| { |
| 465 | var list = ArrayList([]const u8).initCapacity(allocator, v.len) catch @panic("OOM"); | 515 | map.put(field.name, .{ |
| 466 | list.appendSliceAssumeCapacity(v); | ||
| 467 | |||
| 468 | user_input_options.put(field.name, .{ | ||
| 469 | .name = field.name, | 516 | .name = field.name, |
| 470 | .value = .{ .list = list }, | 517 | .value = .{ .scalar = std.fmt.allocPrint(arena, "{x}", .{v}) catch @panic("OOM") }, |
| 471 | .used = false, | 518 | .used = false, |
| 472 | }) catch @panic("OOM"); | 519 | }) catch @panic("OOM"); |
| 473 | }, | 520 | }, |
| 474 | else => switch (@typeInfo(T)) { | 521 | .pointer => |ptr_info| switch (ptr_info.size) { |
| 475 | .bool => { | 522 | .one => switch (@typeInfo(ptr_info.child)) { |
| 476 | user_input_options.put(field.name, .{ | 523 | .array => |array_info| { |
| 477 | .name = field.name, | 524 | comptime var slice_info = ptr_info; |
| 478 | .value = .{ .scalar = if (v) "true" else "false" }, | 525 | slice_info.size = .slice; |
| 479 | .used = false, | 526 | slice_info.is_const = true; |
| 480 | }) catch @panic("OOM"); | 527 | slice_info.child = array_info.child; |
| 481 | }, | 528 | slice_info.sentinel_ptr = null; |
| 482 | .@"enum", .enum_literal => { | 529 | addUserInputOptionFromArg( |
| 483 | user_input_options.put(field.name, .{ | 530 | arena, |
| 484 | .name = field.name, | 531 | map, |
| 485 | .value = .{ .scalar = @tagName(v) }, | 532 | field, |
| 486 | .used = false, | 533 | @Type(.{ .pointer = slice_info }), |
| 487 | }) catch @panic("OOM"); | 534 | maybe_value orelse null, |
| 535 | ); | ||
| 536 | return; | ||
| 537 | }, | ||
| 538 | else => {}, | ||
| 488 | }, | 539 | }, |
| 489 | .comptime_int, .int => { | 540 | .slice => switch (@typeInfo(ptr_info.child)) { |
| 490 | user_input_options.put(field.name, .{ | 541 | .@"enum" => return if (maybe_value) |v| { |
| 491 | .name = field.name, | 542 | var list = ArrayList([]const u8).initCapacity(arena, v.len) catch @panic("OOM"); |
| 492 | .value = .{ .scalar = std.fmt.allocPrint(allocator, "{d}", .{v}) catch @panic("OOM") }, | 543 | for (v) |tag| list.appendAssumeCapacity(@tagName(tag)); |
| 493 | .used = false, | 544 | map.put(field.name, .{ |
| 494 | }) catch @panic("OOM"); | 545 | .name = field.name, |
| 546 | .value = .{ .list = list }, | ||
| 547 | .used = false, | ||
| 548 | }) catch @panic("OOM"); | ||
| 549 | }, | ||
| 550 | else => { | ||
| 551 | comptime var slice_info = ptr_info; | ||
| 552 | slice_info.is_const = true; | ||
| 553 | slice_info.sentinel_ptr = null; | ||
| 554 | addUserInputOptionFromArg( | ||
| 555 | arena, | ||
| 556 | map, | ||
| 557 | field, | ||
| 558 | @Type(.{ .pointer = slice_info }), | ||
| 559 | maybe_value orelse null, | ||
| 560 | ); | ||
| 561 | return; | ||
| 562 | }, | ||
| 495 | }, | 563 | }, |
| 496 | .comptime_float, .float => { | 564 | else => {}, |
| 497 | user_input_options.put(field.name, .{ | 565 | }, |
| 498 | .name = field.name, | 566 | .null => unreachable, |
| 499 | .value = .{ .scalar = std.fmt.allocPrint(allocator, "{e}", .{v}) catch @panic("OOM") }, | 567 | .optional => |info| switch (@typeInfo(info.child)) { |
| 500 | .used = false, | 568 | .optional => {}, |
| 501 | }) catch @panic("OOM"); | 569 | else => { |
| 570 | addUserInputOptionFromArg( | ||
| 571 | arena, | ||
| 572 | map, | ||
| 573 | field, | ||
| 574 | info.child, | ||
| 575 | maybe_value orelse null, | ||
| 576 | ); | ||
| 577 | return; | ||
| 502 | }, | 578 | }, |
| 503 | else => @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(T)), | ||
| 504 | }, | 579 | }, |
| 505 | } | 580 | else => {}, |
| 581 | }, | ||
| 506 | } | 582 | } |
| 507 | 583 | @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(field.type)); | |
| 508 | return user_input_options; | ||
| 509 | } | 584 | } |
| 510 | 585 | ||
| 511 | const OrderedUserValue = union(enum) { | 586 | const OrderedUserValue = union(enum) { |
lib/std/Io/Writer.zig+11-5| ... | @@ -1564,17 +1564,23 @@ pub fn printFloatHexOptions(w: *Writer, value: anytype, options: std.fmt.Number) | ... | @@ -1564,17 +1564,23 @@ pub fn printFloatHexOptions(w: *Writer, value: anytype, options: std.fmt.Number) |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { | 1566 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { |
| 1567 | if (std.math.signbit(value)) try w.writeByte('-'); | 1567 | const v = switch (@TypeOf(value)) { |
| 1568 | if (std.math.isNan(value)) return w.writeAll(switch (case) { | 1568 | // comptime_float internally is a f128; this preserves precision. |
| 1569 | comptime_float => @as(f128, value), | ||
| 1570 | else => value, | ||
| 1571 | }; | ||
| 1572 | |||
| 1573 | if (std.math.signbit(v)) try w.writeByte('-'); | ||
| 1574 | if (std.math.isNan(v)) return w.writeAll(switch (case) { | ||
| 1569 | .lower => "nan", | 1575 | .lower => "nan", |
| 1570 | .upper => "NAN", | 1576 | .upper => "NAN", |
| 1571 | }); | 1577 | }); |
| 1572 | if (std.math.isInf(value)) return w.writeAll(switch (case) { | 1578 | if (std.math.isInf(v)) return w.writeAll(switch (case) { |
| 1573 | .lower => "inf", | 1579 | .lower => "inf", |
| 1574 | .upper => "INF", | 1580 | .upper => "INF", |
| 1575 | }); | 1581 | }); |
| 1576 | 1582 | ||
| 1577 | const T = @TypeOf(value); | 1583 | const T = @TypeOf(v); |
| 1578 | const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); | 1584 | const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| 1579 | 1585 | ||
| 1580 | const mantissa_bits = std.math.floatMantissaBits(T); | 1586 | const mantissa_bits = std.math.floatMantissaBits(T); |
| ... | @@ -1584,7 +1590,7 @@ pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precisi | ... | @@ -1584,7 +1590,7 @@ pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precisi |
| 1584 | const exponent_mask = (1 << exponent_bits) - 1; | 1590 | const exponent_mask = (1 << exponent_bits) - 1; |
| 1585 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; | 1591 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; |
| 1586 | 1592 | ||
| 1587 | const as_bits: TU = @bitCast(value); | 1593 | const as_bits: TU = @bitCast(v); |
| 1588 | var mantissa = as_bits & mantissa_mask; | 1594 | var mantissa = as_bits & mantissa_mask; |
| 1589 | var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask)); | 1595 | var exponent: i32 = @as(u16, @truncate((as_bits >> mantissa_bits) & exponent_mask)); |
| 1590 | 1596 |
lib/std/zig.zig+21| ... | @@ -321,6 +321,27 @@ pub const BuildId = union(enum) { | ... | @@ -321,6 +321,27 @@ pub const BuildId = union(enum) { |
| 321 | try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); | 321 | try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); |
| 322 | try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); | 322 | try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); |
| 323 | } | 323 | } |
| 324 | |||
| 325 | pub fn format(id: BuildId, writer: *std.io.Writer) std.io.Writer.Error!void { | ||
| 326 | switch (id) { | ||
| 327 | .none, .fast, .uuid, .sha1, .md5 => { | ||
| 328 | try writer.writeAll(@tagName(id)); | ||
| 329 | }, | ||
| 330 | .hexstring => |hs| { | ||
| 331 | try writer.print("0x{x}", .{hs.toSlice()}); | ||
| 332 | }, | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | test format { | ||
| 337 | try std.testing.expectFmt("none", "{f}", .{@as(BuildId, .none)}); | ||
| 338 | try std.testing.expectFmt("fast", "{f}", .{@as(BuildId, .fast)}); | ||
| 339 | try std.testing.expectFmt("uuid", "{f}", .{@as(BuildId, .uuid)}); | ||
| 340 | try std.testing.expectFmt("sha1", "{f}", .{@as(BuildId, .sha1)}); | ||
| 341 | try std.testing.expectFmt("md5", "{f}", .{@as(BuildId, .md5)}); | ||
| 342 | try std.testing.expectFmt("0x", "{f}", .{BuildId.initHexString("")}); | ||
| 343 | try std.testing.expectFmt("0x1234cdef", "{f}", .{BuildId.initHexString("\x12\x34\xcd\xef")}); | ||
| 344 | } | ||
| 324 | }; | 345 | }; |
| 325 | 346 | ||
| 326 | pub const LtoMode = enum { none, full, thin }; | 347 | pub const LtoMode = enum { none, full, thin }; |
test/link/build.zig.zon+2-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | .{ | 1 | .{ |
| 2 | .name = "link_test_cases", | 2 | .name = .link_test_cases, |
| 3 | .fingerprint = 0x404f657576fec9f2, | ||
| 3 | .version = "0.0.0", | 4 | .version = "0.0.0", |
| 4 | .dependencies = .{ | 5 | .dependencies = .{ |
| 5 | .bss = .{ | 6 | .bss = .{ |
test/standalone/build.zig.zon+4-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | .{ | 1 | .{ |
| 2 | .name = .standalone_test_cases, | 2 | .name = .standalone_test_cases, |
| 3 | .fingerprint = 0xc0dbdf9c818957be, | 3 | .fingerprint = 0xc0dbdf9c3b92810b, |
| 4 | .version = "0.0.0", | 4 | .version = "0.0.0", |
| 5 | .dependencies = .{ | 5 | .dependencies = .{ |
| 6 | .simple = .{ | 6 | .simple = .{ |
| ... | @@ -181,6 +181,9 @@ | ... | @@ -181,6 +181,9 @@ |
| 181 | .install_headers = .{ | 181 | .install_headers = .{ |
| 182 | .path = "install_headers", | 182 | .path = "install_headers", |
| 183 | }, | 183 | }, |
| 184 | .dependency_options = .{ | ||
| 185 | .path = "dependency_options", | ||
| 186 | }, | ||
| 184 | .dependencyFromBuildZig = .{ | 187 | .dependencyFromBuildZig = .{ |
| 185 | .path = "dependencyFromBuildZig", | 188 | .path = "dependencyFromBuildZig", |
| 186 | }, | 189 | }, |
test/standalone/dependencyFromBuildZig/build.zig.zon+2-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | .{ | 1 | .{ |
| 2 | .name = "dependencyFromBuildZig", | 2 | .name = .dependencyFromBuildZig, |
| 3 | .fingerprint = 0xfd939a1eb8169080, | ||
| 3 | .version = "0.0.0", | 4 | .version = "0.0.0", |
| 4 | .dependencies = .{ | 5 | .dependencies = .{ |
| 5 | .other = .{ | 6 | .other = .{ |
test/standalone/dependencyFromBuildZig/other/build.zig.zon+2-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | .{ | 1 | .{ |
| 2 | .name = "other", | 2 | .name = .other, |
| 3 | .fingerprint = 0xd9583520a2405f6c, | ||
| 3 | .version = "0.0.0", | 4 | .version = "0.0.0", |
| 4 | .dependencies = .{}, | 5 | .dependencies = .{}, |
| 5 | .paths = .{""}, | 6 | .paths = .{""}, |
test/standalone/dependency_options/build.zig created+141| ... | @@ -0,0 +1,141 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub const Enum = enum { alfa, bravo, charlie }; | ||
| 4 | |||
| 5 | pub fn build(b: *std.Build) !void { | ||
| 6 | const test_step = b.step("test", "Test passing options to a dependency"); | ||
| 7 | b.default_step = test_step; | ||
| 8 | |||
| 9 | const none_specified = b.dependency("other", .{}); | ||
| 10 | |||
| 11 | const none_specified_mod = none_specified.module("dummy"); | ||
| 12 | if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed; | ||
| 13 | if (none_specified_mod.optimize.? != .Debug) return error.TestFailed; | ||
| 14 | |||
| 15 | // Passing null is the same as not specifying the option, | ||
| 16 | // so this should resolve to the same cached dependency instance. | ||
| 17 | const null_specified = b.dependency("other", .{ | ||
| 18 | // Null literals | ||
| 19 | .target = null, | ||
| 20 | .optimize = null, | ||
| 21 | .bool = null, | ||
| 22 | |||
| 23 | // Optionals | ||
| 24 | .int = @as(?i64, null), | ||
| 25 | .float = @as(?f64, null), | ||
| 26 | |||
| 27 | // Optionals of the wrong type | ||
| 28 | .string = @as(?usize, null), | ||
| 29 | .@"enum" = @as(?bool, null), | ||
| 30 | |||
| 31 | // Non-defined option names | ||
| 32 | .this_option_does_not_exist = null, | ||
| 33 | .neither_does_this_one = @as(?[]const u8, null), | ||
| 34 | }); | ||
| 35 | |||
| 36 | if (null_specified != none_specified) return error.TestFailed; | ||
| 37 | |||
| 38 | const all_specified = b.dependency("other", .{ | ||
| 39 | .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), | ||
| 40 | .optimize = @as(std.builtin.OptimizeMode, .ReleaseSafe), | ||
| 41 | .bool = @as(bool, true), | ||
| 42 | .int = @as(i64, 123), | ||
| 43 | .float = @as(f64, 0.5), | ||
| 44 | .string = @as([]const u8, "abc"), | ||
| 45 | .string_list = @as([]const []const u8, &.{ "a", "b", "c" }), | ||
| 46 | .lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }), | ||
| 47 | .lazy_path_list = @as([]const std.Build.LazyPath, &.{ | ||
| 48 | .{ .cwd_relative = "a.txt" }, | ||
| 49 | .{ .cwd_relative = "b.txt" }, | ||
| 50 | .{ .cwd_relative = "c.txt" }, | ||
| 51 | }), | ||
| 52 | .@"enum" = @as(Enum, .alfa), | ||
| 53 | .enum_list = @as([]const Enum, &.{ .alfa, .bravo, .charlie }), | ||
| 54 | .build_id = @as(std.zig.BuildId, .uuid), | ||
| 55 | .hex_build_id = std.zig.BuildId.initHexString("\x12\x34\xcd\xef"), | ||
| 56 | }); | ||
| 57 | |||
| 58 | const all_specified_mod = all_specified.module("dummy"); | ||
| 59 | if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed; | ||
| 60 | if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed; | ||
| 61 | if (all_specified_mod.resolved_target.?.result.abi != .gnu) return error.TestFailed; | ||
| 62 | if (all_specified_mod.optimize.? != .ReleaseSafe) return error.TestFailed; | ||
| 63 | |||
| 64 | const all_specified_optional = b.dependency("other", .{ | ||
| 65 | .target = @as(?std.Build.ResolvedTarget, b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu })), | ||
| 66 | .optimize = @as(?std.builtin.OptimizeMode, .ReleaseSafe), | ||
| 67 | .bool = @as(?bool, true), | ||
| 68 | .int = @as(?i64, 123), | ||
| 69 | .float = @as(?f64, 0.5), | ||
| 70 | .string = @as(?[]const u8, "abc"), | ||
| 71 | .string_list = @as(?[]const []const u8, &.{ "a", "b", "c" }), | ||
| 72 | .lazy_path = @as(?std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }), | ||
| 73 | .lazy_path_list = @as(?[]const std.Build.LazyPath, &.{ | ||
| 74 | .{ .cwd_relative = "a.txt" }, | ||
| 75 | .{ .cwd_relative = "b.txt" }, | ||
| 76 | .{ .cwd_relative = "c.txt" }, | ||
| 77 | }), | ||
| 78 | .@"enum" = @as(?Enum, .alfa), | ||
| 79 | .enum_list = @as(?[]const Enum, &.{ .alfa, .bravo, .charlie }), | ||
| 80 | .build_id = @as(?std.zig.BuildId, .uuid), | ||
| 81 | .hex_build_id = @as(?std.zig.BuildId, .initHexString("\x12\x34\xcd\xef")), | ||
| 82 | }); | ||
| 83 | |||
| 84 | if (all_specified_optional != all_specified) return error.TestFailed; | ||
| 85 | |||
| 86 | const all_specified_literal = b.dependency("other", .{ | ||
| 87 | .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), | ||
| 88 | .optimize = .ReleaseSafe, | ||
| 89 | .bool = true, | ||
| 90 | .int = 123, | ||
| 91 | .float = 0.5, | ||
| 92 | .string = "abc", | ||
| 93 | .string_list = &[_][]const u8{ "a", "b", "c" }, | ||
| 94 | .lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }), | ||
| 95 | .lazy_path_list = &[_]std.Build.LazyPath{ | ||
| 96 | .{ .cwd_relative = "a.txt" }, | ||
| 97 | .{ .cwd_relative = "b.txt" }, | ||
| 98 | .{ .cwd_relative = "c.txt" }, | ||
| 99 | }, | ||
| 100 | .@"enum" = .alfa, | ||
| 101 | .enum_list = &[_]Enum{ .alfa, .bravo, .charlie }, | ||
| 102 | .build_id = .uuid, | ||
| 103 | .hex_build_id = std.zig.BuildId.initHexString("\x12\x34\xcd\xef"), | ||
| 104 | }); | ||
| 105 | |||
| 106 | if (all_specified_literal != all_specified) return error.TestFailed; | ||
| 107 | |||
| 108 | var mut_string_buf = "abc".*; | ||
| 109 | const mut_string: []u8 = &mut_string_buf; | ||
| 110 | var mut_string_list_buf = [_][]const u8{ "a", "b", "c" }; | ||
| 111 | const mut_string_list: [][]const u8 = &mut_string_list_buf; | ||
| 112 | var mut_lazy_path_list_buf = [_]std.Build.LazyPath{ | ||
| 113 | .{ .cwd_relative = "a.txt" }, | ||
| 114 | .{ .cwd_relative = "b.txt" }, | ||
| 115 | .{ .cwd_relative = "c.txt" }, | ||
| 116 | }; | ||
| 117 | const mut_lazy_path_list: []std.Build.LazyPath = &mut_lazy_path_list_buf; | ||
| 118 | var mut_enum_list_buf = [_]Enum{ .alfa, .bravo, .charlie }; | ||
| 119 | const mut_enum_list: []Enum = &mut_enum_list_buf; | ||
| 120 | |||
| 121 | // Most supported option types are serialized to a string representation, | ||
| 122 | // so alternative representations of the same option value should resolve | ||
| 123 | // to the same cached dependency instance. | ||
| 124 | const all_specified_alt = b.dependency("other", .{ | ||
| 125 | .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), | ||
| 126 | .optimize = "ReleaseSafe", | ||
| 127 | .bool = .true, | ||
| 128 | .int = "123", | ||
| 129 | .float = @as(f16, 0.5), | ||
| 130 | .string = mut_string, | ||
| 131 | .string_list = mut_string_list, | ||
| 132 | .lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }), | ||
| 133 | .lazy_path_list = mut_lazy_path_list, | ||
| 134 | .@"enum" = "alfa", | ||
| 135 | .enum_list = mut_enum_list, | ||
| 136 | .build_id = "uuid", | ||
| 137 | .hex_build_id = "0x1234cdef", | ||
| 138 | }); | ||
| 139 | |||
| 140 | if (all_specified_alt != all_specified) return error.TestFailed; | ||
| 141 | } | ||
test/standalone/dependency_options/build.zig.zon created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | .{ | ||
| 2 | .name = .dependency_options, | ||
| 3 | .fingerprint = 0x3e3ce1c1f92ba47e, | ||
| 4 | .version = "0.0.0", | ||
| 5 | .dependencies = .{ | ||
| 6 | .other = .{ | ||
| 7 | .path = "other", | ||
| 8 | }, | ||
| 9 | }, | ||
| 10 | .paths = .{""}, | ||
| 11 | } | ||
test/standalone/dependency_options/other/build.zig created+59| ... | @@ -0,0 +1,59 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub const Enum = enum { alfa, bravo, charlie }; | ||
| 4 | |||
| 5 | pub fn build(b: *std.Build) !void { | ||
| 6 | const target = b.standardTargetOptions(.{}); | ||
| 7 | const optimize = b.standardOptimizeOption(.{}); | ||
| 8 | |||
| 9 | const expected_bool: bool = true; | ||
| 10 | const expected_int: i64 = 123; | ||
| 11 | const expected_float: f64 = 0.5; | ||
| 12 | const expected_string: []const u8 = "abc"; | ||
| 13 | const expected_string_list: []const []const u8 = &.{ "a", "b", "c" }; | ||
| 14 | const expected_lazy_path: std.Build.LazyPath = .{ .cwd_relative = "abc.txt" }; | ||
| 15 | const expected_lazy_path_list: []const std.Build.LazyPath = &.{ | ||
| 16 | .{ .cwd_relative = "a.txt" }, | ||
| 17 | .{ .cwd_relative = "b.txt" }, | ||
| 18 | .{ .cwd_relative = "c.txt" }, | ||
| 19 | }; | ||
| 20 | const expected_enum: Enum = .alfa; | ||
| 21 | const expected_enum_list: []const Enum = &.{ .alfa, .bravo, .charlie }; | ||
| 22 | const expected_build_id: std.zig.BuildId = .uuid; | ||
| 23 | const expected_hex_build_id: std.zig.BuildId = .initHexString("\x12\x34\xcd\xef"); | ||
| 24 | |||
| 25 | const @"bool" = b.option(bool, "bool", "bool") orelse expected_bool; | ||
| 26 | const int = b.option(i64, "int", "int") orelse expected_int; | ||
| 27 | const float = b.option(f64, "float", "float") orelse expected_float; | ||
| 28 | const string = b.option([]const u8, "string", "string") orelse expected_string; | ||
| 29 | const string_list = b.option([]const []const u8, "string_list", "string_list") orelse expected_string_list; | ||
| 30 | const lazy_path = b.option(std.Build.LazyPath, "lazy_path", "lazy_path") orelse expected_lazy_path; | ||
| 31 | const lazy_path_list = b.option([]const std.Build.LazyPath, "lazy_path_list", "lazy_path_list") orelse expected_lazy_path_list; | ||
| 32 | const @"enum" = b.option(Enum, "enum", "enum") orelse expected_enum; | ||
| 33 | const enum_list = b.option([]const Enum, "enum_list", "enum_list") orelse expected_enum_list; | ||
| 34 | const build_id = b.option(std.zig.BuildId, "build_id", "build_id") orelse expected_build_id; | ||
| 35 | const hex_build_id = b.option(std.zig.BuildId, "hex_build_id", "hex_build_id") orelse expected_hex_build_id; | ||
| 36 | |||
| 37 | if (@"bool" != expected_bool) return error.TestFailed; | ||
| 38 | if (int != expected_int) return error.TestFailed; | ||
| 39 | if (float != expected_float) return error.TestFailed; | ||
| 40 | if (!std.mem.eql(u8, string, expected_string)) return error.TestFailed; | ||
| 41 | if (string_list.len != expected_string_list.len) return error.TestFailed; | ||
| 42 | for (string_list, expected_string_list) |x, y| { | ||
| 43 | if (!std.mem.eql(u8, x, y)) return error.TestFailed; | ||
| 44 | } | ||
| 45 | if (!std.mem.eql(u8, lazy_path.cwd_relative, expected_lazy_path.cwd_relative)) return error.TestFailed; | ||
| 46 | for (lazy_path_list, expected_lazy_path_list) |x, y| { | ||
| 47 | if (!std.mem.eql(u8, x.cwd_relative, y.cwd_relative)) return error.TestFailed; | ||
| 48 | } | ||
| 49 | if (@"enum" != expected_enum) return error.TestFailed; | ||
| 50 | if (!std.mem.eql(Enum, enum_list, expected_enum_list)) return error.TestFailed; | ||
| 51 | if (!std.meta.eql(build_id, expected_build_id)) return error.TestFailed; | ||
| 52 | if (!hex_build_id.eql(expected_hex_build_id)) return error.TestFailed; | ||
| 53 | |||
| 54 | _ = b.addModule("dummy", .{ | ||
| 55 | .root_source_file = b.path("build.zig"), | ||
| 56 | .target = target, | ||
| 57 | .optimize = optimize, | ||
| 58 | }); | ||
| 59 | } | ||
test/standalone/dependency_options/other/build.zig.zon created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | .{ | ||
| 2 | .name = .other, | ||
| 3 | .fingerprint = 0xd95835207bc8b630, | ||
| 4 | .version = "0.0.0", | ||
| 5 | .dependencies = .{}, | ||
| 6 | .paths = .{""}, | ||
| 7 | } | ||