authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2023-10-28 00:50:56-07:00
committergravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2023-11-02 19:17:03-07:00
log9f2cb920c055bc990cc9d593b8dc9eaa450d07b9
tree4c390b40151bd74e1912d7bde3afbf7327ae642e
parent94cee4fb27a433824c2540dc37375dc14befdf47
signature Signed by SSH key SHA256:cf2/TFgSxv2uRX26INvFSw25Prr1Dy9H8MiRXgLpok4

mingw: Use aro instead of clang for preprocessing import libs

Closes #17753

1 files changed, 47 insertions(+), 58 deletions(-)

src/mingw.zig+47-58
......@@ -288,10 +288,6 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
288288 else => |e| return e,
289289 };
290290
291 // We need to invoke `zig clang` to use the preprocessor.
292 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
293 const self_exe_path = comp.self_exe_path orelse return error.PreprocessorDisabled;
294
295291 const target = comp.getTarget();
296292
297293 var cache: Cache = .{
......@@ -305,6 +301,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
305301 cache.hash.addBytes(build_options.version);
306302 cache.hash.addOptionalBytes(comp.zig_lib_directory.path);
307303 cache.hash.add(target.cpu.arch);
304 cache.hash.addBytes("aro");
308305
309306 var man = cache.obtain();
310307 defer man.deinit();
......@@ -337,67 +334,58 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
337334 "o", &digest, final_def_basename,
338335 });
339336
340 const target_def_arg = switch (target.cpu.arch) {
341 .x86 => "-DDEF_I386",
342 .x86_64 => "-DDEF_X64",
343 .arm, .armeb, .thumb, .thumbeb, .aarch64_32 => "-DDEF_ARM32",
344 .aarch64, .aarch64_be => "-DDEF_ARM64",
337 const target_defines = switch (target.cpu.arch) {
338 .x86 => "#define DEF_I386\n",
339 .x86_64 => "#define DEF_X64\n",
340 .arm, .armeb, .thumb, .thumbeb, .aarch64_32 => "#define DEF_ARM32\n",
341 .aarch64, .aarch64_be => "#define DEF_ARM64\n",
345342 else => unreachable,
346343 };
347344
348 const args = [_][]const u8{
349 self_exe_path,
350 "clang",
351 "-x",
352 "c",
353 def_file_path,
354 "-Wp,-w",
355 "-undef",
356 "-P",
357 "-I",
358 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "def-include" }),
359 target_def_arg,
360 "-E",
361 "-o",
362 def_final_path,
363 };
345 if (builtin.zig_backend == .stage2_c) @panic("the CBE cannot compile Aro yet!");
346 const aro = @import("aro");
347 var aro_comp = aro.Compilation.init(comp.gpa);
348 defer aro_comp.deinit();
364349
365 if (comp.verbose_cc) {
366 Compilation.dump_argv(&args);
350 const include_dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "def-include" });
351
352 if (comp.verbose_cc) print: {
353 std.debug.getStderrMutex().lock();
354 defer std.debug.getStderrMutex().unlock();
355 const stderr = std.io.getStdErr().writer();
356 nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
357 nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
358 nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print;
367359 }
368360
369 if (std.process.can_spawn) {
370 var child = std.ChildProcess.init(&args, arena);
371 child.stdin_behavior = .Ignore;
372 child.stdout_behavior = .Pipe;
373 child.stderr_behavior = .Pipe;
374
375 try child.spawn();
376
377 const stderr = try child.stderr.?.reader().readAllAlloc(arena, std.math.maxInt(usize));
378
379 const term = child.wait() catch |err| {
380 // TODO surface a proper error here
381 log.err("unable to spawn {s}: {s}", .{ args[0], @errorName(err) });
382 return error.ClangPreprocessorFailed;
383 };
384 switch (term) {
385 .Exited => |code| {
386 if (code != 0) {
387 // TODO surface a proper error here
388 log.err("clang exited with code {d} and stderr: {s}", .{ code, stderr });
389 return error.ClangPreprocessorFailed;
390 }
391 },
392 else => {
393 // TODO surface a proper error here
394 log.err("clang terminated unexpectedly with stderr: {s}", .{stderr});
395 return error.ClangPreprocessorFailed;
396 },
361 try aro_comp.include_dirs.append(include_dir);
362
363 const builtin_macros = try aro_comp.generateBuiltinMacros();
364 const user_macros = try aro_comp.addSourceFromBuffer("<command line>", target_defines);
365 const def_file_source = try aro_comp.addSourceFromPath(def_file_path);
366
367 var pp = aro.Preprocessor.init(&aro_comp);
368 defer pp.deinit();
369 pp.linemarkers = .none;
370 pp.preserve_whitespace = true;
371
372 _ = try pp.preprocess(builtin_macros);
373 _ = try pp.preprocess(user_macros);
374 const eof = try pp.preprocess(def_file_source);
375 try pp.tokens.append(pp.comp.gpa, eof);
376
377 for (aro_comp.diag.list.items) |diagnostic| {
378 if (diagnostic.kind == .@"fatal error" or diagnostic.kind == .@"error") {
379 aro_comp.renderErrors();
380 return error.AroPreprocessorFailed;
397381 }
398 } else {
399 log.err("unable to spawn {s}: spawning child process not supported on {s}", .{ args[0], @tagName(builtin.os.tag) });
400 return error.ClangPreprocessorFailed;
382 }
383
384 {
385 // new scope to ensure definition file is written before passing the path to WriteImportLibrary
386 const def_final_file = try comp.global_cache_directory.handle.createFile(def_final_path, .{ .truncate = true });
387 defer def_final_file.close();
388 try pp.prettyPrintTokens(def_final_file.writer());
401389 }
402390
403391 const lib_final_path = try comp.global_cache_directory.join(comp.gpa, &[_][]const u8{
......@@ -405,6 +393,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
405393 });
406394 errdefer comp.gpa.free(lib_final_path);
407395
396 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
408397 const llvm_bindings = @import("codegen/llvm/bindings.zig");
409398 const llvm = @import("codegen/llvm.zig");
410399 const arch_tag = llvm.targetArch(target.cpu.arch);