Commit 0da7c4b0c8
Changed files (5)
lib
std
lib/std/zig.zig
@@ -84,36 +84,36 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro
.uefi => ".efi",
else => ".exe",
};
- return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, suffix });
+ return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, suffix });
},
.Lib => {
const suffix = switch (options.link_mode orelse .Static) {
.Static => ".lib",
.Dynamic => ".dll",
};
- return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
+ return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, suffix });
},
- .Obj => return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, target.abi.oFileExt() }),
+ .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.abi.oFileExt() }),
},
.elf => switch (options.output_mode) {
.Exe => return allocator.dupe(u8, root_name),
.Lib => {
switch (options.link_mode orelse .Static) {
- .Static => return std.fmt.allocPrint(allocator, "{}{}.a", .{
+ .Static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{
target.libPrefix(), root_name,
}),
.Dynamic => {
if (options.version) |ver| {
- return std.fmt.allocPrint(allocator, "{}{}.so.{}.{}.{}", .{
+ return std.fmt.allocPrint(allocator, "{s}{s}.so.{d}.{d}.{d}", .{
target.libPrefix(), root_name, ver.major, ver.minor, ver.patch,
});
} else {
- return std.fmt.allocPrint(allocator, "{}{}.so", .{ target.libPrefix(), root_name });
+ return std.fmt.allocPrint(allocator, "{s}{s}.so", .{ target.libPrefix(), root_name });
}
},
}
},
- .Obj => return std.fmt.allocPrint(allocator, "{}.o", .{root_name}),
+ .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}),
},
.macho => switch (options.output_mode) {
.Exe => return allocator.dupe(u8, root_name),
@@ -122,14 +122,14 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro
.Static => ".a",
.Dynamic => ".dylib",
};
- return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
+ return std.fmt.allocPrint(allocator, "{s}{s}{s}", .{ target.libPrefix(), root_name, suffix });
},
- .Obj => return std.fmt.allocPrint(allocator, "{}.o", .{root_name}),
+ .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}),
},
- .wasm => return std.fmt.allocPrint(allocator, "{}.wasm", .{root_name}),
- .c => return std.fmt.allocPrint(allocator, "{}.c", .{root_name}),
- .hex => return std.fmt.allocPrint(allocator, "{}.ihex", .{root_name}),
- .raw => return std.fmt.allocPrint(allocator, "{}.bin", .{root_name}),
+ .wasm => return std.fmt.allocPrint(allocator, "{s}.wasm", .{root_name}),
+ .c => return std.fmt.allocPrint(allocator, "{s}.c", .{root_name}),
+ .hex => return std.fmt.allocPrint(allocator, "{s}.ihex", .{root_name}),
+ .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}),
}
}
src/link/Coff.zig
@@ -873,287 +873,302 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
};
}
- const is_obj = self.base.options.output_mode == .Obj;
-
- // Create an LLD command line and invoke it.
- var argv = std.ArrayList([]const u8).init(self.base.allocator);
- defer argv.deinit();
- // Even though we're calling LLD as a library it thinks the first argument is its own exe name.
- try argv.append("lld");
- if (is_obj) {
- try argv.append("-r");
- }
+ const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
- try argv.append("-ERRORLIMIT:0");
- try argv.append("-NOLOGO");
- if (!self.base.options.strip) {
- try argv.append("-DEBUG");
- }
- if (self.base.options.output_mode == .Exe) {
- const stack_size = self.base.options.stack_size_override orelse 16777216;
- try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size}));
- }
+ if (self.base.options.output_mode == .Obj) {
+ // LLD's COFF driver does not support the equvialent of `-r` so we do a simple file copy
+ // here. TODO: think carefully about how we can avoid this redundant operation when doing
+ // build-obj. See also the corresponding TODO in linkAsArchive.
+ const the_object_path = blk: {
+ if (self.base.options.objects.len != 0)
+ break :blk self.base.options.objects[0];
- if (target.cpu.arch == .i386) {
- try argv.append("-MACHINE:X86");
- } else if (target.cpu.arch == .x86_64) {
- try argv.append("-MACHINE:X64");
- } else if (target.cpu.arch.isARM()) {
- if (target.cpu.arch.ptrBitWidth() == 32) {
- try argv.append("-MACHINE:ARM");
- } else {
- try argv.append("-MACHINE:ARM64");
+ if (comp.c_object_table.count() != 0)
+ break :blk comp.c_object_table.items()[0].key.status.success.object_path;
+
+ if (module_obj_path) |p|
+ break :blk p;
+
+ // TODO I think this is unreachable. Audit this situation when solving the above TODO
+ // regarding eliding redundant object -> object transformations.
+ return error.NoObjectsToLink;
+ };
+ try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
+ } else {
+ // Create an LLD command line and invoke it.
+ var argv = std.ArrayList([]const u8).init(self.base.allocator);
+ defer argv.deinit();
+ // Even though we're calling LLD as a library it thinks the first argument is its own exe name.
+ try argv.append("lld");
+
+ try argv.append("-ERRORLIMIT:0");
+ try argv.append("-NOLOGO");
+ if (!self.base.options.strip) {
+ try argv.append("-DEBUG");
+ }
+ if (self.base.options.output_mode == .Exe) {
+ const stack_size = self.base.options.stack_size_override orelse 16777216;
+ try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size}));
}
- }
- if (is_dyn_lib) {
- try argv.append("-DLL");
- }
+ if (target.cpu.arch == .i386) {
+ try argv.append("-MACHINE:X86");
+ } else if (target.cpu.arch == .x86_64) {
+ try argv.append("-MACHINE:X64");
+ } else if (target.cpu.arch.isARM()) {
+ if (target.cpu.arch.ptrBitWidth() == 32) {
+ try argv.append("-MACHINE:ARM");
+ } else {
+ try argv.append("-MACHINE:ARM64");
+ }
+ }
- const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
- try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
+ if (is_dyn_lib) {
+ try argv.append("-DLL");
+ }
- if (self.base.options.link_libc) {
- if (self.base.options.libc_installation) |libc_installation| {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
+ try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
- if (target.abi == .msvc) {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
+ if (self.base.options.link_libc) {
+ if (self.base.options.libc_installation) |libc_installation| {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
+
+ if (target.abi == .msvc) {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
+ }
}
}
- }
- for (self.base.options.lib_dirs) |lib_dir| {
- try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
- }
+ for (self.base.options.lib_dirs) |lib_dir| {
+ try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
+ }
- try argv.appendSlice(self.base.options.objects);
+ try argv.appendSlice(self.base.options.objects);
- for (comp.c_object_table.items()) |entry| {
- try argv.append(entry.key.status.success.object_path);
- }
+ for (comp.c_object_table.items()) |entry| {
+ try argv.append(entry.key.status.success.object_path);
+ }
- if (module_obj_path) |p| {
- try argv.append(p);
- }
+ if (module_obj_path) |p| {
+ try argv.append(p);
+ }
- const resolved_subsystem: ?std.Target.SubSystem = blk: {
- if (self.base.options.subsystem) |explicit| break :blk explicit;
- switch (target.os.tag) {
- .windows => {
- if (self.base.options.module) |module| {
- if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
- break :blk null;
- if (module.stage1_flags.have_c_main or self.base.options.is_test or
- module.stage1_flags.have_winmain_crt_startup or
- module.stage1_flags.have_wwinmain_crt_startup)
- {
- break :blk .Console;
+ const resolved_subsystem: ?std.Target.SubSystem = blk: {
+ if (self.base.options.subsystem) |explicit| break :blk explicit;
+ switch (target.os.tag) {
+ .windows => {
+ if (self.base.options.module) |module| {
+ if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
+ break :blk null;
+ if (module.stage1_flags.have_c_main or self.base.options.is_test or
+ module.stage1_flags.have_winmain_crt_startup or
+ module.stage1_flags.have_wwinmain_crt_startup)
+ {
+ break :blk .Console;
+ }
+ if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)
+ break :blk .Windows;
}
- if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)
- break :blk .Windows;
- }
- },
- .uefi => break :blk .EfiApplication,
- else => {},
- }
- break :blk null;
- };
- const Mode = enum { uefi, win32 };
- const mode: Mode = mode: {
- if (resolved_subsystem) |subsystem| switch (subsystem) {
- .Console => {
- try argv.append("-SUBSYSTEM:console");
- break :mode .win32;
- },
- .EfiApplication => {
- try argv.append("-SUBSYSTEM:efi_application");
- break :mode .uefi;
- },
- .EfiBootServiceDriver => {
- try argv.append("-SUBSYSTEM:efi_boot_service_driver");
- break :mode .uefi;
- },
- .EfiRom => {
- try argv.append("-SUBSYSTEM:efi_rom");
- break :mode .uefi;
- },
- .EfiRuntimeDriver => {
- try argv.append("-SUBSYSTEM:efi_runtime_driver");
+ },
+ .uefi => break :blk .EfiApplication,
+ else => {},
+ }
+ break :blk null;
+ };
+ const Mode = enum { uefi, win32 };
+ const mode: Mode = mode: {
+ if (resolved_subsystem) |subsystem| switch (subsystem) {
+ .Console => {
+ try argv.append("-SUBSYSTEM:console");
+ break :mode .win32;
+ },
+ .EfiApplication => {
+ try argv.append("-SUBSYSTEM:efi_application");
+ break :mode .uefi;
+ },
+ .EfiBootServiceDriver => {
+ try argv.append("-SUBSYSTEM:efi_boot_service_driver");
+ break :mode .uefi;
+ },
+ .EfiRom => {
+ try argv.append("-SUBSYSTEM:efi_rom");
+ break :mode .uefi;
+ },
+ .EfiRuntimeDriver => {
+ try argv.append("-SUBSYSTEM:efi_runtime_driver");
+ break :mode .uefi;
+ },
+ .Native => {
+ try argv.append("-SUBSYSTEM:native");
+ break :mode .win32;
+ },
+ .Posix => {
+ try argv.append("-SUBSYSTEM:posix");
+ break :mode .win32;
+ },
+ .Windows => {
+ try argv.append("-SUBSYSTEM:windows");
+ break :mode .win32;
+ },
+ } else if (target.os.tag == .uefi) {
break :mode .uefi;
- },
- .Native => {
- try argv.append("-SUBSYSTEM:native");
- break :mode .win32;
- },
- .Posix => {
- try argv.append("-SUBSYSTEM:posix");
- break :mode .win32;
- },
- .Windows => {
- try argv.append("-SUBSYSTEM:windows");
+ } else {
break :mode .win32;
- },
- } else if (target.os.tag == .uefi) {
- break :mode .uefi;
- } else {
- break :mode .win32;
- }
- };
+ }
+ };
- switch (mode) {
- .uefi => try argv.appendSlice(&[_][]const u8{
- "-BASE:0",
- "-ENTRY:EfiMain",
- "-OPT:REF",
- "-SAFESEH:NO",
- "-MERGE:.rdata=.data",
- "-ALIGN:32",
- "-NODEFAULTLIB",
- "-SECTION:.xdata,D",
- }),
- .win32 => {
- if (link_in_crt) {
- if (target.abi.isGnu()) {
- try argv.append("-lldmingw");
-
- if (target.cpu.arch == .i386) {
- try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
- } else {
- try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
- }
+ switch (mode) {
+ .uefi => try argv.appendSlice(&[_][]const u8{
+ "-BASE:0",
+ "-ENTRY:EfiMain",
+ "-OPT:REF",
+ "-SAFESEH:NO",
+ "-MERGE:.rdata=.data",
+ "-ALIGN:32",
+ "-NODEFAULTLIB",
+ "-SECTION:.xdata,D",
+ }),
+ .win32 => {
+ if (link_in_crt) {
+ if (target.abi.isGnu()) {
+ try argv.append("-lldmingw");
+
+ if (target.cpu.arch == .i386) {
+ try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
+ } else {
+ try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
+ }
- if (is_dyn_lib) {
- try argv.append(try comp.get_libc_crt_file(arena, "dllcrt2.o"));
- } else {
- try argv.append(try comp.get_libc_crt_file(arena, "crt2.o"));
- }
+ if (is_dyn_lib) {
+ try argv.append(try comp.get_libc_crt_file(arena, "dllcrt2.o"));
+ } else {
+ try argv.append(try comp.get_libc_crt_file(arena, "crt2.o"));
+ }
- try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
- try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
- try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
+ try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
+ try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
+ try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
- for (mingw.always_link_libs) |name| {
- if (!self.base.options.system_libs.contains(name)) {
- const lib_basename = try allocPrint(arena, "{s}.lib", .{name});
- try argv.append(try comp.get_libc_crt_file(arena, lib_basename));
+ for (mingw.always_link_libs) |name| {
+ if (!self.base.options.system_libs.contains(name)) {
+ const lib_basename = try allocPrint(arena, "{s}.lib", .{name});
+ try argv.append(try comp.get_libc_crt_file(arena, lib_basename));
+ }
+ }
+ } else {
+ const lib_str = switch (self.base.options.link_mode) {
+ .Dynamic => "",
+ .Static => "lib",
+ };
+ const d_str = switch (self.base.options.optimize_mode) {
+ .Debug => "d",
+ else => "",
+ };
+ switch (self.base.options.link_mode) {
+ .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})),
+ .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})),
}
- }
- } else {
- const lib_str = switch (self.base.options.link_mode) {
- .Dynamic => "",
- .Static => "lib",
- };
- const d_str = switch (self.base.options.optimize_mode) {
- .Debug => "d",
- else => "",
- };
- switch (self.base.options.link_mode) {
- .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})),
- .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})),
- }
- try argv.append(try allocPrint(arena, "{s}vcruntime{s}.lib", .{ lib_str, d_str }));
- try argv.append(try allocPrint(arena, "{s}ucrt{s}.lib", .{ lib_str, d_str }));
+ try argv.append(try allocPrint(arena, "{s}vcruntime{s}.lib", .{ lib_str, d_str }));
+ try argv.append(try allocPrint(arena, "{s}ucrt{s}.lib", .{ lib_str, d_str }));
- //Visual C++ 2015 Conformance Changes
- //https://msdn.microsoft.com/en-us/library/bb531344.aspx
- try argv.append("legacy_stdio_definitions.lib");
+ //Visual C++ 2015 Conformance Changes
+ //https://msdn.microsoft.com/en-us/library/bb531344.aspx
+ try argv.append("legacy_stdio_definitions.lib");
- // msvcrt depends on kernel32 and ntdll
- try argv.append("kernel32.lib");
- try argv.append("ntdll.lib");
- }
- } else {
- try argv.append("-NODEFAULTLIB");
- if (!is_lib) {
- if (self.base.options.module) |module| {
- if (module.stage1_flags.have_winmain) {
- try argv.append("-ENTRY:WinMain");
- } else if (module.stage1_flags.have_wwinmain) {
- try argv.append("-ENTRY:wWinMain");
- } else if (module.stage1_flags.have_wwinmain_crt_startup) {
- try argv.append("-ENTRY:wWinMainCRTStartup");
+ // msvcrt depends on kernel32 and ntdll
+ try argv.append("kernel32.lib");
+ try argv.append("ntdll.lib");
+ }
+ } else {
+ try argv.append("-NODEFAULTLIB");
+ if (!is_lib) {
+ if (self.base.options.module) |module| {
+ if (module.stage1_flags.have_winmain) {
+ try argv.append("-ENTRY:WinMain");
+ } else if (module.stage1_flags.have_wwinmain) {
+ try argv.append("-ENTRY:wWinMain");
+ } else if (module.stage1_flags.have_wwinmain_crt_startup) {
+ try argv.append("-ENTRY:wWinMainCRTStartup");
+ } else {
+ try argv.append("-ENTRY:WinMainCRTStartup");
+ }
} else {
try argv.append("-ENTRY:WinMainCRTStartup");
}
- } else {
- try argv.append("-ENTRY:WinMainCRTStartup");
}
}
- }
- },
- }
+ },
+ }
- if (!is_obj) {
// libc++ dep
if (self.base.options.link_libcpp) {
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
try argv.append(comp.libcxx_static_lib.?.full_object_path);
try argv.append(comp.libunwind_static_lib.?.full_object_path);
}
- }
- // compiler-rt and libc
- if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) {
- if (!self.base.options.link_libc) {
- try argv.append(comp.libc_static_lib.?.full_object_path);
+ // compiler-rt and libc
+ if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) {
+ if (!self.base.options.link_libc) {
+ try argv.append(comp.libc_static_lib.?.full_object_path);
+ }
+ // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
+ // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
+ try argv.append(comp.compiler_rt_static_lib.?.full_object_path);
}
- // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
- // and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
- try argv.append(comp.compiler_rt_static_lib.?.full_object_path);
- }
- for (self.base.options.system_libs.items()) |entry| {
- const lib_basename = try allocPrint(arena, "{s}.lib", .{entry.key});
- if (comp.crt_files.get(lib_basename)) |crt_file| {
- try argv.append(crt_file.full_object_path);
- } else {
- try argv.append(lib_basename);
+ for (self.base.options.system_libs.items()) |entry| {
+ const lib_basename = try allocPrint(arena, "{s}.lib", .{entry.key});
+ if (comp.crt_files.get(lib_basename)) |crt_file| {
+ try argv.append(crt_file.full_object_path);
+ } else {
+ try argv.append(lib_basename);
+ }
}
- }
- if (self.base.options.verbose_link) {
- Compilation.dump_argv(argv.items);
- }
+ if (self.base.options.verbose_link) {
+ Compilation.dump_argv(argv.items);
+ }
- const new_argv = try arena.allocSentinel(?[*:0]const u8, argv.items.len, null);
- for (argv.items) |arg, i| {
- new_argv[i] = try arena.dupeZ(u8, arg);
- }
+ const new_argv = try arena.allocSentinel(?[*:0]const u8, argv.items.len, null);
+ for (argv.items) |arg, i| {
+ new_argv[i] = try arena.dupeZ(u8, arg);
+ }
- var stderr_context: LLDContext = .{
- .coff = self,
- .data = std.ArrayList(u8).init(self.base.allocator),
- };
- defer stderr_context.data.deinit();
- var stdout_context: LLDContext = .{
- .coff = self,
- .data = std.ArrayList(u8).init(self.base.allocator),
- };
- defer stdout_context.data.deinit();
- const llvm = @import("../llvm.zig");
- const ok = llvm.Link(
- .COFF,
- new_argv.ptr,
- new_argv.len,
- append_diagnostic,
- @ptrToInt(&stdout_context),
- @ptrToInt(&stderr_context),
- );
- if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory;
- if (stdout_context.data.items.len != 0) {
- std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items});
- }
- if (!ok) {
- // TODO parse this output and surface with the Compilation API rather than
- // directly outputting to stderr here.
- std.debug.print("{}", .{stderr_context.data.items});
- return error.LLDReportedFailure;
- }
- if (stderr_context.data.items.len != 0) {
- std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
+ var stderr_context: LLDContext = .{
+ .coff = self,
+ .data = std.ArrayList(u8).init(self.base.allocator),
+ };
+ defer stderr_context.data.deinit();
+ var stdout_context: LLDContext = .{
+ .coff = self,
+ .data = std.ArrayList(u8).init(self.base.allocator),
+ };
+ defer stdout_context.data.deinit();
+ const llvm = @import("../llvm.zig");
+ const ok = llvm.Link(
+ .COFF,
+ new_argv.ptr,
+ new_argv.len,
+ append_diagnostic,
+ @ptrToInt(&stdout_context),
+ @ptrToInt(&stderr_context),
+ );
+ if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory;
+ if (stdout_context.data.items.len != 0) {
+ std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items});
+ }
+ if (!ok) {
+ // TODO parse this output and surface with the Compilation API rather than
+ // directly outputting to stderr here.
+ std.debug.print("{}", .{stderr_context.data.items});
+ return error.LLDReportedFailure;
+ }
+ if (stderr_context.data.items.len != 0) {
+ std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
+ }
}
if (!self.base.options.disable_lld_caching) {
src/Compilation.zig
@@ -879,6 +879,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
try comp.work_queue.ensureUnusedCapacity(static_lib_jobs.len + 1);
comp.work_queue.writeAssumeCapacity(&static_lib_jobs);
comp.work_queue.writeItemAssumeCapacity(crt_job);
+
+ // When linking mingw-w64 there are some import libs we always need.
+ for (mingw.always_link_libs) |name| {
+ try comp.bin_file.options.system_libs.put(comp.gpa, name, .{});
+ }
}
// Generate Windows import libs.
if (comp.getTarget().os.tag == .windows) {
src/link.zig
@@ -321,7 +321,7 @@ pub const File = struct {
// TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
// Until then, we do `lld -r -o output.o input.o` even though the output is the same
// as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
- // to the final location.
+ // to the final location. See also the corresponding TODO in Coff linking.
const full_out_path = try emit.directory.join(comp.gpa, &[_][]const u8{emit.sub_path});
defer comp.gpa.free(full_out_path);
assert(comp.c_object_table.count() == 1);
src/main.zig
@@ -1314,8 +1314,8 @@ fn buildOutputType(
}
}
- const object_format: ?std.Target.ObjectFormat = blk: {
- const ofmt = target_ofmt orelse break :blk null;
+ const object_format: std.Target.ObjectFormat = blk: {
+ const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat();
if (mem.eql(u8, ofmt, "elf")) {
break :blk .elf;
} else if (mem.eql(u8, ofmt, "c")) {
@@ -1337,6 +1337,15 @@ fn buildOutputType(
}
};
+ if (output_mode == .Obj and object_format == .coff) {
+ const total_obj_count = c_source_files.items.len +
+ @boolToInt(root_src_file != null) +
+ link_objects.items.len;
+ if (total_obj_count > 1) {
+ fatal("COFF does not support linking multiple objects into one", .{});
+ }
+ }
+
var cleanup_emit_bin_dir: ?fs.Dir = null;
defer if (cleanup_emit_bin_dir) |*dir| dir.close();