| ... | ... | @@ -1137,53 +1137,121 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si |
| 1137 | 1137 | } |
| 1138 | 1138 | |
| 1139 | 1139 | static void add_uefi_link_args(LinkJob *lj) { |
| 1140 | | lj->args.append("/BASE:0"); |
| 1141 | | lj->args.append("/ENTRY:EfiMain"); |
| 1142 | | lj->args.append("/OPT:REF"); |
| 1143 | | lj->args.append("/SAFESEH:NO"); |
| 1144 | | lj->args.append("/MERGE:.rdata=.data"); |
| 1145 | | lj->args.append("/ALIGN:32"); |
| 1146 | | lj->args.append("/NODEFAULTLIB"); |
| 1147 | | lj->args.append("/SECTION:.xdata,D"); |
| 1140 | lj->args.append("-BASE:0"); |
| 1141 | lj->args.append("-ENTRY:EfiMain"); |
| 1142 | lj->args.append("-OPT:REF"); |
| 1143 | lj->args.append("-SAFESEH:NO"); |
| 1144 | lj->args.append("-MERGE:.rdata=.data"); |
| 1145 | lj->args.append("-ALIGN:32"); |
| 1146 | lj->args.append("-NODEFAULTLIB"); |
| 1147 | lj->args.append("-SECTION:.xdata,D"); |
| 1148 | 1148 | } |
| 1149 | 1149 | |
| 1150 | | static void add_nt_link_args(LinkJob *lj, bool is_library) { |
| 1150 | static void add_msvc_link_args(LinkJob *lj, bool is_library) { |
| 1151 | 1151 | CodeGen *g = lj->codegen; |
| 1152 | 1152 | |
| 1153 | | if (lj->link_in_crt) { |
| 1154 | | // TODO: https://github.com/ziglang/zig/issues/2064 |
| 1155 | | bool is_dynamic = true; // g->is_dynamic; |
| 1156 | | const char *lib_str = is_dynamic ? "" : "lib"; |
| 1157 | | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; |
| 1158 | | |
| 1159 | | if (!is_dynamic) { |
| 1160 | | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); |
| 1161 | | lj->args.append(buf_ptr(cmt_lib_name)); |
| 1162 | | } else { |
| 1163 | | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); |
| 1164 | | lj->args.append(buf_ptr(msvcrt_lib_name)); |
| 1165 | | } |
| 1153 | // TODO: https://github.com/ziglang/zig/issues/2064 |
| 1154 | bool is_dynamic = true; // g->is_dynamic; |
| 1155 | const char *lib_str = is_dynamic ? "" : "lib"; |
| 1156 | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; |
| 1157 | |
| 1158 | if (!is_dynamic) { |
| 1159 | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); |
| 1160 | lj->args.append(buf_ptr(cmt_lib_name)); |
| 1161 | } else { |
| 1162 | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); |
| 1163 | lj->args.append(buf_ptr(msvcrt_lib_name)); |
| 1164 | } |
| 1165 | |
| 1166 | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); |
| 1167 | lj->args.append(buf_ptr(vcruntime_lib_name)); |
| 1168 | |
| 1169 | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); |
| 1170 | lj->args.append(buf_ptr(crt_lib_name)); |
| 1171 | |
| 1172 | //Visual C++ 2015 Conformance Changes |
| 1173 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx |
| 1174 | lj->args.append("legacy_stdio_definitions.lib"); |
| 1175 | |
| 1176 | // msvcrt depends on kernel32 and ntdll |
| 1177 | lj->args.append("kernel32.lib"); |
| 1178 | lj->args.append("ntdll.lib"); |
| 1179 | } |
| 1166 | 1180 | |
| 1167 | | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); |
| 1168 | | lj->args.append(buf_ptr(vcruntime_lib_name)); |
| 1181 | static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) { |
| 1182 | Buf *out_buf = buf_alloc(); |
| 1183 | os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf); |
| 1184 | return buf_ptr(out_buf); |
| 1185 | } |
| 1186 | |
| 1187 | static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) { |
| 1188 | Buf *out_buf = buf_alloc(); |
| 1189 | os_path_join(&lib->static_crt_dir, buf_create_from_str(file), out_buf); |
| 1190 | return buf_ptr(out_buf); |
| 1191 | } |
| 1169 | 1192 | |
| 1170 | | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); |
| 1171 | | lj->args.append(buf_ptr(crt_lib_name)); |
| 1193 | static void add_mingw_link_args(LinkJob *lj, bool is_library) { |
| 1194 | CodeGen *g = lj->codegen; |
| 1172 | 1195 | |
| 1173 | | //Visual C++ 2015 Conformance Changes |
| 1174 | | //https://msdn.microsoft.com/en-us/library/bb531344.aspx |
| 1175 | | lj->args.append("legacy_stdio_definitions.lib"); |
| 1196 | bool is_dll = g->out_type == OutTypeLib && g->is_dynamic; |
| 1176 | 1197 | |
| 1177 | | // msvcrt depends on kernel32 and ntdll |
| 1178 | | lj->args.append("kernel32.lib"); |
| 1179 | | lj->args.append("ntdll.lib"); |
| 1198 | if (g->zig_target->arch == ZigLLVM_x86) { |
| 1199 | lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase"); |
| 1180 | 1200 | } else { |
| 1181 | | lj->args.append("/NODEFAULTLIB"); |
| 1201 | lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase"); |
| 1202 | } |
| 1203 | |
| 1204 | if (is_dll) { |
| 1205 | lj->args.append(get_libc_file(g->libc, "dllcrt2.o")); |
| 1206 | } else { |
| 1207 | lj->args.append(get_libc_file(g->libc, "crt2.o")); |
| 1208 | } |
| 1209 | |
| 1210 | lj->args.append(get_libc_static_file(g->libc, "crtbegin.o")); |
| 1211 | |
| 1212 | lj->args.append(get_libc_file(g->libc, "libmingw32.a")); |
| 1213 | |
| 1214 | if (is_dll) { |
| 1215 | lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a")); |
| 1216 | lj->args.append(get_libc_static_file(g->libc, "libgcc.a")); |
| 1217 | } else { |
| 1218 | lj->args.append(get_libc_static_file(g->libc, "libgcc.a")); |
| 1219 | lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a")); |
| 1220 | } |
| 1221 | |
| 1222 | lj->args.append(get_libc_static_file(g->libc, "libssp.a")); |
| 1223 | lj->args.append(get_libc_file(g->libc, "libmoldname.a")); |
| 1224 | lj->args.append(get_libc_file(g->libc, "libmingwex.a")); |
| 1225 | lj->args.append(get_libc_file(g->libc, "libmsvcrt.a")); |
| 1226 | |
| 1227 | if (g->subsystem == TargetSubsystemWindows) { |
| 1228 | lj->args.append(get_libc_file(g->libc, "libgdi32.a")); |
| 1229 | lj->args.append(get_libc_file(g->libc, "libcomdlg32.a")); |
| 1230 | } |
| 1231 | |
| 1232 | lj->args.append(get_libc_file(g->libc, "libadvapi32.a")); |
| 1233 | lj->args.append(get_libc_file(g->libc, "libadvapi32.a")); |
| 1234 | lj->args.append(get_libc_file(g->libc, "libshell32.a")); |
| 1235 | lj->args.append(get_libc_file(g->libc, "libuser32.a")); |
| 1236 | lj->args.append(get_libc_file(g->libc, "libkernel32.a")); |
| 1237 | |
| 1238 | lj->args.append(get_libc_static_file(g->libc, "crtend.o")); |
| 1239 | } |
| 1240 | |
| 1241 | static void add_win_link_args(LinkJob *lj, bool is_library) { |
| 1242 | if (lj->link_in_crt) { |
| 1243 | if (target_abi_is_gnu(lj->codegen->zig_target->abi)) { |
| 1244 | add_mingw_link_args(lj, is_library); |
| 1245 | } else { |
| 1246 | add_msvc_link_args(lj, is_library); |
| 1247 | } |
| 1248 | } else { |
| 1249 | lj->args.append("-NODEFAULTLIB"); |
| 1182 | 1250 | if (!is_library) { |
| 1183 | | if (g->have_winmain) { |
| 1184 | | lj->args.append("/ENTRY:WinMain"); |
| 1251 | if (lj->codegen->have_winmain) { |
| 1252 | lj->args.append("-ENTRY:WinMain"); |
| 1185 | 1253 | } else { |
| 1186 | | lj->args.append("/ENTRY:WinMainCRTStartup"); |
| 1254 | lj->args.append("-ENTRY:WinMainCRTStartup"); |
| 1187 | 1255 | } |
| 1188 | 1256 | } |
| 1189 | 1257 | } |
| ... | ... | @@ -1193,87 +1261,93 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1193 | 1261 | Error err; |
| 1194 | 1262 | CodeGen *g = lj->codegen; |
| 1195 | 1263 | |
| 1196 | | lj->args.append("/ERRORLIMIT:0"); |
| 1264 | lj->args.append("-ERRORLIMIT:0"); |
| 1197 | 1265 | |
| 1198 | | lj->args.append("/NOLOGO"); |
| 1266 | lj->args.append("-NOLOGO"); |
| 1199 | 1267 | |
| 1200 | 1268 | if (!g->strip_debug_symbols) { |
| 1201 | | lj->args.append("/DEBUG"); |
| 1269 | lj->args.append("-DEBUG"); |
| 1202 | 1270 | } |
| 1203 | 1271 | |
| 1204 | 1272 | if (g->out_type == OutTypeExe) { |
| 1205 | 1273 | // TODO compile time stack upper bound detection |
| 1206 | | lj->args.append("/STACK:16777216"); |
| 1274 | lj->args.append("-STACK:16777216"); |
| 1207 | 1275 | } |
| 1208 | 1276 | |
| 1209 | 1277 | coff_append_machine_arg(g, &lj->args); |
| 1210 | 1278 | |
| 1211 | 1279 | bool is_library = g->out_type == OutTypeLib; |
| 1280 | if (is_library && g->is_dynamic) { |
| 1281 | lj->args.append("-DLL"); |
| 1282 | } |
| 1283 | |
| 1284 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); |
| 1285 | |
| 1286 | if (g->libc_link_lib != nullptr) { |
| 1287 | assert(g->libc != nullptr); |
| 1288 | |
| 1289 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); |
| 1290 | |
| 1291 | if (target_abi_is_gnu(g->zig_target->abi)) { |
| 1292 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir)))); |
| 1293 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir)))); |
| 1294 | } else { |
| 1295 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); |
| 1296 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); |
| 1297 | } |
| 1298 | } |
| 1299 | |
| 1300 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { |
| 1301 | const char *lib_dir = g->lib_dirs.at(i); |
| 1302 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); |
| 1303 | } |
| 1304 | |
| 1305 | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| 1306 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 1307 | } |
| 1308 | |
| 1212 | 1309 | switch (g->subsystem) { |
| 1213 | 1310 | case TargetSubsystemAuto: |
| 1214 | 1311 | if (g->zig_target->os == OsUefi) { |
| 1215 | 1312 | add_uefi_link_args(lj); |
| 1216 | 1313 | } else { |
| 1217 | | add_nt_link_args(lj, is_library); |
| 1314 | add_win_link_args(lj, is_library); |
| 1218 | 1315 | } |
| 1219 | 1316 | break; |
| 1220 | 1317 | case TargetSubsystemConsole: |
| 1221 | | lj->args.append("/SUBSYSTEM:console"); |
| 1222 | | add_nt_link_args(lj, is_library); |
| 1318 | lj->args.append("-SUBSYSTEM:console"); |
| 1319 | add_win_link_args(lj, is_library); |
| 1223 | 1320 | break; |
| 1224 | 1321 | case TargetSubsystemEfiApplication: |
| 1225 | | lj->args.append("/SUBSYSTEM:efi_application"); |
| 1322 | lj->args.append("-SUBSYSTEM:efi_application"); |
| 1226 | 1323 | add_uefi_link_args(lj); |
| 1227 | 1324 | break; |
| 1228 | 1325 | case TargetSubsystemEfiBootServiceDriver: |
| 1229 | | lj->args.append("/SUBSYSTEM:efi_boot_service_driver"); |
| 1326 | lj->args.append("-SUBSYSTEM:efi_boot_service_driver"); |
| 1230 | 1327 | add_uefi_link_args(lj); |
| 1231 | 1328 | break; |
| 1232 | 1329 | case TargetSubsystemEfiRom: |
| 1233 | | lj->args.append("/SUBSYSTEM:efi_rom"); |
| 1330 | lj->args.append("-SUBSYSTEM:efi_rom"); |
| 1234 | 1331 | add_uefi_link_args(lj); |
| 1235 | 1332 | break; |
| 1236 | 1333 | case TargetSubsystemEfiRuntimeDriver: |
| 1237 | | lj->args.append("/SUBSYSTEM:efi_runtime_driver"); |
| 1334 | lj->args.append("-SUBSYSTEM:efi_runtime_driver"); |
| 1238 | 1335 | add_uefi_link_args(lj); |
| 1239 | 1336 | break; |
| 1240 | 1337 | case TargetSubsystemNative: |
| 1241 | | lj->args.append("/SUBSYSTEM:native"); |
| 1242 | | add_nt_link_args(lj, is_library); |
| 1338 | lj->args.append("-SUBSYSTEM:native"); |
| 1339 | add_win_link_args(lj, is_library); |
| 1243 | 1340 | break; |
| 1244 | 1341 | case TargetSubsystemPosix: |
| 1245 | | lj->args.append("/SUBSYSTEM:posix"); |
| 1246 | | add_nt_link_args(lj, is_library); |
| 1342 | lj->args.append("-SUBSYSTEM:posix"); |
| 1343 | add_win_link_args(lj, is_library); |
| 1247 | 1344 | break; |
| 1248 | 1345 | case TargetSubsystemWindows: |
| 1249 | | lj->args.append("/SUBSYSTEM:windows"); |
| 1250 | | add_nt_link_args(lj, is_library); |
| 1346 | lj->args.append("-SUBSYSTEM:windows"); |
| 1347 | add_win_link_args(lj, is_library); |
| 1251 | 1348 | break; |
| 1252 | 1349 | } |
| 1253 | 1350 | |
| 1254 | | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); |
| 1255 | | |
| 1256 | | if (g->libc_link_lib != nullptr) { |
| 1257 | | assert(g->libc != nullptr); |
| 1258 | | |
| 1259 | | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); |
| 1260 | | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); |
| 1261 | | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); |
| 1262 | | } |
| 1263 | | |
| 1264 | | if (is_library && g->is_dynamic) { |
| 1265 | | lj->args.append("-DLL"); |
| 1266 | | } |
| 1267 | | |
| 1268 | | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { |
| 1269 | | const char *lib_dir = g->lib_dirs.at(i); |
| 1270 | | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); |
| 1271 | | } |
| 1272 | | |
| 1273 | | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| 1274 | | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| 1275 | | } |
| 1276 | | |
| 1277 | 1351 | if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { |
| 1278 | 1352 | if (g->libc_link_lib == nullptr && !g->is_dummy_so) { |
| 1279 | 1353 | Buf *builtin_a_path = build_a(g, "builtin"); |
| ... | ... | @@ -1293,11 +1367,10 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1293 | 1367 | continue; |
| 1294 | 1368 | } |
| 1295 | 1369 | if (link_lib->provided_explicitly) { |
| 1296 | | if (lj->codegen->zig_target->abi == ZigLLVM_GNU) { |
| 1297 | | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); |
| 1298 | | lj->args.append(buf_ptr(arg)); |
| 1299 | | } |
| 1300 | | else { |
| 1370 | if (target_abi_is_gnu(lj->codegen->zig_target->abi)) { |
| 1371 | Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name)); |
| 1372 | lj->args.append(buf_ptr(lib_name)); |
| 1373 | } else { |
| 1301 | 1374 | lj->args.append(buf_ptr(link_lib->name)); |
| 1302 | 1375 | } |
| 1303 | 1376 | } else { |