| ... | @@ -358,7 +358,10 @@ pub const CObject = struct { | ... | @@ -358,7 +358,10 @@ pub const CObject = struct { |
| 358 | | 358 | |
| 359 | pub const Win32Resource = struct { | 359 | pub const Win32Resource = struct { |
| 360 | /// Relative to cwd. Owned by arena. | 360 | /// Relative to cwd. Owned by arena. |
| 361 | src: RcSourceFile, | 361 | src: union(enum) { |
| | 362 | rc: RcSourceFile, |
| | 363 | manifest: []const u8, |
| | 364 | }, |
| 362 | status: union(enum) { | 365 | status: union(enum) { |
| 363 | new, | 366 | new, |
| 364 | success: struct { | 367 | success: struct { |
| ... | @@ -582,6 +585,7 @@ pub const InitOptions = struct { | ... | @@ -582,6 +585,7 @@ pub const InitOptions = struct { |
| 582 | symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}, | 585 | symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{}, |
| 583 | c_source_files: []const CSourceFile = &[0]CSourceFile{}, | 586 | c_source_files: []const CSourceFile = &[0]CSourceFile{}, |
| 584 | rc_source_files: []const RcSourceFile = &[0]RcSourceFile{}, | 587 | rc_source_files: []const RcSourceFile = &[0]RcSourceFile{}, |
| | 588 | manifest_file: ?[]const u8 = null, |
| 585 | rc_includes: RcIncludes = .any, | 589 | rc_includes: RcIncludes = .any, |
| 586 | link_objects: []LinkObject = &[0]LinkObject{}, | 590 | link_objects: []LinkObject = &[0]LinkObject{}, |
| 587 | framework_dirs: []const []const u8 = &[0][]const u8{}, | 591 | framework_dirs: []const []const u8 = &[0][]const u8{}, |
| ... | @@ -1749,16 +1753,26 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1749,16 +1753,26 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1749 | comp.c_object_table.putAssumeCapacityNoClobber(c_object, {}); | 1753 | comp.c_object_table.putAssumeCapacityNoClobber(c_object, {}); |
| 1750 | } | 1754 | } |
| 1751 | | 1755 | |
| 1752 | // Add a `Win32Resource` for each `rc_source_files`. | 1756 | // Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`. |
| 1753 | if (!build_options.only_core_functionality) { | 1757 | if (!build_options.only_core_functionality) { |
| 1754 | try comp.win32_resource_table.ensureTotalCapacity(gpa, options.rc_source_files.len); | 1758 | try comp.win32_resource_table.ensureTotalCapacity(gpa, options.rc_source_files.len + @intFromBool(options.manifest_file != null)); |
| 1755 | for (options.rc_source_files) |rc_source_file| { | 1759 | for (options.rc_source_files) |rc_source_file| { |
| 1756 | const win32_resource = try gpa.create(Win32Resource); | 1760 | const win32_resource = try gpa.create(Win32Resource); |
| 1757 | errdefer gpa.destroy(win32_resource); | 1761 | errdefer gpa.destroy(win32_resource); |
| 1758 | | 1762 | |
| 1759 | win32_resource.* = .{ | 1763 | win32_resource.* = .{ |
| 1760 | .status = .{ .new = {} }, | 1764 | .status = .{ .new = {} }, |
| 1761 | .src = rc_source_file, | 1765 | .src = .{ .rc = rc_source_file }, |
| | 1766 | }; |
| | 1767 | comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {}); |
| | 1768 | } |
| | 1769 | if (options.manifest_file) |manifest_path| { |
| | 1770 | const win32_resource = try gpa.create(Win32Resource); |
| | 1771 | errdefer gpa.destroy(win32_resource); |
| | 1772 | |
| | 1773 | win32_resource.* = .{ |
| | 1774 | .status = .{ .new = {} }, |
| | 1775 | .src = .{ .manifest = manifest_path }, |
| 1762 | }; | 1776 | }; |
| 1763 | comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {}); | 1777 | comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {}); |
| 1764 | } | 1778 | } |
| ... | @@ -2477,8 +2491,15 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes | ... | @@ -2477,8 +2491,15 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes |
| 2477 | | 2491 | |
| 2478 | if (!build_options.only_core_functionality) { | 2492 | if (!build_options.only_core_functionality) { |
| 2479 | for (comp.win32_resource_table.keys()) |key| { | 2493 | for (comp.win32_resource_table.keys()) |key| { |
| 2480 | _ = try man.addFile(key.src.src_path, null); | 2494 | switch (key.src) { |
| 2481 | man.hash.addListOfBytes(key.src.extra_flags); | 2495 | .rc => |rc_src| { |
| | 2496 | _ = try man.addFile(rc_src.src_path, null); |
| | 2497 | man.hash.addListOfBytes(rc_src.extra_flags); |
| | 2498 | }, |
| | 2499 | .manifest => |manifest_path| { |
| | 2500 | _ = try man.addFile(manifest_path, null); |
| | 2501 | }, |
| | 2502 | } |
| 2482 | } | 2503 | } |
| 2483 | } | 2504 | } |
| 2484 | | 2505 | |
| ... | @@ -4172,7 +4193,10 @@ fn reportRetryableWin32ResourceError( | ... | @@ -4172,7 +4193,10 @@ fn reportRetryableWin32ResourceError( |
| 4172 | try bundle.addRootErrorMessage(.{ | 4193 | try bundle.addRootErrorMessage(.{ |
| 4173 | .msg = try bundle.printString("{s}", .{@errorName(err)}), | 4194 | .msg = try bundle.printString("{s}", .{@errorName(err)}), |
| 4174 | .src_loc = try bundle.addSourceLocation(.{ | 4195 | .src_loc = try bundle.addSourceLocation(.{ |
| 4175 | .src_path = try bundle.addString(win32_resource.src.src_path), | 4196 | .src_path = try bundle.addString(switch (win32_resource.src) { |
| | 4197 | .rc => |rc_src| rc_src.src_path, |
| | 4198 | .manifest => |manifest_src| manifest_src, |
| | 4199 | }), |
| 4176 | .line = 0, | 4200 | .line = 0, |
| 4177 | .column = 0, | 4201 | .column = 0, |
| 4178 | .span_start = 0, | 4202 | .span_start = 0, |
| ... | @@ -4542,7 +4566,17 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4542,7 +4566,17 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4542 | const tracy_trace = trace(@src()); | 4566 | const tracy_trace = trace(@src()); |
| 4543 | defer tracy_trace.end(); | 4567 | defer tracy_trace.end(); |
| 4544 | | 4568 | |
| 4545 | log.debug("updating win32 resource: {s}", .{win32_resource.src.src_path}); | 4569 | const src_path = switch (win32_resource.src) { |
| | 4570 | .rc => |rc_src| rc_src.src_path, |
| | 4571 | .manifest => |src_path| src_path, |
| | 4572 | }; |
| | 4573 | const src_basename = std.fs.path.basename(src_path); |
| | 4574 | |
| | 4575 | log.debug("updating win32 resource: {s}", .{src_path}); |
| | 4576 | |
| | 4577 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); |
| | 4578 | defer arena_allocator.deinit(); |
| | 4579 | const arena = arena_allocator.allocator(); |
| 4546 | | 4580 | |
| 4547 | if (win32_resource.clearStatus(comp.gpa)) { | 4581 | if (win32_resource.clearStatus(comp.gpa)) { |
| 4548 | // There was previous failure. | 4582 | // There was previous failure. |
| ... | @@ -4553,24 +4587,113 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4553,24 +4587,113 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4553 | _ = comp.failed_win32_resources.swapRemove(win32_resource); | 4587 | _ = comp.failed_win32_resources.swapRemove(win32_resource); |
| 4554 | } | 4588 | } |
| 4555 | | 4589 | |
| | 4590 | win32_resource_prog_node.activate(); |
| | 4591 | var child_progress_node = win32_resource_prog_node.start(src_basename, 0); |
| | 4592 | child_progress_node.activate(); |
| | 4593 | defer child_progress_node.end(); |
| | 4594 | |
| 4556 | var man = comp.obtainWin32ResourceCacheManifest(); | 4595 | var man = comp.obtainWin32ResourceCacheManifest(); |
| 4557 | defer man.deinit(); | 4596 | defer man.deinit(); |
| 4558 | | 4597 | |
| 4559 | _ = try man.addFile(win32_resource.src.src_path, null); | 4598 | // For .manifest files, we ultimately just want to generate a .res with |
| 4560 | man.hash.addListOfBytes(win32_resource.src.extra_flags); | 4599 | // the XML data as a RT_MANIFEST resource. This means we can skip preprocessing, |
| | 4600 | // include paths, CLI options, etc. |
| | 4601 | if (win32_resource.src == .manifest) { |
| | 4602 | _ = try man.addFile(src_path, null); |
| 4561 | | 4603 | |
| 4562 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | 4604 | const res_basename = try std.fmt.allocPrint(arena, "{s}.res", .{src_basename}); |
| 4563 | defer arena_allocator.deinit(); | | |
| 4564 | const arena = arena_allocator.allocator(); | | |
| 4565 | | 4605 | |
| 4566 | const rc_basename = std.fs.path.basename(win32_resource.src.src_path); | 4606 | const digest = if (try man.hit()) man.final() else blk: { |
| | 4607 | // The digest only depends on the .manifest file, so we can |
| | 4608 | // get the digest now and write the .res directly to the cache |
| | 4609 | const digest = man.final(); |
| 4567 | | 4610 | |
| 4568 | win32_resource_prog_node.activate(); | 4611 | const o_sub_path = try std.fs.path.join(arena, &.{ "o", &digest }); |
| 4569 | var child_progress_node = win32_resource_prog_node.start(rc_basename, 0); | 4612 | var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{}); |
| 4570 | child_progress_node.activate(); | 4613 | defer o_dir.close(); |
| 4571 | defer child_progress_node.end(); | | |
| 4572 | | 4614 | |
| 4573 | const rc_basename_noext = rc_basename[0 .. rc_basename.len - std.fs.path.extension(rc_basename).len]; | 4615 | var output_file = o_dir.createFile(res_basename, .{}) catch |err| { |
| | 4616 | const output_file_path = try comp.local_cache_directory.join(arena, &.{ o_sub_path, res_basename }); |
| | 4617 | return comp.failWin32Resource(win32_resource, "failed to create output file '{s}': {s}", .{ output_file_path, @errorName(err) }); |
| | 4618 | }; |
| | 4619 | var output_file_closed = false; |
| | 4620 | defer if (!output_file_closed) output_file.close(); |
| | 4621 | |
| | 4622 | var diagnostics = resinator.errors.Diagnostics.init(arena); |
| | 4623 | defer diagnostics.deinit(); |
| | 4624 | |
| | 4625 | var output_buffered_stream = std.io.bufferedWriter(output_file.writer()); |
| | 4626 | |
| | 4627 | // In .rc files, a " within a quoted string is escaped as "" |
| | 4628 | const fmtRcEscape = struct { |
| | 4629 | fn formatRcEscape(bytes: []const u8, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| | 4630 | _ = fmt; |
| | 4631 | _ = options; |
| | 4632 | for (bytes) |byte| switch (byte) { |
| | 4633 | '"' => try writer.writeAll("\"\""), |
| | 4634 | '\\' => try writer.writeAll("\\\\"), |
| | 4635 | else => try writer.writeByte(byte), |
| | 4636 | }; |
| | 4637 | } |
| | 4638 | |
| | 4639 | pub fn fmtRcEscape(bytes: []const u8) std.fmt.Formatter(formatRcEscape) { |
| | 4640 | return .{ .data = bytes }; |
| | 4641 | } |
| | 4642 | }.fmtRcEscape; |
| | 4643 | |
| | 4644 | // 1 is CREATEPROCESS_MANIFEST_RESOURCE_ID which is the default ID used for RT_MANIFEST resources |
| | 4645 | // 24 is RT_MANIFEST |
| | 4646 | const input = try std.fmt.allocPrint(arena, "1 24 \"{s}\"", .{fmtRcEscape(src_path)}); |
| | 4647 | |
| | 4648 | resinator.compile.compile(arena, input, output_buffered_stream.writer(), .{ |
| | 4649 | .cwd = std.fs.cwd(), |
| | 4650 | .diagnostics = &diagnostics, |
| | 4651 | .ignore_include_env_var = true, |
| | 4652 | .default_code_page = .utf8, |
| | 4653 | }) catch |err| switch (err) { |
| | 4654 | error.ParseError, error.CompileError => { |
| | 4655 | // Delete the output file on error |
| | 4656 | output_file.close(); |
| | 4657 | output_file_closed = true; |
| | 4658 | // Failing to delete is not really a big deal, so swallow any errors |
| | 4659 | o_dir.deleteFile(res_basename) catch { |
| | 4660 | const output_file_path = try comp.local_cache_directory.join(arena, &.{ o_sub_path, res_basename }); |
| | 4661 | log.warn("failed to delete '{s}': {s}", .{ output_file_path, @errorName(err) }); |
| | 4662 | }; |
| | 4663 | return comp.failWin32ResourceCompile(win32_resource, input, &diagnostics, null); |
| | 4664 | }, |
| | 4665 | else => |e| return e, |
| | 4666 | }; |
| | 4667 | |
| | 4668 | try output_buffered_stream.flush(); |
| | 4669 | |
| | 4670 | break :blk digest; |
| | 4671 | }; |
| | 4672 | |
| | 4673 | if (man.have_exclusive_lock) { |
| | 4674 | man.writeManifest() catch |err| { |
| | 4675 | log.warn("failed to write cache manifest when compiling '{s}': {s}", .{ src_path, @errorName(err) }); |
| | 4676 | }; |
| | 4677 | } |
| | 4678 | |
| | 4679 | win32_resource.status = .{ |
| | 4680 | .success = .{ |
| | 4681 | .res_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ |
| | 4682 | "o", &digest, res_basename, |
| | 4683 | }), |
| | 4684 | .lock = man.toOwnedLock(), |
| | 4685 | }, |
| | 4686 | }; |
| | 4687 | return; |
| | 4688 | } |
| | 4689 | |
| | 4690 | // We now know that we're compiling an .rc file |
| | 4691 | const rc_src = win32_resource.src.rc; |
| | 4692 | |
| | 4693 | _ = try man.addFile(rc_src.src_path, null); |
| | 4694 | man.hash.addListOfBytes(rc_src.extra_flags); |
| | 4695 | |
| | 4696 | const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; |
| 4574 | | 4697 | |
| 4575 | const digest = if (try man.hit()) man.final() else blk: { | 4698 | const digest = if (try man.hit()) man.final() else blk: { |
| 4576 | const rcpp_filename = try std.fmt.allocPrint(arena, "{s}.rcpp", .{rc_basename_noext}); | 4699 | const rcpp_filename = try std.fmt.allocPrint(arena, "{s}.rcpp", .{rc_basename_noext}); |
| ... | @@ -4586,11 +4709,11 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4586,11 +4709,11 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4586 | const out_res_path = try comp.tmpFilePath(arena, res_filename); | 4709 | const out_res_path = try comp.tmpFilePath(arena, res_filename); |
| 4587 | | 4710 | |
| 4588 | var options = options: { | 4711 | var options = options: { |
| 4589 | var resinator_args = try std.ArrayListUnmanaged([]const u8).initCapacity(comp.gpa, win32_resource.src.extra_flags.len + 4); | 4712 | var resinator_args = try std.ArrayListUnmanaged([]const u8).initCapacity(comp.gpa, rc_src.extra_flags.len + 4); |
| 4590 | defer resinator_args.deinit(comp.gpa); | 4713 | defer resinator_args.deinit(comp.gpa); |
| 4591 | | 4714 | |
| 4592 | resinator_args.appendAssumeCapacity(""); // dummy 'process name' arg | 4715 | resinator_args.appendAssumeCapacity(""); // dummy 'process name' arg |
| 4593 | resinator_args.appendSliceAssumeCapacity(win32_resource.src.extra_flags); | 4716 | resinator_args.appendSliceAssumeCapacity(rc_src.extra_flags); |
| 4594 | resinator_args.appendSliceAssumeCapacity(&.{ "--", out_rcpp_path, out_res_path }); | 4717 | resinator_args.appendSliceAssumeCapacity(&.{ "--", out_rcpp_path, out_res_path }); |
| 4595 | | 4718 | |
| 4596 | var cli_diagnostics = resinator.cli.Diagnostics.init(comp.gpa); | 4719 | var cli_diagnostics = resinator.cli.Diagnostics.init(comp.gpa); |
| ... | @@ -4619,7 +4742,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4619,7 +4742,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4619 | .nostdinc = false, // handled by addCCArgs | 4742 | .nostdinc = false, // handled by addCCArgs |
| 4620 | }); | 4743 | }); |
| 4621 | | 4744 | |
| 4622 | try argv.append(win32_resource.src.src_path); | 4745 | try argv.append(rc_src.src_path); |
| 4623 | try argv.appendSlice(&[_][]const u8{ | 4746 | try argv.appendSlice(&[_][]const u8{ |
| 4624 | "-o", | 4747 | "-o", |
| 4625 | out_rcpp_path, | 4748 | out_rcpp_path, |
| ... | @@ -4693,7 +4816,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4693,7 +4816,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4693 | }, | 4816 | }, |
| 4694 | }; | 4817 | }; |
| 4695 | | 4818 | |
| 4696 | var mapping_results = try resinator.source_mapping.parseAndRemoveLineCommands(arena, full_input, full_input, .{ .initial_filename = win32_resource.src.src_path }); | 4819 | var mapping_results = try resinator.source_mapping.parseAndRemoveLineCommands(arena, full_input, full_input, .{ .initial_filename = rc_src.src_path }); |
| 4697 | defer mapping_results.mappings.deinit(arena); | 4820 | defer mapping_results.mappings.deinit(arena); |
| 4698 | | 4821 | |
| 4699 | var final_input = resinator.comments.removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings); | 4822 | var final_input = resinator.comments.removeComments(mapping_results.result, mapping_results.result, &mapping_results.mappings); |
| ... | @@ -4776,7 +4899,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 | ... | @@ -4776,7 +4899,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 4776 | // the contents were the same, we hit the cache but the manifest is dirty and we need to update | 4899 | // the contents were the same, we hit the cache but the manifest is dirty and we need to update |
| 4777 | // it to prevent doing a full file content comparison the next time around. | 4900 | // it to prevent doing a full file content comparison the next time around. |
| 4778 | man.writeManifest() catch |err| { | 4901 | man.writeManifest() catch |err| { |
| 4779 | log.warn("failed to write cache manifest when compiling '{s}': {s}", .{ win32_resource.src.src_path, @errorName(err) }); | 4902 | log.warn("failed to write cache manifest when compiling '{s}': {s}", .{ rc_src.src_path, @errorName(err) }); |
| 4780 | }; | 4903 | }; |
| 4781 | } | 4904 | } |
| 4782 | | 4905 | |
| ... | @@ -5114,7 +5237,7 @@ pub fn addCCArgs( | ... | @@ -5114,7 +5237,7 @@ pub fn addCCArgs( |
| 5114 | try argv.append("-fno-unwind-tables"); | 5237 | try argv.append("-fno-unwind-tables"); |
| 5115 | } | 5238 | } |
| 5116 | }, | 5239 | }, |
| 5117 | .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res => {}, | 5240 | .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {}, |
| 5118 | .assembly, .assembly_with_cpp => { | 5241 | .assembly, .assembly_with_cpp => { |
| 5119 | if (ext == .assembly_with_cpp) { | 5242 | if (ext == .assembly_with_cpp) { |
| 5120 | const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" }); | 5243 | const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" }); |
| ... | @@ -5340,7 +5463,10 @@ fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptim | ... | @@ -5340,7 +5463,10 @@ fn failWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, comptim |
| 5340 | try bundle.addRootErrorMessage(.{ | 5463 | try bundle.addRootErrorMessage(.{ |
| 5341 | .msg = try bundle.printString(format, args), | 5464 | .msg = try bundle.printString(format, args), |
| 5342 | .src_loc = try bundle.addSourceLocation(.{ | 5465 | .src_loc = try bundle.addSourceLocation(.{ |
| 5343 | .src_path = try bundle.addString(win32_resource.src.src_path), | 5466 | .src_path = try bundle.addString(switch (win32_resource.src) { |
| | 5467 | .rc => |rc_src| rc_src.src_path, |
| | 5468 | .manifest => |manifest_src| manifest_src, |
| | 5469 | }), |
| 5344 | .line = 0, | 5470 | .line = 0, |
| 5345 | .column = 0, | 5471 | .column = 0, |
| 5346 | .span_start = 0, | 5472 | .span_start = 0, |
| ... | @@ -5381,7 +5507,10 @@ fn failWin32ResourceCli( | ... | @@ -5381,7 +5507,10 @@ fn failWin32ResourceCli( |
| 5381 | try bundle.addRootErrorMessage(.{ | 5507 | try bundle.addRootErrorMessage(.{ |
| 5382 | .msg = try bundle.addString("invalid command line option(s)"), | 5508 | .msg = try bundle.addString("invalid command line option(s)"), |
| 5383 | .src_loc = try bundle.addSourceLocation(.{ | 5509 | .src_loc = try bundle.addSourceLocation(.{ |
| 5384 | .src_path = try bundle.addString(win32_resource.src.src_path), | 5510 | .src_path = try bundle.addString(switch (win32_resource.src) { |
| | 5511 | .rc => |rc_src| rc_src.src_path, |
| | 5512 | .manifest => |manifest_src| manifest_src, |
| | 5513 | }), |
| 5385 | .line = 0, | 5514 | .line = 0, |
| 5386 | .column = 0, | 5515 | .column = 0, |
| 5387 | .span_start = 0, | 5516 | .span_start = 0, |
| ... | @@ -5427,7 +5556,7 @@ fn failWin32ResourceCompile( | ... | @@ -5427,7 +5556,7 @@ fn failWin32ResourceCompile( |
| 5427 | win32_resource: *Win32Resource, | 5556 | win32_resource: *Win32Resource, |
| 5428 | source: []const u8, | 5557 | source: []const u8, |
| 5429 | diagnostics: *resinator.errors.Diagnostics, | 5558 | diagnostics: *resinator.errors.Diagnostics, |
| 5430 | mappings: resinator.source_mapping.SourceMappings, | 5559 | opt_mappings: ?resinator.source_mapping.SourceMappings, |
| 5431 | ) SemaError { | 5560 | ) SemaError { |
| 5432 | @setCold(true); | 5561 | @setCold(true); |
| 5433 | | 5562 | |
| ... | @@ -5451,19 +5580,26 @@ fn failWin32ResourceCompile( | ... | @@ -5451,19 +5580,26 @@ fn failWin32ResourceCompile( |
| 5451 | .note => if (cur_err == null) continue, | 5580 | .note => if (cur_err == null) continue, |
| 5452 | .err => {}, | 5581 | .err => {}, |
| 5453 | } | 5582 | } |
| 5454 | const corresponding_span = mappings.get(err_details.token.line_number); | 5583 | const err_line, const err_filename = blk: { |
| 5455 | const corresponding_file = mappings.files.get(corresponding_span.filename_offset); | 5584 | if (opt_mappings) |mappings| { |
| | 5585 | const corresponding_span = mappings.get(err_details.token.line_number); |
| | 5586 | const corresponding_file = mappings.files.get(corresponding_span.filename_offset); |
| | 5587 | const err_line = corresponding_span.start_line; |
| | 5588 | break :blk .{ err_line, corresponding_file }; |
| | 5589 | } else { |
| | 5590 | break :blk .{ err_details.token.line_number, "<generated rc>" }; |
| | 5591 | } |
| | 5592 | }; |
| 5456 | | 5593 | |
| 5457 | const source_line_start = err_details.token.getLineStart(source); | 5594 | const source_line_start = err_details.token.getLineStart(source); |
| 5458 | const column = err_details.token.calculateColumn(source, 1, source_line_start); | 5595 | const column = err_details.token.calculateColumn(source, 1, source_line_start); |
| 5459 | const err_line = corresponding_span.start_line; | | |
| 5460 | | 5596 | |
| 5461 | msg_buf.clearRetainingCapacity(); | 5597 | msg_buf.clearRetainingCapacity(); |
| 5462 | try err_details.render(msg_buf.writer(comp.gpa), source, diagnostics.strings.items); | 5598 | try err_details.render(msg_buf.writer(comp.gpa), source, diagnostics.strings.items); |
| 5463 | | 5599 | |
| 5464 | const src_loc = src_loc: { | 5600 | const src_loc = src_loc: { |
| 5465 | var src_loc: ErrorBundle.SourceLocation = .{ | 5601 | var src_loc: ErrorBundle.SourceLocation = .{ |
| 5466 | .src_path = try bundle.addString(corresponding_file), | 5602 | .src_path = try bundle.addString(err_filename), |
| 5467 | .line = @intCast(err_line - 1), // 1-based -> 0-based | 5603 | .line = @intCast(err_line - 1), // 1-based -> 0-based |
| 5468 | .column = @intCast(column), | 5604 | .column = @intCast(column), |
| 5469 | .span_start = 0, | 5605 | .span_start = 0, |
| ... | @@ -5536,6 +5672,7 @@ pub const FileExt = enum { | ... | @@ -5536,6 +5672,7 @@ pub const FileExt = enum { |
| 5536 | def, | 5672 | def, |
| 5537 | rc, | 5673 | rc, |
| 5538 | res, | 5674 | res, |
| | 5675 | manifest, |
| 5539 | unknown, | 5676 | unknown, |
| 5540 | | 5677 | |
| 5541 | pub fn clangSupportsDepFile(ext: FileExt) bool { | 5678 | pub fn clangSupportsDepFile(ext: FileExt) bool { |
| ... | @@ -5553,6 +5690,7 @@ pub const FileExt = enum { | ... | @@ -5553,6 +5690,7 @@ pub const FileExt = enum { |
| 5553 | .def, | 5690 | .def, |
| 5554 | .rc, | 5691 | .rc, |
| 5555 | .res, | 5692 | .res, |
| | 5693 | .manifest, |
| 5556 | .unknown, | 5694 | .unknown, |
| 5557 | => false, | 5695 | => false, |
| 5558 | }; | 5696 | }; |
| ... | @@ -5577,6 +5715,7 @@ pub const FileExt = enum { | ... | @@ -5577,6 +5715,7 @@ pub const FileExt = enum { |
| 5577 | .def => ".def", | 5715 | .def => ".def", |
| 5578 | .rc => ".rc", | 5716 | .rc => ".rc", |
| 5579 | .res => ".res", | 5717 | .res => ".res", |
| | 5718 | .manifest => ".manifest", |
| 5580 | .unknown => "", | 5719 | .unknown => "", |
| 5581 | }; | 5720 | }; |
| 5582 | } | 5721 | } |
| ... | @@ -5672,6 +5811,8 @@ pub fn classifyFileExt(filename: []const u8) FileExt { | ... | @@ -5672,6 +5811,8 @@ pub fn classifyFileExt(filename: []const u8) FileExt { |
| 5672 | return .rc; | 5811 | return .rc; |
| 5673 | } else if (std.ascii.endsWithIgnoreCase(filename, ".res")) { | 5812 | } else if (std.ascii.endsWithIgnoreCase(filename, ".res")) { |
| 5674 | return .res; | 5813 | return .res; |
| | 5814 | } else if (std.ascii.endsWithIgnoreCase(filename, ".manifest")) { |
| | 5815 | return .manifest; |
| 5675 | } else { | 5816 | } else { |
| 5676 | return .unknown; | 5817 | return .unknown; |
| 5677 | } | 5818 | } |