authorgravatar for inkryption07@gmail.comInKryption <inkryption07@gmail.com> 2024-10-05 00:58:48+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-06 12:39:35-07:00
log3284d1ffb125c460ec8c19323cb53a7b0cea5e5e
tree1ed2a4d64fa416e95349df47575748b4059dda44
parent148b5b4c7806a694084f1e6f9514b0333cb75c6a

Build: Add `option(LazyPath, ...)` support

Also adds support for `[]const LazyPath` in a similar vein, and refactors a few other bits of code.

1 files changed, 166 insertions(+), 29 deletions(-)

lib/std/Build.zig+166-29
...@@ -217,6 +217,8 @@ const UserValue = union(enum) {...@@ -217,6 +217,8 @@ const UserValue = union(enum) {
217 scalar: []const u8,217 scalar: []const u8,
218 list: ArrayList([]const u8),218 list: ArrayList([]const u8),
219 map: StringHashMap(*const UserValue),219 map: StringHashMap(*const UserValue),
220 lazy_path: LazyPath,
221 lazy_path_list: ArrayList(LazyPath),
220};222};
221223
222const TypeId = enum {224const TypeId = enum {
...@@ -228,6 +230,8 @@ const TypeId = enum {...@@ -228,6 +230,8 @@ const TypeId = enum {
228 string,230 string,
229 list,231 list,
230 build_id,232 build_id,
233 lazy_path,
234 lazy_path_list,
231};235};
232236
233const TopLevelStep = struct {237const TopLevelStep = struct {
...@@ -433,6 +437,22 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption...@@ -433,6 +437,22 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption
433 .used = false,437 .used = false,
434 }) catch @panic("OOM");438 }) catch @panic("OOM");
435 },439 },
440 LazyPath => {
441 user_input_options.put(field.name, .{
442 .name = field.name,
443 .value = .{ .lazy_path = v.dupeInner(allocator) },
444 .used = false,
445 }) catch @panic("OOM");
446 },
447 []const LazyPath => {
448 var list = ArrayList(LazyPath).initCapacity(allocator, v.len) catch @panic("OOM");
449 for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(allocator));
450 user_input_options.put(field.name, .{
451 .name = field.name,
452 .value = .{ .lazy_path_list = list },
453 .used = false,
454 }) catch @panic("OOM");
455 },
436 []const u8 => {456 []const u8 => {
437 user_input_options.put(field.name, .{457 user_input_options.put(field.name, .{
438 .name = field.name,458 .name = field.name,
...@@ -492,6 +512,8 @@ const OrderedUserValue = union(enum) {...@@ -492,6 +512,8 @@ const OrderedUserValue = union(enum) {
492 scalar: []const u8,512 scalar: []const u8,
493 list: ArrayList([]const u8),513 list: ArrayList([]const u8),
494 map: ArrayList(Pair),514 map: ArrayList(Pair),
515 lazy_path: LazyPath,
516 lazy_path_list: ArrayList(LazyPath),
495517
496 const Pair = struct {518 const Pair = struct {
497 name: []const u8,519 name: []const u8,
...@@ -502,6 +524,7 @@ const OrderedUserValue = union(enum) {...@@ -502,6 +524,7 @@ const OrderedUserValue = union(enum) {
502 };524 };
503525
504 fn hash(val: OrderedUserValue, hasher: *std.hash.Wyhash) void {526 fn hash(val: OrderedUserValue, hasher: *std.hash.Wyhash) void {
527 hasher.update(&std.mem.toBytes(std.meta.activeTag(val)));
505 switch (val) {528 switch (val) {
506 .flag => {},529 .flag => {},
507 .scalar => |scalar| hasher.update(scalar),530 .scalar => |scalar| hasher.update(scalar),
...@@ -512,6 +535,31 @@ const OrderedUserValue = union(enum) {...@@ -512,6 +535,31 @@ const OrderedUserValue = union(enum) {
512 hasher.update(map_entry.name);535 hasher.update(map_entry.name);
513 map_entry.value.hash(hasher);536 map_entry.value.hash(hasher);
514 },537 },
538 .lazy_path => |lp| hashLazyPath(lp, hasher),
539 .lazy_path_list => |lp_list| for (lp_list.items) |lp| {
540 hashLazyPath(lp, hasher);
541 },
542 }
543 }
544
545 fn hashLazyPath(lp: LazyPath, hasher: *std.hash.Wyhash) void {
546 switch (lp) {
547 .src_path => |sp| {
548 hasher.update(sp.owner.pkg_hash);
549 hasher.update(sp.sub_path);
550 },
551 .generated => |gen| {
552 hasher.update(gen.file.step.owner.pkg_hash);
553 hasher.update(std.mem.asBytes(&gen.up));
554 hasher.update(gen.sub_path);
555 },
556 .cwd_relative => |rel_path| {
557 hasher.update(rel_path);
558 },
559 .dependency => |dep| {
560 hasher.update(dep.dependency.builder.pkg_hash);
561 hasher.update(dep.sub_path);
562 },
515 }563 }
516 }564 }
517565
...@@ -535,6 +583,8 @@ const OrderedUserValue = union(enum) {...@@ -535,6 +583,8 @@ const OrderedUserValue = union(enum) {
535 .scalar => |scalar| .{ .scalar = scalar },583 .scalar => |scalar| .{ .scalar = scalar },
536 .list => |list| .{ .list = list },584 .list => |list| .{ .list = list },
537 .map => |map| .{ .map = OrderedUserValue.mapFromUnordered(allocator, map) },585 .map => |map| .{ .map = OrderedUserValue.mapFromUnordered(allocator, map) },
586 .lazy_path => |lp| .{ .lazy_path = lp },
587 .lazy_path_list => |list| .{ .lazy_path_list = list },
538 };588 };
539 }589 }
540};590};
...@@ -1023,7 +1073,11 @@ pub fn addConfigHeader(...@@ -1023,7 +1073,11 @@ pub fn addConfigHeader(
10231073
1024/// Allocator.dupe without the need to handle out of memory.1074/// Allocator.dupe without the need to handle out of memory.
1025pub fn dupe(b: *Build, bytes: []const u8) []u8 {1075pub fn dupe(b: *Build, bytes: []const u8) []u8 {
1026 return b.allocator.dupe(u8, bytes) catch @panic("OOM");1076 return dupeInner(b.allocator, bytes);
1077}
1078
1079pub fn dupeInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
1080 return allocator.dupe(u8, bytes) catch @panic("OOM");
1027}1081}
10281082
1029/// Duplicates an array of strings without the need to handle out of memory.1083/// Duplicates an array of strings without the need to handle out of memory.
...@@ -1035,7 +1089,11 @@ pub fn dupeStrings(b: *Build, strings: []const []const u8) [][]u8 {...@@ -1035,7 +1089,11 @@ pub fn dupeStrings(b: *Build, strings: []const []const u8) [][]u8 {
10351089
1036/// Duplicates a path and converts all slashes to the OS's canonical path separator.1090/// Duplicates a path and converts all slashes to the OS's canonical path separator.
1037pub fn dupePath(b: *Build, bytes: []const u8) []u8 {1091pub fn dupePath(b: *Build, bytes: []const u8) []u8 {
1038 const the_copy = b.dupe(bytes);1092 return dupePathInner(b.allocator, bytes);
1093}
1094
1095fn dupePathInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
1096 const the_copy = dupeInner(allocator, bytes);
1039 for (the_copy) |*byte| {1097 for (the_copy) |*byte| {
1040 switch (byte.*) {1098 switch (byte.*) {
1041 '/', '\\' => byte.* = fs.path.sep,1099 '/', '\\' => byte.* = fs.path.sep,
...@@ -1149,7 +1207,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1149,7 +1207,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1149 return null;1207 return null;
1150 }1208 }
1151 },1209 },
1152 .list, .map => {1210 .list, .map, .lazy_path, .lazy_path_list => {
1153 log.err("Expected -D{s} to be a boolean, but received a {s}.", .{1211 log.err("Expected -D{s} to be a boolean, but received a {s}.", .{
1154 name, @tagName(option_ptr.value),1212 name, @tagName(option_ptr.value),
1155 });1213 });
...@@ -1158,7 +1216,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1158,7 +1216,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1158 },1216 },
1159 },1217 },
1160 .int => switch (option_ptr.value) {1218 .int => switch (option_ptr.value) {
1161 .flag, .list, .map => {1219 .flag, .list, .map, .lazy_path, .lazy_path_list => {
1162 log.err("Expected -D{s} to be an integer, but received a {s}.", .{1220 log.err("Expected -D{s} to be an integer, but received a {s}.", .{
1163 name, @tagName(option_ptr.value),1221 name, @tagName(option_ptr.value),
1164 });1222 });
...@@ -1182,7 +1240,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1182,7 +1240,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1182 },1240 },
1183 },1241 },
1184 .float => switch (option_ptr.value) {1242 .float => switch (option_ptr.value) {
1185 .flag, .map, .list => {1243 .flag, .map, .list, .lazy_path, .lazy_path_list => {
1186 log.err("Expected -D{s} to be a float, but received a {s}.", .{1244 log.err("Expected -D{s} to be a float, but received a {s}.", .{
1187 name, @tagName(option_ptr.value),1245 name, @tagName(option_ptr.value),
1188 });1246 });
...@@ -1199,7 +1257,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1199,7 +1257,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1199 },1257 },
1200 },1258 },
1201 .@"enum" => switch (option_ptr.value) {1259 .@"enum" => switch (option_ptr.value) {
1202 .flag, .map, .list => {1260 .flag, .map, .list, .lazy_path, .lazy_path_list => {
1203 log.err("Expected -D{s} to be an enum, but received a {s}.", .{1261 log.err("Expected -D{s} to be an enum, but received a {s}.", .{
1204 name, @tagName(option_ptr.value),1262 name, @tagName(option_ptr.value),
1205 });1263 });
...@@ -1217,7 +1275,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1217,7 +1275,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1217 },1275 },
1218 },1276 },
1219 .string => switch (option_ptr.value) {1277 .string => switch (option_ptr.value) {
1220 .flag, .list, .map => {1278 .flag, .list, .map, .lazy_path, .lazy_path_list => {
1221 log.err("Expected -D{s} to be a string, but received a {s}.", .{1279 log.err("Expected -D{s} to be a string, but received a {s}.", .{
1222 name, @tagName(option_ptr.value),1280 name, @tagName(option_ptr.value),
1223 });1281 });
...@@ -1227,7 +1285,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1227,7 +1285,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1227 .scalar => |s| return s,1285 .scalar => |s| return s,
1228 },1286 },
1229 .build_id => switch (option_ptr.value) {1287 .build_id => switch (option_ptr.value) {
1230 .flag, .map, .list => {1288 .flag, .map, .list, .lazy_path, .lazy_path_list => {
1231 log.err("Expected -D{s} to be an enum, but received a {s}.", .{1289 log.err("Expected -D{s} to be an enum, but received a {s}.", .{
1232 name, @tagName(option_ptr.value),1290 name, @tagName(option_ptr.value),
1233 });1291 });
...@@ -1245,7 +1303,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1245,7 +1303,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1245 },1303 },
1246 },1304 },
1247 .list => switch (option_ptr.value) {1305 .list => switch (option_ptr.value) {
1248 .flag, .map => {1306 .flag, .map, .lazy_path, .lazy_path_list => {
1249 log.err("Expected -D{s} to be a list, but received a {s}.", .{1307 log.err("Expected -D{s} to be a list, but received a {s}.", .{
1250 name, @tagName(option_ptr.value),1308 name, @tagName(option_ptr.value),
1251 });1309 });
...@@ -1258,7 +1316,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1258,7 +1316,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1258 .list => |lst| return lst.items,1316 .list => |lst| return lst.items,
1259 },1317 },
1260 .enum_list => switch (option_ptr.value) {1318 .enum_list => switch (option_ptr.value) {
1261 .flag, .map => {1319 .flag, .map, .lazy_path, .lazy_path_list => {
1262 log.err("Expected -D{s} to be a list, but received a {s}.", .{1320 log.err("Expected -D{s} to be a list, but received a {s}.", .{
1263 name, @tagName(option_ptr.value),1321 name, @tagName(option_ptr.value),
1264 });1322 });
...@@ -1276,19 +1334,48 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw...@@ -1276,19 +1334,48 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw
1276 },1334 },
1277 .list => |lst| {1335 .list => |lst| {
1278 const Child = @typeInfo(T).pointer.child;1336 const Child = @typeInfo(T).pointer.child;
1279 var new_list = b.allocator.alloc(Child, lst.items.len) catch @panic("OOM");1337 const new_list = b.allocator.alloc(Child, lst.items.len) catch @panic("OOM");
1280 for (lst.items, 0..) |str, i| {1338 for (new_list, lst.items) |*new_item, str| {
1281 const value = std.meta.stringToEnum(Child, str) orelse {1339 new_item.* = std.meta.stringToEnum(Child, str) orelse {
1282 log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(Child) });1340 log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(Child) });
1283 b.markInvalidUserInput();1341 b.markInvalidUserInput();
1284 b.allocator.free(new_list);1342 b.allocator.free(new_list);
1285 return null;1343 return null;
1286 };1344 };
1287 new_list[i] = value;
1288 }1345 }
1289 return new_list;1346 return new_list;
1290 },1347 },
1291 },1348 },
1349 .lazy_path => switch (option_ptr.value) {
1350 .scalar => |s| return .{ .cwd_relative = s },
1351 .lazy_path => |lp| return lp,
1352 .flag, .map, .list, .lazy_path_list => {
1353 log.err("Expected -D{s} to be a path, but received a {s}.", .{
1354 name, @tagName(option_ptr.value),
1355 });
1356 b.markInvalidUserInput();
1357 return null;
1358 },
1359 },
1360 .lazy_path_list => switch (option_ptr.value) {
1361 .scalar => |s| return b.allocator.dupe(LazyPath, &[_]LazyPath{.{ .cwd_relative = s }}) catch @panic("OOM"),
1362 .lazy_path => |lp| return b.allocator.dupe(LazyPath, &[_]LazyPath{lp}) catch @panic("OOM"),
1363 .list => |lst| {
1364 const new_list = b.allocator.alloc(LazyPath, lst.items.len) catch @panic("OOM");
1365 for (new_list, lst.items) |*new_item, str| {
1366 new_item.* = .{ .cwd_relative = str };
1367 }
1368 return new_list;
1369 },
1370 .lazy_path_list => |lp_list| return lp_list.items,
1371 .flag, .map => {
1372 log.err("Expected -D{s} to be a path, but received a {s}.", .{
1373 name, @tagName(option_ptr.value),
1374 });
1375 b.markInvalidUserInput();
1376 return null;
1377 },
1378 },
1292 }1379 }
1293}1380}
12941381
...@@ -1508,6 +1595,10 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8...@@ -1508,6 +1595,10 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8
1508 log.warn("TODO maps as command line arguments is not implemented yet.", .{});1595 log.warn("TODO maps as command line arguments is not implemented yet.", .{});
1509 return true;1596 return true;
1510 },1597 },
1598 .lazy_path, .lazy_path_list => {
1599 log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) });
1600 return true;
1601 },
1511 }1602 }
1512 return false;1603 return false;
1513}1604}
...@@ -1530,10 +1621,15 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool {...@@ -1530,10 +1621,15 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool {
1530 log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, s });1621 log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, s });
1531 return true;1622 return true;
1532 },1623 },
1533 .list, .map => {1624 .list, .map, .lazy_path_list => {
1534 log.err("Flag '-D{s}' conflicts with multiple options of the same name.", .{name});1625 log.err("Flag '-D{s}' conflicts with multiple options of the same name.", .{name});
1535 return true;1626 return true;
1536 },1627 },
1628 .lazy_path => |lp| {
1629 log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, lp.getDisplayName() });
1630 return true;
1631 },
1632
1537 .flag => {},1633 .flag => {},
1538 }1634 }
1539 return false;1635 return false;
...@@ -1542,6 +1638,7 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool {...@@ -1542,6 +1638,7 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool {
1542fn typeToEnum(comptime T: type) TypeId {1638fn typeToEnum(comptime T: type) TypeId {
1543 return switch (T) {1639 return switch (T) {
1544 std.zig.BuildId => .build_id,1640 std.zig.BuildId => .build_id,
1641 LazyPath => .lazy_path,
1545 else => return switch (@typeInfo(T)) {1642 else => return switch (@typeInfo(T)) {
1546 .int => .int,1643 .int => .int,
1547 .float => .float,1644 .float => .float,
...@@ -1550,6 +1647,7 @@ fn typeToEnum(comptime T: type) TypeId {...@@ -1550,6 +1647,7 @@ fn typeToEnum(comptime T: type) TypeId {
1550 .pointer => |pointer| switch (pointer.child) {1647 .pointer => |pointer| switch (pointer.child) {
1551 u8 => .string,1648 u8 => .string,
1552 []const u8 => .list,1649 []const u8 => .list,
1650 LazyPath => .lazy_path_list,
1553 else => switch (@typeInfo(pointer.child)) {1651 else => switch (@typeInfo(pointer.child)) {
1554 .@"enum" => .enum_list,1652 .@"enum" => .enum_list,
1555 else => @compileError("Unsupported type: " ++ @typeName(T)),1653 else => @compileError("Unsupported type: " ++ @typeName(T)),
...@@ -2065,22 +2163,17 @@ pub fn dependencyFromBuildZig(...@@ -2065,22 +2163,17 @@ pub fn dependencyFromBuildZig(
2065}2163}
20662164
2067fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {2165fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {
2166 if (std.meta.activeTag(lhs) != rhs) return false;
2068 switch (lhs) {2167 switch (lhs) {
2069 .flag => {},2168 .flag => {},
2070 .scalar => |lhs_scalar| {2169 .scalar => |lhs_scalar| {
2071 const rhs_scalar = switch (rhs) {2170 const rhs_scalar = rhs.scalar;
2072 .scalar => |scalar| scalar,
2073 else => return false,
2074 };
20752171
2076 if (!std.mem.eql(u8, lhs_scalar, rhs_scalar))2172 if (!std.mem.eql(u8, lhs_scalar, rhs_scalar))
2077 return false;2173 return false;
2078 },2174 },
2079 .list => |lhs_list| {2175 .list => |lhs_list| {
2080 const rhs_list = switch (rhs) {2176 const rhs_list = rhs.list;
2081 .list => |list| list,
2082 else => return false,
2083 };
20842177
2085 if (lhs_list.items.len != rhs_list.items.len)2178 if (lhs_list.items.len != rhs_list.items.len)
2086 return false;2179 return false;
...@@ -2091,10 +2184,7 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {...@@ -2091,10 +2184,7 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {
2091 }2184 }
2092 },2185 },
2093 .map => |lhs_map| {2186 .map => |lhs_map| {
2094 const rhs_map = switch (rhs) {2187 const rhs_map = rhs.map;
2095 .map => |map| map,
2096 else => return false,
2097 };
20982188
2099 if (lhs_map.count() != rhs_map.count())2189 if (lhs_map.count() != rhs_map.count())
2100 return false;2190 return false;
...@@ -2106,11 +2196,54 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {...@@ -2106,11 +2196,54 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {
2106 return false;2196 return false;
2107 }2197 }
2108 },2198 },
2199 .lazy_path => |lhs_lp| {
2200 const rhs_lp = rhs.lazy_path;
2201 return userLazyPathsAreTheSame(lhs_lp, rhs_lp);
2202 },
2203 .lazy_path_list => |lhs_lp_list| {
2204 const rhs_lp_list = rhs.lazy_path_list;
2205 if (lhs_lp_list.items.len != rhs_lp_list.items.len) return false;
2206 for (lhs_lp_list.items, rhs_lp_list.items) |lhs_lp, rhs_lp| {
2207 if (!userLazyPathsAreTheSame(lhs_lp, rhs_lp)) return false;
2208 }
2209 return true;
2210 },
2109 }2211 }
21102212
2111 return true;2213 return true;
2112}2214}
21132215
2216fn userLazyPathsAreTheSame(lhs_lp: LazyPath, rhs_lp: LazyPath) bool {
2217 if (std.meta.activeTag(lhs_lp) != rhs_lp) return false;
2218 switch (lhs_lp) {
2219 .src_path => |lhs_sp| {
2220 const rhs_sp = rhs_lp.src_path;
2221
2222 if (lhs_sp.owner != rhs_sp.owner) return false;
2223 if (std.mem.eql(u8, lhs_sp.sub_path, rhs_sp.sub_path)) return false;
2224 },
2225 .generated => |lhs_gen| {
2226 const rhs_gen = rhs_lp.generated;
2227
2228 if (lhs_gen.file != rhs_gen.file) return false;
2229 if (lhs_gen.up != rhs_gen.up) return false;
2230 if (std.mem.eql(u8, lhs_gen.sub_path, rhs_gen.sub_path)) return false;
2231 },
2232 .cwd_relative => |lhs_rel_path| {
2233 const rhs_rel_path = rhs_lp.cwd_relative;
2234
2235 if (!std.mem.eql(u8, lhs_rel_path, rhs_rel_path)) return false;
2236 },
2237 .dependency => |lhs_dep| {
2238 const rhs_dep = rhs_lp.dependency;
2239
2240 if (lhs_dep.dependency != rhs_dep.dependency) return false;
2241 if (!std.mem.eql(u8, lhs_dep.sub_path, rhs_dep.sub_path)) return false;
2242 },
2243 }
2244 return true;
2245}
2246
2114fn dependencyInner(2247fn dependencyInner(
2115 b: *Build,2248 b: *Build,
2116 name: []const u8,2249 name: []const u8,
...@@ -2435,16 +2568,20 @@ pub const LazyPath = union(enum) {...@@ -2435,16 +2568,20 @@ pub const LazyPath = union(enum) {
2435 /// The `b` parameter is only used for its allocator. All *Build instances2568 /// The `b` parameter is only used for its allocator. All *Build instances
2436 /// share the same allocator.2569 /// share the same allocator.
2437 pub fn dupe(lazy_path: LazyPath, b: *Build) LazyPath {2570 pub fn dupe(lazy_path: LazyPath, b: *Build) LazyPath {
2571 return lazy_path.dupeInner(b.allocator);
2572 }
2573
2574 fn dupeInner(lazy_path: LazyPath, allocator: std.mem.Allocator) LazyPath {
2438 return switch (lazy_path) {2575 return switch (lazy_path) {
2439 .src_path => |sp| .{ .src_path = .{2576 .src_path => |sp| .{ .src_path = .{
2440 .owner = sp.owner,2577 .owner = sp.owner,
2441 .sub_path = sp.owner.dupePath(sp.sub_path),2578 .sub_path = sp.owner.dupePath(sp.sub_path),
2442 } },2579 } },
2443 .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },2580 .cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) },
2444 .generated => |gen| .{ .generated = .{2581 .generated => |gen| .{ .generated = .{
2445 .file = gen.file,2582 .file = gen.file,
2446 .up = gen.up,2583 .up = gen.up,
2447 .sub_path = b.dupePath(gen.sub_path),2584 .sub_path = dupePathInner(allocator, gen.sub_path),
2448 } },2585 } },
2449 .dependency => |dep| .{ .dependency = dep },2586 .dependency => |dep| .{ .dependency = dep },
2450 };2587 };