diff options
| author | Kurt Kartaltepe <kkartaltepe@gmail.com> | 2021-07-09 20:41:35 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-11-24 17:14:20 -0700 |
| commit | a950cb42bdf7b3f339071868c6675e7dcc892bae (patch) | |
| tree | ddf75e85213e2b1ea0d8accb78471b6d25d01b60 | |
| parent | fdcac5ecbd324170f7281f6704ead18b7d904e72 (diff) | |
| download | zig-a950cb42bdf7b3f339071868c6675e7dcc892bae.tar.gz zig-a950cb42bdf7b3f339071868c6675e7dcc892bae.zip | |
Coff linker: Add IMPLIB support
Allow --out-implib and -implib as passed by cmake and meson to be
correctly passed through to the linker to generate import libraries.
| -rw-r--r-- | src/Compilation.zig | 6 | ||||
| -rw-r--r-- | src/link.zig | 1 | ||||
| -rw-r--r-- | src/link/Coff.zig | 5 | ||||
| -rw-r--r-- | src/main.zig | 29 |
4 files changed, 40 insertions, 1 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 48899f6f6e..61533eebb0 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -767,6 +767,8 @@ pub const InitOptions = struct { test_filter: ?[]const u8 = null, test_name_prefix: ?[]const u8 = null, subsystem: ?std.Target.SubSystem = null, + /// Windows/PE only. Where to output the import library, can contain directories. + out_implib: ?[]const u8 = null, /// WASI-only. Type of WASI execution model ("command" or "reactor"). wasi_exec_model: ?std.builtin.WasiExecModel = null, /// (Zig compiler development) Enable dumping linker's state as JSON. @@ -946,7 +948,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { options.output_mode == .Lib or options.lld_argv.len != 0 or options.image_base_override != null or - options.linker_script != null or options.version_script != null) + options.linker_script != null or options.version_script != null or + options.out_implib != null) { break :blk true; } @@ -1461,6 +1464,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, .disable_lld_caching = options.disable_lld_caching, .subsystem = options.subsystem, + .out_implib = options.out_implib, .is_test = options.is_test, .wasi_exec_model = wasi_exec_model, .use_stage1 = use_stage1, diff --git a/src/link.zig b/src/link.zig index 4ad5952767..76f50a78fe 100644 --- a/src/link.zig +++ b/src/link.zig @@ -127,6 +127,7 @@ pub const Options = struct { gc_sections: ?bool = null, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, + out_implib: ?[]const u8, linker_script: ?[]const u8, version_script: ?[]const u8, soname: ?[]const u8, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index b6f3279779..ee59f4f034 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -948,6 +948,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { man.hash.add(self.base.options.dynamicbase); man.hash.addOptional(self.base.options.major_subsystem_version); man.hash.addOptional(self.base.options.minor_subsystem_version); + man.hash.addOptionalBytes(self.base.options.out_implib); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try man.hit(); @@ -1094,6 +1095,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { try argv.append(p); } + if (self.base.options.out_implib != null) { + try argv.append(try allocPrint(arena, "-IMPLIB:{s}.lib", .{full_out_path})); + } + const resolved_subsystem: ?std.Target.SubSystem = blk: { if (self.base.options.subsystem) |explicit| break :blk explicit; switch (target.os.tag) { diff --git a/src/main.zig b/src/main.zig index 0b274b3aee..4900743677 100644 --- a/src/main.zig +++ b/src/main.zig @@ -654,6 +654,7 @@ fn buildOutputType( var main_pkg_path: ?[]const u8 = null; var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; + var out_implib: ?[]const u8 = null; var major_subsystem_version: ?u32 = null; var minor_subsystem_version: ?u32 = null; var wasi_exec_model: ?std.builtin.WasiExecModel = null; @@ -1637,6 +1638,14 @@ fn buildOutputType( fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); }; have_version = true; + } else if (mem.eql(u8, arg, "--out-implib") or + mem.eql(u8, arg, "-implib")) + { + i += 1; + if (i >= linker_args.items.len) { + fatal("expected linker arg after '{s}'", .{arg}); + } + out_implib = linker_args.items[i]; } else { warn("unsupported linker arg: {s}", .{arg}); } @@ -2154,6 +2163,16 @@ fn buildOutputType( else => false, }; + // Always output import libraries (.lib) when building for msvc to replicate + // `link` behavior. lld does not always output import libraries so on the + // gnu abi users must set out_implib. + if (output_mode == .Lib and emit_bin == .yes and target_info.target.abi == .msvc and out_implib == null) { + const emit_bin_ext = fs.path.extension(emit_bin.yes); + out_implib = try std.fmt.allocPrint(gpa, "{s}.lib", .{ + emit_bin.yes[0 .. emit_bin.yes.len - emit_bin_ext.len], + }); + } + gimmeMoreOfThoseSweetSweetFileDescriptors(); const comp = Compilation.create(gpa, .{ @@ -2263,6 +2282,7 @@ fn buildOutputType( .test_name_prefix = test_name_prefix, .disable_lld_caching = !have_enable_cache, .subsystem = subsystem, + .out_implib = out_implib, .wasi_exec_model = wasi_exec_model, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, @@ -2661,6 +2681,15 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !voi _ = try cache_dir.updateFile(src_pdb_path, cwd, dst_pdb_path, .{}); } + + if (comp.bin_file.options.out_implib) |out_implib| { + const src_implib_path = try std.fmt.allocPrint(gpa, "{s}.lib", .{bin_sub_path}); + defer gpa.free(src_implib_path); + if (std.fs.path.dirname(out_implib)) |implib_dir| { + try cwd.makePath(implib_dir); + } + _ = try cache_dir.updateFile(src_implib_path, cwd, out_implib, .{}); + } }, } } |
