authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-25 18:00:46-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-25 18:00:46-07:00
log9e11727c7c88289554251646166f844376dcbbe9
treedb80e9778647f1f53c1f5078bab944bd51abd1ff
parent869ef00602328f97ea8c88358310cbd34d4391ab
parentca57115da7c4603dbcefce1dc9395617e28a86f8
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23340 from castholm/pass-null-to-b-dependency

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}
410410
411fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOptionsMap {411fn 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") },420fn 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 }
507583 @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(field.type));
508 return user_input_options;
509}584}
510585
511const OrderedUserValue = union(enum) {586const 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}
15651565
1566pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void {1566pub 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 });
15761582
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));
15791585
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;
15861592
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));
15901596
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};
325346
326pub const LtoMode = enum { none, full, thin };347pub 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 @@
1const std = @import("std");
2
3pub const Enum = enum { alfa, bravo, charlie };
4
5pub 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 @@
1const std = @import("std");
2
3pub const Enum = enum { alfa, bravo, charlie };
4
5pub 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}