authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-17 19:11:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-19 12:39:37-07:00
log5b8bee462a63538083e7b2e16f1dae7b39c8529b
treef7f86646f4c2130e57d7379f74b3b6d480c3147e
parent5a6c3aaedfef1ff242317f622252e0c7eebf0159

mingw: fix path usage

- better reporting of cache checking failure - fix not using Path properly - fix not using Path properly in Preprocessor code

3 files changed, 51 insertions(+), 47 deletions(-)

src/Compilation.zig+2-1
......@@ -5351,6 +5351,7 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
53515351
53525352fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: bool, prog_node: std.Progress.Node) void {
53535353 const crt_file_path = mingw.buildImportLib(comp, lib_name, prog_node) catch |err| switch (err) {
5354 error.AlreadyReported => return,
53545355 // TODO: This isn't actually true for self-hosted
53555356 // In the non-prelink case we will end up putting foo.lib onto the linker line and letting the linker
53565357 // use its library paths to look for libraries and report any problems.
......@@ -5364,7 +5365,7 @@ fn buildMingwImportLib(comp: *Compilation, lib_name: []const u8, is_prelink: boo
53645365 // TODO Surface more error details.
53655366 else => |e| return comp.lockAndSetMiscFailure(
53665367 .windows_import_lib,
5367 "unable to generate mingw DLL import .lib file for {s}: {t}",
5368 "generating mingw DLL import .lib file for {s} failed: {t}",
53685369 .{ lib_name, e },
53695370 ),
53705371 };
src/libs/mingw.zig+37-24
......@@ -215,12 +215,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
215215 defer arena_allocator.deinit();
216216 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) {
219 error.FileNotFound => return error.DefNotFound,
220 else => |e| return e,
218 const def_file_path: Cache.Path = .{
219 .root_dir = comp.dirs.zig_lib,
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 },
221224 };
222225 // 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
225228 const target = comp.getTarget();
226229
......@@ -243,15 +246,34 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
243246 var man = cache.obtain();
244247 defer man.deinit();
245248
246 _ = try man.addFilePath(.{
247 .root_dir = comp.dirs.zig_lib,
248 .sub_path = def_file_path,
249 }, null);
249 _ = try man.addFilePath(def_file_path, null);
250250
251251 const final_lib_basename = try std.fmt.allocPrint(gpa, "{s}.lib", .{lib_name});
252252 errdefer gpa.free(final_lib_basename);
253253
254 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) {
255277 const digest = man.final();
256278 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
257279 errdefer gpa.free(sub_path);
......@@ -276,20 +298,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
276298 var o_dir = try comp.dirs.global_cache.handle.createDirPathOpen(io, o_sub_path, .{});
277299 defer o_dir.close(io);
278300
279 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
280
281 if (comp.verbose_cc) {
282 var buffer: [256]u8 = undefined;
283 const stderr = try io.lockStderr(&buffer, null);
284 defer io.unlockStderr();
285 const w = &stderr.file_writer.interface;
286 w.print("def file: {s}\n", .{def_file_path}) catch |err| switch (err) {
287 error.WriteFailed => return stderr.file_writer.err.?,
288 };
289 w.print("include dir: {s}\n", .{include_dir}) catch |err| switch (err) {
290 error.WriteFailed => return stderr.file_writer.err.?,
291 };
292 }
301 const sep = path.sep_str;
302 const include_dir: Cache.Path = .{
303 .root_dir = comp.dirs.zig_lib,
304 .sub_path = "libc" ++ sep ++ "mingw" ++ sep ++ "def-include",
305 };
293306
294307 const members = members: {
295308 const members_node = sub_node.start("Members", 0);
......@@ -313,7 +326,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8, prog_node: std.P
313326
314327 break :pp try aw.toOwnedSliceSentinel(0);
315328 },
316 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),
317330 };
318331 defer gpa.free(input);
319332
src/libs/mingw/Preprocessor.zig+12-22
......@@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;
44const Token = Tokenizer.Token;
55const mem = std.mem;
66const assert = std.debug.assert;
7const Path = std.Build.Cache.Path;
78
89test {
910 _ = Tokenizer;
......@@ -25,15 +26,15 @@ pub const Source = struct {
2526 pub const generated: Source.Id = std.math.maxInt(usize);
2627 pub const Id = usize;
2728 id: Id = generated,
28 path: []const u8,
29 path: Path,
2930 buf: []const u8,
3031};
3132
32sources: std.array_hash_map.String(Source) = .empty,
33sources: std.array_hash_map.Custom(Path, Source, Path.TableAdapter, false) = .empty,
3334
3435arena: Allocator,
3536io: std.Io,
36include_dir: []const u8,
37include_dir: Path,
3738
3839top_expansion_buf: ExpandBuf = .empty,
3940add_expansion_nl: usize = 0,
......@@ -132,7 +133,7 @@ fn defineBuiltin(pp: *Preprocessor, name: []const u8) !void {
132133 });
133134}
134135
135pub fn preprocess(pp: *Preprocessor, file_path: []const u8) !void {
136pub fn preprocess(pp: *Preprocessor, file_path: Path) !void {
136137 const source = try pp.addSourceFromPath(file_path);
137138 try pp.preprocessFile(source);
138139}
......@@ -789,13 +790,9 @@ fn makeGeneratedToken(
789790 return pasted_token;
790791}
791792
792fn findInclude(
793 pp: *Preprocessor,
794 filename: []const u8,
795 includer_token: Token,
796) !?Source {
793fn findInclude(pp: *Preprocessor, filename: []const u8, includer_token: Token) !?Source {
797794 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();
799796 if (try pp.checkIncludeDir(filename, dir)) |res| return res;
800797
801798 return pp.checkIncludeDir(filename, pp.include_dir);
......@@ -804,31 +801,24 @@ fn findInclude(
804801fn checkIncludeDir(
805802 pp: *Preprocessor,
806803 include_path: []const u8,
807 include_dir: []const u8,
804 include_dir: Path,
808805) !?Source {
809 const format = "{s}{c}{s}";
810806 var bfa_buf: [1024]u8 = undefined;
811807 var bfa_state: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.arena);
812808 const bfa = bfa_state.allocator();
813 const header_path = try std.fmt.allocPrint(bfa, format, .{
814 include_dir,
815 std.fs.path.sep,
816 include_path,
817 });
818 defer bfa.free(header_path);
819
809 const header_path = try include_dir.join(bfa, include_path);
820810 return pp.addSourceFromPath(header_path) catch |err| switch (err) {
821811 error.OutOfMemory => |e| return e,
822812 else => return null,
823813 };
824814}
825815
826pub fn addSourceFromPath(pp: *Preprocessor, path: []const u8) !Source {
816pub fn addSourceFromPath(pp: *Preprocessor, path: Path) !Source {
827817 if (pp.sources.get(path)) |src| return src;
828818 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)));
831 const duped_path = try pp.arena.dupe(u8, path);
820 const contents = try path.root_dir.handle.readFileAlloc(pp.io, path.sub_path, pp.arena, .limited(std.math.maxInt(u32)));
821 const duped_path = try path.clone(pp.arena);
832822
833823 const src: Source = .{
834824 .buf = contents,