| ... | ... | @@ -809,6 +809,36 @@ pub fn updateDeclExports( |
| 809 | 809 | if (build_options.skip_non_native and builtin.object_format != .coff) { |
| 810 | 810 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 811 | 811 | } |
| 812 | |
| 813 | // Even in the case of LLVM, we need to notice certain exported symbols in order to |
| 814 | // detect the default subsystem. |
| 815 | for (exports) |exp| { |
| 816 | const exported_decl = module.declPtr(exp.exported_decl); |
| 817 | if (exported_decl.getFunction() == null) continue; |
| 818 | const winapi_cc = switch (self.base.options.target.cpu.arch) { |
| 819 | .i386 => std.builtin.CallingConvention.Stdcall, |
| 820 | else => std.builtin.CallingConvention.C, |
| 821 | }; |
| 822 | const decl_cc = exported_decl.ty.fnCallingConvention(); |
| 823 | if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and |
| 824 | self.base.options.link_libc) |
| 825 | { |
| 826 | module.stage1_flags.have_c_main = true; |
| 827 | } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) { |
| 828 | if (mem.eql(u8, exp.options.name, "WinMain")) { |
| 829 | module.stage1_flags.have_winmain = true; |
| 830 | } else if (mem.eql(u8, exp.options.name, "wWinMain")) { |
| 831 | module.stage1_flags.have_wwinmain = true; |
| 832 | } else if (mem.eql(u8, exp.options.name, "WinMainCRTStartup")) { |
| 833 | module.stage1_flags.have_winmain_crt_startup = true; |
| 834 | } else if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) { |
| 835 | module.stage1_flags.have_wwinmain_crt_startup = true; |
| 836 | } else if (mem.eql(u8, exp.options.name, "DllMainCRTStartup")) { |
| 837 | module.stage1_flags.have_dllmain_crt_startup = true; |
| 838 | } |
| 839 | } |
| 840 | } |
| 841 | |
| 812 | 842 | if (build_options.have_llvm) { |
| 813 | 843 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports); |
| 814 | 844 | } |
| ... | ... | @@ -1114,17 +1144,6 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 1114 | 1144 | try argv.append("-dynamicbase"); |
| 1115 | 1145 | } |
| 1116 | 1146 | |
| 1117 | | const subsystem_suffix = ss: { |
| 1118 | | if (self.base.options.major_subsystem_version) |major| { |
| 1119 | | if (self.base.options.minor_subsystem_version) |minor| { |
| 1120 | | break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); |
| 1121 | | } else { |
| 1122 | | break :ss try allocPrint(arena, ",{d}", .{major}); |
| 1123 | | } |
| 1124 | | } |
| 1125 | | break :ss ""; |
| 1126 | | }; |
| 1127 | | |
| 1128 | 1147 | try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); |
| 1129 | 1148 | |
| 1130 | 1149 | if (self.base.options.implib_emit) |emit| { |
| ... | ... | @@ -1186,57 +1205,71 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 1186 | 1205 | } |
| 1187 | 1206 | break :blk null; |
| 1188 | 1207 | }; |
| 1208 | |
| 1189 | 1209 | const Mode = enum { uefi, win32 }; |
| 1190 | 1210 | const mode: Mode = mode: { |
| 1191 | | if (resolved_subsystem) |subsystem| switch (subsystem) { |
| 1192 | | .Console => { |
| 1193 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{ |
| 1194 | | subsystem_suffix, |
| 1195 | | })); |
| 1196 | | break :mode .win32; |
| 1197 | | }, |
| 1198 | | .EfiApplication => { |
| 1199 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{ |
| 1200 | | subsystem_suffix, |
| 1201 | | })); |
| 1202 | | break :mode .uefi; |
| 1203 | | }, |
| 1204 | | .EfiBootServiceDriver => { |
| 1205 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{ |
| 1206 | | subsystem_suffix, |
| 1207 | | })); |
| 1208 | | break :mode .uefi; |
| 1209 | | }, |
| 1210 | | .EfiRom => { |
| 1211 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{ |
| 1212 | | subsystem_suffix, |
| 1213 | | })); |
| 1214 | | break :mode .uefi; |
| 1215 | | }, |
| 1216 | | .EfiRuntimeDriver => { |
| 1217 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{ |
| 1218 | | subsystem_suffix, |
| 1219 | | })); |
| 1220 | | break :mode .uefi; |
| 1221 | | }, |
| 1222 | | .Native => { |
| 1223 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{ |
| 1224 | | subsystem_suffix, |
| 1225 | | })); |
| 1226 | | break :mode .win32; |
| 1227 | | }, |
| 1228 | | .Posix => { |
| 1229 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{ |
| 1230 | | subsystem_suffix, |
| 1231 | | })); |
| 1232 | | break :mode .win32; |
| 1233 | | }, |
| 1234 | | .Windows => { |
| 1235 | | try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{ |
| 1236 | | subsystem_suffix, |
| 1237 | | })); |
| 1238 | | break :mode .win32; |
| 1239 | | }, |
| 1211 | if (resolved_subsystem) |subsystem| { |
| 1212 | const subsystem_suffix = ss: { |
| 1213 | if (self.base.options.major_subsystem_version) |major| { |
| 1214 | if (self.base.options.minor_subsystem_version) |minor| { |
| 1215 | break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); |
| 1216 | } else { |
| 1217 | break :ss try allocPrint(arena, ",{d}", .{major}); |
| 1218 | } |
| 1219 | } |
| 1220 | break :ss ""; |
| 1221 | }; |
| 1222 | |
| 1223 | switch (subsystem) { |
| 1224 | .Console => { |
| 1225 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{ |
| 1226 | subsystem_suffix, |
| 1227 | })); |
| 1228 | break :mode .win32; |
| 1229 | }, |
| 1230 | .EfiApplication => { |
| 1231 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{ |
| 1232 | subsystem_suffix, |
| 1233 | })); |
| 1234 | break :mode .uefi; |
| 1235 | }, |
| 1236 | .EfiBootServiceDriver => { |
| 1237 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{ |
| 1238 | subsystem_suffix, |
| 1239 | })); |
| 1240 | break :mode .uefi; |
| 1241 | }, |
| 1242 | .EfiRom => { |
| 1243 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{ |
| 1244 | subsystem_suffix, |
| 1245 | })); |
| 1246 | break :mode .uefi; |
| 1247 | }, |
| 1248 | .EfiRuntimeDriver => { |
| 1249 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{ |
| 1250 | subsystem_suffix, |
| 1251 | })); |
| 1252 | break :mode .uefi; |
| 1253 | }, |
| 1254 | .Native => { |
| 1255 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{ |
| 1256 | subsystem_suffix, |
| 1257 | })); |
| 1258 | break :mode .win32; |
| 1259 | }, |
| 1260 | .Posix => { |
| 1261 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{ |
| 1262 | subsystem_suffix, |
| 1263 | })); |
| 1264 | break :mode .win32; |
| 1265 | }, |
| 1266 | .Windows => { |
| 1267 | try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{ |
| 1268 | subsystem_suffix, |
| 1269 | })); |
| 1270 | break :mode .win32; |
| 1271 | }, |
| 1272 | } |
| 1240 | 1273 | } else if (target.os.tag == .uefi) { |
| 1241 | 1274 | break :mode .uefi; |
| 1242 | 1275 | } else { |