| author | |
| committer | |
| log | a950cb42bdf7b3f339071868c6675e7dcc892bae |
| tree | ddf75e85213e2b1ea0d8accb78471b6d25d01b60 |
| parent | fdcac5ecbd324170f7281f6704ead18b7d904e72 |
Allow --out-implib and -implib as passed by cmake and meson to be
correctly passed through to the linker to generate import libraries.4 files changed, 40 insertions(+), 1 deletions(-)
src/Compilation.zig+5-1| ... | @@ -767,6 +767,8 @@ pub const InitOptions = struct { | ... | @@ -767,6 +767,8 @@ pub const InitOptions = struct { |
| 767 | test_filter: ?[]const u8 = null, | 767 | test_filter: ?[]const u8 = null, |
| 768 | test_name_prefix: ?[]const u8 = null, | 768 | test_name_prefix: ?[]const u8 = null, |
| 769 | subsystem: ?std.Target.SubSystem = null, | 769 | subsystem: ?std.Target.SubSystem = null, |
| 770 | /// Windows/PE only. Where to output the import library, can contain directories. | ||
| 771 | out_implib: ?[]const u8 = null, | ||
| 770 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). | 772 | /// WASI-only. Type of WASI execution model ("command" or "reactor"). |
| 771 | wasi_exec_model: ?std.builtin.WasiExecModel = null, | 773 | wasi_exec_model: ?std.builtin.WasiExecModel = null, |
| 772 | /// (Zig compiler development) Enable dumping linker's state as JSON. | 774 | /// (Zig compiler development) Enable dumping linker's state as JSON. |
| ... | @@ -946,7 +948,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -946,7 +948,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 946 | options.output_mode == .Lib or | 948 | options.output_mode == .Lib or |
| 947 | options.lld_argv.len != 0 or | 949 | options.lld_argv.len != 0 or |
| 948 | options.image_base_override != null or | 950 | options.image_base_override != null or |
| 949 | options.linker_script != null or options.version_script != null) | 951 | options.linker_script != null or options.version_script != null or |
| 952 | options.out_implib != null) | ||
| 950 | { | 953 | { |
| 951 | break :blk true; | 954 | break :blk true; |
| 952 | } | 955 | } |
| ... | @@ -1461,6 +1464,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1461,6 +1464,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1461 | .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, | 1464 | .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, |
| 1462 | .disable_lld_caching = options.disable_lld_caching, | 1465 | .disable_lld_caching = options.disable_lld_caching, |
| 1463 | .subsystem = options.subsystem, | 1466 | .subsystem = options.subsystem, |
| 1467 | .out_implib = options.out_implib, | ||
| 1464 | .is_test = options.is_test, | 1468 | .is_test = options.is_test, |
| 1465 | .wasi_exec_model = wasi_exec_model, | 1469 | .wasi_exec_model = wasi_exec_model, |
| 1466 | .use_stage1 = use_stage1, | 1470 | .use_stage1 = use_stage1, |
src/link.zig+1| ... | @@ -127,6 +127,7 @@ pub const Options = struct { | ... | @@ -127,6 +127,7 @@ pub const Options = struct { |
| 127 | gc_sections: ?bool = null, | 127 | gc_sections: ?bool = null, |
| 128 | allow_shlib_undefined: ?bool, | 128 | allow_shlib_undefined: ?bool, |
| 129 | subsystem: ?std.Target.SubSystem, | 129 | subsystem: ?std.Target.SubSystem, |
| 130 | out_implib: ?[]const u8, | ||
| 130 | linker_script: ?[]const u8, | 131 | linker_script: ?[]const u8, |
| 131 | version_script: ?[]const u8, | 132 | version_script: ?[]const u8, |
| 132 | soname: ?[]const u8, | 133 | soname: ?[]const u8, |
src/link/Coff.zig+5| ... | @@ -948,6 +948,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -948,6 +948,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 948 | man.hash.add(self.base.options.dynamicbase); | 948 | man.hash.add(self.base.options.dynamicbase); |
| 949 | man.hash.addOptional(self.base.options.major_subsystem_version); | 949 | man.hash.addOptional(self.base.options.major_subsystem_version); |
| 950 | man.hash.addOptional(self.base.options.minor_subsystem_version); | 950 | man.hash.addOptional(self.base.options.minor_subsystem_version); |
| 951 | man.hash.addOptionalBytes(self.base.options.out_implib); | ||
| 951 | 952 | ||
| 952 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. | 953 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 953 | _ = try man.hit(); | 954 | _ = try man.hit(); |
| ... | @@ -1094,6 +1095,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -1094,6 +1095,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 1094 | try argv.append(p); | 1095 | try argv.append(p); |
| 1095 | } | 1096 | } |
| 1096 | 1097 | ||
| 1098 | if (self.base.options.out_implib != null) { | ||
| 1099 | try argv.append(try allocPrint(arena, "-IMPLIB:{s}.lib", .{full_out_path})); | ||
| 1100 | } | ||
| 1101 | |||
| 1097 | const resolved_subsystem: ?std.Target.SubSystem = blk: { | 1102 | const resolved_subsystem: ?std.Target.SubSystem = blk: { |
| 1098 | if (self.base.options.subsystem) |explicit| break :blk explicit; | 1103 | if (self.base.options.subsystem) |explicit| break :blk explicit; |
| 1099 | switch (target.os.tag) { | 1104 | switch (target.os.tag) { |
src/main.zig+29| ... | @@ -654,6 +654,7 @@ fn buildOutputType( | ... | @@ -654,6 +654,7 @@ fn buildOutputType( |
| 654 | var main_pkg_path: ?[]const u8 = null; | 654 | var main_pkg_path: ?[]const u8 = null; |
| 655 | var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; | 655 | var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; |
| 656 | var subsystem: ?std.Target.SubSystem = null; | 656 | var subsystem: ?std.Target.SubSystem = null; |
| 657 | var out_implib: ?[]const u8 = null; | ||
| 657 | var major_subsystem_version: ?u32 = null; | 658 | var major_subsystem_version: ?u32 = null; |
| 658 | var minor_subsystem_version: ?u32 = null; | 659 | var minor_subsystem_version: ?u32 = null; |
| 659 | var wasi_exec_model: ?std.builtin.WasiExecModel = null; | 660 | var wasi_exec_model: ?std.builtin.WasiExecModel = null; |
| ... | @@ -1637,6 +1638,14 @@ fn buildOutputType( | ... | @@ -1637,6 +1638,14 @@ fn buildOutputType( |
| 1637 | fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | 1638 | fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); |
| 1638 | }; | 1639 | }; |
| 1639 | have_version = true; | 1640 | have_version = true; |
| 1641 | } else if (mem.eql(u8, arg, "--out-implib") or | ||
| 1642 | mem.eql(u8, arg, "-implib")) | ||
| 1643 | { | ||
| 1644 | i += 1; | ||
| 1645 | if (i >= linker_args.items.len) { | ||
| 1646 | fatal("expected linker arg after '{s}'", .{arg}); | ||
| 1647 | } | ||
| 1648 | out_implib = linker_args.items[i]; | ||
| 1640 | } else { | 1649 | } else { |
| 1641 | warn("unsupported linker arg: {s}", .{arg}); | 1650 | warn("unsupported linker arg: {s}", .{arg}); |
| 1642 | } | 1651 | } |
| ... | @@ -2154,6 +2163,16 @@ fn buildOutputType( | ... | @@ -2154,6 +2163,16 @@ fn buildOutputType( |
| 2154 | else => false, | 2163 | else => false, |
| 2155 | }; | 2164 | }; |
| 2156 | 2165 | ||
| 2166 | // Always output import libraries (.lib) when building for msvc to replicate | ||
| 2167 | // `link` behavior. lld does not always output import libraries so on the | ||
| 2168 | // gnu abi users must set out_implib. | ||
| 2169 | if (output_mode == .Lib and emit_bin == .yes and target_info.target.abi == .msvc and out_implib == null) { | ||
| 2170 | const emit_bin_ext = fs.path.extension(emit_bin.yes); | ||
| 2171 | out_implib = try std.fmt.allocPrint(gpa, "{s}.lib", .{ | ||
| 2172 | emit_bin.yes[0 .. emit_bin.yes.len - emit_bin_ext.len], | ||
| 2173 | }); | ||
| 2174 | } | ||
| 2175 | |||
| 2157 | gimmeMoreOfThoseSweetSweetFileDescriptors(); | 2176 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| 2158 | 2177 | ||
| 2159 | const comp = Compilation.create(gpa, .{ | 2178 | const comp = Compilation.create(gpa, .{ |
| ... | @@ -2263,6 +2282,7 @@ fn buildOutputType( | ... | @@ -2263,6 +2282,7 @@ fn buildOutputType( |
| 2263 | .test_name_prefix = test_name_prefix, | 2282 | .test_name_prefix = test_name_prefix, |
| 2264 | .disable_lld_caching = !have_enable_cache, | 2283 | .disable_lld_caching = !have_enable_cache, |
| 2265 | .subsystem = subsystem, | 2284 | .subsystem = subsystem, |
| 2285 | .out_implib = out_implib, | ||
| 2266 | .wasi_exec_model = wasi_exec_model, | 2286 | .wasi_exec_model = wasi_exec_model, |
| 2267 | .debug_compile_errors = debug_compile_errors, | 2287 | .debug_compile_errors = debug_compile_errors, |
| 2268 | .enable_link_snapshots = enable_link_snapshots, | 2288 | .enable_link_snapshots = enable_link_snapshots, |
| ... | @@ -2661,6 +2681,15 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !voi | ... | @@ -2661,6 +2681,15 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !voi |
| 2661 | 2681 | ||
| 2662 | _ = try cache_dir.updateFile(src_pdb_path, cwd, dst_pdb_path, .{}); | 2682 | _ = try cache_dir.updateFile(src_pdb_path, cwd, dst_pdb_path, .{}); |
| 2663 | } | 2683 | } |
| 2684 | |||
| 2685 | if (comp.bin_file.options.out_implib) |out_implib| { | ||
| 2686 | const src_implib_path = try std.fmt.allocPrint(gpa, "{s}.lib", .{bin_sub_path}); | ||
| 2687 | defer gpa.free(src_implib_path); | ||
| 2688 | if (std.fs.path.dirname(out_implib)) |implib_dir| { | ||
| 2689 | try cwd.makePath(implib_dir); | ||
| 2690 | } | ||
| 2691 | _ = try cache_dir.updateFile(src_implib_path, cwd, out_implib, .{}); | ||
| 2692 | } | ||
| 2664 | }, | 2693 | }, |
| 2665 | } | 2694 | } |
| 2666 | } | 2695 | } |