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()`
This commit is contained in:
Andrew Kelley
2025-07-25 18:00:46 -07:00
committed by GitHub
11 changed files with 430 additions and 104 deletions

View File

@@ -1,6 +1,6 @@
.{
.name = .standalone_test_cases,
.fingerprint = 0xc0dbdf9c818957be,
.fingerprint = 0xc0dbdf9c3b92810b,
.version = "0.0.0",
.dependencies = .{
.simple = .{
@@ -181,6 +181,9 @@
.install_headers = .{
.path = "install_headers",
},
.dependency_options = .{
.path = "dependency_options",
},
.dependencyFromBuildZig = .{
.path = "dependencyFromBuildZig",
},

View File

@@ -1,5 +1,6 @@
.{
.name = "dependencyFromBuildZig",
.name = .dependencyFromBuildZig,
.fingerprint = 0xfd939a1eb8169080,
.version = "0.0.0",
.dependencies = .{
.other = .{

View File

@@ -1,5 +1,6 @@
.{
.name = "other",
.name = .other,
.fingerprint = 0xd9583520a2405f6c,
.version = "0.0.0",
.dependencies = .{},
.paths = .{""},

View File

@@ -0,0 +1,141 @@
const std = @import("std");
pub const Enum = enum { alfa, bravo, charlie };
pub fn build(b: *std.Build) !void {
const test_step = b.step("test", "Test passing options to a dependency");
b.default_step = test_step;
const none_specified = b.dependency("other", .{});
const none_specified_mod = none_specified.module("dummy");
if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;
if (none_specified_mod.optimize.? != .Debug) return error.TestFailed;
// Passing null is the same as not specifying the option,
// so this should resolve to the same cached dependency instance.
const null_specified = b.dependency("other", .{
// Null literals
.target = null,
.optimize = null,
.bool = null,
// Optionals
.int = @as(?i64, null),
.float = @as(?f64, null),
// Optionals of the wrong type
.string = @as(?usize, null),
.@"enum" = @as(?bool, null),
// Non-defined option names
.this_option_does_not_exist = null,
.neither_does_this_one = @as(?[]const u8, null),
});
if (null_specified != none_specified) return error.TestFailed;
const all_specified = b.dependency("other", .{
.target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
.optimize = @as(std.builtin.OptimizeMode, .ReleaseSafe),
.bool = @as(bool, true),
.int = @as(i64, 123),
.float = @as(f64, 0.5),
.string = @as([]const u8, "abc"),
.string_list = @as([]const []const u8, &.{ "a", "b", "c" }),
.lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }),
.lazy_path_list = @as([]const std.Build.LazyPath, &.{
.{ .cwd_relative = "a.txt" },
.{ .cwd_relative = "b.txt" },
.{ .cwd_relative = "c.txt" },
}),
.@"enum" = @as(Enum, .alfa),
.enum_list = @as([]const Enum, &.{ .alfa, .bravo, .charlie }),
.build_id = @as(std.zig.BuildId, .uuid),
.hex_build_id = std.zig.BuildId.initHexString("\x12\x34\xcd\xef"),
});
const all_specified_mod = all_specified.module("dummy");
if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed;
if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed;
if (all_specified_mod.resolved_target.?.result.abi != .gnu) return error.TestFailed;
if (all_specified_mod.optimize.? != .ReleaseSafe) return error.TestFailed;
const all_specified_optional = b.dependency("other", .{
.target = @as(?std.Build.ResolvedTarget, b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu })),
.optimize = @as(?std.builtin.OptimizeMode, .ReleaseSafe),
.bool = @as(?bool, true),
.int = @as(?i64, 123),
.float = @as(?f64, 0.5),
.string = @as(?[]const u8, "abc"),
.string_list = @as(?[]const []const u8, &.{ "a", "b", "c" }),
.lazy_path = @as(?std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }),
.lazy_path_list = @as(?[]const std.Build.LazyPath, &.{
.{ .cwd_relative = "a.txt" },
.{ .cwd_relative = "b.txt" },
.{ .cwd_relative = "c.txt" },
}),
.@"enum" = @as(?Enum, .alfa),
.enum_list = @as(?[]const Enum, &.{ .alfa, .bravo, .charlie }),
.build_id = @as(?std.zig.BuildId, .uuid),
.hex_build_id = @as(?std.zig.BuildId, .initHexString("\x12\x34\xcd\xef")),
});
if (all_specified_optional != all_specified) return error.TestFailed;
const all_specified_literal = b.dependency("other", .{
.target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
.optimize = .ReleaseSafe,
.bool = true,
.int = 123,
.float = 0.5,
.string = "abc",
.string_list = &[_][]const u8{ "a", "b", "c" },
.lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }),
.lazy_path_list = &[_]std.Build.LazyPath{
.{ .cwd_relative = "a.txt" },
.{ .cwd_relative = "b.txt" },
.{ .cwd_relative = "c.txt" },
},
.@"enum" = .alfa,
.enum_list = &[_]Enum{ .alfa, .bravo, .charlie },
.build_id = .uuid,
.hex_build_id = std.zig.BuildId.initHexString("\x12\x34\xcd\xef"),
});
if (all_specified_literal != all_specified) return error.TestFailed;
var mut_string_buf = "abc".*;
const mut_string: []u8 = &mut_string_buf;
var mut_string_list_buf = [_][]const u8{ "a", "b", "c" };
const mut_string_list: [][]const u8 = &mut_string_list_buf;
var mut_lazy_path_list_buf = [_]std.Build.LazyPath{
.{ .cwd_relative = "a.txt" },
.{ .cwd_relative = "b.txt" },
.{ .cwd_relative = "c.txt" },
};
const mut_lazy_path_list: []std.Build.LazyPath = &mut_lazy_path_list_buf;
var mut_enum_list_buf = [_]Enum{ .alfa, .bravo, .charlie };
const mut_enum_list: []Enum = &mut_enum_list_buf;
// Most supported option types are serialized to a string representation,
// so alternative representations of the same option value should resolve
// to the same cached dependency instance.
const all_specified_alt = b.dependency("other", .{
.target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }),
.optimize = "ReleaseSafe",
.bool = .true,
.int = "123",
.float = @as(f16, 0.5),
.string = mut_string,
.string_list = mut_string_list,
.lazy_path = @as(std.Build.LazyPath, .{ .cwd_relative = "abc.txt" }),
.lazy_path_list = mut_lazy_path_list,
.@"enum" = "alfa",
.enum_list = mut_enum_list,
.build_id = "uuid",
.hex_build_id = "0x1234cdef",
});
if (all_specified_alt != all_specified) return error.TestFailed;
}

View File

@@ -0,0 +1,11 @@
.{
.name = .dependency_options,
.fingerprint = 0x3e3ce1c1f92ba47e,
.version = "0.0.0",
.dependencies = .{
.other = .{
.path = "other",
},
},
.paths = .{""},
}

View File

@@ -0,0 +1,59 @@
const std = @import("std");
pub const Enum = enum { alfa, bravo, charlie };
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const expected_bool: bool = true;
const expected_int: i64 = 123;
const expected_float: f64 = 0.5;
const expected_string: []const u8 = "abc";
const expected_string_list: []const []const u8 = &.{ "a", "b", "c" };
const expected_lazy_path: std.Build.LazyPath = .{ .cwd_relative = "abc.txt" };
const expected_lazy_path_list: []const std.Build.LazyPath = &.{
.{ .cwd_relative = "a.txt" },
.{ .cwd_relative = "b.txt" },
.{ .cwd_relative = "c.txt" },
};
const expected_enum: Enum = .alfa;
const expected_enum_list: []const Enum = &.{ .alfa, .bravo, .charlie };
const expected_build_id: std.zig.BuildId = .uuid;
const expected_hex_build_id: std.zig.BuildId = .initHexString("\x12\x34\xcd\xef");
const @"bool" = b.option(bool, "bool", "bool") orelse expected_bool;
const int = b.option(i64, "int", "int") orelse expected_int;
const float = b.option(f64, "float", "float") orelse expected_float;
const string = b.option([]const u8, "string", "string") orelse expected_string;
const string_list = b.option([]const []const u8, "string_list", "string_list") orelse expected_string_list;
const lazy_path = b.option(std.Build.LazyPath, "lazy_path", "lazy_path") orelse expected_lazy_path;
const lazy_path_list = b.option([]const std.Build.LazyPath, "lazy_path_list", "lazy_path_list") orelse expected_lazy_path_list;
const @"enum" = b.option(Enum, "enum", "enum") orelse expected_enum;
const enum_list = b.option([]const Enum, "enum_list", "enum_list") orelse expected_enum_list;
const build_id = b.option(std.zig.BuildId, "build_id", "build_id") orelse expected_build_id;
const hex_build_id = b.option(std.zig.BuildId, "hex_build_id", "hex_build_id") orelse expected_hex_build_id;
if (@"bool" != expected_bool) return error.TestFailed;
if (int != expected_int) return error.TestFailed;
if (float != expected_float) return error.TestFailed;
if (!std.mem.eql(u8, string, expected_string)) return error.TestFailed;
if (string_list.len != expected_string_list.len) return error.TestFailed;
for (string_list, expected_string_list) |x, y| {
if (!std.mem.eql(u8, x, y)) return error.TestFailed;
}
if (!std.mem.eql(u8, lazy_path.cwd_relative, expected_lazy_path.cwd_relative)) return error.TestFailed;
for (lazy_path_list, expected_lazy_path_list) |x, y| {
if (!std.mem.eql(u8, x.cwd_relative, y.cwd_relative)) return error.TestFailed;
}
if (@"enum" != expected_enum) return error.TestFailed;
if (!std.mem.eql(Enum, enum_list, expected_enum_list)) return error.TestFailed;
if (!std.meta.eql(build_id, expected_build_id)) return error.TestFailed;
if (!hex_build_id.eql(expected_hex_build_id)) return error.TestFailed;
_ = b.addModule("dummy", .{
.root_source_file = b.path("build.zig"),
.target = target,
.optimize = optimize,
});
}

View File

@@ -0,0 +1,7 @@
.{
.name = .other,
.fingerprint = 0xd95835207bc8b630,
.version = "0.0.0",
.dependencies = .{},
.paths = .{""},
}