aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-11-10 16:52:43 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-11-10 16:52:43 +0100
commit04b8ce5fd32776cb5c8d34c424efd40cee86412a (patch)
treef74dd9c60e879caf8552459acd2b66b700171bd2 /src
parent4b3637820d0f43bc5b0e2c938b51ea1545b1c84e (diff)
parent1357790ec969bb6ee19ade6e8a348bd9d7cbbc4d (diff)
downloadzig-04b8ce5fd32776cb5c8d34c424efd40cee86412a.tar.gz
zig-04b8ce5fd32776cb5c8d34c424efd40cee86412a.zip
Merge branch 'jcmoyer-lld-explicit-pdb'
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig25
-rw-r--r--src/link.zig4
-rw-r--r--src/link/Coff/lld.zig11
3 files changed, 40 insertions, 0 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 7903586450..35be4e86cf 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1016,6 +1016,9 @@ pub const InitOptions = struct {
/// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
dead_strip_dylibs: bool = false,
libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,
+ /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
+ /// paths when consolidating CodeView streams into a single PDB file.
+ pdb_source_path: ?[]const u8 = null,
};
fn addPackageTableToCacheHash(
@@ -1719,6 +1722,27 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
};
};
+ const pdb_source_path: ?[]const u8 = options.pdb_source_path orelse blk: {
+ if (builtin.target.os.tag == .windows) {
+ // PDB requires all file paths to be fully resolved, and it is really the
+ // linker's responsibility to canonicalize any path extracted from the CodeView
+ // in the object file. However, LLD-link has some very questionable defaults, and
+ // in particular, it purposely bakes in path separator of the host system it was
+ // built on rather than the targets, or just throw an error. Thankfully, they have
+ // left a backdoor we can use via -PDBSOURCEPATH.
+ const mod = module orelse break :blk null;
+ var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+ const resolved_path = if (mod.main_pkg.root_src_directory.path) |base_path| p: {
+ if (std.fs.path.isAbsolute(base_path)) break :blk base_path;
+ const resolved_path = std.os.realpath(base_path, &buffer) catch break :blk null;
+ const pos = std.mem.lastIndexOfLinear(u8, resolved_path, base_path) orelse resolved_path.len;
+ break :p resolved_path[0..pos];
+ } else std.os.realpath(".", &buffer) catch break :blk null;
+ break :blk try arena.dupe(u8, resolved_path);
+ }
+ break :blk null;
+ };
+
const implib_emit: ?link.Emit = blk: {
const emit_implib = options.emit_implib orelse break :blk null;
@@ -1865,6 +1889,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.headerpad_max_install_names = options.headerpad_max_install_names,
.dead_strip_dylibs = options.dead_strip_dylibs,
.force_undefined_symbols = .{},
+ .pdb_source_path = pdb_source_path,
});
errdefer bin_file.destroy();
comp.* = .{
diff --git a/src/link.zig b/src/link.zig
index 3097e5cf1f..4dfcf171af 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -218,6 +218,10 @@ pub const Options = struct {
/// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
dead_strip_dylibs: bool = false,
+ /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
+ /// paths when consolidating CodeView streams into a single PDB file.
+ pdb_source_path: ?[]const u8 = null,
+
pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
return if (options.use_lld) .Obj else options.output_mode;
}
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig
index 7047d4fdba..00e6c4d8d1 100644
--- a/src/link/Coff/lld.zig
+++ b/src/link/Coff/lld.zig
@@ -181,6 +181,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
try argv.append("-NOLOGO");
if (!self.base.options.strip) {
try argv.append("-DEBUG");
+
+ const out_ext = std.fs.path.extension(full_out_path);
+ const out_pdb = try allocPrint(arena, "{s}.pdb", .{
+ full_out_path[0 .. full_out_path.len - out_ext.len],
+ });
+ try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
+ try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));
+
+ if (self.base.options.pdb_source_path) |path| {
+ try argv.append(try std.fmt.allocPrint(arena, "-PDBSOURCEPATH:{s}", .{path}));
+ }
}
if (self.base.options.lto) {
switch (self.base.options.optimize_mode) {