authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-20 11:25:43+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-20 11:25:43+02:00
log73b010e2216331b0b87240b05ea061294749383b
treec7d08b440f359918ca3842eecb5e026a952d8c0e
parentefd227eca2e2013b4e540ab2ba44664668a5253b
parent5ee54cd52ad5f03ce24ec8c0ffee35972df3a5f3

Merge pull request 'make frontend and build system more resistant to absolute paths' (#36548) from absolutely-not into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36548 Reviewed-by: mlugg <mlugg@mlugg.co.uk>

23 files changed, 380 insertions(+), 312 deletions(-)

lib/compiler/Maker.zig+4-1
...@@ -614,6 +614,8 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -614,6 +614,8 @@ pub fn main(init: process.Init.Minimal) !void {
614 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));614 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
615 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));615 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));
616 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));616 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
617 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
618 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
617619
618 graph.cache.hash.addBytes(builtin.zig_version_string);620 graph.cache.hash.addBytes(builtin.zig_version_string);
619621
...@@ -1118,6 +1120,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {...@@ -1118,6 +1120,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
1118 graph.zig_exe, "build-exe", //1120 graph.zig_exe, "build-exe", //
1119 "--cache-dir", graph.local_cache_root.path orelse ".", //1121 "--cache-dir", graph.local_cache_root.path orelse ".", //
1120 "--global-cache-dir", graph.global_cache_root.path orelse ".", //1122 "--global-cache-dir", graph.global_cache_root.path orelse ".", //
1123 "--build-root", graph.build_root_directory.path orelse ".", //
1121 "--zig-lib-dir", graph.zig_lib_directory.path orelse ".", //1124 "--zig-lib-dir", graph.zig_lib_directory.path orelse ".", //
1122 "--name", configurer_exe_name, //1125 "--name", configurer_exe_name, //
1123 "-fsingle-threaded", //1126 "-fsingle-threaded", //
...@@ -1412,7 +1415,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {...@@ -1412,7 +1415,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
14121415
1413 if (config_man) |man| {1416 if (config_man) |man| {
1414 if (try man.hit(compile_prog_node)) {1417 if (try man.hit(compile_prog_node)) {
1415 log.debug("configuration cache hit", .{});
1416 const digest = man.final();1418 const digest = man.final();
1417 const path: Path = .{1419 const path: Path = .{
1418 .root_dir = graph.local_cache_root,1420 .root_dir = graph.local_cache_root,
...@@ -1422,6 +1424,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {...@@ -1422,6 +1424,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig {
1422 break :cp .{ path, man.toOwnedLock() };1424 break :cp .{ path, man.toOwnedLock() };
1423 }1425 }
1424 }1426 }
1427 try graph.handleVerbose(null, null, build_configurer_argv.items);
1425 const configure_exe_path: Path = if (std.zig.buildExeSubprocess(gpa, io, .{1428 const configure_exe_path: Path = if (std.zig.buildExeSubprocess(gpa, io, .{
1426 .argv = build_configurer_argv.items,1429 .argv = build_configurer_argv.items,
1427 .cache_root = graph.local_cache_root,1430 .cache_root = graph.local_cache_root,
lib/compiler/Maker/Step.zig+7
...@@ -656,6 +656,13 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi...@@ -656,6 +656,13 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
656 };656 };
657 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));657 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
658 },658 },
659 .build_root => {
660 const path: Path = .{
661 .root_dir = graph.build_root_directory,
662 .sub_path = sub_path_dirname,
663 };
664 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
665 },
659 }666 }
660 }667 }
661 },668 },
lib/compiler/Maker/Step/Compile.zig+2-1
...@@ -658,9 +658,10 @@ fn lowerZigArgs(...@@ -658,9 +658,10 @@ fn lowerZigArgs(
658 zig_args.appendAssumeCapacity(libc_file);658 zig_args.appendAssumeCapacity(libc_file);
659 }659 }
660660
661 (try zig_args.addManyAsArray(gpa, 4)).* = .{661 (try zig_args.addManyAsArray(gpa, 6)).* = .{
662 "--cache-dir", graph.local_cache_root.path orelse ".",662 "--cache-dir", graph.local_cache_root.path orelse ".",
663 "--global-cache-dir", graph.global_cache_root.path orelse ".",663 "--global-cache-dir", graph.global_cache_root.path orelse ".",
664 "--build-root", graph.build_root_directory.path orelse ".",
664 };665 };
665666
666 try zig_args.ensureUnusedCapacity(gpa, 1);667 try zig_args.ensureUnusedCapacity(gpa, 1);
lib/std/Build/Cache.zig+34-51
...@@ -417,18 +417,6 @@ pub const Manifest = struct {...@@ -417,18 +417,6 @@ pub const Manifest = struct {
417 return addFileInner(m, prefixed_path, handle, max_file_size);417 return addFileInner(m, prefixed_path, handle, max_file_size);
418 }418 }
419419
420 /// Deprecated; use `addFilePath`.
421 pub fn addFile(self: *Manifest, file_path: []const u8, max_file_size: ?usize) !usize {
422 assert(self.manifest_file == null);
423
424 const gpa = self.cache.gpa;
425 try self.files.ensureUnusedCapacity(gpa, 1);
426 const prefixed_path = try self.cache.findPrefix(file_path);
427 errdefer gpa.free(prefixed_path.sub_path);
428
429 return addFileInner(self, prefixed_path, null, max_file_size);
430 }
431
432 fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?Io.File, max_file_size: ?usize) usize {420 fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?Io.File, max_file_size: ?usize) usize {
433 const gop = self.files.getOrPutAssumeCapacityAdapted(prefixed_path, FilesAdapter{});421 const gop = self.files.getOrPutAssumeCapacityAdapted(prefixed_path, FilesAdapter{});
434 if (gop.found_existing) {422 if (gop.found_existing) {
...@@ -452,26 +440,12 @@ pub const Manifest = struct {...@@ -452,26 +440,12 @@ pub const Manifest = struct {
452 return gop.index;440 return gop.index;
453 }441 }
454442
455 /// Deprecated, use `addOptionalFilePath`.
456 pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void {
457 self.hash.add(optional_file_path != null);
458 const file_path = optional_file_path orelse return;
459 _ = try self.addFile(file_path, null);
460 }
461
462 pub fn addOptionalFilePath(self: *Manifest, optional_file_path: ?Path) !void {443 pub fn addOptionalFilePath(self: *Manifest, optional_file_path: ?Path) !void {
463 self.hash.add(optional_file_path != null);444 self.hash.add(optional_file_path != null);
464 const file_path = optional_file_path orelse return;445 const file_path = optional_file_path orelse return;
465 _ = try self.addFilePath(file_path, null);446 _ = try self.addFilePath(file_path, null);
466 }447 }
467448
468 pub fn addListOfFiles(self: *Manifest, list_of_files: []const []const u8) !void {
469 self.hash.add(list_of_files.len);
470 for (list_of_files) |file_path| {
471 _ = try self.addFile(file_path, null);
472 }
473 }
474
475 pub fn addDepFile(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void {449 pub fn addDepFile(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void {
476 assert(self.manifest_file == null);450 assert(self.manifest_file == null);
477 return self.addDepFileMaybePost(dir, dep_file_sub_path);451 return self.addDepFileMaybePost(dir, dep_file_sub_path);
...@@ -1058,24 +1032,32 @@ pub const Manifest = struct {...@@ -1058,24 +1032,32 @@ pub const Manifest = struct {
10581032
1059 /// Like `addFilePost` but when the file contents have already been loaded from disk.1033 /// Like `addFilePost` but when the file contents have already been loaded from disk.
1060 pub fn addFilePostContents(1034 pub fn addFilePostContents(
1061 self: *Manifest,1035 man: *Manifest,
1062 file_path: []const u8,1036 file_path: []const u8,
1063 bytes: []const u8,1037 bytes: []const u8,
1064 stat: File.Stat,1038 stat: File.Stat,
1065 ) !void {1039 ) !void {
1066 assert(self.manifest_file != null);1040 assert(man.manifest_file != null);
1067 const gpa = self.cache.gpa;1041 const gpa = man.cache.gpa;
10681042 const prefixed_path = try man.cache.findPrefix(file_path);
1069 const prefixed_path = try self.cache.findPrefix(file_path);1043 var keep = false;
1070 errdefer gpa.free(prefixed_path.sub_path);1044 defer if (!keep) gpa.free(prefixed_path.sub_path);
1045 keep = try addPrefixedPathPostContents(man, prefixed_path, bytes, stat);
1046 }
10711047
1072 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});1048 /// Low level function. `prefixed_path` references cloned memory. Returns
1073 errdefer _ = self.files.pop();1049 /// whether or not `prefixed_path.sub_path` should be kept.
1050 pub fn addPrefixedPathPostContents(
1051 man: *Manifest,
1052 prefixed_path: PrefixedPath,
1053 bytes: []const u8,
1054 stat: File.Stat,
1055 ) !bool {
1056 const gpa = man.cache.gpa;
1057 const gop = try man.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
1058 errdefer _ = man.files.pop();
10741059
1075 if (gop.found_existing) {1060 if (gop.found_existing) return false;
1076 gpa.free(prefixed_path.sub_path);
1077 return;
1078 }
10791061
1080 const new_file = gop.key_ptr;1062 const new_file = gop.key_ptr;
10811063
...@@ -1088,7 +1070,7 @@ pub const Manifest = struct {...@@ -1088,7 +1070,7 @@ pub const Manifest = struct {
1088 .contents = null,1070 .contents = null,
1089 };1071 };
10901072
1091 if (try self.isProblematicTimestamp(new_file.stat.mtime)) {1073 if (try man.isProblematicTimestamp(new_file.stat.mtime)) {
1092 // The actual file has an unreliable timestamp, force it to be hashed1074 // The actual file has an unreliable timestamp, force it to be hashed
1093 new_file.stat.mtime = .zero;1075 new_file.stat.mtime = .zero;
1094 new_file.stat.inode = 0;1076 new_file.stat.inode = 0;
...@@ -1100,7 +1082,8 @@ pub const Manifest = struct {...@@ -1100,7 +1082,8 @@ pub const Manifest = struct {
1100 hasher.final(&new_file.bin_digest);1082 hasher.final(&new_file.bin_digest);
1101 }1083 }
11021084
1103 self.hash.hasher.update(&new_file.bin_digest);1085 man.hash.hasher.update(&new_file.bin_digest);
1086 return true;
1104 }1087 }
11051088
1106 pub fn addDepFilePost(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void {1089 pub fn addDepFilePost(self: *Manifest, dir: Io.Dir, dep_file_sub_path: []const u8) !void {
...@@ -1127,13 +1110,13 @@ pub const Manifest = struct {...@@ -1127,13 +1110,13 @@ pub const Manifest = struct {
1127 // Clang is invoked in single-source mode but other programs may not1110 // Clang is invoked in single-source mode but other programs may not
1128 .target, .target_must_resolve => {},1111 .target, .target_must_resolve => {},
1129 .prereq => |file_path| if (self.manifest_file == null) {1112 .prereq => |file_path| if (self.manifest_file == null) {
1130 _ = try self.addFile(file_path, null);1113 _ = try self.addFilePath(.initCwd(file_path), null);
1131 } else try self.addFilePost(file_path),1114 } else try self.addFilePost(file_path),
1132 .prereq_must_resolve => {1115 .prereq_must_resolve => {
1133 resolve_buf.clearRetainingCapacity();1116 resolve_buf.clearRetainingCapacity();
1134 try token.resolve(gpa, &resolve_buf);1117 try token.resolve(gpa, &resolve_buf);
1135 if (self.manifest_file == null) {1118 if (self.manifest_file == null) {
1136 _ = try self.addFile(resolve_buf.items, null);1119 _ = try self.addFilePath(.initCwd(resolve_buf.items), null);
1137 } else try self.addFilePost(resolve_buf.items);1120 } else try self.addFilePost(resolve_buf.items);
1138 },1121 },
1139 else => |err| {1122 else => |err| {
...@@ -1290,10 +1273,10 @@ pub const Manifest = struct {...@@ -1290,10 +1273,10 @@ pub const Manifest = struct {
1290 }1273 }
1291 }1274 }
12921275
1293 pub fn populateOtherManifest(man: *Manifest, other: *Manifest, prefix_map: [4]u8) Allocator.Error!void {1276 pub fn populateOtherManifest(man: *Manifest, other: *Manifest, prefix_map: [5]u8) Allocator.Error!void {
1294 const gpa = other.cache.gpa;1277 const gpa = other.cache.gpa;
1295 assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == man.cache.prefixes_len);1278 assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == man.cache.prefixes_len);
1296 assert(man.cache.prefixes_len == 4);1279 assert(man.cache.prefixes_len == 5);
1297 for (man.files.keys()) |file| {1280 for (man.files.keys()) |file| {
1298 const prefixed_path: PrefixedPath = .{1281 const prefixed_path: PrefixedPath = .{
1299 .prefix = prefix_map[file.prefixed_path.prefix],1282 .prefix = prefix_map[file.prefixed_path.prefix],
...@@ -1392,7 +1375,7 @@ test "cache file and then recall it" {...@@ -1392,7 +1375,7 @@ test "cache file and then recall it" {
1392 ch.hash.add(true);1375 ch.hash.add(true);
1393 ch.hash.add(@as(u16, 1234));1376 ch.hash.add(@as(u16, 1234));
1394 ch.hash.addBytes("1234");1377 ch.hash.addBytes("1234");
1395 _ = try ch.addFile(temp_file, null);1378 _ = try ch.addFilePath(.initCwd(temp_file), null);
13961379
1397 // There should be nothing in the cache1380 // There should be nothing in the cache
1398 try testing.expectEqual(false, try ch.hit(.none));1381 try testing.expectEqual(false, try ch.hit(.none));
...@@ -1407,7 +1390,7 @@ test "cache file and then recall it" {...@@ -1407,7 +1390,7 @@ test "cache file and then recall it" {
1407 ch.hash.add(true);1390 ch.hash.add(true);
1408 ch.hash.add(@as(u16, 1234));1391 ch.hash.add(@as(u16, 1234));
1409 ch.hash.addBytes("1234");1392 ch.hash.addBytes("1234");
1410 _ = try ch.addFile(temp_file, null);1393 _ = try ch.addFilePath(.initCwd(temp_file), null);
14111394
1412 // Cache hit! We just "built" the same file1395 // Cache hit! We just "built" the same file
1413 try testing.expect(try ch.hit(.none));1396 try testing.expect(try ch.hit(.none));
...@@ -1460,7 +1443,7 @@ test "check that changing a file makes cache fail" {...@@ -1460,7 +1443,7 @@ test "check that changing a file makes cache fail" {
1460 defer ch.deinit();1443 defer ch.deinit();
14611444
1462 ch.hash.addBytes("1234");1445 ch.hash.addBytes("1234");
1463 const temp_file_idx = try ch.addFile(temp_file, 100);1446 const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100);
14641447
1465 // There should be nothing in the cache1448 // There should be nothing in the cache
1466 try testing.expectEqual(false, try ch.hit(.none));1449 try testing.expectEqual(false, try ch.hit(.none));
...@@ -1479,7 +1462,7 @@ test "check that changing a file makes cache fail" {...@@ -1479,7 +1462,7 @@ test "check that changing a file makes cache fail" {
1479 defer ch.deinit();1462 defer ch.deinit();
14801463
1481 ch.hash.addBytes("1234");1464 ch.hash.addBytes("1234");
1482 const temp_file_idx = try ch.addFile(temp_file, 100);1465 const temp_file_idx = try ch.addFilePath(.initCwd(temp_file), 100);
14831466
1484 // A file that we depend on has been updated, so the cache should not contain an entry for it1467 // A file that we depend on has been updated, so the cache should not contain an entry for it
1485 try testing.expectEqual(false, try ch.hit(.none));1468 try testing.expectEqual(false, try ch.hit(.none));
...@@ -1587,7 +1570,7 @@ test "Manifest with files added after initial hash work" {...@@ -1587,7 +1570,7 @@ test "Manifest with files added after initial hash work" {
1587 defer ch.deinit();1570 defer ch.deinit();
15881571
1589 ch.hash.addBytes("1234");1572 ch.hash.addBytes("1234");
1590 _ = try ch.addFile(temp_file1, null);1573 _ = try ch.addFilePath(.initCwd(temp_file1), null);
15911574
1592 // There should be nothing in the cache1575 // There should be nothing in the cache
1593 try testing.expectEqual(false, try ch.hit(.none));1576 try testing.expectEqual(false, try ch.hit(.none));
...@@ -1602,7 +1585,7 @@ test "Manifest with files added after initial hash work" {...@@ -1602,7 +1585,7 @@ test "Manifest with files added after initial hash work" {
1602 defer ch.deinit();1585 defer ch.deinit();
16031586
1604 ch.hash.addBytes("1234");1587 ch.hash.addBytes("1234");
1605 _ = try ch.addFile(temp_file1, null);1588 _ = try ch.addFilePath(.initCwd(temp_file1), null);
16061589
1607 try testing.expect(try ch.hit(.none));1590 try testing.expect(try ch.hit(.none));
1608 digest2 = ch.final();1591 digest2 = ch.final();
...@@ -1625,7 +1608,7 @@ test "Manifest with files added after initial hash work" {...@@ -1625,7 +1608,7 @@ test "Manifest with files added after initial hash work" {
1625 defer ch.deinit();1608 defer ch.deinit();
16261609
1627 ch.hash.addBytes("1234");1610 ch.hash.addBytes("1234");
1628 _ = try ch.addFile(temp_file1, null);1611 _ = try ch.addFilePath(.initCwd(temp_file1), null);
16291612
1630 // A file that we depend on has been updated, so the cache should not contain an entry for it1613 // A file that we depend on has been updated, so the cache should not contain an entry for it
1631 try testing.expectEqual(false, try ch.hit(.none));1614 try testing.expectEqual(false, try ch.hit(.none));
lib/std/fs/path.zig+16-16
...@@ -1093,23 +1093,23 @@ pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) Allocator...@@ -1093,23 +1093,23 @@ pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) Allocator
1093 return result.toOwnedSlice(allocator);1093 return result.toOwnedSlice(allocator);
1094}1094}
10951095
1096/// This function is like a series of `cd` statements executed one after another.1096/// Simulates a series of relative directory changes on a virtual filesystem
1097///1097/// that has no symlinks.
1098/// It resolves "." and ".." to the best of its ability, but will not convert relative paths to
1099/// an absolute path, use Io.Dir.realpath instead.
1100///1098///
1101/// ".." components may persist in the resolved path if the resolved path is relative.1099/// "." and ".." are resolved but will not make relative paths absolute. ".."
1100/// components remain in the resolved path when the resolved path is relative
1101/// and there are not previous components to cancel out.
1102///1102///
1103/// The result does not have a trailing path separator.1103/// The result does not have a trailing path separator.
1104///1104///
1105/// This function does not perform any syscalls. Executing this series of path1105/// This function does not perform any syscalls. Executing this series of path
1106/// lookups on the actual filesystem may produce different results due to1106/// lookups on an actual filesystem may produce different results due to
1107/// symlinks.1107/// symlinks.
1108pub fn resolvePosix(allocator: Allocator, paths: []const []const u8) Allocator.Error![]u8 {1108pub fn resolvePosix(gpa: Allocator, paths: []const []const u8) Allocator.Error![]u8 {
1109 assert(paths.len > 0);1109 assert(paths.len > 0);
11101110
1111 var result = std.array_list.Managed(u8).init(allocator);1111 var result: std.ArrayList(u8) = .empty;
1112 defer result.deinit();1112 defer result.deinit(gpa);
11131113
1114 var negative_count: usize = 0;1114 var negative_count: usize = 0;
1115 var is_abs = false;1115 var is_abs = false;
...@@ -1135,23 +1135,23 @@ pub fn resolvePosix(allocator: Allocator, paths: []const []const u8) Allocator.E...@@ -1135,23 +1135,23 @@ pub fn resolvePosix(allocator: Allocator, paths: []const []const u8) Allocator.E
1135 if (ends_with_slash or result.items.len == 0) break;1135 if (ends_with_slash or result.items.len == 0) break;
1136 }1136 }
1137 } else if (result.items.len > 0 or is_abs) {1137 } else if (result.items.len > 0 or is_abs) {
1138 try result.ensureUnusedCapacity(1 + component.len);1138 try result.ensureUnusedCapacity(gpa, 1 + component.len);
1139 result.appendAssumeCapacity('/');1139 result.appendAssumeCapacity('/');
1140 result.appendSliceAssumeCapacity(component);1140 result.appendSliceAssumeCapacity(component);
1141 } else {1141 } else {
1142 try result.appendSlice(component);1142 try result.appendSlice(gpa, component);
1143 }1143 }
1144 }1144 }
1145 }1145 }
11461146
1147 if (result.items.len == 0) {1147 if (result.items.len == 0) {
1148 if (is_abs) {1148 if (is_abs) {
1149 return allocator.dupe(u8, "/");1149 return gpa.dupe(u8, "/");
1150 }1150 }
1151 if (negative_count == 0) {1151 if (negative_count == 0) {
1152 return allocator.dupe(u8, ".");1152 return gpa.dupe(u8, ".");
1153 } else {1153 } else {
1154 const real_result = try allocator.alloc(u8, 3 * negative_count - 1);1154 const real_result = try gpa.alloc(u8, 3 * negative_count - 1);
1155 var count = negative_count - 1;1155 var count = negative_count - 1;
1156 var i: usize = 0;1156 var i: usize = 0;
1157 while (count > 0) : (count -= 1) {1157 while (count > 0) : (count -= 1) {
...@@ -1164,9 +1164,9 @@ pub fn resolvePosix(allocator: Allocator, paths: []const []const u8) Allocator.E...@@ -1164,9 +1164,9 @@ pub fn resolvePosix(allocator: Allocator, paths: []const []const u8) Allocator.E
1164 }1164 }
11651165
1166 if (negative_count == 0) {1166 if (negative_count == 0) {
1167 return result.toOwnedSlice();1167 return result.toOwnedSlice(gpa);
1168 } else {1168 } else {
1169 const real_result = try allocator.alloc(u8, 3 * negative_count + result.items.len);1169 const real_result = try gpa.alloc(u8, 3 * negative_count + result.items.len);
1170 var count = negative_count;1170 var count = negative_count;
1171 var i: usize = 0;1171 var i: usize = 0;
1172 while (count > 0) : (count -= 1) {1172 while (count > 0) : (count -= 1) {
lib/std/zig.zig+31-15
...@@ -1283,14 +1283,20 @@ pub const Directories = struct {...@@ -1283,14 +1283,20 @@ pub const Directories = struct {
1283 /// `local_cache.path` is resolved (`resolvePath`) or `null` for cwd.1283 /// `local_cache.path` is resolved (`resolvePath`) or `null` for cwd.
1284 /// This may be the same as `global_cache`.1284 /// This may be the same as `global_cache`.
1285 local_cache: Cache.Directory,1285 local_cache: Cache.Directory,
1286 /// The directory that contains build.zig. This path is provided by the
1287 /// build system, when the build system is used, otherwise, it is `null`
1288 /// for cwd.
1289 build_root: Cache.Directory,
12861290
1287 pub fn deinit(dirs: *Directories, io: Io) void {1291 pub fn deinit(dirs: *Directories, io: Io) void {
1288 // The local and global caches could be the same.1292 // The local and global caches could be the same.
1289 const close_local = dirs.local_cache.handle.handle != dirs.global_cache.handle.handle;1293 const close_local = dirs.local_cache.handle.handle != dirs.global_cache.handle.handle;
1294 const close_build_root = dirs.build_root.handle.handle != Io.Dir.cwd().handle;
12901295
1291 dirs.global_cache.handle.close(io);1296 dirs.global_cache.handle.close(io);
1292 if (close_local) dirs.local_cache.handle.close(io);1297 if (close_local) dirs.local_cache.handle.close(io);
1293 dirs.zig_lib.handle.close(io);1298 dirs.zig_lib.handle.close(io);
1299 if (close_build_root) dirs.build_root.handle.close(io);
1294 }1300 }
12951301
1296 /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for1302 /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for
...@@ -1302,6 +1308,7 @@ pub const Directories = struct {...@@ -1302,6 +1308,7 @@ pub const Directories = struct {
1302 .zig_lib = dirs.zig_lib,1308 .zig_lib = dirs.zig_lib,
1303 .global_cache = dirs.global_cache,1309 .global_cache = dirs.global_cache,
1304 .local_cache = dirs.global_cache,1310 .local_cache = dirs.global_cache,
1311 .build_root = dirs.build_root,
1305 };1312 };
1306 }1313 }
13071314
...@@ -1311,12 +1318,10 @@ pub const Directories = struct {...@@ -1311,12 +1318,10 @@ pub const Directories = struct {
1311 global,1318 global,
1312 };1319 };
13131320
1314 /// Uses `std.process.fatal` on error conditions.1321 pub const InitOptions = struct {
1315 pub fn init(
1316 arena: Allocator,
1317 io: Io,
1318 override_zig_lib: ?[]const u8,1322 override_zig_lib: ?[]const u8,
1319 override_global_cache: ?[]const u8,1323 override_global_cache: ?[]const u8,
1324 build_root: ?[]const u8,
1320 local_cache_strat: LocalCacheStrategy,1325 local_cache_strat: LocalCacheStrategy,
1321 preopens: std.process.Preopens,1326 preopens: std.process.Preopens,
1322 self_exe_path: switch (builtin.target.os.tag) {1327 self_exe_path: switch (builtin.target.os.tag) {
...@@ -1325,27 +1330,37 @@ pub const Directories = struct {...@@ -1325,27 +1330,37 @@ pub const Directories = struct {
1325 },1330 },
1326 environ_map: *const std.process.Environ.Map,1331 environ_map: *const std.process.Environ.Map,
1327 cwd: []const u8,1332 cwd: []const u8,
1328 ) Directories {1333 };
1334
1335 /// Uses `std.process.fatal` on error conditions.
1336 pub fn init(arena: Allocator, io: Io, options: InitOptions) Directories {
1329 const wasi = builtin.target.os.tag == .wasi;1337 const wasi = builtin.target.os.tag == .wasi;
1338 const cwd = options.cwd;
13301339
1331 const zig_lib: Cache.Directory = d: {1340 const zig_lib: Cache.Directory = d: {
1332 if (override_zig_lib) |path| break :d openUnresolved(arena, io, cwd, path, .@"zig lib");1341 if (options.override_zig_lib) |path| break :d openUnresolved(arena, io, cwd, path, .@"zig lib");
1333 if (wasi) break :d getPreopen(preopens, "/lib");1342 if (wasi) break :d getPreopen(options.preopens, "/lib");
1334 break :d findZigLibDirFromSelfExe(arena, io, cwd, self_exe_path) catch |err| {1343 break :d findZigLibDirFromSelfExe(arena, io, cwd, options.self_exe_path) catch |err| {
1335 fatal("unable to find zig installation directory from executable path {q}: {t}", .{ self_exe_path, err });1344 fatal("unable to find zig installation directory from executable path {q}: {t}", .{
1345 options.self_exe_path, err,
1346 });
1336 };1347 };
1337 };1348 };
1349 const build_root: Cache.Directory = if (options.build_root) |s|
1350 openUnresolved(arena, io, cwd, s, .@"build root")
1351 else
1352 .cwd();
13381353
1339 const global_cache: Cache.Directory = d: {1354 const global_cache: Cache.Directory = d: {
1340 if (override_global_cache) |path| break :d openUnresolved(arena, io, cwd, path, .@"global cache");1355 if (options.override_global_cache) |path| break :d openUnresolved(arena, io, cwd, path, .@"global cache");
1341 if (wasi) break :d getPreopen(preopens, "/cache");1356 if (wasi) break :d getPreopen(options.preopens, "/cache");
1342 const path = resolveGlobalCacheDir(arena, environ_map) catch |err| {1357 const path = resolveGlobalCacheDir(arena, options.environ_map) catch |err| {
1343 fatal("unable to resolve zig cache directory: {t}", .{err});1358 fatal("unable to resolve zig cache directory: {t}", .{err});
1344 };1359 };
1345 break :d openUnresolved(arena, io, cwd, path, .@"global cache");1360 break :d openUnresolved(arena, io, cwd, path, .@"global cache");
1346 };1361 };
13471362
1348 const local_cache = getLocalCacheDirectory(arena, io, cwd, global_cache, local_cache_strat);1363 const local_cache = getLocalCacheDirectory(arena, io, cwd, global_cache, options.local_cache_strat);
13491364
1350 if (mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {1365 if (mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {
1351 fatal("zig lib directory '{f}' cannot be equal to global cache directory '{f}'", .{ zig_lib, global_cache });1366 fatal("zig lib directory '{f}' cannot be equal to global cache directory '{f}'", .{ zig_lib, global_cache });
...@@ -1359,6 +1374,7 @@ pub const Directories = struct {...@@ -1359,6 +1374,7 @@ pub const Directories = struct {
1359 .zig_lib = zig_lib,1374 .zig_lib = zig_lib,
1360 .global_cache = global_cache,1375 .global_cache = global_cache,
1361 .local_cache = local_cache,1376 .local_cache = local_cache,
1377 .build_root = build_root,
1362 };1378 };
1363 }1379 }
13641380
...@@ -1395,14 +1411,14 @@ pub const Directories = struct {...@@ -1395,14 +1411,14 @@ pub const Directories = struct {
1395 io: Io,1411 io: Io,
1396 cwd: []const u8,1412 cwd: []const u8,
1397 unresolved_path: []const u8,1413 unresolved_path: []const u8,
1398 thing: enum { @"zig lib", @"global cache", @"local cache" },1414 thing: enum { @"zig lib", @"global cache", @"local cache", @"build root" },
1399 ) Cache.Directory {1415 ) Cache.Directory {
1400 const path = resolvePath(arena, cwd, &.{unresolved_path}) catch |err| {1416 const path = resolvePath(arena, cwd, &.{unresolved_path}) catch |err| {
1401 fatal("unable to resolve {t} directory: {t}", .{ thing, err });1417 fatal("unable to resolve {t} directory: {t}", .{ thing, err });
1402 };1418 };
1403 const nonempty_path = if (path.len == 0) "." else path;1419 const nonempty_path = if (path.len == 0) "." else path;
1404 const handle_or_err = switch (thing) {1420 const handle_or_err = switch (thing) {
1405 .@"zig lib" => Dir.cwd().openDir(io, nonempty_path, .{}),1421 .@"zig lib", .@"build root" => Dir.cwd().openDir(io, nonempty_path, .{}),
1406 .@"global cache", .@"local cache" => Dir.cwd().createDirPathOpen(io, nonempty_path, .{}),1422 .@"global cache", .@"local cache" => Dir.cwd().createDirPathOpen(io, nonempty_path, .{}),
1407 };1423 };
1408 return .{1424 return .{
lib/std/zig/Server.zig+1
...@@ -135,6 +135,7 @@ pub const Message = struct {...@@ -135,6 +135,7 @@ pub const Message = struct {
135 zig_lib,135 zig_lib,
136 local_cache,136 local_cache,
137 global_cache,137 global_cache,
138 build_root,
138 };139 };
139140
140 /// Trailing:141 /// Trailing:
src/Compilation.zig+126-68
...@@ -397,6 +397,7 @@ pub const Path = struct {...@@ -397,6 +397,7 @@ pub const Path = struct {
397 global_cache,397 global_cache,
398 /// `sub_path` is relative to the local cache directory on `Compilation`.398 /// `sub_path` is relative to the local cache directory on `Compilation`.
399 local_cache,399 local_cache,
400 build_root,
400 /// `sub_path` is not relative to any of the roots listed above.401 /// `sub_path` is not relative to any of the roots listed above.
401 /// It is resolved starting with `Directories.cwd`; so it is an absolute path on most402 /// It is resolved starting with `Directories.cwd`; so it is an absolute path on most
402 /// targets, but cwd-relative on WASI. We do not make it cwd-relative on other targets403 /// targets, but cwd-relative on WASI. We do not make it cwd-relative on other targets
...@@ -434,11 +435,12 @@ pub const Path = struct {...@@ -434,11 +435,12 @@ pub const Path = struct {
434 const dir = switch (p.root) {435 const dir = switch (p.root) {
435 .none => {436 .none => {
436 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);437 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);
437 return .{ Io.Dir.cwd(), cwd_sub_path };438 return .{ Io.Dir.cwd(), if (cwd_sub_path.len == 0) "." else cwd_sub_path };
438 },439 },
439 .zig_lib => dirs.zig_lib.handle,440 .zig_lib => dirs.zig_lib.handle,
440 .global_cache => dirs.global_cache.handle,441 .global_cache => dirs.global_cache.handle,
441 .local_cache => dirs.local_cache.handle,442 .local_cache => dirs.local_cache.handle,
443 .build_root => dirs.build_root.handle,
442 };444 };
443 if (p.sub_path.len == 0) return .{ dir, "." };445 if (p.sub_path.len == 0) return .{ dir, "." };
444 assert(!fs.path.isAbsolute(p.sub_path));446 assert(!fs.path.isAbsolute(p.sub_path));
...@@ -454,19 +456,18 @@ pub const Path = struct {...@@ -454,19 +456,18 @@ pub const Path = struct {
454 comp: *Compilation,456 comp: *Compilation,
455 pub fn format(f: Formatter, w: *Writer) Writer.Error!void {457 pub fn format(f: Formatter, w: *Writer) Writer.Error!void {
456 const root_path: []const u8 = switch (f.p.root) {458 const root_path: []const u8 = switch (f.p.root) {
457 .zig_lib => f.comp.dirs.zig_lib.path orelse ".",459 .zig_lib => f.comp.dirs.zig_lib.path orelse "",
458 .global_cache => f.comp.dirs.global_cache.path orelse ".",460 .global_cache => f.comp.dirs.global_cache.path orelse "",
459 .local_cache => f.comp.dirs.local_cache.path orelse ".",461 .local_cache => f.comp.dirs.local_cache.path orelse "",
462 .build_root => f.comp.dirs.build_root.path orelse "",
460 .none => {463 .none => {
461 const cwd_sub_path = absToCwdRelative(f.p.sub_path, f.comp.dirs.cwd);464 try w.writeAll(absToCwdRelative(f.p.sub_path, f.comp.dirs.cwd));
462 try w.writeAll(cwd_sub_path);
463 return;465 return;
464 },466 },
465 };467 };
466 assert(root_path.len != 0);
467 try w.writeAll(root_path);468 try w.writeAll(root_path);
468 if (f.p.sub_path.len > 0) {469 if (f.p.sub_path.len > 0) {
469 try w.writeByte(fs.path.sep);470 if (root_path.len != 0) try w.writeByte(fs.path.sep);
470 try w.writeAll(f.p.sub_path);471 try w.writeAll(f.p.sub_path);
471 }472 }
472 }473 }
...@@ -474,16 +475,16 @@ pub const Path = struct {...@@ -474,16 +475,16 @@ pub const Path = struct {
474475
475 /// Given the `sub_path` of a `Path` with `Path.root == .none`, attempts to convert476 /// Given the `sub_path` of a `Path` with `Path.root == .none`, attempts to convert
476 /// the (absolute) path to a cwd-relative path. Otherwise, returns the absolute path477 /// the (absolute) path to a cwd-relative path. Otherwise, returns the absolute path
477 /// unmodified. The returned string is never empty: "" is converted to ".".478 /// unmodified. The returned string is never "."; empty string will be returned instead.
478 fn absToCwdRelative(sub_path: []const u8, cwd_path: []const u8) []const u8 {479 fn absToCwdRelative(sub_path: []const u8, cwd_path: []const u8) []const u8 {
479 if (builtin.target.os.tag == .wasi) {480 if (builtin.target.os.tag == .wasi) {
480 if (sub_path.len == 0) return ".";481 if (sub_path.len == 0) return "";
481 assert(!fs.path.isAbsolute(sub_path));482 assert(!fs.path.isAbsolute(sub_path));
482 return sub_path;483 return sub_path;
483 }484 }
484 assert(fs.path.isAbsolute(sub_path));485 assert(fs.path.isAbsolute(sub_path));
485 if (!std.mem.startsWith(u8, sub_path, cwd_path)) return sub_path;486 if (!std.mem.startsWith(u8, sub_path, cwd_path)) return sub_path;
486 if (sub_path.len == cwd_path.len) return "."; // the strings are equal487 if (sub_path.len == cwd_path.len) return ""; // the strings are equal
487 const path_sep_index = path_sep_index: {488 const path_sep_index = path_sep_index: {
488 // cwd is just a root, e.g. / or C:\489 // cwd is just a root, e.g. / or C:\
489 if (cwd_path[cwd_path.len - 1] == fs.path.sep) break :path_sep_index cwd_path.len - 1;490 if (cwd_path[cwd_path.len - 1] == fs.path.sep) break :path_sep_index cwd_path.len - 1;
...@@ -503,10 +504,11 @@ pub const Path = struct {...@@ -503,10 +504,11 @@ pub const Path = struct {
503 // so that we prefer `.root = .local_cache` over `.root = .zig_lib`. The easiest way to do504 // so that we prefer `.root = .local_cache` over `.root = .zig_lib`. The easiest way to do
504 // this is simply to prioritize the longest root path.505 // this is simply to prioritize the longest root path.
505 const PathAndRoot = struct { ?[]const u8, Root };506 const PathAndRoot = struct { ?[]const u8, Root };
506 var roots: [3]PathAndRoot = .{507 var roots: [4]PathAndRoot = .{
507 .{ dirs.zig_lib.path, .zig_lib },508 .{ dirs.zig_lib.path, .zig_lib },
508 .{ dirs.global_cache.path, .global_cache },509 .{ dirs.global_cache.path, .global_cache },
509 .{ dirs.local_cache.path, .local_cache },510 .{ dirs.local_cache.path, .local_cache },
511 .{ dirs.build_root.path, .build_root },
510 };512 };
511 // This must be a stable sort, because the global and local cache directories may be the same, in513 // This must be a stable sort, because the global and local cache directories may be the same, in
512 // which case we need to make a consistent choice.514 // which case we need to make a consistent choice.
...@@ -581,6 +583,7 @@ pub const Path = struct {...@@ -581,6 +583,7 @@ pub const Path = struct {
581 .zig_lib => dirs.zig_lib.path orelse "",583 .zig_lib => dirs.zig_lib.path orelse "",
582 .global_cache => dirs.global_cache.path orelse "",584 .global_cache => dirs.global_cache.path orelse "",
583 .local_cache => dirs.local_cache.path orelse "",585 .local_cache => dirs.local_cache.path orelse "",
586 .build_root => dirs.build_root.path orelse "",
584 .none => "",587 .none => "",
585 },588 },
586 sub_path,589 sub_path,
...@@ -603,6 +606,7 @@ pub const Path = struct {...@@ -603,6 +606,7 @@ pub const Path = struct {
603 .zig_lib => dirs.zig_lib.path orelse "",606 .zig_lib => dirs.zig_lib.path orelse "",
604 .global_cache => dirs.global_cache.path orelse "",607 .global_cache => dirs.global_cache.path orelse "",
605 .local_cache => dirs.local_cache.path orelse "",608 .local_cache => dirs.local_cache.path orelse "",
609 .build_root => dirs.build_root.path orelse "",
606 .none => "",610 .none => "",
607 },611 },
608 p.sub_path,612 p.sub_path,
...@@ -622,6 +626,7 @@ pub const Path = struct {...@@ -622,6 +626,7 @@ pub const Path = struct {
622 .zig_lib => dirs.zig_lib.path orelse "",626 .zig_lib => dirs.zig_lib.path orelse "",
623 .global_cache => dirs.global_cache.path orelse "",627 .global_cache => dirs.global_cache.path orelse "",
624 .local_cache => dirs.local_cache.path orelse "",628 .local_cache => dirs.local_cache.path orelse "",
629 .build_root => dirs.build_root.path orelse "",
625 .none => "",630 .none => "",
626 },631 },
627 p.sub_path,632 p.sub_path,
...@@ -635,11 +640,12 @@ pub const Path = struct {...@@ -635,11 +640,12 @@ pub const Path = struct {
635 .zig_lib => dirs.zig_lib,640 .zig_lib => dirs.zig_lib,
636 .global_cache => dirs.global_cache,641 .global_cache => dirs.global_cache,
637 .local_cache => dirs.local_cache,642 .local_cache => dirs.local_cache,
643 .build_root => dirs.build_root,
638 else => {644 else => {
639 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);645 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);
640 return .{646 return .{
641 .root_dir = .cwd(),647 .root_dir = .cwd(),
642 .sub_path = cwd_sub_path,648 .sub_path = if (cwd_sub_path.len == 0) null else cwd_sub_path,
643 };649 };
644 },650 },
645 };651 };
...@@ -653,18 +659,15 @@ pub const Path = struct {...@@ -653,18 +659,15 @@ pub const Path = struct {
653 /// This should not be used for most of the compiler pipeline, but is useful when emitting659 /// This should not be used for most of the compiler pipeline, but is useful when emitting
654 /// paths from the compilation (e.g. in debug info), because they will not depend on the cwd.660 /// paths from the compilation (e.g. in debug info), because they will not depend on the cwd.
655 /// The returned path is owned by the caller and allocated into `gpa`.661 /// The returned path is owned by the caller and allocated into `gpa`.
656 pub fn toAbsolute(p: Path, dirs: std.zig.Directories, gpa: Allocator) Allocator.Error![]u8 {662 pub fn toAbsolute(p: Path, dirs: *const std.zig.Directories, gpa: Allocator) Allocator.Error![]u8 {
657 const root_path: []const u8 = switch (p.root) {663 const root_path: []const u8 = switch (p.root) {
658 .zig_lib => dirs.zig_lib.path orelse "",664 .zig_lib => dirs.zig_lib.path orelse "",
659 .global_cache => dirs.global_cache.path orelse "",665 .global_cache => dirs.global_cache.path orelse "",
660 .local_cache => dirs.local_cache.path orelse "",666 .local_cache => dirs.local_cache.path orelse "",
667 .build_root => dirs.build_root.path orelse "",
661 .none => "",668 .none => "",
662 };669 };
663 return fs.path.resolve(gpa, &.{670 return fs.path.resolve(gpa, &.{ dirs.cwd, root_path, p.sub_path });
664 dirs.cwd,
665 root_path,
666 p.sub_path,
667 });
668 }671 }
669672
670 pub fn isNested(inner: Path, outer: Path) union(enum) {673 pub fn isNested(inner: Path, outer: Path) union(enum) {
...@@ -697,6 +700,66 @@ pub const Path = struct {...@@ -697,6 +700,66 @@ pub const Path = struct {
697 .no, .different_roots => false,700 .no, .different_roots => false,
698 };701 };
699 }702 }
703
704 pub fn addToCacheManifestPostHit(p: Path, man: *Cache.Manifest, dirs: *const std.zig.Directories) !void {
705 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
706 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
707 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));
708 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
709 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
710 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
711 const gpa = man.cache.gpa;
712 const prefixed_path: Cache.PrefixedPath = .{
713 .prefix = switch (p.root) {
714 .none => {
715 const path = try p.toAbsolute(dirs, gpa);
716 defer gpa.free(path);
717 return man.addFilePost(path);
718 },
719 .zig_lib => 1,
720 .local_cache => 2,
721 .global_cache => 3,
722 .build_root => 4,
723 },
724 .sub_path = try gpa.dupe(u8, p.sub_path),
725 };
726 var keep = false;
727 defer if (!keep) gpa.free(prefixed_path.sub_path);
728 keep = try man.addPrefixedPathPost(prefixed_path);
729 }
730
731 pub fn addToCacheManifestPostHitContents(
732 p: Path,
733 man: *Cache.Manifest,
734 dirs: *const std.zig.Directories,
735 bytes: []const u8,
736 stat: Cache.File.Stat,
737 ) !void {
738 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
739 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
740 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));
741 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
742 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
743 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
744 const gpa = man.cache.gpa;
745 const prefixed_path: Cache.PrefixedPath = .{
746 .prefix = switch (p.root) {
747 .none => {
748 const path = try p.toAbsolute(dirs, gpa);
749 defer gpa.free(path);
750 return man.addFilePostContents(path, bytes, stat);
751 },
752 .zig_lib => 1,
753 .local_cache => 2,
754 .global_cache => 3,
755 .build_root => 4,
756 },
757 .sub_path = try gpa.dupe(u8, p.sub_path),
758 };
759 var keep = false;
760 defer if (!keep) gpa.free(prefixed_path.sub_path);
761 keep = try man.addPrefixedPathPostContents(prefixed_path, bytes, stat);
762 }
700};763};
701764
702/// This small wrapper function just checks whether debug extensions are enabled before checking765/// This small wrapper function just checks whether debug extensions are enabled before checking
...@@ -1278,7 +1341,7 @@ pub const cache_helpers = struct {...@@ -1278,7 +1341,7 @@ pub const cache_helpers = struct {
1278 }1341 }
12791342
1280 pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void {1343 pub fn hashCSource(self: *Cache.Manifest, c_source: CSourceFile) !void {
1281 _ = try self.addFile(c_source.src_path, null);1344 _ = try self.addFilePath(.initCwd(c_source.src_path), null);
1282 // Hash the extra flags, with special care to call addFile for file parameters.1345 // Hash the extra flags, with special care to call addFile for file parameters.
1283 // TODO this logic can likely be improved by utilizing clang_options_data.zig.1346 // TODO this logic can likely be improved by utilizing clang_options_data.zig.
1284 const file_args = [_][]const u8{"-include"};1347 const file_args = [_][]const u8{"-include"};
...@@ -1289,7 +1352,7 @@ pub const cache_helpers = struct {...@@ -1289,7 +1352,7 @@ pub const cache_helpers = struct {
1289 for (file_args) |file_arg| {1352 for (file_args) |file_arg| {
1290 if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_source.extra_flags.len) {1353 if (mem.eql(u8, file_arg, arg) and arg_i + 1 < c_source.extra_flags.len) {
1291 arg_i += 1;1354 arg_i += 1;
1292 _ = try self.addFile(c_source.extra_flags[arg_i], null);1355 _ = try self.addFilePath(.initCwd(c_source.extra_flags[arg_i]), null);
1293 }1356 }
1294 }1357 }
1295 }1358 }
...@@ -1348,7 +1411,7 @@ pub const CacheMode = enum {...@@ -1348,7 +1411,7 @@ pub const CacheMode = enum {
1348pub const ParentWholeCache = struct {1411pub const ParentWholeCache = struct {
1349 manifest: *Cache.Manifest,1412 manifest: *Cache.Manifest,
1350 mutex: *std.Io.Mutex,1413 mutex: *std.Io.Mutex,
1351 prefix_map: [4]u8,1414 prefix_map: [5]u8,
1352};1415};
13531416
1354const CacheUse = union(CacheMode) {1417const CacheUse = union(CacheMode) {
...@@ -1466,8 +1529,8 @@ pub const CreateOptions = struct {...@@ -1466,8 +1529,8 @@ pub const CreateOptions = struct {
1466 stack_report: bool = false,1529 stack_report: bool = false,
1467 link_eh_frame_hdr: bool = false,1530 link_eh_frame_hdr: bool = false,
1468 link_emit_relocs: bool = false,1531 link_emit_relocs: bool = false,
1469 linker_script: ?[]const u8 = null,1532 linker_script: ?Cache.Path = null,
1470 version_script: ?[]const u8 = null,1533 version_script: ?Cache.Path = null,
1471 linker_allow_undefined_version: bool = false,1534 linker_allow_undefined_version: bool = false,
1472 linker_enable_new_dtags: ?bool = null,1535 linker_enable_new_dtags: ?bool = null,
1473 soname: ?[]const u8 = null,1536 soname: ?[]const u8 = null,
...@@ -1546,7 +1609,7 @@ pub const CreateOptions = struct {...@@ -1546,7 +1609,7 @@ pub const CreateOptions = struct {
1546 /// (Darwin) Install name of the dylib1609 /// (Darwin) Install name of the dylib
1547 install_name: ?[]const u8 = null,1610 install_name: ?[]const u8 = null,
1548 /// (Darwin) Path to entitlements file1611 /// (Darwin) Path to entitlements file
1549 entitlements: ?[]const u8 = null,1612 entitlements: ?Cache.Path = null,
1550 /// (Darwin) size of the __PAGEZERO segment1613 /// (Darwin) size of the __PAGEZERO segment
1551 pagezero_size: ?u64 = null,1614 pagezero_size: ?u64 = null,
1552 /// (Darwin) set minimum space for future expansion of the load commands1615 /// (Darwin) set minimum space for future expansion of the load commands
...@@ -1613,15 +1676,7 @@ pub const CreateOptions = struct {...@@ -1613,15 +1676,7 @@ pub const CreateOptions = struct {
1613 };1676 };
1614};1677};
16151678
1616fn addModuleTableToCacheHash(1679fn addModuleTableToCacheHash(zcu: *Zcu, hash: *Cache.HashHelper) error{ OutOfMemory, Unexpected }!void {
1617 zcu: *Zcu,
1618 arena: Allocator,
1619 hash: *Cache.HashHelper,
1620 hash_type: union(enum) { path_bytes, files: *Cache.Manifest },
1621) error{
1622 OutOfMemory,
1623 Unexpected,
1624}!void {
1625 assert(zcu.module_roots.count() != 0); // module_roots is populated1680 assert(zcu.module_roots.count() != 0); // module_roots is populated
16261681
1627 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, opt_mod_root_file| {1682 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, opt_mod_root_file| {
...@@ -1630,17 +1685,9 @@ fn addModuleTableToCacheHash(...@@ -1630,17 +1685,9 @@ fn addModuleTableToCacheHash(
1630 if (zcu.fileByIndex(mod_root_file).is_builtin) continue; // redundant1685 if (zcu.fileByIndex(mod_root_file).is_builtin) continue; // redundant
1631 }1686 }
1632 cache_helpers.addModule(hash, mod);1687 cache_helpers.addModule(hash, mod);
1633 switch (hash_type) {1688 hash.add(mod.root.root);
1634 .path_bytes => {1689 hash.addBytes(mod.root.sub_path);
1635 hash.add(mod.root.root);1690 hash.addBytes(mod.root_src_path);
1636 hash.addBytes(mod.root.sub_path);
1637 hash.addBytes(mod.root_src_path);
1638 },
1639 .files => |man| if (mod.root_src_path.len != 0) {
1640 const root_src_path = try mod.root.toCachePath(zcu.comp.dirs).join(arena, mod.root_src_path);
1641 _ = try man.addFilePath(root_src_path, null);
1642 },
1643 }
1644 hash.addListOfBytes(mod.deps.keys());1691 hash.addListOfBytes(mod.deps.keys());
1645 }1692 }
1646}1693}
...@@ -1926,6 +1973,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1926,6 +1973,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1926 }1973 }
19271974
1928 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);1975 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
1976 const main_mod = options.main_mod orelse options.root_mod;
19291977
1930 // We put everything into the cache hash that *cannot be modified1978 // We put everything into the cache hash that *cannot be modified
1931 // during an incremental update*. For example, one cannot change the1979 // during an incremental update*. For example, one cannot change the
...@@ -1944,11 +1992,17 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1944,11 +1992,17 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1944 },1992 },
1945 .cwd = options.dirs.cwd,1993 .cwd = options.dirs.cwd,
1946 };1994 };
1947 // These correspond to std.zig.Server.Message.PathPrefix.1995 comptime assert(0 == @backingInt(std.zig.Server.Message.PathPrefix.cwd));
1996 comptime assert(1 == @backingInt(std.zig.Server.Message.PathPrefix.zig_lib));
1997 comptime assert(2 == @backingInt(std.zig.Server.Message.PathPrefix.local_cache));
1998 comptime assert(3 == @backingInt(std.zig.Server.Message.PathPrefix.global_cache));
1999 comptime assert(4 == @backingInt(std.zig.Server.Message.PathPrefix.build_root));
2000 comptime assert(@typeInfo(std.zig.Server.Message.PathPrefix).@"enum".field_names.len == 5);
1948 cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() });2001 cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() });
1949 cache.addPrefix(options.dirs.zig_lib);2002 cache.addPrefix(options.dirs.zig_lib);
1950 cache.addPrefix(options.dirs.local_cache);2003 cache.addPrefix(options.dirs.local_cache);
1951 cache.addPrefix(options.dirs.global_cache);2004 cache.addPrefix(options.dirs.global_cache);
2005 cache.addPrefix(options.dirs.build_root);
1952 errdefer cache.manifest_dir.close(io);2006 errdefer cache.manifest_dir.close(io);
19532007
1954 // This is shared hasher state common to zig source and all C source files.2008 // This is shared hasher state common to zig source and all C source files.
...@@ -1984,7 +2038,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -1984,7 +2038,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1984 cache.hash.add(options.emit_docs != .no);2038 cache.hash.add(options.emit_docs != .no);
1985 // TODO audit this and make sure everything is in it2039 // TODO audit this and make sure everything is in it
19862040
1987 const main_mod = options.main_mod orelse options.root_mod;
1988 const comp = try arena.create(Compilation);2041 const comp = try arena.create(Compilation);
1989 const opt_zcu: ?*Zcu = if (have_zcu) blk: {2042 const opt_zcu: ?*Zcu = if (have_zcu) blk: {
1990 // Pre-open the directory handles for cached ZIR code so that it does not need2043 // Pre-open the directory handles for cached ZIR code so that it does not need
...@@ -2265,7 +2318,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2265,7 +2318,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2265 // likely different compilations and therefore this would be likely to2318 // likely different compilations and therefore this would be likely to
2266 // cause cache hits.2319 // cause cache hits.
2267 if (comp.zcu) |zcu| {2320 if (comp.zcu) |zcu| {
2268 try addModuleTableToCacheHash(zcu, arena, &hash, .path_bytes);2321 try addModuleTableToCacheHash(zcu, &hash);
2269 } else {2322 } else {
2270 cache_helpers.addModule(&hash, options.root_mod);2323 cache_helpers.addModule(&hash, options.root_mod);
2271 }2324 }
...@@ -2741,7 +2794,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2741,7 +2794,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
27412794
2742 // If using the whole caching strategy, we check for *everything* up front, including2795 // If using the whole caching strategy, we check for *everything* up front, including
2743 // C source files.2796 // C source files.
2744 log.debug("Compilation.update for {s}, CacheMode.{s}", .{ comp.root_name, @tagName(comp.cache_use) });2797 log.debug("Compilation.update for {s}, CacheMode.{t}", .{ comp.root_name, comp.cache_use });
2745 switch (comp.cache_use) {2798 switch (comp.cache_use) {
2746 .none => |none| {2799 .none => |none| {
2747 assert(none.tmp_artifact_directory == null);2800 assert(none.tmp_artifact_directory == null);
...@@ -2750,7 +2803,9 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2750,7 +2803,9 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2750 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);2803 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
2751 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});2804 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2752 const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| {2805 const handle = comp.dirs.local_cache.handle.createDirPathOpen(io, tmp_dir_sub_path, .{}) catch |err| {
2753 return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err });2806 return comp.setMiscFailure(.open_output, "failed to create output directory {q}: {t}", .{
2807 path, err,
2808 });
2754 };2809 };
2755 break :d .{ .path = path, .handle = handle };2810 break :d .{ .path = path, .handle = handle };
2756 };2811 };
...@@ -2763,7 +2818,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2763,7 +2818,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
27632818
2764 man = comp.cache_parent.obtain();2819 man = comp.cache_parent.obtain();
2765 whole.cache_manifest = &man;2820 whole.cache_manifest = &man;
2766 try addNonIncrementalStuffToCacheManifest(comp, arena, &man);2821 try addNonIncrementalStuffToCacheManifest(comp, &man);
27672822
2768 // Under `--time-report`, ignore cache hits; do the work anyway for those juicy numbers.2823 // Under `--time-report`, ignore cache hits; do the work anyway for those juicy numbers.
2769 const ignore_hit = comp.time_report != null;2824 const ignore_hit = comp.time_report != null;
...@@ -3114,6 +3169,7 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat...@@ -3114,6 +3169,7 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
3114 .zig_lib => comp.dirs.zig_lib,3169 .zig_lib => comp.dirs.zig_lib,
3115 .global_cache => comp.dirs.global_cache,3170 .global_cache => comp.dirs.global_cache,
3116 .local_cache => comp.dirs.local_cache,3171 .local_cache => comp.dirs.local_cache,
3172 .build_root => comp.dirs.build_root,
3117 .none => .cwd(),3173 .none => .cwd(),
3118 };3174 };
3119 const prefix: u8 = for (prefixes, 1..) |prefix_dir, i| {3175 const prefix: u8 = for (prefixes, 1..) |prefix_dir, i| {
...@@ -3121,8 +3177,8 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat...@@ -3121,8 +3177,8 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
3121 break @intCast(i);3177 break @intCast(i);
3122 }3178 }
3123 } else std.debug.panic(3179 } else std.debug.panic(
3124 "missing prefix directory '{s}' ('{f}') for '{s}'",3180 "missing prefix directory {t} ('{f}') for {q}",
3125 .{ @tagName(path.root), want_prefix_dir, path.sub_path },3181 .{ path.root, want_prefix_dir, path.sub_path },
3126 );3182 );
31273183
3128 // There may be concurrent calls to this function from C object workers and/or the main thread.3184 // There may be concurrent calls to this function from C object workers and/or the main thread.
...@@ -3314,15 +3370,15 @@ fn renameTmpIntoCache(...@@ -3314,15 +3370,15 @@ fn renameTmpIntoCache(
3314/// anything from the link cache manifest.3370/// anything from the link cache manifest.
3315pub const link_hash_implementation_version = 14;3371pub const link_hash_implementation_version = 14;
33163372
3317fn addNonIncrementalStuffToCacheManifest(3373fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
3318 comp: *Compilation,
3319 arena: Allocator,
3320 man: *Cache.Manifest,
3321) !void {
3322 comptime assert(link_hash_implementation_version == 14);3374 comptime assert(link_hash_implementation_version == 14);
33233375
3324 if (comp.zcu) |zcu| {3376 if (comp.zcu) |zcu| {
3325 try addModuleTableToCacheHash(zcu, arena, &man.hash, .{ .files = man });3377 // No need to hash the actual file contents here because it is
3378 // redundant with the logic in `PerThread.update` which iterates over
3379 // `zcu.alive_files` and adds those files discovered via `@import` to
3380 // the whole cache manifest.
3381 try addModuleTableToCacheHash(zcu, &man.hash);
33263382
3327 // Synchronize with other matching comments: ZigOnlyHashStuff3383 // Synchronize with other matching comments: ZigOnlyHashStuff
3328 man.hash.addListOfBytes(comp.test_filters);3384 man.hash.addListOfBytes(comp.test_filters);
...@@ -3336,7 +3392,7 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -3336,7 +3392,7 @@ fn addNonIncrementalStuffToCacheManifest(
3336 try link.hashInputs(man, comp.link_inputs);3392 try link.hashInputs(man, comp.link_inputs);
33373393
3338 for (comp.c_objects.items) |c_object| {3394 for (comp.c_objects.items) |c_object| {
3339 _ = try man.addFile(c_object.src.src_path, null);3395 _ = try man.addFilePath(.initCwd(c_object.src.src_path), null);
3340 man.hash.addOptional(c_object.src.ext);3396 man.hash.addOptional(c_object.src.ext);
3341 man.hash.addListOfBytes(c_object.src.extra_flags);3397 man.hash.addListOfBytes(c_object.src.extra_flags);
3342 }3398 }
...@@ -3344,11 +3400,11 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -3344,11 +3400,11 @@ fn addNonIncrementalStuffToCacheManifest(
3344 for (comp.win32_resources.items) |win32_resource| {3400 for (comp.win32_resources.items) |win32_resource| {
3345 switch (win32_resource.src) {3401 switch (win32_resource.src) {
3346 .rc => |rc_src| {3402 .rc => |rc_src| {
3347 _ = try man.addFile(rc_src.src_path, null);3403 _ = try man.addFilePath(.initCwd(rc_src.src_path), null);
3348 man.hash.addListOfBytes(rc_src.extra_flags);3404 man.hash.addListOfBytes(rc_src.extra_flags);
3349 },3405 },
3350 .manifest => |manifest_path| {3406 .manifest => |manifest_path| {
3351 _ = try man.addFile(manifest_path, null);3407 _ = try man.addFilePath(.initCwd(manifest_path), null);
3352 },3408 },
3353 }3409 }
3354 }3410 }
...@@ -3380,8 +3436,8 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -3380,8 +3436,8 @@ fn addNonIncrementalStuffToCacheManifest(
33803436
3381 const opts = comp.cache_use.whole.lf_open_opts;3437 const opts = comp.cache_use.whole.lf_open_opts;
33823438
3383 try man.addOptionalFile(opts.linker_script);3439 try man.addOptionalFilePath(opts.linker_script);
3384 try man.addOptionalFile(opts.version_script);3440 try man.addOptionalFilePath(opts.version_script);
3385 man.hash.add(opts.allow_undefined_version);3441 man.hash.add(opts.allow_undefined_version);
3386 man.hash.addOptional(opts.enable_new_dtags);3442 man.hash.addOptional(opts.enable_new_dtags);
33873443
...@@ -3440,7 +3496,7 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -3440,7 +3496,7 @@ fn addNonIncrementalStuffToCacheManifest(
34403496
3441 // Mach-O specific stuff3497 // Mach-O specific stuff
3442 try link.File.MachO.hashAddFrameworks(man, opts.frameworks);3498 try link.File.MachO.hashAddFrameworks(man, opts.frameworks);
3443 try man.addOptionalFile(opts.entitlements);3499 try man.addOptionalFilePath(opts.entitlements);
3444 man.hash.addOptional(opts.pagezero_size);3500 man.hash.addOptional(opts.pagezero_size);
3445 man.hash.addOptional(opts.headerpad_size);3501 man.hash.addOptional(opts.headerpad_size);
3446 man.hash.add(opts.headerpad_max_install_names);3502 man.hash.add(opts.headerpad_max_install_names);
...@@ -5278,6 +5334,7 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std...@@ -5278,6 +5334,7 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
52785334
5279fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: bool, prog_node: std.Progress.Node) void {5335fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: bool, prog_node: std.Progress.Node) void {
5280 const crt_file_path = mingw.buildImportLib(comp, lib_name, prog_node) catch |err| switch (err) {5336 const crt_file_path = mingw.buildImportLib(comp, lib_name, prog_node) catch |err| switch (err) {
5337 error.AlreadyReported => return,
5281 // TODO: This isn't actually true for self-hosted5338 // TODO: This isn't actually true for self-hosted
5282 // In the non-prelink case we will end up putting foo.lib onto the linker line and letting the linker5339 // In the non-prelink case we will end up putting foo.lib onto the linker line and letting the linker
5283 // use its library paths to look for libraries and report any problems.5340 // use its library paths to look for libraries and report any problems.
...@@ -5291,7 +5348,7 @@ fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: boo...@@ -5291,7 +5348,7 @@ fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: boo
5291 // TODO Surface more error details.5348 // TODO Surface more error details.
5292 else => |e| return comp.lockAndSetMiscFailure(5349 else => |e| return comp.lockAndSetMiscFailure(
5293 .windows_import_lib,5350 .windows_import_lib,
5294 "unable to generate mingw DLL import .lib file for {s}: {t}",5351 "generating mingw DLL import .lib file for {s} failed: {t}",
5295 .{ lib_name, e },5352 .{ lib_name, e },
5296 ),5353 ),
5297 };5354 };
...@@ -5818,7 +5875,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5818,7 +5875,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5818 // the XML data as a RT_MANIFEST resource. This means we can skip preprocessing,5875 // the XML data as a RT_MANIFEST resource. This means we can skip preprocessing,
5819 // include paths, CLI options, etc.5876 // include paths, CLI options, etc.
5820 if (win32_resource.src == .manifest) {5877 if (win32_resource.src == .manifest) {
5821 _ = try man.addFile(src_path, null);5878 _ = try man.addFilePath(.initCwd(src_path), null);
58225879
5823 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});5880 const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename});
5824 const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename});5881 const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename});
...@@ -5911,7 +5968,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5911,7 +5968,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5911 // We now know that we're compiling an .rc file5968 // We now know that we're compiling an .rc file
5912 const rc_src = win32_resource.src.rc;5969 const rc_src = win32_resource.src.rc;
59135970
5914 _ = try man.addFile(rc_src.src_path, null);5971 _ = try man.addFilePath(.initCwd(rc_src.src_path), null);
5915 man.hash.addListOfBytes(rc_src.extra_flags);5972 man.hash.addListOfBytes(rc_src.extra_flags);
59165973
5917 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];5974 const rc_basename_noext = src_basename[0 .. src_basename.len - fs.path.extension(src_basename).len];
...@@ -7321,6 +7378,7 @@ fn buildOutputFromZig(...@@ -7321,6 +7378,7 @@ fn buildOutputFromZig(
7321 1, // zig lib dir is the same7378 1, // zig lib dir is the same
7322 3, // local cache is mapped to global cache7379 3, // local cache is mapped to global cache
7323 3, // global cache is the same7380 3, // global cache is the same
7381 0, // build root is not provided
7324 },7382 },
7325 },7383 },
7326 .incremental, .none => null,7384 .incremental, .none => null,
src/Zcu/PerThread.zig+5-11
...@@ -221,22 +221,19 @@ pub fn update(...@@ -221,22 +221,19 @@ pub fn update(
221 .astgen_failure, .success => {}, // the file was read successfully221 .astgen_failure, .success => {}, // the file was read successfully
222 }222 }
223223
224 const path = try file.path.toAbsolute(comp.dirs, gpa);
225 defer gpa.free(path);
226
227 const result = res: {224 const result = res: {
228 try whole.cache_manifest_mutex.lock(io);225 try whole.cache_manifest_mutex.lock(io);
229 defer whole.cache_manifest_mutex.unlock(io);226 defer whole.cache_manifest_mutex.unlock(io);
230 if (file.source) |source| {227 if (file.source) |source| {
231 break :res man.addFilePostContents(path, source, file.stat);228 break :res file.path.addToCacheManifestPostHitContents(man, &comp.dirs, source, file.stat);
232 } else {229 } else {
233 break :res man.addFilePost(path);230 break :res file.path.addToCacheManifestPostHit(man, &comp.dirs);
234 }231 }
235 };232 };
236 result catch |err| switch (err) {233 result catch |err| switch (err) {
237 error.OutOfMemory => |e| return e,234 error.OutOfMemory => |e| return e,
238 else => {235 else => {
239 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});236 try pt.reportRetryableFileError(file_index, "unable to update cache: {t}", .{err});
240 continue;237 continue;
241 },238 },
242 };239 };
...@@ -481,7 +478,7 @@ pub fn updateFile(...@@ -481,7 +478,7 @@ pub fn updateFile(
481 const stat = try source_file.stat(io);478 const stat = try source_file.stat(io);
482479
483 const want_local_cache = switch (file.path.root) {480 const want_local_cache = switch (file.path.root) {
484 .none, .local_cache => true,481 .none, .local_cache, .build_root => true,
485 .global_cache, .zig_lib => false,482 .global_cache, .zig_lib => false,
486 };483 };
487484
...@@ -2965,13 +2962,10 @@ fn newEmbedFile(...@@ -2965,13 +2962,10 @@ fn newEmbedFile(
2965 const array_len = Value.fromInterned(new_file.val).typeOf(zcu).childType(zcu).arrayLen(zcu);2962 const array_len = Value.fromInterned(new_file.val).typeOf(zcu).childType(zcu).arrayLen(zcu);
2966 const contents = ip_str.toSlice(array_len, ip);2963 const contents = ip_str.toSlice(array_len, ip);
29672964
2968 const path_str = try path.toAbsolute(comp.dirs, gpa);
2969 defer gpa.free(path_str);
2970
2971 try whole.cache_manifest_mutex.lock(io);2965 try whole.cache_manifest_mutex.lock(io);
2972 defer whole.cache_manifest_mutex.unlock(io);2966 defer whole.cache_manifest_mutex.unlock(io);
29732967
2974 try man.addFilePostContents(path_str, contents, new_file.stat);2968 try path.addToCacheManifestPostHitContents(man, &comp.dirs, contents, new_file.stat);
2975 }2969 }
29762970
2977 return new_file;2971 return new_file;
src/codegen/llvm.zig+2-1
...@@ -481,7 +481,7 @@ pub const Object = struct {...@@ -481,7 +481,7 @@ pub const Object = struct {
481 // way already, but here we throw all that sweet information481 // way already, but here we throw all that sweet information
482 // into the garbage can by converting into absolute paths. What482 // into the garbage can by converting into absolute paths. What
483 // a terrible tragedy.483 // a terrible tragedy.
484 const compile_unit_dir = try zcu.main_mod.root.toAbsolute(comp.dirs, arena);484 const compile_unit_dir = try zcu.main_mod.root.toAbsolute(&comp.dirs, arena);
485485
486 const debug_file = try builder.debugFile(486 const debug_file = try builder.debugFile(
487 try builder.metadataString(comp.root_name),487 try builder.metadataString(comp.root_name),
...@@ -1701,6 +1701,7 @@ pub const Object = struct {...@@ -1701,6 +1701,7 @@ pub const Object = struct {
1701 .zig_lib => dirs.zig_lib.path,1701 .zig_lib => dirs.zig_lib.path,
1702 .global_cache => dirs.global_cache.path,1702 .global_cache => dirs.global_cache.path,
1703 .local_cache => dirs.local_cache.path,1703 .local_cache => dirs.local_cache.path,
1704 .build_root => dirs.build_root.path,
1704 .none => null,1705 .none => null,
1705 };1706 };
17061707
src/libs/freebsd.zig+8-4
...@@ -458,8 +458,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -458,8 +458,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
458 man.hash.add(target.abi);458 man.hash.add(target.abi);
459 man.hash.add(target_os_version);459 man.hash.add(target_os_version);
460460
461 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});461 const abilists_index = try man.addFilePath(.{
462 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);462 .root_dir = comp.dirs.zig_lib,
463 .sub_path = abilists_path,
464 }, abilists_max_size);
463465
464 if (try man.hit(prog_node)) {466 if (try man.hit(prog_node)) {
465 const digest = man.final();467 const digest = man.final();
...@@ -1044,7 +1046,6 @@ fn buildSharedLib(...@@ -1044,7 +1046,6 @@ fn buildSharedLib(
1044 const version: Version = .{ .major = sover, .minor = 0, .patch = 0 };1046 const version: Version = .{ .major = sover, .minor = 0, .patch = 0 };
1045 const ld_basename = path.basename(target.standardDynamicLinkerPath().get().?);1047 const ld_basename = path.basename(target.standardDynamicLinkerPath().get().?);
1046 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;1048 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
1047 const map_file_path = try path.join(arena, &.{ bin_directory.path.?, all_map_basename });
10481049
1049 const optimize_mode = comp.compilerRtOptMode();1050 const optimize_mode = comp.compilerRtOptMode();
1050 const strip = comp.compilerRtStrip();1051 const strip = comp.compilerRtStrip();
...@@ -1113,7 +1114,10 @@ fn buildSharedLib(...@@ -1113,7 +1114,10 @@ fn buildSharedLib(
1113 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,1114 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
1114 .clang_passthrough_mode = comp.clang_passthrough_mode,1115 .clang_passthrough_mode = comp.clang_passthrough_mode,
1115 .version = version,1116 .version = version,
1116 .version_script = map_file_path,1117 .version_script = .{
1118 .root_dir = bin_directory,
1119 .sub_path = all_map_basename,
1120 },
1117 .soname = soname,1121 .soname = soname,
1118 .c_source_files = &c_source_files,1122 .c_source_files = &c_source_files,
1119 .skip_linker_dependencies = true,1123 .skip_linker_dependencies = true,
src/libs/glibc.zig+8-4
...@@ -698,8 +698,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -698,8 +698,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
698 man.hash.add(target.abi);698 man.hash.add(target.abi);
699 man.hash.add(target_version);699 man.hash.add(target_version);
700700
701 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});701 const abilists_index = try man.addFilePath(.{
702 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);702 .root_dir = comp.dirs.zig_lib,
703 .sub_path = abilists_path,
704 }, abilists_max_size);
703705
704 if (try man.hit(prog_node)) {706 if (try man.hit(prog_node)) {
705 const digest = man.final();707 const digest = man.final();
...@@ -1188,7 +1190,6 @@ fn buildSharedLib(...@@ -1188,7 +1190,6 @@ fn buildSharedLib(
1188 const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };1190 const version: Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
1189 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);1191 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
1190 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;1192 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
1191 const map_file_path = try path.join(arena, &.{ bin_directory.path.?, all_map_basename });
11921193
1193 const optimize_mode = comp.compilerRtOptMode();1194 const optimize_mode = comp.compilerRtOptMode();
1194 const strip = comp.compilerRtStrip();1195 const strip = comp.compilerRtStrip();
...@@ -1257,7 +1258,10 @@ fn buildSharedLib(...@@ -1257,7 +1258,10 @@ fn buildSharedLib(
1257 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,1258 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
1258 .clang_passthrough_mode = comp.clang_passthrough_mode,1259 .clang_passthrough_mode = comp.clang_passthrough_mode,
1259 .version = version,1260 .version = version,
1260 .version_script = map_file_path,1261 .version_script = .{
1262 .root_dir = bin_directory,
1263 .sub_path = all_map_basename,
1264 },
1261 .soname = soname,1265 .soname = soname,
1262 .c_source_files = &c_source_files,1266 .c_source_files = &c_source_files,
1263 .skip_linker_dependencies = true,1267 .skip_linker_dependencies = true,
src/libs/mingw.zig+50-48
...@@ -215,12 +215,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P...@@ -215,12 +215,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
215 defer arena_allocator.deinit();215 defer arena_allocator.deinit();
216 const arena = arena_allocator.allocator();216 const arena = arena_allocator.allocator();
217217
218 const def_file_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {218 const def_file_path: Cache.Path = .{
219 error.FileNotFound => return error.DefNotFound,219 .root_dir = comp.dirs.zig_lib,
220 else => |e| return e,220 .sub_path = findDef(arena, io, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {
221 error.FileNotFound => return error.DefNotFound,
222 else => |e| return e,
223 },
221 };224 };
222 // Only .def.in files need preprocessing225 // Only .def.in files need preprocessing
223 const def_needs_preprocessing = mem.endsWith(u8, def_file_path, ".def.in");226 const def_needs_preprocessing = mem.endsWith(u8, def_file_path.sub_path, ".def.in");
224227
225 const target = comp.getTarget();228 const target = comp.getTarget();
226229
...@@ -243,12 +246,34 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P...@@ -243,12 +246,34 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
243 var man = cache.obtain();246 var man = cache.obtain();
244 defer man.deinit();247 defer man.deinit();
245248
246 _ = try man.addFile(def_file_path, null);249 _ = try man.addFilePath(def_file_path, null);
247250
248 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});251 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});
249 errdefer gpa.free(final_lib_basename);252 errdefer gpa.free(final_lib_basename);
250253
251 if (try man.hit(prog_node)) {254 const is_hit = man.hit(prog_node) catch |err| switch (err) {
255 error.CacheCheckFailed => switch (man.diagnostic) {
256 .none => unreachable,
257 .manifest_create, .manifest_read, .manifest_lock => |e| {
258 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {t} {t}", .{ man.diagnostic, e });
259 return error.AlreadyReported;
260 },
261 .file_open, .file_stat, .file_read, .file_hash => |op| {
262 const pp = man.files.keys()[op.file_index].prefixed_path;
263 const prefix = man.cache.prefixes()[pp.prefix];
264 comp.setMiscFailure(.windows_import_lib, "checking cache failed: {f}{s} {t} {t}", .{
265 prefix, pp.sub_path, man.diagnostic, op.err,
266 });
267 return error.AlreadyReported;
268 },
269 },
270 error.OutOfMemory, error.Canceled => |e| return e,
271 error.InvalidFormat => {
272 comp.setMiscFailure(.windows_import_lib, "checking cache failed: invalid manifest file format", .{});
273 return error.AlreadyReported;
274 },
275 };
276 if (is_hit) {
252 const digest = man.final();277 const digest = man.final();
253 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });278 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
254 errdefer gpa.free(sub_path);279 errdefer gpa.free(sub_path);
...@@ -273,20 +298,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P...@@ -273,20 +298,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
273 var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{});298 var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{});
274 defer o_dir.close(io);299 defer o_dir.close(io);
275300
276 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });301 const sep = path.sep_str;
277302 const include_dir: Cache.Path = .{
278 if (comp.verbose_cc) {303 .root_dir = comp.dirs.zig_lib,
279 var buffer: [256]u8 = undefined;304 .sub_path = "libc" ++ sep ++ "mingw" ++ sep ++ "def-include",
280 const stderr = try io.lockStderr(&buffer, null);305 };
281 defer io.unlockStderr();
282 const w = &stderr.file_writer.interface;
283 w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) {
284 error.WriteFailed => return stderr.file_writer.err.?,
285 };
286 w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) {
287 error.WriteFailed => return stderr.file_writer.err.?,
288 };
289 }
290306
291 const members = members: {307 const members = members: {
292 const members_node = sub_node.start("Members", 0);308 const members_node = sub_node.start("Members", 0);
...@@ -310,7 +326,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P...@@ -310,7 +326,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
310326
311 break :pp try aw.toOwnedSliceSentinel(0);327 break :pp try aw.toOwnedSliceSentinel(0);
312 },328 },
313 false => try Io.Dir.cwd().readFileAllocOptions(io, def_file_path, gpa, .unlimited, .of(u8), 0),329 false => try def_file_path.root_dir.handle.readFileAllocOptions(io, def_file_path.sub_path, gpa, .unlimited, .of(u8), 0),
314 };330 };
315 defer gpa.free(input);331 defer gpa.free(input);
316332
...@@ -384,7 +400,7 @@ pub fn libExists(...@@ -384,7 +400,7 @@ pub fn libExists(
384/// This function body is verbose but all it does is test 3 different paths and400/// This function body is verbose but all it does is test 3 different paths and
385/// see if a .def file exists.401/// see if a .def file exists.
386fn findDef(402fn findDef(
387 allocator: Allocator,403 gpa: Allocator,
388 io: Io,404 io: Io,
389 target: *const std.Target,405 target: *const std.Target,
390 zig_lib_directory: Cache.Directory,406 zig_lib_directory: Cache.Directory,
...@@ -398,21 +414,17 @@ fn findDef(...@@ -398,21 +414,17 @@ fn findDef(
398 else => unreachable,414 else => unreachable,
399 };415 };
400416
401 var override_path = std.array_list.Managed(u8).init(allocator);417 var override_path: std.ArrayList(u8) = .empty;
402 defer override_path.deinit();418 defer override_path.deinit(gpa);
403419
404 const s = path.sep_str;420 const s = path.sep_str;
405421
406 {422 {
407 // Try the archtecture-specific path first.423 // Try the archtecture-specific path first.
408 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";424 override_path.shrinkRetainingCapacity(0);
409 if (zig_lib_directory.path) |p| {425 try override_path.print(gpa, "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def", .{ lib_path, lib_name });
410 try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });426 if (zig_lib_directory.handle.access(io, override_path.items, .{})) |_| {
411 } else {427 return override_path.toOwnedSlice(gpa);
412 try override_path.print(fmt_path, .{ lib_path, lib_name });
413 }
414 if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| {
415 return override_path.toOwnedSlice();
416 } else |err| switch (err) {428 } else |err| switch (err) {
417 error.FileNotFound => {},429 error.FileNotFound => {},
418 else => |e| return e,430 else => |e| return e,
...@@ -422,14 +434,9 @@ fn findDef(...@@ -422,14 +434,9 @@ fn findDef(
422 {434 {
423 // Try the generic version.435 // Try the generic version.
424 override_path.shrinkRetainingCapacity(0);436 override_path.shrinkRetainingCapacity(0);
425 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";437 try override_path.print(gpa, "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def", .{lib_name});
426 if (zig_lib_directory.path) |p| {438 if (zig_lib_directory.handle.access(io, override_path.items, .{})) |_| {
427 try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });439 return override_path.toOwnedSlice(gpa);
428 } else {
429 try override_path.print(fmt_path, .{lib_name});
430 }
431 if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| {
432 return override_path.toOwnedSlice();
433 } else |err| switch (err) {440 } else |err| switch (err) {
434 error.FileNotFound => {},441 error.FileNotFound => {},
435 else => |e| return e,442 else => |e| return e,
...@@ -439,14 +446,9 @@ fn findDef(...@@ -439,14 +446,9 @@ fn findDef(
439 {446 {
440 // Try the generic version and preprocess it.447 // Try the generic version and preprocess it.
441 override_path.shrinkRetainingCapacity(0);448 override_path.shrinkRetainingCapacity(0);
442 const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";449 try override_path.print(gpa, "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in", .{lib_name});
443 if (zig_lib_directory.path) |p| {450 if (zig_lib_directory.handle.access(io, override_path.items, .{})) |_| {
444 try override_path.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });451 return override_path.toOwnedSlice(gpa);
445 } else {
446 try override_path.print(fmt_path, .{lib_name});
447 }
448 if (Io.Dir.cwd().access(io, override_path.items, .{})) |_| {
449 return override_path.toOwnedSlice();
450 } else |err| switch (err) {452 } else |err| switch (err) {
451 error.FileNotFound => {},453 error.FileNotFound => {},
452 else => |e| return e,454 else => |e| return e,
src/libs/mingw/Preprocessor.zig+12-22
...@@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;...@@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;
4const Token = Tokenizer.Token;4const Token = Tokenizer.Token;
5const mem = std.mem;5const mem = std.mem;
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const Path = std.Build.Cache.Path;
78
8test {9test {
9 _ = Tokenizer;10 _ = Tokenizer;
...@@ -25,15 +26,15 @@ pub const Source = struct {...@@ -25,15 +26,15 @@ pub const Source = struct {
25 pub const generated: Source.Id = std.math.maxInt(usize);26 pub const generated: Source.Id = std.math.maxInt(usize);
26 pub const Id = usize;27 pub const Id = usize;
27 id: Id = generated,28 id: Id = generated,
28 path: []const u8,29 path: Path,
29 buf: []const u8,30 buf: []const u8,
30};31};
3132
32sources: std.array_hash_map.String(Source) = .empty,33sources: std.array_hash_map.Custom(Path, Source, Path.TableAdapter, false) = .empty,
3334
34arena: Allocator,35arena: Allocator,
35io: std.Io,36io: std.Io,
36include_dir: []const u8,37include_dir: Path,
3738
38top_expansion_buf: ExpandBuf = .empty,39top_expansion_buf: ExpandBuf = .empty,
39add_expansion_nl: usize = 0,40add_expansion_nl: usize = 0,
...@@ -132,7 +133,7 @@ fn defineBuiltin(pp: *Preprocessor, name: []const u8) !void {...@@ -132,7 +133,7 @@ fn defineBuiltin(pp: *Preprocessor, name: []const u8) !void {
132 });133 });
133}134}
134135
135pub fn preprocess(pp: *Preprocessor, file_path: []const u8) !void {136pub fn preprocess(pp: *Preprocessor, file_path: Path) !void {
136 const source = try pp.addSourceFromPath(file_path);137 const source = try pp.addSourceFromPath(file_path);
137 try pp.preprocessFile(source);138 try pp.preprocessFile(source);
138}139}
...@@ -789,13 +790,9 @@ fn makeGeneratedToken(...@@ -789,13 +790,9 @@ fn makeGeneratedToken(
789 return pasted_token;790 return pasted_token;
790}791}
791792
792fn findInclude(793fn findInclude(pp: *Preprocessor, filename: []const u8, includer_token: Token) !?Source {
793 pp: *Preprocessor,
794 filename: []const u8,
795 includer_token: Token,
796) !?Source {
797 const other_file = pp.sources.values()[includer_token.source].path;794 const other_file = pp.sources.values()[includer_token.source].path;
798 const dir = std.fs.path.dirname(other_file) orelse ".";795 const dir: Path = other_file.dirname() orelse .cwd();
799 if (try pp.checkIncludeDir(filename, dir)) |res| return res;796 if (try pp.checkIncludeDir(filename, dir)) |res| return res;
800797
801 return pp.checkIncludeDir(filename, pp.include_dir);798 return pp.checkIncludeDir(filename, pp.include_dir);
...@@ -804,31 +801,24 @@ fn findInclude(...@@ -804,31 +801,24 @@ fn findInclude(
804fn checkIncludeDir(801fn checkIncludeDir(
805 pp: *Preprocessor,802 pp: *Preprocessor,
806 include_path: []const u8,803 include_path: []const u8,
807 include_dir: []const u8,804 include_dir: Path,
808) !?Source {805) !?Source {
809 const format = "{s}{c}{s}";
810 var bfa_buf: [1024]u8 = undefined;806 var bfa_buf: [1024]u8 = undefined;
811 var bfa_state: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.arena);807 var bfa_state: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.arena);
812 const bfa = bfa_state.allocator();808 const bfa = bfa_state.allocator();
813 const header_path = try std.fmt.allocPrint(bfa, format, .{809 const header_path = try include_dir.join(bfa, include_path);
814 include_dir,
815 std.fs.path.sep,
816 include_path,
817 });
818 defer bfa.free(header_path);
819
820 return pp.addSourceFromPath(header_path) catch |err| switch (err) {810 return pp.addSourceFromPath(header_path) catch |err| switch (err) {
821 error.OutOfMemory => |e| return e,811 error.OutOfMemory => |e| return e,
822 else => return null,812 else => return null,
823 };813 };
824}814}
825815
826pub fn addSourceFromPath(pp: *Preprocessor, path: []const u8) !Source {816pub fn addSourceFromPath(pp: *Preprocessor, path: Path) !Source {
827 if (pp.sources.get(path)) |src| return src;817 if (pp.sources.get(path)) |src| return src;
828 try pp.sources.ensureUnusedCapacity(pp.arena, 1);818 try pp.sources.ensureUnusedCapacity(pp.arena, 1);
829819
830 const contents = try std.Io.Dir.cwd().readFileAlloc(pp.io, path, pp.arena, .limited(std.math.maxInt(u32)));820 const contents = try path.root_dir.handle.readFileAlloc(pp.io, path.sub_path, pp.arena, .limited(std.math.maxInt(u32)));
831 const duped_path = try pp.arena.dupe(u8, path);821 const duped_path = try path.clone(pp.arena);
832822
833 const src: Source = .{823 const src: Source = .{
834 .buf = contents,824 .buf = contents,
src/libs/netbsd.zig+4-2
...@@ -406,8 +406,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -406,8 +406,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
406 man.hash.add(target.abi);406 man.hash.add(target.abi);
407 man.hash.add(target_version);407 man.hash.add(target_version);
408408
409 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});409 const abilists_index = try man.addFilePath(.{
410 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);410 .root_dir = comp.dirs.zig_lib,
411 .sub_path = abilists_path,
412 }, abilists_max_size);
411413
412 if (try man.hit(prog_node)) {414 if (try man.hit(prog_node)) {
413 const digest = man.final();415 const digest = man.final();
src/libs/openbsd.zig+4-2
...@@ -327,8 +327,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -327,8 +327,10 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
327 man.hash.add(target.abi);327 man.hash.add(target.abi);
328 man.hash.add(target_version);328 man.hash.add(target_version);
329329
330 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});330 const abilists_index = try man.addFilePath(.{
331 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);331 .root_dir = comp.dirs.zig_lib,
332 .sub_path = abilists_path,
333 }, abilists_max_size);
332334
333 if (try man.hit(prog_node)) {335 if (try man.hit(prog_node)) {
334 const digest = man.final();336 const digest = man.final();
src/link.zig+3-3
...@@ -461,8 +461,8 @@ pub const File = struct {...@@ -461,8 +461,8 @@ pub const File = struct {
461 allow_undefined_version: bool,461 allow_undefined_version: bool,
462 enable_new_dtags: ?bool,462 enable_new_dtags: ?bool,
463 subsystem: ?std.zig.Subsystem,463 subsystem: ?std.zig.Subsystem,
464 linker_script: ?[]const u8,464 linker_script: ?Path,
465 version_script: ?[]const u8,465 version_script: ?Path,
466 soname: ?[]const u8,466 soname: ?[]const u8,
467 print_gc_sections: bool,467 print_gc_sections: bool,
468 print_icf_sections: bool,468 print_icf_sections: bool,
...@@ -493,7 +493,7 @@ pub const File = struct {...@@ -493,7 +493,7 @@ pub const File = struct {
493 /// Install name for the dylib493 /// Install name for the dylib
494 install_name: ?[]const u8,494 install_name: ?[]const u8,
495 /// Path to entitlements file495 /// Path to entitlements file
496 entitlements: ?[]const u8,496 entitlements: ?Path,
497 /// size of the __PAGEZERO segment497 /// size of the __PAGEZERO segment
498 pagezero_size: ?u64,498 pagezero_size: ?u64,
499 /// Set minimum space for future expansion of the load commands499 /// Set minimum space for future expansion of the load commands
src/link/Dwarf.zig+1-1
...@@ -4735,7 +4735,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err...@@ -4735,7 +4735,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (UpdateError || Writer.Err
4735 }4735 }
47364736
4737 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {4737 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {
4738 const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa);4738 const root_dir_path = try mod.root.toAbsolute(&zcu.comp.dirs, dwarf.gpa);
4739 defer dwarf.gpa.free(root_dir_path);4739 defer dwarf.gpa.free(root_dir_path);
4740 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);4740 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);
4741 }4741 }
src/link/Lld.zig+4-4
...@@ -75,8 +75,8 @@ pub const Elf = struct {...@@ -75,8 +75,8 @@ pub const Elf = struct {
75 entry_name: ?[]const u8,75 entry_name: ?[]const u8,
76 hash_style: HashStyle,76 hash_style: HashStyle,
77 image_base: u64,77 image_base: u64,
78 linker_script: ?[]const u8,78 linker_script: ?Cache.Path,
79 version_script: ?[]const u8,79 version_script: ?Cache.Path,
80 sort_section: ?SortSection,80 sort_section: ?SortSection,
81 print_icf_sections: bool,81 print_icf_sections: bool,
82 print_map: bool,82 print_map: bool,
...@@ -930,7 +930,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -930,7 +930,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
930930
931 if (elf.linker_script) |linker_script| {931 if (elf.linker_script) |linker_script| {
932 try argv.append("-T");932 try argv.append("-T");
933 try argv.append(linker_script);933 try argv.append(try linker_script.toString(arena));
934 }934 }
935935
936 if (elf.sort_section) |how| {936 if (elf.sort_section) |how| {
...@@ -1086,7 +1086,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {...@@ -1086,7 +1086,7 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
1086 }1086 }
1087 if (elf.version_script) |version_script| {1087 if (elf.version_script) |version_script| {
1088 try argv.append("-version-script");1088 try argv.append("-version-script");
1089 try argv.append(version_script);1089 try argv.append(try version_script.toString(arena));
1090 }1090 }
1091 if (elf.allow_undefined_version) {1091 if (elf.allow_undefined_version) {
1092 try argv.append("--undefined-version");1092 try argv.append("--undefined-version");
src/link/MachO.zig+2-2
...@@ -127,7 +127,7 @@ frameworks: []const Framework,...@@ -127,7 +127,7 @@ frameworks: []const Framework,
127/// TODO: unify with soname127/// TODO: unify with soname
128install_name: ?[]const u8,128install_name: ?[]const u8,
129/// Path to entitlements file.129/// Path to entitlements file.
130entitlements: ?[]const u8,130entitlements: ?Path,
131compatibility_version: ?std.SemanticVersion,131compatibility_version: ?std.SemanticVersion,
132/// Entry name132/// Entry name
133entry_name: ?[]const u8,133entry_name: ?[]const u8,
...@@ -580,7 +580,7 @@ pub fn flush(...@@ -580,7 +580,7 @@ pub fn flush(
580 var codesig = CodeSignature.init(self.getPageSize());580 var codesig = CodeSignature.init(self.getPageSize());
581 codesig.code_directory.ident = fs.path.basename(self.base.emit.sub_path);581 codesig.code_directory.ident = fs.path.basename(self.base.emit.sub_path);
582 if (self.entitlements) |path| codesig.addEntitlements(gpa, io, path) catch |err|582 if (self.entitlements) |path| codesig.addEntitlements(gpa, io, path) catch |err|
583 return diags.fail("failed to add entitlements from {s}: {t}", .{ path, err });583 return diags.fail("failed to add entitlements from {f}: {t}", .{ path, err });
584 try self.writeCodeSignaturePadding(&codesig);584 try self.writeCodeSignaturePadding(&codesig);
585 break :blk codesig;585 break :blk codesig;
586 } else null;586 } else null;
src/link/MachO/CodeSignature.zig+2-2
...@@ -246,8 +246,8 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void {...@@ -246,8 +246,8 @@ pub fn deinit(self: *CodeSignature, allocator: Allocator) void {
246 }246 }
247}247}
248248
249pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, io: Io, path: []const u8) !void {249pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, io: Io, path: std.Build.Cache.Path) !void {
250 const inner = try Io.Dir.cwd().readFileAlloc(io, path, allocator, .limited(std.math.maxInt(u32)));250 const inner = try path.root_dir.handle.readFileAlloc(io, path.sub_path, allocator, .limited(std.math.maxInt(u32)));
251 self.entitlements = .{ .inner = inner };251 self.entitlements = .{ .inner = inner };
252}252}
253253
src/main.zig+52-52
...@@ -423,17 +423,16 @@ fn mainArgs(...@@ -423,17 +423,16 @@ fn mainArgs(
423 .wasi => {},423 .wasi => {},
424 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}),424 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}),
425 };425 };
426 var dirs: std.zig.Directories = .init(426 var dirs: std.zig.Directories = .init(arena, io, .{
427 arena,427 .override_zig_lib = EnvVar.ZIG_LIB_DIR.get(environ_map),
428 io,428 .override_global_cache = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map),
429 EnvVar.ZIG_LIB_DIR.get(environ_map),429 .build_root = null,
430 EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map),430 .local_cache_strat = .global,
431 .global,431 .preopens = preopens,
432 preopens,432 .self_exe_path = self_exe_path,
433 self_exe_path,433 .environ_map = environ_map,
434 environ_map,434 .cwd = try std.zig.getResolvedCwd(io, arena),
435 try std.zig.getResolvedCwd(io, arena),435 });
436 );
437 defer dirs.deinit(io);436 defer dirs.deinit(io);
438 const host = std.zig.resolveTargetQueryOrFatal(io, .{});437 const host = std.zig.resolveTargetQueryOrFatal(io, .{});
439 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);438 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
...@@ -458,17 +457,16 @@ fn mainArgs(...@@ -458,17 +457,16 @@ fn mainArgs(
458 .wasi => args[0],457 .wasi => args[0],
459 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}),458 else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}),
460 };459 };
461 var dirs: std.zig.Directories = .init(460 var dirs: std.zig.Directories = .init(arena, io, .{
462 arena,461 .override_zig_lib = EnvVar.ZIG_LIB_DIR.get(environ_map),
463 io,462 .override_global_cache = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map),
464 EnvVar.ZIG_LIB_DIR.get(environ_map),463 .build_root = null,
465 EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map),464 .local_cache_strat = .global,
466 .global,465 .preopens = preopens,
467 preopens,466 .self_exe_path = if (native_os != .wasi) self_exe_path,
468 if (native_os != .wasi) self_exe_path,467 .environ_map = environ_map,
469 environ_map,468 .cwd = try std.zig.getResolvedCwd(io, arena),
470 try std.zig.getResolvedCwd(io, arena),469 });
471 );
472 defer dirs.deinit(io);470 defer dirs.deinit(io);
473 const host = std.zig.resolveTargetQueryOrFatal(io, .{});471 const host = std.zig.resolveTargetQueryOrFatal(io, .{});
474 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);472 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
...@@ -511,7 +509,7 @@ fn mainArgs(...@@ -511,7 +509,7 @@ fn mainArgs(
511 }509 }
512}510}
513511
514const usage_build_generic =512const compile_usage =
515 \\Usage: zig build-exe [options] [files]513 \\Usage: zig build-exe [options] [files]
516 \\ zig build-lib [options] [files]514 \\ zig build-lib [options] [files]
517 \\ zig build-obj [options] [files]515 \\ zig build-obj [options] [files]
...@@ -565,16 +563,16 @@ const usage_build_generic =...@@ -565,16 +563,16 @@ const usage_build_generic =
565 \\ --cache-dir [path] Override the local cache directory563 \\ --cache-dir [path] Override the local cache directory
566 \\ --global-cache-dir [path] Override the global cache directory564 \\ --global-cache-dir [path] Override the global cache directory
567 \\ --zig-lib-dir [path] Override path to Zig installation lib directory565 \\ --zig-lib-dir [path] Override path to Zig installation lib directory
566 \\ --build-root [path] Override path to project source files
568 \\567 \\
569 \\Global Compile Options:568 \\Global Compile Options:
570 \\ --name [name] Compilation unit name (not a file path)569 \\ --name [name] Compilation unit name (not a file path)
571 \\ --libc [file] Provide a file which specifies libc paths
572 \\ -x language Treat subsequent input files as having type <language>
573 \\ --dep [[import=]name] Add an entry to the next module's import table
574 \\ -M[name][=src] Create a module based on the current per-module settings.570 \\ -M[name][=src] Create a module based on the current per-module settings.
575 \\ The first module is the main module.571 \\ The first module is the main module.
576 \\ "std" can be configured by omitting src572 \\ "std" can be configured by omitting src
577 \\ After a -M argument, per-module settings are reset.573 \\ After a -M argument, per-module settings are reset.
574 \\ --libc [file] Provide a file which specifies libc paths
575 \\ -x [language] Treat subsequent input files as having type <language>
578 \\ --error-limit [num] Set the maximum amount of distinct error values576 \\ --error-limit [num] Set the maximum amount of distinct error values
579 \\ -fllvm Force using LLVM as the codegen backend577 \\ -fllvm Force using LLVM as the codegen backend
580 \\ -fno-llvm Prevent using LLVM as the codegen backend578 \\ -fno-llvm Prevent using LLVM as the codegen backend
...@@ -599,6 +597,7 @@ const usage_build_generic =...@@ -599,6 +597,7 @@ const usage_build_generic =
599 \\ --time-report Send timing diagnostics to '--listen' clients597 \\ --time-report Send timing diagnostics to '--listen' clients
600 \\598 \\
601 \\Per-Module Compile Options:599 \\Per-Module Compile Options:
600 \\ --dep [[import=]name] Add an entry to the next module's import table
602 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command601 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
603 \\ -O [mode] Choose what to optimize for602 \\ -O [mode] Choose what to optimize for
604 \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed603 \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed
...@@ -1054,6 +1053,7 @@ fn buildOutputType(...@@ -1054,6 +1053,7 @@ fn buildOutputType(
1054 var rc_includes: std.zig.RcIncludes = .any;1053 var rc_includes: std.zig.RcIncludes = .any;
1055 var manifest_file: ?[]const u8 = null;1054 var manifest_file: ?[]const u8 = null;
1056 var linker_export_symbol_names: std.ArrayList([]const u8) = .empty;1055 var linker_export_symbol_names: std.ArrayList([]const u8) = .empty;
1056 var build_root_path: ?[]const u8 = null;
10571057
1058 // Tracks the position in c_source_files which have already their owner populated.1058 // Tracks the position in c_source_files which have already their owner populated.
1059 var c_source_files_owner_index: usize = 0;1059 var c_source_files_owner_index: usize = 0;
...@@ -1167,7 +1167,7 @@ fn buildOutputType(...@@ -1167,7 +1167,7 @@ fn buildOutputType(
1167 fatal("unable to read response file {q}: {t}", .{ resp_file_path, err });1167 fatal("unable to read response file {q}: {t}", .{ resp_file_path, err });
1168 } else if (mem.startsWith(u8, arg, "-")) {1168 } else if (mem.startsWith(u8, arg, "-")) {
1169 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {1169 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
1170 try Io.File.stdout().writeStreamingAll(io, usage_build_generic);1170 try Io.File.stdout().writeStreamingAll(io, compile_usage);
1171 return cleanExit(io);1171 return cleanExit(io);
1172 } else if (mem.eql(u8, arg, "--")) {1172 } else if (mem.eql(u8, arg, "--")) {
1173 if (arg_mode == .run) {1173 if (arg_mode == .run) {
...@@ -1440,6 +1440,8 @@ fn buildOutputType(...@@ -1440,6 +1440,8 @@ fn buildOutputType(
1440 override_global_cache_dir = args_iter.nextOrFatal();1440 override_global_cache_dir = args_iter.nextOrFatal();
1441 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {1441 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
1442 override_lib_dir = args_iter.nextOrFatal();1442 override_lib_dir = args_iter.nextOrFatal();
1443 } else if (mem.eql(u8, arg, "--build-root")) {
1444 build_root_path = args_iter.nextOrFatal();
1443 } else if (mem.eql(u8, arg, "--debug-log")) {1445 } else if (mem.eql(u8, arg, "--debug-log")) {
1444 try addDebugLog(arena, args_iter.nextOrFatal());1446 try addDebugLog(arena, args_iter.nextOrFatal());
1445 } else if (mem.eql(u8, arg, "--listen")) {1447 } else if (mem.eql(u8, arg, "--listen")) {
...@@ -3254,23 +3256,22 @@ fn buildOutputType(...@@ -3254,23 +3256,22 @@ fn buildOutputType(
3254 const cwd_path = try std.zig.getResolvedCwd(io, arena);3256 const cwd_path = try std.zig.getResolvedCwd(io, arena);
32553257
3256 // This `init` calls `fatal` on error.3258 // This `init` calls `fatal` on error.
3257 var dirs: std.zig.Directories = .init(3259 var dirs: std.zig.Directories = .init(arena, io, .{
3258 arena,3260 .override_zig_lib = override_lib_dir,
3259 io,3261 .override_global_cache = override_global_cache_dir,
3260 override_lib_dir,3262 .build_root = build_root_path,
3261 override_global_cache_dir,3263 .local_cache_strat = s: {
3262 s: {
3263 if (override_local_cache_dir) |p| break :s .{ .override = p };3264 if (override_local_cache_dir) |p| break :s .{ .override = p };
3264 break :s switch (arg_mode) {3265 break :s switch (arg_mode) {
3265 .run => .global,3266 .run => .global,
3266 else => .search,3267 else => .search,
3267 };3268 };
3268 },3269 },
3269 preopens,3270 .preopens = preopens,
3270 self_exe_path,3271 .self_exe_path = self_exe_path,
3271 environ_map,3272 .environ_map = environ_map,
3272 cwd_path,3273 .cwd = cwd_path,
3273 );3274 });
3274 defer dirs.deinit(io);3275 defer dirs.deinit(io);
32753276
3276 if (linker_optimization) |o| warn("ignoring deprecated linker optimization setting {q}", .{o});3277 if (linker_optimization) |o| warn("ignoring deprecated linker optimization setting {q}", .{o});
...@@ -3666,8 +3667,8 @@ fn buildOutputType(...@@ -3666,8 +3667,8 @@ fn buildOutputType(
3666 .want_compiler_rt = if (zig_cc_explicitly_link_compiler_rt) true else want_compiler_rt,3667 .want_compiler_rt = if (zig_cc_explicitly_link_compiler_rt) true else want_compiler_rt,
3667 .want_ubsan_rt = want_ubsan_rt,3668 .want_ubsan_rt = want_ubsan_rt,
3668 .hash_style = hash_style,3669 .hash_style = hash_style,
3669 .linker_script = linker_script,3670 .linker_script = if (linker_script) |p| .initCwd(p) else null,
3670 .version_script = version_script,3671 .version_script = if (version_script) |p| .initCwd(p) else null,
3671 .linker_allow_undefined_version = linker_allow_undefined_version,3672 .linker_allow_undefined_version = linker_allow_undefined_version,
3672 .linker_enable_new_dtags = linker_enable_new_dtags,3673 .linker_enable_new_dtags = linker_enable_new_dtags,
3673 .disable_c_depfile = disable_c_depfile,3674 .disable_c_depfile = disable_c_depfile,
...@@ -3740,7 +3741,7 @@ fn buildOutputType(...@@ -3740,7 +3741,7 @@ fn buildOutputType(
3740 .debug_incremental = debug_incremental,3741 .debug_incremental = debug_incremental,
3741 .enable_link_snapshots = enable_link_snapshots,3742 .enable_link_snapshots = enable_link_snapshots,
3742 .install_name = install_name,3743 .install_name = install_name,
3743 .entitlements = entitlements,3744 .entitlements = if (entitlements) |p| .initCwd(p) else null,
3744 .pagezero_size = pagezero_size,3745 .pagezero_size = pagezero_size,
3745 .headerpad_size = headerpad_size,3746 .headerpad_size = headerpad_size,
3746 .headerpad_max_install_names = headerpad_max_install_names,3747 .headerpad_max_install_names = headerpad_max_install_names,
...@@ -5020,17 +5021,16 @@ fn jitCmdInner(...@@ -5020,17 +5021,16 @@ fn jitCmdInner(
5020 const cwd_path = try std.zig.getResolvedCwd(io, arena);5021 const cwd_path = try std.zig.getResolvedCwd(io, arena);
50215022
5022 // This `init` calls `fatal` on error.5023 // This `init` calls `fatal` on error.
5023 var dirs: std.zig.Directories = .init(5024 var dirs: std.zig.Directories = .init(arena, io, .{
5024 arena,5025 .override_zig_lib = override_lib_dir,
5025 io,5026 .override_global_cache = override_global_cache_dir,
5026 override_lib_dir,5027 .build_root = null,
5027 override_global_cache_dir,5028 .local_cache_strat = .global,
5028 .global,5029 .preopens = preopens,
5029 preopens,5030 .self_exe_path = self_exe_path,
5030 self_exe_path,5031 .environ_map = environ_map,
5031 environ_map,5032 .cwd = cwd_path,
5032 cwd_path,5033 });
5033 );
5034 defer dirs.deinit(io);5034 defer dirs.deinit(io);
50355035
5036 var child_argv: std.ArrayList([]const u8) = .empty;5036 var child_argv: std.ArrayList([]const u8) = .empty;
tools/check_mingw.zig+2-2
...@@ -71,11 +71,11 @@ pub fn main(init: std.process.Init) !void {...@@ -71,11 +71,11 @@ pub fn main(init: std.process.Init) !void {
71 var pp: Preprocessor = .{71 var pp: Preprocessor = .{
72 .io = io,72 .io = io,
73 .arena = pp_arena,73 .arena = pp_arena,
74 .include_dir = mingw_include_path,74 .include_dir = .initCwd(mingw_include_path),
75 .target = target,75 .target = target,
76 };76 };
7777
78 pp.preprocess(file_path) catch |err| {78 pp.preprocess(.initCwd(file_path)) catch |err| {
79 std.log.err("error preprocessing file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });79 std.log.err("error preprocessing file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });
80 fail = true;80 fail = true;
81 continue;81 continue;