diff options
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 634 |
1 files changed, 182 insertions, 452 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 0fdfb6038f..97b7e448db 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -36,7 +36,6 @@ const Cache = std.Build.Cache; const c_codegen = @import("codegen/c.zig"); const libtsan = @import("libtsan.zig"); const Zir = std.zig.Zir; -const resinator = @import("resinator.zig"); const Builtin = @import("Builtin.zig"); const LlvmObject = @import("codegen/llvm.zig").Object; @@ -174,7 +173,7 @@ local_cache_directory: Directory, global_cache_directory: Directory, libc_include_dir_list: []const []const u8, libc_framework_dir_list: []const []const u8, -rc_include_dir_list: []const []const u8, +rc_includes: RcIncludes, thread_pool: *ThreadPool, /// Populated when we build the libc++ static library. A Job to build this is placed in the queue @@ -1243,68 +1242,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil options.libc_installation, ); - // The include directories used when preprocessing .rc files are separate from the - // target. Which include directories are used is determined by `options.rc_includes`. - // - // Note: It should be okay that the include directories used when compiling .rc - // files differ from the include directories used when compiling the main - // binary, since the .res format is not dependent on anything ABI-related. The - // only relevant differences would be things like `#define` constants being - // different in the MinGW headers vs the MSVC headers, but any such - // differences would likely be a MinGW bug. - const rc_dirs: std.zig.LibCDirs = b: { - // Set the includes to .none here when there are no rc files to compile - var includes = if (options.rc_source_files.len > 0) options.rc_includes else .none; - const target = options.root_mod.resolved_target.result; - if (!options.root_mod.resolved_target.is_native_os or target.os.tag != .windows) { - switch (includes) { - // MSVC can't be found when the host isn't Windows, so short-circuit. - .msvc => return error.WindowsSdkNotFound, - // Skip straight to gnu since we won't be able to detect - // MSVC on non-Windows hosts. - .any => includes = .gnu, - .none, .gnu => {}, - } - } - while (true) switch (includes) { - .any, .msvc => break :b std.zig.LibCDirs.detect( - arena, - options.zig_lib_directory.path.?, - .{ - .cpu = target.cpu, - .os = target.os, - .abi = .msvc, - .ofmt = target.ofmt, - }, - options.root_mod.resolved_target.is_native_abi, - // The .rc preprocessor will need to know the libc include dirs even if we - // are not linking libc, so force 'link_libc' to true - true, - options.libc_installation, - ) catch |err| { - if (includes == .any) { - // fall back to mingw - includes = .gnu; - continue; - } - return err; - }, - .gnu => break :b try std.zig.LibCDirs.detectFromBuilding(arena, options.zig_lib_directory.path.?, .{ - .cpu = target.cpu, - .os = target.os, - .abi = .gnu, - .ofmt = target.ofmt, - }), - .none => break :b .{ - .libc_include_dir_list = &[0][]u8{}, - .libc_installation = null, - .libc_framework_dir_list = &.{}, - .sysroot = null, - .darwin_sdk_layout = null, - }, - }; - }; - const sysroot = options.sysroot orelse libc_dirs.sysroot; const include_compiler_rt = options.want_compiler_rt orelse @@ -1492,7 +1429,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .self_exe_path = options.self_exe_path, .libc_include_dir_list = libc_dirs.libc_include_dir_list, .libc_framework_dir_list = libc_dirs.libc_framework_dir_list, - .rc_include_dir_list = rc_dirs.libc_include_dir_list, + .rc_includes = options.rc_includes, .thread_pool = options.thread_pool, .clang_passthrough_mode = options.clang_passthrough_mode, .clang_preprocessor_mode = options.clang_preprocessor_mode, @@ -2506,7 +2443,7 @@ fn addNonIncrementalStuffToCacheManifest( man.hash.add(comp.link_eh_frame_hdr); man.hash.add(comp.skip_linker_dependencies); man.hash.add(comp.include_compiler_rt); - man.hash.addListOfBytes(comp.rc_include_dir_list); + man.hash.add(comp.rc_includes); man.hash.addListOfBytes(comp.force_undefined_symbols.keys()); man.hash.addListOfBytes(comp.framework_dirs); try link.hashAddSystemLibs(man, comp.system_libs); @@ -4172,7 +4109,7 @@ pub fn obtainCObjectCacheManifest( pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest { var man = comp.cache_parent.obtain(); - man.hash.addListOfBytes(comp.rc_include_dir_list); + man.hash.add(comp.rc_includes); return man; } @@ -4812,11 +4749,12 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P } fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: *std.Progress.Node) !void { - if (!build_options.have_llvm) { - return comp.failWin32Resource(win32_resource, "clang not available: compiler built without LLVM extensions", .{}); + if (!std.process.can_spawn) { + return comp.failWin32Resource(win32_resource, "{s} does not support spawning a child process", .{@tagName(builtin.os.tag)}); } + const self_exe_path = comp.self_exe_path orelse - return comp.failWin32Resource(win32_resource, "clang compilation disabled", .{}); + return comp.failWin32Resource(win32_resource, "unable to find self exe path", .{}); const tracy_trace = trace(@src()); defer tracy_trace.end(); @@ -4856,6 +4794,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 if (win32_resource.src == .manifest) { _ = try man.addFile(src_path, null); + const rc_basename = try std.fmt.allocPrint(arena, "{s}.rc", .{src_basename}); const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename}); const digest = if (try man.hit()) man.final() else blk: { @@ -4867,17 +4806,12 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); defer o_dir.close(); - var output_file = o_dir.createFile(res_basename, .{}) catch |err| { - const output_file_path = try comp.local_cache_directory.join(arena, &.{ o_sub_path, res_basename }); - return comp.failWin32Resource(win32_resource, "failed to create output file '{s}': {s}", .{ output_file_path, @errorName(err) }); - }; - var output_file_closed = false; - defer if (!output_file_closed) output_file.close(); - - var diagnostics = resinator.errors.Diagnostics.init(arena); - defer diagnostics.deinit(); - - var output_buffered_stream = std.io.bufferedWriter(output_file.writer()); + const in_rc_path = try comp.local_cache_directory.join(comp.gpa, &.{ + o_sub_path, rc_basename, + }); + const out_res_path = try comp.local_cache_directory.join(comp.gpa, &.{ + o_sub_path, res_basename, + }); // In .rc files, a " within a quoted string is escaped as "" const fmtRcEscape = struct { @@ -4899,28 +4833,24 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // 1 is CREATEPROCESS_MANIFEST_RESOURCE_ID which is the default ID used for RT_MANIFEST resources // 24 is RT_MANIFEST const input = try std.fmt.allocPrint(arena, "1 24 \"{s}\"", .{fmtRcEscape(src_path)}); + try o_dir.writeFile(rc_basename, input); + + var argv = std.ArrayList([]const u8).init(comp.gpa); + defer argv.deinit(); + + try argv.appendSlice(&.{ + self_exe_path, + "rc", + "--zig-integration", + "/:no-preprocess", + "/x", // ignore INCLUDE environment variable + "/c65001", // UTF-8 codepage + "/:auto-includes", + "none", + }); + try argv.appendSlice(&.{ "--", in_rc_path, out_res_path }); - resinator.compile.compile(arena, input, output_buffered_stream.writer(), .{ - .cwd = std.fs.cwd(), - .diagnostics = &diagnostics, - .ignore_include_env_var = true, - .default_code_page = .utf8, - }) catch |err| switch (err) { - error.ParseError, error.CompileError => { - // Delete the output file on error - output_file.close(); - output_file_closed = true; - // Failing to delete is not really a big deal, so swallow any errors - o_dir.deleteFile(res_basename) catch { - const output_file_path = try comp.local_cache_directory.join(arena, &.{ o_sub_path, res_basename }); - log.warn("failed to delete '{s}': {s}", .{ output_file_path, @errorName(err) }); - }; - return comp.failWin32ResourceCompile(win32_resource, input, &diagnostics, null); - }, - else => |e| return e, - }; - - try output_buffered_stream.flush(); + try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node); break :blk digest; }; @@ -4951,9 +4881,6 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; const digest = if (try man.hit()) man.final() else blk: { - const rcpp_filename = try std.fmt.allocPrint(arena, "{s}.rcpp", .{rc_basename_noext}); - - const out_rcpp_path = try comp.tmpFilePath(arena, rcpp_filename); var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); defer zig_cache_tmp_dir.close(); @@ -4963,193 +4890,66 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 // so we need a temporary filename. const out_res_path = try comp.tmpFilePath(arena, res_filename); - var options = options: { - var resinator_args = try std.ArrayListUnmanaged([]const u8).initCapacity(comp.gpa, rc_src.extra_flags.len + 4); - defer resinator_args.deinit(comp.gpa); - - resinator_args.appendAssumeCapacity(""); // dummy 'process name' arg - resinator_args.appendSliceAssumeCapacity(rc_src.extra_flags); - resinator_args.appendSliceAssumeCapacity(&.{ "--", out_rcpp_path, out_res_path }); - - var cli_diagnostics = resinator.cli.Diagnostics.init(comp.gpa); - defer cli_diagnostics.deinit(); - const options = resinator.cli.parse(comp.gpa, resinator_args.items, &cli_diagnostics) catch |err| switch (err) { - error.ParseError => { - return comp.failWin32ResourceCli(win32_resource, &cli_diagnostics); - }, - else => |e| return e, - }; - break :options options; - }; - defer options.deinit(); - - // We never want to read the INCLUDE environment variable, so - // unconditionally set `ignore_include_env_var` to true - options.ignore_include_env_var = true; - - if (options.preprocess != .yes) { - return comp.failWin32Resource(win32_resource, "the '{s}' option is not supported in this context", .{switch (options.preprocess) { - .no => "/:no-preprocess", - .only => "/p", - .yes => unreachable, - }}); - } - var argv = std.ArrayList([]const u8).init(comp.gpa); defer argv.deinit(); - try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang" }); - - try resinator.preprocess.appendClangArgs(arena, &argv, options, .{ - .clang_target = null, // handled by addCCArgs - .system_include_paths = &.{}, // handled by addCCArgs - .needs_gnu_workaround = comp.getTarget().isGnu(), - .nostdinc = false, // handled by addCCArgs + const depfile_filename = try std.fmt.allocPrint(arena, "{s}.d.json", .{rc_basename_noext}); + const out_dep_path = try comp.tmpFilePath(arena, depfile_filename); + try argv.appendSlice(&.{ + self_exe_path, + "rc", + "--zig-integration", + "/:depfile", + out_dep_path, + "/:depfile-fmt", + "json", + "/x", // ignore INCLUDE environment variable + "/:auto-includes", + @tagName(comp.rc_includes), }); - - try argv.append(rc_src.src_path); - try argv.appendSlice(&[_][]const u8{ - "-o", - out_rcpp_path, - }); - - const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_rcpp_path}); - // Note: addCCArgs will implicitly add _DEBUG/NDEBUG depending on the optimization - // mode. While these defines are not normally present when calling rc.exe directly, + // While these defines are not normally present when calling rc.exe directly, // them being defined matches the behavior of how MSVC calls rc.exe which is the more // relevant behavior in this case. - try comp.addCCArgs(arena, &argv, .rc, out_dep_path, rc_src.owner); - - if (comp.verbose_cc) { - dump_argv(argv.items); + switch (rc_src.owner.optimize_mode) { + .Debug => try argv.append("-D_DEBUG"), + .ReleaseSafe => {}, + .ReleaseFast, .ReleaseSmall => try argv.append("-DNDEBUG"), } + try argv.appendSlice(rc_src.extra_flags); + try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path }); - if (std.process.can_spawn) { - var child = std.ChildProcess.init(argv.items, arena); - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Ignore; - child.stderr_behavior = .Pipe; - - try child.spawn(); - - const stderr_reader = child.stderr.?.reader(); - - const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); - - const term = child.wait() catch |err| { - return comp.failWin32Resource(win32_resource, "unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) }); - }; + try spawnZigRc(comp, win32_resource, src_basename, arena, argv.items, &child_progress_node); - switch (term) { - .Exited => |code| { - if (code != 0) { - // TODO parse clang stderr and turn it into an error message - // and then call failCObjWithOwnedErrorMsg - log.err("clang preprocessor failed with stderr:\n{s}", .{stderr}); - return comp.failWin32Resource(win32_resource, "clang preprocessor exited with code {d}", .{code}); - } - }, - else => { - log.err("clang preprocessor terminated with stderr:\n{s}", .{stderr}); - return comp.failWin32Resource(win32_resource, "clang preprocessor terminated unexpectedly", .{}); - }, - } - } else { - const exit_code = try clangMain(arena, argv.items); - if (exit_code != 0) { - return comp.failWin32Resource(win32_resource, "clang preprocessor exited with code {d}", .{exit_code}); - } - } - - const dep_basename = std.fs.path.basename(out_dep_path); - // Add the files depended on to the cache system. - try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); - switch (comp.cache_use) { - .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); - try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); - }, - .incremental => {}, - } - // Just to save disk space, we delete the file because it is never needed again. - zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { - log.warn("failed to delete '{s}': {s}", .{ out_dep_path, @errorName(err) }); - }; - - const full_input = std.fs.cwd().readFileAlloc(arena, out_rcpp_path, std.math.maxInt(usize)) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| { - return comp.failWin32Resource(win32_resource, "failed to read preprocessed file '{s}': {s}", .{ out_rcpp_path, @errorName(e) }); - }, - }; - - var mapping_results = try resinator.source_mapping.parseAndRemoveLineCommands(arena, full_input, full_input, .{ .initial_filename = rc_src.src_path }); - defer mapping_results.mappings.deinit(arena); - - const final_input = resinator.comments.removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings); - - var output_file = zig_cache_tmp_dir.createFile(out_res_path, .{}) catch |err| { - return comp.failWin32Resource(win32_resource, "failed to create output file '{s}': {s}", .{ out_res_path, @errorName(err) }); - }; - var output_file_closed = false; - defer if (!output_file_closed) output_file.close(); - - var diagnostics = resinator.errors.Diagnostics.init(arena); - defer diagnostics.deinit(); + // Read depfile and update cache manifest + { + const dep_basename = std.fs.path.basename(out_dep_path); + const dep_file_contents = try zig_cache_tmp_dir.readFileAlloc(arena, dep_basename, 50 * 1024 * 1024); + defer arena.free(dep_file_contents); - var dependencies_list = std.ArrayList([]const u8).init(comp.gpa); - defer { - for (dependencies_list.items) |item| { - comp.gpa.free(item); + const value = try std.json.parseFromSliceLeaky(std.json.Value, arena, dep_file_contents, .{}); + if (value != .array) { + return comp.failWin32Resource(win32_resource, "depfile from zig rc has unexpected format", .{}); } - dependencies_list.deinit(); - } - var output_buffered_stream = std.io.bufferedWriter(output_file.writer()); - - resinator.compile.compile(arena, final_input, output_buffered_stream.writer(), .{ - .cwd = std.fs.cwd(), - .diagnostics = &diagnostics, - .source_mappings = &mapping_results.mappings, - .dependencies_list = &dependencies_list, - .system_include_paths = comp.rc_include_dir_list, - .ignore_include_env_var = true, - // options - .extra_include_paths = options.extra_include_paths.items, - .default_language_id = options.default_language_id, - .default_code_page = options.default_code_page orelse .windows1252, - .verbose = options.verbose, - .null_terminate_string_table_strings = options.null_terminate_string_table_strings, - .max_string_literal_codepoints = options.max_string_literal_codepoints, - .silent_duplicate_control_ids = options.silent_duplicate_control_ids, - .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page, - }) catch |err| switch (err) { - error.ParseError, error.CompileError => { - // Delete the output file on error - output_file.close(); - output_file_closed = true; - // Failing to delete is not really a big deal, so swallow any errors - zig_cache_tmp_dir.deleteFile(out_res_path) catch { - log.warn("failed to delete '{s}': {s}", .{ out_res_path, @errorName(err) }); - }; - return comp.failWin32ResourceCompile(win32_resource, final_input, &diagnostics, mapping_results.mappings); - }, - else => |e| return e, - }; - - try output_buffered_stream.flush(); - - for (dependencies_list.items) |dep_file_path| { - try man.addFilePost(dep_file_path); - switch (comp.cache_use) { - .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); - try whole_cache_manifest.addFilePost(dep_file_path); - }, - .incremental => {}, + for (value.array.items) |element| { + if (element != .string) { + return comp.failWin32Resource(win32_resource, "depfile from zig rc has unexpected format", .{}); + } + const dep_file_path = element.string; + try man.addFilePost(dep_file_path); + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addFilePost(dep_file_path); + }, + .incremental => {}, + } } + // Just to save disk space, we delete the file because it is never needed again. + zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { + log.warn("failed to delete '{s}': {s}", .{ out_dep_path, @errorName(err) }); + }; } // Rename into place. @@ -5159,8 +4959,6 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 defer o_dir.close(); const tmp_basename = std.fs.path.basename(out_res_path); try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename); - const tmp_rcpp_basename = std.fs.path.basename(out_rcpp_path); - try std.fs.rename(zig_cache_tmp_dir, tmp_rcpp_basename, o_dir, rcpp_filename); break :blk digest; }; @@ -5186,6 +4984,106 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 }; } +fn spawnZigRc( + comp: *Compilation, + win32_resource: *Win32Resource, + src_basename: []const u8, + arena: Allocator, + argv: []const []const u8, + child_progress_node: *std.Progress.Node, +) !void { + var node_name: std.ArrayListUnmanaged(u8) = .{}; + defer node_name.deinit(arena); + + var child = std.ChildProcess.init(argv, arena); + child.stdin_behavior = .Ignore; + child.stdout_behavior = .Pipe; + child.stderr_behavior = .Pipe; + + child.spawn() catch |err| { + return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) }); + }; + + var poller = std.io.poll(comp.gpa, enum { stdout }, .{ + .stdout = child.stdout.?, + }); + defer poller.deinit(); + + const stdout = poller.fifo(.stdout); + + poll: while (true) { + while (stdout.readableLength() < @sizeOf(std.zig.Server.Message.Header)) { + if (!(try poller.poll())) break :poll; + } + const header = stdout.reader().readStruct(std.zig.Server.Message.Header) catch unreachable; + while (stdout.readableLength() < header.bytes_len) { + if (!(try poller.poll())) break :poll; + } + const body = stdout.readableSliceOfLen(header.bytes_len); + + switch (header.tag) { + // We expect exactly one ErrorBundle, and if any error_bundle header is + // sent then it's a fatal error. + .error_bundle => { + const EbHdr = std.zig.Server.Message.ErrorBundle; + const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); + const extra_bytes = + body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; + const string_bytes = + body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; + const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); + const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len); + @memcpy(extra_array, unaligned_extra); + const error_bundle = std.zig.ErrorBundle{ + .string_bytes = try comp.gpa.dupe(u8, string_bytes), + .extra = extra_array, + }; + return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle); + }, + .progress => { + node_name.clearRetainingCapacity(); + // <resinator> is a special string that indicates that the child + // process has reached resinator's main function + if (std.mem.eql(u8, body, "<resinator>")) { + child_progress_node.setName(src_basename); + } + // Ignore 0-length strings since if multiple zig rc commands + // are executed at the same time, only one will send progress strings + // while the other(s) will send empty strings. + else if (body.len > 0) { + try node_name.appendSlice(arena, "build 'zig rc'... "); + try node_name.appendSlice(arena, body); + child_progress_node.setName(node_name.items); + } + }, + else => {}, // ignore other messages + } + + stdout.discard(body.len); + } + + // Just in case there's a failure that didn't send an ErrorBundle (e.g. an error return trace) + const stderr_reader = child.stderr.?.reader(); + const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); + + const term = child.wait() catch |err| { + return comp.failWin32Resource(win32_resource, "unable to wait for {s} rc: {s}", .{ argv[0], @errorName(err) }); + }; + + switch (term) { + .Exited => |code| { + if (code != 0) { + log.err("zig rc failed with stderr:\n{s}", .{stderr}); + return comp.failWin32Resource(win32_resource, "zig rc exited with code {d}", .{code}); + } + }, + else => { + log.err("zig rc terminated with stderr:\n{s}", .{stderr}); + return comp.failWin32Resource(win32_resource, "zig rc terminated unexpectedly", .{}); + }, + } +} + pub fn tmpFilePath(comp: *Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 { const s = std.fs.path.sep_str; const rand_int = std.crypto.random.int(u64); @@ -5352,16 +5250,9 @@ pub fn addCCArgs( try argv.append("-isystem"); try argv.append(c_headers_dir); - if (ext == .rc) { - for (comp.rc_include_dir_list) |include_dir| { - try argv.append("-isystem"); - try argv.append(include_dir); - } - } else { - for (comp.libc_include_dir_list) |include_dir| { - try argv.append("-isystem"); - try argv.append(include_dir); - } + for (comp.libc_include_dir_list) |include_dir| { + try argv.append("-isystem"); + try argv.append(include_dir); } if (target.cpu.model.llvm_name) |llvm_name| { @@ -5726,167 +5617,6 @@ fn failWin32ResourceWithOwnedBundle( return error.AnalysisFail; } -fn failWin32ResourceCli( - comp: *Compilation, - win32_resource: *Win32Resource, - diagnostics: *resinator.cli.Diagnostics, -) SemaError { - @setCold(true); - - var bundle: ErrorBundle.Wip = undefined; - try bundle.init(comp.gpa); - errdefer bundle.deinit(); - - try bundle.addRootErrorMessage(.{ - .msg = try bundle.addString("invalid command line option(s)"), - .src_loc = try bundle.addSourceLocation(.{ - .src_path = try bundle.addString(switch (win32_resource.src) { - .rc => |rc_src| rc_src.src_path, - .manifest => |manifest_src| manifest_src, - }), - .line = 0, - .column = 0, - .span_start = 0, - .span_main = 0, - .span_end = 0, - }), - }); - - var cur_err: ?ErrorBundle.ErrorMessage = null; - var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .{}; - defer cur_notes.deinit(comp.gpa); - for (diagnostics.errors.items) |err_details| { - switch (err_details.type) { - .err => { - if (cur_err) |err| { - try win32ResourceFlushErrorMessage(&bundle, err, cur_notes.items); - } - cur_err = .{ - .msg = try bundle.addString(err_details.msg.items), - }; - cur_notes.clearRetainingCapacity(); - }, - .warning => cur_err = null, - .note => { - if (cur_err == null) continue; - cur_err.?.notes_len += 1; - try cur_notes.append(comp.gpa, .{ - .msg = try bundle.addString(err_details.msg.items), - }); - }, - } - } - if (cur_err) |err| { - try win32ResourceFlushErrorMessage(&bundle, err, cur_notes.items); - } - - const finished_bundle = try bundle.toOwnedBundle(""); - return comp.failWin32ResourceWithOwnedBundle(win32_resource, finished_bundle); -} - -fn failWin32ResourceCompile( - comp: *Compilation, - win32_resource: *Win32Resource, - source: []const u8, - diagnostics: *resinator.errors.Diagnostics, - opt_mappings: ?resinator.source_mapping.SourceMappings, -) SemaError { - @setCold(true); - - var bundle: ErrorBundle.Wip = undefined; - try bundle.init(comp.gpa); - errdefer bundle.deinit(); - - var msg_buf: std.ArrayListUnmanaged(u8) = .{}; - defer msg_buf.deinit(comp.gpa); - var cur_err: ?ErrorBundle.ErrorMessage = null; - var cur_notes: std.ArrayListUnmanaged(ErrorBundle.ErrorMessage) = .{}; - defer cur_notes.deinit(comp.gpa); - for (diagnostics.errors.items) |err_details| { - switch (err_details.type) { - .hint => continue, - // Clear the current error so that notes don't bleed into unassociated errors - .warning => { - cur_err = null; - continue; - }, - .note => if (cur_err == null) continue, - .err => {}, - } - const err_line, const err_filename = blk: { - if (opt_mappings) |mappings| { - const corresponding_span = mappings.get(err_details.token.line_number); - const corresponding_file = mappings.files.get(corresponding_span.filename_offset); - const err_line = corresponding_span.start_line; - break :blk .{ err_line, corresponding_file }; - } else { - break :blk .{ err_details.token.line_number, "<generated rc>" }; - } - }; - - const source_line_start = err_details.token.getLineStart(source); - const column = err_details.token.calculateColumn(source, 1, source_line_start); - - msg_buf.clearRetainingCapacity(); - try err_details.render(msg_buf.writer(comp.gpa), source, diagnostics.strings.items); - - const src_loc = src_loc: { - var src_loc: ErrorBundle.SourceLocation = .{ - .src_path = try bundle.addString(err_filename), - .line = @intCast(err_line - 1), // 1-based -> 0-based - .column = @intCast(column), - .span_start = 0, - .span_main = 0, - .span_end = 0, - }; - if (err_details.print_source_line) { - const source_line = err_details.token.getLine(source, source_line_start); - const visual_info = err_details.visualTokenInfo(source_line_start, source_line_start + source_line.len); - src_loc.span_start = @intCast(visual_info.point_offset - visual_info.before_len); - src_loc.span_main = @intCast(visual_info.point_offset); - src_loc.span_end = @intCast(visual_info.point_offset + 1 + visual_info.after_len); - src_loc.source_line = try bundle.addString(source_line); - } - break :src_loc try bundle.addSourceLocation(src_loc); - }; - - switch (err_details.type) { - .err => { - if (cur_err) |err| { - try win32ResourceFlushErrorMessage(&bundle, err, cur_notes.items); - } - cur_err = .{ - .msg = try bundle.addString(msg_buf.items), - .src_loc = src_loc, - }; - cur_notes.clearRetainingCapacity(); - }, - .note => { - cur_err.?.notes_len += 1; - try cur_notes.append(comp.gpa, .{ - .msg = try bundle.addString(msg_buf.items), - .src_loc = src_loc, - }); - }, - .warning, .hint => unreachable, - } - } - if (cur_err) |err| { - try win32ResourceFlushErrorMessage(&bundle, err, cur_notes.items); - } - - const finished_bundle = try bundle.toOwnedBundle(""); - return comp.failWin32ResourceWithOwnedBundle(win32_resource, finished_bundle); -} - -fn win32ResourceFlushErrorMessage(wip: *ErrorBundle.Wip, msg: ErrorBundle.ErrorMessage, notes: []const ErrorBundle.ErrorMessage) !void { - try wip.addRootErrorMessage(msg); - const notes_start = try wip.reserveNotes(@intCast(notes.len)); - for (notes_start.., notes) |i, note| { - wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note)); - } -} - pub const FileExt = enum { c, cpp, |
