authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-24 17:47:56-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-24 17:47:56-08:00
log0581756453a98d4e1100c684896783606dc86374
tree865fcfffdc31cf0b7220d41198266f0627b2d118
parentfdcac5ecbd324170f7281f6704ead18b7d904e72
parent20cc7af8e6e47ba209ab0d462826f40516c86b9d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9347 from kkartaltepe/implib-support

Coff linker: Add IMPLIB support

7 files changed, 176 insertions(+), 60 deletions(-)

src/Compilation.zig+33-4
...@@ -654,6 +654,8 @@ pub const InitOptions = struct {...@@ -654,6 +654,8 @@ pub const InitOptions = struct {
654 emit_analysis: ?EmitLoc = null,654 emit_analysis: ?EmitLoc = null,
655 /// `null` means to not emit docs.655 /// `null` means to not emit docs.
656 emit_docs: ?EmitLoc = null,656 emit_docs: ?EmitLoc = null,
657 /// `null` means to not emit an import lib.
658 emit_implib: ?EmitLoc = null,
657 link_mode: ?std.builtin.LinkMode = null,659 link_mode: ?std.builtin.LinkMode = null,
658 dll_export_fns: ?bool = false,660 dll_export_fns: ?bool = false,
659 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the661 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the
...@@ -667,7 +669,6 @@ pub const InitOptions = struct {...@@ -667,7 +669,6 @@ pub const InitOptions = struct {
667 optimize_mode: std.builtin.Mode = .Debug,669 optimize_mode: std.builtin.Mode = .Debug,
668 keep_source_files_loaded: bool = false,670 keep_source_files_loaded: bool = false,
669 clang_argv: []const []const u8 = &[0][]const u8{},671 clang_argv: []const []const u8 = &[0][]const u8{},
670 lld_argv: []const []const u8 = &[0][]const u8{},
671 lib_dirs: []const []const u8 = &[0][]const u8{},672 lib_dirs: []const []const u8 = &[0][]const u8{},
672 rpath_list: []const []const u8 = &[0][]const u8{},673 rpath_list: []const []const u8 = &[0][]const u8{},
673 c_source_files: []const CSourceFile = &[0]CSourceFile{},674 c_source_files: []const CSourceFile = &[0]CSourceFile{},
...@@ -735,6 +736,7 @@ pub const InitOptions = struct {...@@ -735,6 +736,7 @@ pub const InitOptions = struct {
735 linker_tsaware: bool = false,736 linker_tsaware: bool = false,
736 linker_nxcompat: bool = false,737 linker_nxcompat: bool = false,
737 linker_dynamicbase: bool = false,738 linker_dynamicbase: bool = false,
739 linker_optimization: ?u8 = null,
738 major_subsystem_version: ?u32 = null,740 major_subsystem_version: ?u32 = null,
739 minor_subsystem_version: ?u32 = null,741 minor_subsystem_version: ?u32 = null,
740 clang_passthrough_mode: bool = false,742 clang_passthrough_mode: bool = false,
...@@ -944,9 +946,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -944,9 +946,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
944 link_eh_frame_hdr or946 link_eh_frame_hdr or
945 options.link_emit_relocs or947 options.link_emit_relocs or
946 options.output_mode == .Lib or948 options.output_mode == .Lib or
947 options.lld_argv.len != 0 or
948 options.image_base_override != null or949 options.image_base_override != null or
949 options.linker_script != null or options.version_script != null)950 options.linker_script != null or options.version_script != null or
951 options.emit_implib != null)
950 {952 {
951 break :blk true;953 break :blk true;
952 }954 }
...@@ -1139,6 +1141,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1139,6 +1141,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1139 const strip = options.strip or !target_util.hasDebugInfo(options.target);1141 const strip = options.strip or !target_util.hasDebugInfo(options.target);
1140 const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);1142 const red_zone = options.want_red_zone orelse target_util.hasRedZone(options.target);
1141 const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug);1143 const omit_frame_pointer = options.omit_frame_pointer orelse (options.optimize_mode != .Debug);
1144 const linker_optimization: u8 = options.linker_optimization orelse switch (options.optimize_mode) {
1145 .Debug => @as(u8, 0),
1146 else => @as(u8, 3),
1147 };
11421148
1143 // We put everything into the cache hash that *cannot be modified during an incremental update*.1149 // We put everything into the cache hash that *cannot be modified during an incremental update*.
1144 // For example, one cannot change the target between updates, but one can change source files,1150 // For example, one cannot change the target between updates, but one can change source files,
...@@ -1182,6 +1188,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1182,6 +1188,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1182 cache.hash.add(options.output_mode);1188 cache.hash.add(options.output_mode);
1183 cache.hash.add(options.machine_code_model);1189 cache.hash.add(options.machine_code_model);
1184 cache.hash.addOptionalEmitLoc(options.emit_bin);1190 cache.hash.addOptionalEmitLoc(options.emit_bin);
1191 cache.hash.addOptionalEmitLoc(options.emit_implib);
1185 cache.hash.addBytes(options.root_name);1192 cache.hash.addBytes(options.root_name);
1186 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);1193 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);
1187 // TODO audit this and make sure everything is in it1194 // TODO audit this and make sure everything is in it
...@@ -1338,18 +1345,21 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1338,18 +1345,21 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
13381345
1339 const bin_file_emit: ?link.Emit = blk: {1346 const bin_file_emit: ?link.Emit = blk: {
1340 const emit_bin = options.emit_bin orelse break :blk null;1347 const emit_bin = options.emit_bin orelse break :blk null;
1348
1341 if (emit_bin.directory) |directory| {1349 if (emit_bin.directory) |directory| {
1342 break :blk link.Emit{1350 break :blk link.Emit{
1343 .directory = directory,1351 .directory = directory,
1344 .sub_path = emit_bin.basename,1352 .sub_path = emit_bin.basename,
1345 };1353 };
1346 }1354 }
1355
1347 if (module) |zm| {1356 if (module) |zm| {
1348 break :blk link.Emit{1357 break :blk link.Emit{
1349 .directory = zm.zig_cache_artifact_directory,1358 .directory = zm.zig_cache_artifact_directory,
1350 .sub_path = emit_bin.basename,1359 .sub_path = emit_bin.basename,
1351 };1360 };
1352 }1361 }
1362
1353 // We could use the cache hash as is no problem, however, we increase1363 // We could use the cache hash as is no problem, however, we increase
1354 // the likelihood of cache hits by adding the first C source file1364 // the likelihood of cache hits by adding the first C source file
1355 // path name (not contents) to the hash. This way if the user is compiling1365 // path name (not contents) to the hash. This way if the user is compiling
...@@ -1376,6 +1386,24 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1376,6 +1386,24 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1376 };1386 };
1377 };1387 };
13781388
1389 const implib_emit: ?link.Emit = blk: {
1390 const emit_implib = options.emit_implib orelse break :blk null;
1391
1392 if (emit_implib.directory) |directory| {
1393 break :blk link.Emit{
1394 .directory = directory,
1395 .sub_path = emit_implib.basename,
1396 };
1397 }
1398
1399 // Use the same directory as the bin. The CLI already emits an
1400 // error if -fno-emit-bin is combined with -femit-implib.
1401 break :blk link.Emit{
1402 .directory = bin_file_emit.?.directory,
1403 .sub_path = emit_implib.basename,
1404 };
1405 };
1406
1379 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};1407 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
1380 errdefer system_libs.deinit(gpa);1408 errdefer system_libs.deinit(gpa);
1381 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);1409 try system_libs.ensureTotalCapacity(gpa, options.system_lib_names.len);
...@@ -1385,6 +1413,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1385,6 +1413,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
13851413
1386 const bin_file = try link.File.openPath(gpa, .{1414 const bin_file = try link.File.openPath(gpa, .{
1387 .emit = bin_file_emit,1415 .emit = bin_file_emit,
1416 .implib_emit = implib_emit,
1388 .root_name = root_name,1417 .root_name = root_name,
1389 .module = module,1418 .module = module,
1390 .target = options.target,1419 .target = options.target,
...@@ -1426,6 +1455,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1426,6 +1455,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1426 .tsaware = options.linker_tsaware,1455 .tsaware = options.linker_tsaware,
1427 .nxcompat = options.linker_nxcompat,1456 .nxcompat = options.linker_nxcompat,
1428 .dynamicbase = options.linker_dynamicbase,1457 .dynamicbase = options.linker_dynamicbase,
1458 .linker_optimization = linker_optimization,
1429 .major_subsystem_version = options.major_subsystem_version,1459 .major_subsystem_version = options.major_subsystem_version,
1430 .minor_subsystem_version = options.minor_subsystem_version,1460 .minor_subsystem_version = options.minor_subsystem_version,
1431 .stack_size_override = options.stack_size_override,1461 .stack_size_override = options.stack_size_override,
...@@ -1437,7 +1467,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1437,7 +1467,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1437 .eh_frame_hdr = link_eh_frame_hdr,1467 .eh_frame_hdr = link_eh_frame_hdr,
1438 .emit_relocs = options.link_emit_relocs,1468 .emit_relocs = options.link_emit_relocs,
1439 .rdynamic = options.rdynamic,1469 .rdynamic = options.rdynamic,
1440 .extra_lld_args = options.lld_argv,
1441 .soname = options.soname,1470 .soname = options.soname,
1442 .version = options.version,1471 .version = options.version,
1443 .compatibility_version = options.compatibility_version,1472 .compatibility_version = options.compatibility_version,
src/link.zig+3-2
...@@ -47,6 +47,8 @@ pub const Options = struct {...@@ -47,6 +47,8 @@ pub const Options = struct {
47 /// This is `null` when -fno-emit-bin is used. When `openPath` or `flush` is called,47 /// This is `null` when -fno-emit-bin is used. When `openPath` or `flush` is called,
48 /// it will have already been null-checked.48 /// it will have already been null-checked.
49 emit: ?Emit,49 emit: ?Emit,
50 /// This is `null` not building a Windows DLL, or when -fno-emit-implib is used.
51 implib_emit: ?Emit,
50 target: std.Target,52 target: std.Target,
51 output_mode: std.builtin.OutputMode,53 output_mode: std.builtin.OutputMode,
52 link_mode: std.builtin.LinkMode,54 link_mode: std.builtin.LinkMode,
...@@ -97,6 +99,7 @@ pub const Options = struct {...@@ -97,6 +99,7 @@ pub const Options = struct {
97 tsaware: bool,99 tsaware: bool,
98 nxcompat: bool,100 nxcompat: bool,
99 dynamicbase: bool,101 dynamicbase: bool,
102 linker_optimization: u8,
100 bind_global_refs_locally: bool,103 bind_global_refs_locally: bool,
101 import_memory: bool,104 import_memory: bool,
102 initial_memory: ?u64,105 initial_memory: ?u64,
...@@ -131,8 +134,6 @@ pub const Options = struct {...@@ -131,8 +134,6 @@ pub const Options = struct {
131 version_script: ?[]const u8,134 version_script: ?[]const u8,
132 soname: ?[]const u8,135 soname: ?[]const u8,
133 llvm_cpu_features: ?[*:0]const u8,136 llvm_cpu_features: ?[*:0]const u8,
134 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
135 extra_lld_args: []const []const u8,
136137
137 objects: []const []const u8,138 objects: []const []const u8,
138 framework_dirs: []const []const u8,139 framework_dirs: []const []const u8,
src/link/Coff.zig+6-2
...@@ -927,7 +927,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -927,7 +927,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
927 try man.addOptionalFile(module_obj_path);927 try man.addOptionalFile(module_obj_path);
928 man.hash.addOptional(self.base.options.stack_size_override);928 man.hash.addOptional(self.base.options.stack_size_override);
929 man.hash.addOptional(self.base.options.image_base_override);929 man.hash.addOptional(self.base.options.image_base_override);
930 man.hash.addListOfBytes(self.base.options.extra_lld_args);
931 man.hash.addListOfBytes(self.base.options.lib_dirs);930 man.hash.addListOfBytes(self.base.options.lib_dirs);
932 man.hash.add(self.base.options.skip_linker_dependencies);931 man.hash.add(self.base.options.skip_linker_dependencies);
933 if (self.base.options.link_libc) {932 if (self.base.options.link_libc) {
...@@ -978,7 +977,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -978,7 +977,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
978 }977 }
979978
980 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});979 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
981
982 if (self.base.options.output_mode == .Obj) {980 if (self.base.options.output_mode == .Obj) {
983 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy981 // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy
984 // here. TODO: think carefully about how we can avoid this redundant operation when doing982 // here. TODO: think carefully about how we can avoid this redundant operation when doing
...@@ -1056,6 +1054,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1056,6 +1054,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
1056 if (self.base.options.dynamicbase) {1054 if (self.base.options.dynamicbase) {
1057 try argv.append("-dynamicbase");1055 try argv.append("-dynamicbase");
1058 }1056 }
1057
1059 const subsystem_suffix = ss: {1058 const subsystem_suffix = ss: {
1060 if (self.base.options.major_subsystem_version) |major| {1059 if (self.base.options.major_subsystem_version) |major| {
1061 if (self.base.options.minor_subsystem_version) |minor| {1060 if (self.base.options.minor_subsystem_version) |minor| {
...@@ -1069,6 +1068,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {...@@ -1069,6 +1068,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
10691068
1070 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));1069 try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
10711070
1071 if (self.base.options.implib_emit) |emit| {
1072 const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
1073 try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
1074 }
1075
1072 if (self.base.options.link_libc) {1076 if (self.base.options.link_libc) {
1073 if (self.base.options.libc_installation) |libc_installation| {1077 if (self.base.options.libc_installation) |libc_installation| {
1074 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));1078 try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
src/link/Elf.zig+6-5
...@@ -1322,7 +1322,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1322,7 +1322,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1322 man.hash.add(self.base.options.eh_frame_hdr);1322 man.hash.add(self.base.options.eh_frame_hdr);
1323 man.hash.add(self.base.options.emit_relocs);1323 man.hash.add(self.base.options.emit_relocs);
1324 man.hash.add(self.base.options.rdynamic);1324 man.hash.add(self.base.options.rdynamic);
1325 man.hash.addListOfBytes(self.base.options.extra_lld_args);
1326 man.hash.addListOfBytes(self.base.options.lib_dirs);1325 man.hash.addListOfBytes(self.base.options.lib_dirs);
1327 man.hash.addListOfBytes(self.base.options.rpath_list);1326 man.hash.addListOfBytes(self.base.options.rpath_list);
1328 man.hash.add(self.base.options.each_lib_rpath);1327 man.hash.add(self.base.options.each_lib_rpath);
...@@ -1350,6 +1349,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1350,6 +1349,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1350 man.hash.add(self.base.options.bind_global_refs_locally);1349 man.hash.add(self.base.options.bind_global_refs_locally);
1351 man.hash.add(self.base.options.tsan);1350 man.hash.add(self.base.options.tsan);
1352 man.hash.addOptionalBytes(self.base.options.sysroot);1351 man.hash.addOptionalBytes(self.base.options.sysroot);
1352 man.hash.add(self.base.options.linker_optimization);
13531353
1354 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.1354 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1355 _ = try man.hit();1355 _ = try man.hit();
...@@ -1426,10 +1426,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1426,10 +1426,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1426 if (self.base.options.lto) {1426 if (self.base.options.lto) {
1427 switch (self.base.options.optimize_mode) {1427 switch (self.base.options.optimize_mode) {
1428 .Debug => {},1428 .Debug => {},
1429 .ReleaseSmall => try argv.append("-O2"),1429 .ReleaseSmall => try argv.append("--lto-O2"),
1430 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),1430 .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
1431 }1431 }
1432 }1432 }
1433 try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{
1434 self.base.options.linker_optimization,
1435 }));
14331436
1434 if (self.base.options.output_mode == .Exe) {1437 if (self.base.options.output_mode == .Exe) {
1435 try argv.append("-z");1438 try argv.append("-z");
...@@ -1461,8 +1464,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1461,8 +1464,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1461 try argv.append("--export-dynamic");1464 try argv.append("--export-dynamic");
1462 }1465 }
14631466
1464 try argv.appendSlice(self.base.options.extra_lld_args);
1465
1466 if (self.base.options.z_nodelete) {1467 if (self.base.options.z_nodelete) {
1467 try argv.append("-z");1468 try argv.append("-z");
1468 try argv.append("nodelete");1469 try argv.append("nodelete");
src/link/Wasm.zig-1
...@@ -714,7 +714,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {...@@ -714,7 +714,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
714 try man.addOptionalFile(module_obj_path);714 try man.addOptionalFile(module_obj_path);
715 try man.addOptionalFile(compiler_rt_path);715 try man.addOptionalFile(compiler_rt_path);
716 man.hash.addOptional(self.base.options.stack_size_override);716 man.hash.addOptional(self.base.options.stack_size_override);
717 man.hash.addListOfBytes(self.base.options.extra_lld_args);
718 man.hash.add(self.base.options.import_memory);717 man.hash.add(self.base.options.import_memory);
719 man.hash.addOptional(self.base.options.initial_memory);718 man.hash.addOptional(self.base.options.initial_memory);
720 man.hash.addOptional(self.base.options.max_memory);719 man.hash.addOptional(self.base.options.max_memory);
src/main.zig+104-22
...@@ -317,6 +317,8 @@ const usage_build_generic =...@@ -317,6 +317,8 @@ const usage_build_generic =
317 \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation317 \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation
318 \\ -femit-analysis[=path] Write analysis JSON file with type information318 \\ -femit-analysis[=path] Write analysis JSON file with type information
319 \\ -fno-emit-analysis (default) Do not write analysis JSON file with type information319 \\ -fno-emit-analysis (default) Do not write analysis JSON file with type information
320 \\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL
321 \\ -fno-emit-implib Do not produce an import .lib when building a Windows DLL
320 \\ --show-builtin Output the source of @import("builtin") then exit322 \\ --show-builtin Output the source of @import("builtin") then exit
321 \\ --cache-dir [path] Override the local cache directory323 \\ --cache-dir [path] Override the local cache directory
322 \\ --global-cache-dir [path] Override the global cache directory324 \\ --global-cache-dir [path] Override the global cache directory
...@@ -585,6 +587,8 @@ fn buildOutputType(...@@ -585,6 +587,8 @@ fn buildOutputType(
585 var emit_llvm_bc: Emit = .no;587 var emit_llvm_bc: Emit = .no;
586 var emit_docs: Emit = .no;588 var emit_docs: Emit = .no;
587 var emit_analysis: Emit = .no;589 var emit_analysis: Emit = .no;
590 var emit_implib: Emit = .yes_default_path;
591 var emit_implib_arg_provided = false;
588 var target_arch_os_abi: []const u8 = "native";592 var target_arch_os_abi: []const u8 = "native";
589 var target_mcpu: ?[]const u8 = null;593 var target_mcpu: ?[]const u8 = null;
590 var target_dynamic_linker: ?[]const u8 = null;594 var target_dynamic_linker: ?[]const u8 = null;
...@@ -631,6 +635,7 @@ fn buildOutputType(...@@ -631,6 +635,7 @@ fn buildOutputType(
631 var linker_tsaware = false;635 var linker_tsaware = false;
632 var linker_nxcompat = false;636 var linker_nxcompat = false;
633 var linker_dynamicbase = false;637 var linker_dynamicbase = false;
638 var linker_optimization: ?u8 = null;
634 var test_evented_io = false;639 var test_evented_io = false;
635 var test_no_exec = false;640 var test_no_exec = false;
636 var stack_size_override: ?u64 = null;641 var stack_size_override: ?u64 = null;
...@@ -671,9 +676,6 @@ fn buildOutputType(...@@ -671,9 +676,6 @@ fn buildOutputType(
671 var extra_cflags = std.ArrayList([]const u8).init(gpa);676 var extra_cflags = std.ArrayList([]const u8).init(gpa);
672 defer extra_cflags.deinit();677 defer extra_cflags.deinit();
673678
674 var lld_argv = std.ArrayList([]const u8).init(gpa);
675 defer lld_argv.deinit();
676
677 var lib_dirs = std.ArrayList([]const u8).init(gpa);679 var lib_dirs = std.ArrayList([]const u8).init(gpa);
678 defer lib_dirs.deinit();680 defer lib_dirs.deinit();
679681
...@@ -1093,6 +1095,15 @@ fn buildOutputType(...@@ -1093,6 +1095,15 @@ fn buildOutputType(
1093 emit_analysis = .{ .yes = arg["-femit-analysis=".len..] };1095 emit_analysis = .{ .yes = arg["-femit-analysis=".len..] };
1094 } else if (mem.eql(u8, arg, "-fno-emit-analysis")) {1096 } else if (mem.eql(u8, arg, "-fno-emit-analysis")) {
1095 emit_analysis = .no;1097 emit_analysis = .no;
1098 } else if (mem.eql(u8, arg, "-femit-implib")) {
1099 emit_implib = .yes_default_path;
1100 emit_implib_arg_provided = true;
1101 } else if (mem.startsWith(u8, arg, "-femit-implib=")) {
1102 emit_implib = .{ .yes = arg["-femit-implib=".len..] };
1103 emit_implib_arg_provided = true;
1104 } else if (mem.eql(u8, arg, "-fno-emit-implib")) {
1105 emit_implib = .no;
1106 emit_implib_arg_provided = true;
1096 } else if (mem.eql(u8, arg, "-dynamic")) {1107 } else if (mem.eql(u8, arg, "-dynamic")) {
1097 link_mode = .Dynamic;1108 link_mode = .Dynamic;
1098 } else if (mem.eql(u8, arg, "-static")) {1109 } else if (mem.eql(u8, arg, "-static")) {
...@@ -1473,8 +1484,18 @@ fn buildOutputType(...@@ -1473,8 +1484,18 @@ fn buildOutputType(
1473 fatal("expected linker arg after '{s}'", .{arg});1484 fatal("expected linker arg after '{s}'", .{arg});
1474 }1485 }
1475 version_script = linker_args.items[i];1486 version_script = linker_args.items[i];
1487 } else if (mem.eql(u8, arg, "-O")) {
1488 i += 1;
1489 if (i >= linker_args.items.len) {
1490 fatal("expected linker arg after '{s}'", .{arg});
1491 }
1492 linker_optimization = std.fmt.parseUnsigned(u8, linker_args.items[i], 10) catch |err| {
1493 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1494 };
1476 } else if (mem.startsWith(u8, arg, "-O")) {1495 } else if (mem.startsWith(u8, arg, "-O")) {
1477 try lld_argv.append(arg);1496 linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| {
1497 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1498 };
1478 } else if (mem.eql(u8, arg, "--gc-sections")) {1499 } else if (mem.eql(u8, arg, "--gc-sections")) {
1479 linker_gc_sections = true;1500 linker_gc_sections = true;
1480 } else if (mem.eql(u8, arg, "--no-gc-sections")) {1501 } else if (mem.eql(u8, arg, "--no-gc-sections")) {
...@@ -1637,6 +1658,15 @@ fn buildOutputType(...@@ -1637,6 +1658,15 @@ fn buildOutputType(
1637 fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });1658 fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
1638 };1659 };
1639 have_version = true;1660 have_version = true;
1661 } else if (mem.eql(u8, arg, "--out-implib") or
1662 mem.eql(u8, arg, "-implib"))
1663 {
1664 i += 1;
1665 if (i >= linker_args.items.len) {
1666 fatal("expected linker arg after '{s}'", .{arg});
1667 }
1668 emit_implib = .{ .yes = linker_args.items[i] };
1669 emit_implib_arg_provided = true;
1640 } else {1670 } else {
1641 warn("unsupported linker arg: {s}", .{arg});1671 warn("unsupported linker arg: {s}", .{arg});
1642 }1672 }
...@@ -1984,11 +2014,15 @@ fn buildOutputType(...@@ -1984,11 +2014,15 @@ fn buildOutputType(
1984 const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});2014 const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});
1985 var emit_h_resolved = emit_h.resolve(default_h_basename) catch |err| {2015 var emit_h_resolved = emit_h.resolve(default_h_basename) catch |err| {
1986 switch (emit_h) {2016 switch (emit_h) {
1987 .yes => {2017 .yes => |p| {
1988 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{ emit_h.yes, @errorName(err) });2018 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{
2019 p, @errorName(err),
2020 });
1989 },2021 },
1990 .yes_default_path => {2022 .yes_default_path => {
1991 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{ default_h_basename, @errorName(err) });2023 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
2024 default_h_basename, @errorName(err),
2025 });
1992 },2026 },
1993 .no => unreachable,2027 .no => unreachable,
1994 }2028 }
...@@ -1998,11 +2032,15 @@ fn buildOutputType(...@@ -1998,11 +2032,15 @@ fn buildOutputType(
1998 const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});2032 const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});
1999 var emit_asm_resolved = emit_asm.resolve(default_asm_basename) catch |err| {2033 var emit_asm_resolved = emit_asm.resolve(default_asm_basename) catch |err| {
2000 switch (emit_asm) {2034 switch (emit_asm) {
2001 .yes => {2035 .yes => |p| {
2002 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{ emit_asm.yes, @errorName(err) });2036 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{
2037 p, @errorName(err),
2038 });
2003 },2039 },
2004 .yes_default_path => {2040 .yes_default_path => {
2005 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{ default_asm_basename, @errorName(err) });2041 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
2042 default_asm_basename, @errorName(err),
2043 });
2006 },2044 },
2007 .no => unreachable,2045 .no => unreachable,
2008 }2046 }
...@@ -2012,11 +2050,15 @@ fn buildOutputType(...@@ -2012,11 +2050,15 @@ fn buildOutputType(
2012 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});2050 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});
2013 var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename) catch |err| {2051 var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename) catch |err| {
2014 switch (emit_llvm_ir) {2052 switch (emit_llvm_ir) {
2015 .yes => {2053 .yes => |p| {
2016 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{ emit_llvm_ir.yes, @errorName(err) });2054 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{
2055 p, @errorName(err),
2056 });
2017 },2057 },
2018 .yes_default_path => {2058 .yes_default_path => {
2019 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{ default_llvm_ir_basename, @errorName(err) });2059 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
2060 default_llvm_ir_basename, @errorName(err),
2061 });
2020 },2062 },
2021 .no => unreachable,2063 .no => unreachable,
2022 }2064 }
...@@ -2026,11 +2068,15 @@ fn buildOutputType(...@@ -2026,11 +2068,15 @@ fn buildOutputType(
2026 const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});2068 const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});
2027 var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename) catch |err| {2069 var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename) catch |err| {
2028 switch (emit_llvm_bc) {2070 switch (emit_llvm_bc) {
2029 .yes => {2071 .yes => |p| {
2030 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{ emit_llvm_bc.yes, @errorName(err) });2072 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{
2073 p, @errorName(err),
2074 });
2031 },2075 },
2032 .yes_default_path => {2076 .yes_default_path => {
2033 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{ default_llvm_bc_basename, @errorName(err) });2077 fatal("unable to open directory from arguments '--name' or '-fsoname', '{s}': {s}", .{
2078 default_llvm_bc_basename, @errorName(err),
2079 });
2034 },2080 },
2035 .no => unreachable,2081 .no => unreachable,
2036 }2082 }
...@@ -2040,11 +2086,15 @@ fn buildOutputType(...@@ -2040,11 +2086,15 @@ fn buildOutputType(
2040 const default_analysis_basename = try std.fmt.allocPrint(arena, "{s}-analysis.json", .{root_name});2086 const default_analysis_basename = try std.fmt.allocPrint(arena, "{s}-analysis.json", .{root_name});
2041 var emit_analysis_resolved = emit_analysis.resolve(default_analysis_basename) catch |err| {2087 var emit_analysis_resolved = emit_analysis.resolve(default_analysis_basename) catch |err| {
2042 switch (emit_analysis) {2088 switch (emit_analysis) {
2043 .yes => {2089 .yes => |p| {
2044 fatal("unable to open directory from argument 'femit-analysis', '{s}': {s}", .{ emit_analysis.yes, @errorName(err) });2090 fatal("unable to open directory from argument '-femit-analysis', '{s}': {s}", .{
2091 p, @errorName(err),
2092 });
2045 },2093 },
2046 .yes_default_path => {2094 .yes_default_path => {
2047 fatal("unable to open directory from arguments 'name' or 'soname', '{s}': {s}", .{ default_analysis_basename, @errorName(err) });2095 fatal("unable to open directory from arguments 'name' or 'soname', '{s}': {s}", .{
2096 default_analysis_basename, @errorName(err),
2097 });
2048 },2098 },
2049 .no => unreachable,2099 .no => unreachable,
2050 }2100 }
...@@ -2053,8 +2103,10 @@ fn buildOutputType(...@@ -2053,8 +2103,10 @@ fn buildOutputType(
20532103
2054 var emit_docs_resolved = emit_docs.resolve("docs") catch |err| {2104 var emit_docs_resolved = emit_docs.resolve("docs") catch |err| {
2055 switch (emit_docs) {2105 switch (emit_docs) {
2056 .yes => {2106 .yes => |p| {
2057 fatal("unable to open directory from argument 'femit-docs', '{s}': {s}", .{ emit_h.yes, @errorName(err) });2107 fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{
2108 p, @errorName(err),
2109 });
2058 },2110 },
2059 .yes_default_path => {2111 .yes_default_path => {
2060 fatal("unable to open directory 'docs': {s}", .{@errorName(err)});2112 fatal("unable to open directory 'docs': {s}", .{@errorName(err)});
...@@ -2064,6 +2116,35 @@ fn buildOutputType(...@@ -2064,6 +2116,35 @@ fn buildOutputType(
2064 };2116 };
2065 defer emit_docs_resolved.deinit();2117 defer emit_docs_resolved.deinit();
20662118
2119 const is_dyn_lib = switch (output_mode) {
2120 .Obj, .Exe => false,
2121 .Lib => (link_mode orelse .Static) == .Dynamic,
2122 };
2123 const implib_eligible = is_dyn_lib and
2124 emit_bin_loc != null and target_info.target.os.tag == .windows;
2125 if (!implib_eligible) {
2126 if (!emit_implib_arg_provided) {
2127 emit_implib = .no;
2128 } else if (emit_implib != .no) {
2129 fatal("the argument -femit-implib is allowed only when building a Windows DLL", .{});
2130 }
2131 }
2132 const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});
2133 var emit_implib_resolved = emit_implib.resolve(default_implib_basename) catch |err| {
2134 switch (emit_implib) {
2135 .yes => |p| {
2136 fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{
2137 p, @errorName(err),
2138 });
2139 },
2140 .yes_default_path => {
2141 fatal("unable to open directory 'docs': {s}", .{@errorName(err)});
2142 },
2143 .no => unreachable,
2144 }
2145 };
2146 defer emit_implib_resolved.deinit();
2147
2067 const main_pkg: ?*Package = if (root_src_file) |src_path| blk: {2148 const main_pkg: ?*Package = if (root_src_file) |src_path| blk: {
2068 if (main_pkg_path) |p| {2149 if (main_pkg_path) |p| {
2069 const rel_src_path = try fs.path.relative(gpa, p, src_path);2150 const rel_src_path = try fs.path.relative(gpa, p, src_path);
...@@ -2175,13 +2256,13 @@ fn buildOutputType(...@@ -2175,13 +2256,13 @@ fn buildOutputType(
2175 .emit_llvm_bc = emit_llvm_bc_resolved.data,2256 .emit_llvm_bc = emit_llvm_bc_resolved.data,
2176 .emit_docs = emit_docs_resolved.data,2257 .emit_docs = emit_docs_resolved.data,
2177 .emit_analysis = emit_analysis_resolved.data,2258 .emit_analysis = emit_analysis_resolved.data,
2259 .emit_implib = emit_implib_resolved.data,
2178 .link_mode = link_mode,2260 .link_mode = link_mode,
2179 .dll_export_fns = dll_export_fns,2261 .dll_export_fns = dll_export_fns,
2180 .object_format = object_format,2262 .object_format = object_format,
2181 .optimize_mode = optimize_mode,2263 .optimize_mode = optimize_mode,
2182 .keep_source_files_loaded = false,2264 .keep_source_files_loaded = false,
2183 .clang_argv = clang_argv.items,2265 .clang_argv = clang_argv.items,
2184 .lld_argv = lld_argv.items,
2185 .lib_dirs = lib_dirs.items,2266 .lib_dirs = lib_dirs.items,
2186 .rpath_list = rpath_list.items,2267 .rpath_list = rpath_list.items,
2187 .c_source_files = c_source_files.items,2268 .c_source_files = c_source_files.items,
...@@ -2231,6 +2312,7 @@ fn buildOutputType(...@@ -2231,6 +2312,7 @@ fn buildOutputType(
2231 .linker_tsaware = linker_tsaware,2312 .linker_tsaware = linker_tsaware,
2232 .linker_nxcompat = linker_nxcompat,2313 .linker_nxcompat = linker_nxcompat,
2233 .linker_dynamicbase = linker_dynamicbase,2314 .linker_dynamicbase = linker_dynamicbase,
2315 .linker_optimization = linker_optimization,
2234 .major_subsystem_version = major_subsystem_version,2316 .major_subsystem_version = major_subsystem_version,
2235 .minor_subsystem_version = minor_subsystem_version,2317 .minor_subsystem_version = minor_subsystem_version,
2236 .link_eh_frame_hdr = link_eh_frame_hdr,2318 .link_eh_frame_hdr = link_eh_frame_hdr,
test/standalone/install_raw_hex/build.zig+24-24
...@@ -35,7 +35,7 @@ pub fn build(b: *Builder) void {...@@ -35,7 +35,7 @@ pub fn build(b: *Builder) void {
35 ":1001140000000000000000000000000000000000DB",35 ":1001140000000000000000000000000000000000DB",
36 ":1001240000000000000000000000000000000000CB",36 ":1001240000000000000000000000000000000000CB",
37 ":1001340000000000000000000000000000000000BB",37 ":1001340000000000000000000000000000000000BB",
38 ":10014400830202006C020100090000002102010088",38 ":1001440083020200F401010009000000FE01010025",
39 ":100154000900000001000000000000000000000091",39 ":100154000900000001000000000000000000000091",
40 ":1001640000080002008001010004000010000000EB",40 ":1001640000080002008001010004000010000000EB",
41 ":100174000000000000000000000000001F0000005C",41 ":100174000000000000000000000000001F0000005C",
...@@ -44,17 +44,17 @@ pub fn build(b: *Builder) void {...@@ -44,17 +44,17 @@ pub fn build(b: *Builder) void {
44 ":1001A40000000000000000001F000000000000002C",44 ":1001A40000000000000000001F000000000000002C",
45 ":1001B400000000000000000000000000000000003B",45 ":1001B400000000000000000000000000000000003B",
46 ":1001C400000000000000000000000000000000002B",46 ":1001C400000000000000000000000000000000002B",
47 ":1001D4005B02010010000000F40101002C0000008B",47 ":1001D4000802010010000000190201002C000000B8",
48 ":1001E4003F0201001B0000002B020100130000006D",48 ":1001E400460201001B00000062020100130000002F",
49 ":1001F40072656D61696E646572206469766973699C",49 ":1001F400636F727465785F6D3400636F72746578D1",
50 ":100204006F6E206279207A65726F206F72206E653E",50 ":100204002D6D34006469766973696F6E206279209C",
51 ":100214006761746976652076616C756500636F72D9",51 ":100214007A65726F0072656D61696E6465722064DF",
52 ":100224007465782D6D3400696E646578206F75741B",52 ":1002240069766973696F6E206279207A65726F20CE",
53 ":10023400206F6620626F756E647300696E74656703",53 ":100234006F72206E656761746976652076616C758E",
54 ":1002440065722063617374207472756E6361746582",54 ":100244006500696E746567657220636173742074F8",
55 ":10025400642062697473006469766973696F6E20DF",55 ":1002540072756E6361746564206269747300696E9B",
56 ":100264006279207A65726F00636F727465785F6D6E",56 ":10026400646578206F7574206F6620626F756E64A4",
57 ":100274003400000081B00091FFE700BEFDE7D0B577",57 ":100274007300000081B00091FFE700BEFDE7D0B538",
58 ":1002840002AF90B00391029007A800F029F80399F7",58 ":1002840002AF90B00391029007A800F029F80399F7",
59 ":100294000020069048680490FFE7049906980190AE",59 ":100294000020069048680490FFE7049906980190AE",
60 ":1002A40088420FD2FFE7019903980068405C07F881",60 ":1002A40088420FD2FFE7019903980068405C07F881",
...@@ -89,7 +89,7 @@ pub fn build(b: *Builder) void {...@@ -89,7 +89,7 @@ pub fn build(b: *Builder) void {
89 ":1001140000000000000000000000000000000000DB",89 ":1001140000000000000000000000000000000000DB",
90 ":1001240000000000000000000000000000000000CB",90 ":1001240000000000000000000000000000000000CB",
91 ":1001340000000000000000000000000000000000BB",91 ":1001340000000000000000000000000000000000BB",
92 ":10014400830202006C020100090000002102010088",92 ":1001440083020200F401010009000000FE01010025",
93 ":100154000900000001000000000000000000000091",93 ":100154000900000001000000000000000000000091",
94 ":1001640000080002008001010004000010000000EB",94 ":1001640000080002008001010004000010000000EB",
95 ":100174000000000000000000000000001F0000005C",95 ":100174000000000000000000000000001F0000005C",
...@@ -98,17 +98,17 @@ pub fn build(b: *Builder) void {...@@ -98,17 +98,17 @@ pub fn build(b: *Builder) void {
98 ":1001A40000000000000000001F000000000000002C",98 ":1001A40000000000000000001F000000000000002C",
99 ":1001B400000000000000000000000000000000003B",99 ":1001B400000000000000000000000000000000003B",
100 ":1001C400000000000000000000000000000000002B",100 ":1001C400000000000000000000000000000000002B",
101 ":1001D4005B02010010000000F40101002C0000008B",101 ":1001D4000802010010000000190201002C000000B8",
102 ":1001E4003F0201001B0000002B020100130000006D",102 ":1001E400460201001B00000062020100130000002F",
103 ":1001F40072656D61696E646572206469766973699C",103 ":1001F400636F727465785F6D3400636F72746578D1",
104 ":100204006F6E206279207A65726F206F72206E653E",104 ":100204002D6D34006469766973696F6E206279209C",
105 ":100214006761746976652076616C756500636F72D9",105 ":100214007A65726F0072656D61696E6465722064DF",
106 ":100224007465782D6D3400696E646578206F75741B",106 ":1002240069766973696F6E206279207A65726F20CE",
107 ":10023400206F6620626F756E647300696E74656703",107 ":100234006F72206E656761746976652076616C758E",
108 ":1002440065722063617374207472756E6361746582",108 ":100244006500696E746567657220636173742074F8",
109 ":10025400642062697473006469766973696F6E20DF",109 ":1002540072756E6361746564206269747300696E9B",
110 ":100264006279207A65726F00636F727465785F6D6E",110 ":10026400646578206F7574206F6620626F756E64A4",
111 ":100274003400000081B00091FFE700BEFDE7D0B577",111 ":100274007300000081B00091FFE700BEFDE7D0B538",
112 ":1002840002AF90B00391029007A800F029F80399F7",112 ":1002840002AF90B00391029007A800F029F80399F7",
113 ":100294000020069048680490FFE7049906980190AE",113 ":100294000020069048680490FFE7049906980190AE",
114 ":1002A40088420FD2FFE7019903980068405C07F881",114 ":1002A40088420FD2FFE7019903980068405C07F881",