| ... | @@ -1016,6 +1016,9 @@ pub const InitOptions = struct { | ... | @@ -1016,6 +1016,9 @@ pub const InitOptions = struct { |
| 1016 | /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols | 1016 | /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols |
| 1017 | dead_strip_dylibs: bool = false, | 1017 | dead_strip_dylibs: bool = false, |
| 1018 | libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default, | 1018 | libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default, |
| | 1019 | /// (Windows) PDB source path prefix to instruct the linker how to resolve relative |
| | 1020 | /// paths when consolidating CodeView streams into a single PDB file. |
| | 1021 | pdb_source_path: ?[]const u8 = null, |
| 1019 | }; | 1022 | }; |
| 1020 | | 1023 | |
| 1021 | fn addPackageTableToCacheHash( | 1024 | fn addPackageTableToCacheHash( |
| ... | @@ -1719,6 +1722,27 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1719,6 +1722,27 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1719 | }; | 1722 | }; |
| 1720 | }; | 1723 | }; |
| 1721 | | 1724 | |
| | 1725 | const pdb_source_path: ?[]const u8 = options.pdb_source_path orelse blk: { |
| | 1726 | if (builtin.target.os.tag == .windows) { |
| | 1727 | // PDB requires all file paths to be fully resolved, and it is really the |
| | 1728 | // linker's responsibility to canonicalize any path extracted from the CodeView |
| | 1729 | // in the object file. However, LLD-link has some very questionable defaults, and |
| | 1730 | // in particular, it purposely bakes in path separator of the host system it was |
| | 1731 | // built on rather than the targets, or just throw an error. Thankfully, they have |
| | 1732 | // left a backdoor we can use via -PDBSOURCEPATH. |
| | 1733 | const mod = module orelse break :blk null; |
| | 1734 | var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| | 1735 | const resolved_path = if (mod.main_pkg.root_src_directory.path) |base_path| p: { |
| | 1736 | if (std.fs.path.isAbsolute(base_path)) break :blk base_path; |
| | 1737 | const resolved_path = std.os.realpath(base_path, &buffer) catch break :blk null; |
| | 1738 | const pos = std.mem.lastIndexOfLinear(u8, resolved_path, base_path) orelse resolved_path.len; |
| | 1739 | break :p resolved_path[0..pos]; |
| | 1740 | } else std.os.realpath(".", &buffer) catch break :blk null; |
| | 1741 | break :blk try arena.dupe(u8, resolved_path); |
| | 1742 | } |
| | 1743 | break :blk null; |
| | 1744 | }; |
| | 1745 | |
| 1722 | const implib_emit: ?link.Emit = blk: { | 1746 | const implib_emit: ?link.Emit = blk: { |
| 1723 | const emit_implib = options.emit_implib orelse break :blk null; | 1747 | const emit_implib = options.emit_implib orelse break :blk null; |
| 1724 | | 1748 | |
| ... | @@ -1865,6 +1889,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { | ... | @@ -1865,6 +1889,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1865 | .headerpad_max_install_names = options.headerpad_max_install_names, | 1889 | .headerpad_max_install_names = options.headerpad_max_install_names, |
| 1866 | .dead_strip_dylibs = options.dead_strip_dylibs, | 1890 | .dead_strip_dylibs = options.dead_strip_dylibs, |
| 1867 | .force_undefined_symbols = .{}, | 1891 | .force_undefined_symbols = .{}, |
| | 1892 | .pdb_source_path = pdb_source_path, |
| 1868 | }); | 1893 | }); |
| 1869 | errdefer bin_file.destroy(); | 1894 | errdefer bin_file.destroy(); |
| 1870 | comp.* = .{ | 1895 | comp.* = .{ |