| ... | @@ -1132,40 +1132,114 @@ static void add_uefi_link_args(LinkJob *lj) { | ... | @@ -1132,40 +1132,114 @@ static void add_uefi_link_args(LinkJob *lj) { |
| 1132 | lj->args.append("-SECTION:.xdata,D"); | 1132 | lj->args.append("-SECTION:.xdata,D"); |
| 1133 | } | 1133 | } |
| 1134 | | 1134 | |
| 1135 | static void add_nt_link_args(LinkJob *lj, bool is_library) { | 1135 | static void add_msvc_link_args(LinkJob *lj, bool is_library) { |
| 1136 | CodeGen *g = lj->codegen; | 1136 | CodeGen *g = lj->codegen; |
| 1137 | | 1137 | |
| 1138 | if (lj->link_in_crt) { | 1138 | // TODO: https://github.com/ziglang/zig/issues/2064 |
| 1139 | // TODO: https://github.com/ziglang/zig/issues/2064 | 1139 | bool is_dynamic = true; // g->is_dynamic; |
| 1140 | bool is_dynamic = true; // g->is_dynamic; | 1140 | const char *lib_str = is_dynamic ? "" : "lib"; |
| 1141 | const char *lib_str = is_dynamic ? "" : "lib"; | 1141 | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; |
| 1142 | const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : ""; | 1142 | |
| 1143 | | 1143 | if (!is_dynamic) { |
| 1144 | if (!is_dynamic) { | 1144 | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); |
| 1145 | Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str); | 1145 | lj->args.append(buf_ptr(cmt_lib_name)); |
| 1146 | lj->args.append(buf_ptr(cmt_lib_name)); | 1146 | } else { |
| | 1147 | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); |
| | 1148 | lj->args.append(buf_ptr(msvcrt_lib_name)); |
| | 1149 | } |
| | 1150 | |
| | 1151 | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); |
| | 1152 | lj->args.append(buf_ptr(vcruntime_lib_name)); |
| | 1153 | |
| | 1154 | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); |
| | 1155 | lj->args.append(buf_ptr(crt_lib_name)); |
| | 1156 | |
| | 1157 | //Visual C++ 2015 Conformance Changes |
| | 1158 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx |
| | 1159 | lj->args.append("legacy_stdio_definitions.lib"); |
| | 1160 | |
| | 1161 | // msvcrt depends on kernel32 and ntdll |
| | 1162 | lj->args.append("kernel32.lib"); |
| | 1163 | lj->args.append("ntdll.lib"); |
| | 1164 | } |
| | 1165 | |
| | 1166 | static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) { |
| | 1167 | Buf *out_buf = buf_alloc(); |
| | 1168 | os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf); |
| | 1169 | return buf_ptr(out_buf); |
| | 1170 | } |
| | 1171 | |
| | 1172 | static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) { |
| | 1173 | Buf *static_crt_dir = buf_alloc(); |
| | 1174 | Buf *out_buf = buf_alloc(); |
| | 1175 | if (zig_libc_cc_print_file_name(file, static_crt_dir, true, true) != ErrorNone) { |
| | 1176 | abort(); |
| | 1177 | } |
| | 1178 | os_path_join(static_crt_dir, buf_create_from_str(file), out_buf); |
| | 1179 | return buf_ptr(out_buf); |
| | 1180 | } |
| | 1181 | |
| | 1182 | static void add_gnu_link_args(LinkJob *lj, bool is_library) { |
| | 1183 | CodeGen *g = lj->codegen; |
| | 1184 | |
| | 1185 | bool is_dll = g->out_type == OutTypeLib && g->is_dynamic; |
| | 1186 | |
| | 1187 | if (g->zig_target->arch == ZigLLVM_x86) { |
| | 1188 | lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase"); |
| | 1189 | } else { |
| | 1190 | lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase"); |
| | 1191 | } |
| | 1192 | |
| | 1193 | if (is_dll) { |
| | 1194 | lj->args.append(get_libc_file(g->libc, "dllcrt2.o")); |
| | 1195 | } else { |
| | 1196 | lj->args.append(get_libc_file(g->libc, "crt2.o")); |
| | 1197 | } |
| | 1198 | |
| | 1199 | lj->args.append(get_libc_static_file(g->libc, "crtbegin.o")); |
| | 1200 | |
| | 1201 | if (g->libc_link_lib != nullptr) { |
| | 1202 | lj->args.append("libmingw32.a"); |
| | 1203 | |
| | 1204 | if (is_dll) { |
| | 1205 | lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a")); |
| | 1206 | lj->args.append(get_libc_static_file(g->libc, "libgcc.a")); |
| 1147 | } else { | 1207 | } else { |
| 1148 | Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str); | 1208 | lj->args.append(get_libc_static_file(g->libc, "libgcc.a")); |
| 1149 | lj->args.append(buf_ptr(msvcrt_lib_name)); | 1209 | lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a")); |
| 1150 | } | 1210 | } |
| 1151 | | 1211 | |
| 1152 | Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str); | 1212 | lj->args.append(get_libc_static_file(g->libc, "libssp.a")); |
| 1153 | lj->args.append(buf_ptr(vcruntime_lib_name)); | 1213 | lj->args.append("libmoldname.a"); |
| | 1214 | lj->args.append("libmingwex.a"); |
| | 1215 | lj->args.append("libmsvcrt.a"); |
| 1154 | | 1216 | |
| 1155 | Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str); | 1217 | if (g->subsystem == TargetSubsystemWindows) { |
| 1156 | lj->args.append(buf_ptr(crt_lib_name)); | 1218 | lj->args.append("libgdi32.a"); |
| | 1219 | lj->args.append("libcomdlg32.a"); |
| | 1220 | } |
| 1157 | | 1221 | |
| 1158 | //Visual C++ 2015 Conformance Changes | 1222 | lj->args.append("libadvapi32.a"); |
| 1159 | //https://msdn.microsoft.com/en-us/library/bb531344.aspx | 1223 | lj->args.append("libadvapi32.a"); |
| 1160 | lj->args.append("legacy_stdio_definitions.lib"); | 1224 | lj->args.append("libshell32.a"); |
| | 1225 | lj->args.append("libuser32.a"); |
| | 1226 | lj->args.append("libkernel32.a"); |
| 1161 | | 1227 | |
| 1162 | // msvcrt depends on kernel32 and ntdll | 1228 | lj->args.append(get_libc_static_file(g->libc, "crtend.o")); |
| 1163 | lj->args.append("kernel32.lib"); | 1229 | } |
| 1164 | lj->args.append("ntdll.lib"); | 1230 | } |
| | 1231 | |
| | 1232 | static void add_win_link_args(LinkJob *lj, bool is_library) { |
| | 1233 | if (lj->link_in_crt) { |
| | 1234 | if (target_abi_is_gnu(lj->codegen->zig_target->abi)) { |
| | 1235 | add_gnu_link_args(lj, is_library); |
| | 1236 | } else { |
| | 1237 | add_msvc_link_args(lj, is_library); |
| | 1238 | } |
| 1165 | } else { | 1239 | } else { |
| 1166 | lj->args.append("-NODEFAULTLIB"); | 1240 | lj->args.append("-NODEFAULTLIB"); |
| 1167 | if (!is_library) { | 1241 | if (!is_library) { |
| 1168 | if (g->have_winmain) { | 1242 | if (lj->codegen->have_winmain) { |
| 1169 | lj->args.append("-ENTRY:WinMain"); | 1243 | lj->args.append("-ENTRY:WinMain"); |
| 1170 | } else { | 1244 | } else { |
| 1171 | lj->args.append("-ENTRY:WinMainCRTStartup"); | 1245 | lj->args.append("-ENTRY:WinMainCRTStartup"); |
| ... | @@ -1194,17 +1268,46 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -1194,17 +1268,46 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1194 | coff_append_machine_arg(g, &lj->args); | 1268 | coff_append_machine_arg(g, &lj->args); |
| 1195 | | 1269 | |
| 1196 | bool is_library = g->out_type == OutTypeLib; | 1270 | bool is_library = g->out_type == OutTypeLib; |
| | 1271 | if (is_library && g->is_dynamic) { |
| | 1272 | lj->args.append("-DLL"); |
| | 1273 | } |
| | 1274 | |
| | 1275 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); |
| | 1276 | |
| | 1277 | if (g->libc_link_lib != nullptr) { |
| | 1278 | assert(g->libc != nullptr); |
| | 1279 | |
| | 1280 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); |
| | 1281 | |
| | 1282 | if (target_abi_is_gnu(g->zig_target->abi)) { |
| | 1283 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir)))); |
| | 1284 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir)))); |
| | 1285 | } else { |
| | 1286 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); |
| | 1287 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); |
| | 1288 | } |
| | 1289 | } |
| | 1290 | |
| | 1291 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { |
| | 1292 | const char *lib_dir = g->lib_dirs.at(i); |
| | 1293 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); |
| | 1294 | } |
| | 1295 | |
| | 1296 | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| | 1297 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); |
| | 1298 | } |
| | 1299 | |
| 1197 | switch (g->subsystem) { | 1300 | switch (g->subsystem) { |
| 1198 | case TargetSubsystemAuto: | 1301 | case TargetSubsystemAuto: |
| 1199 | if (g->zig_target->os == OsUefi) { | 1302 | if (g->zig_target->os == OsUefi) { |
| 1200 | add_uefi_link_args(lj); | 1303 | add_uefi_link_args(lj); |
| 1201 | } else { | 1304 | } else { |
| 1202 | add_nt_link_args(lj, is_library); | 1305 | add_win_link_args(lj, is_library); |
| 1203 | } | 1306 | } |
| 1204 | break; | 1307 | break; |
| 1205 | case TargetSubsystemConsole: | 1308 | case TargetSubsystemConsole: |
| 1206 | lj->args.append("-SUBSYSTEM:console"); | 1309 | lj->args.append("-SUBSYSTEM:console"); |
| 1207 | add_nt_link_args(lj, is_library); | 1310 | add_win_link_args(lj, is_library); |
| 1208 | break; | 1311 | break; |
| 1209 | case TargetSubsystemEfiApplication: | 1312 | case TargetSubsystemEfiApplication: |
| 1210 | lj->args.append("-SUBSYSTEM:efi_application"); | 1313 | lj->args.append("-SUBSYSTEM:efi_application"); |
| ... | @@ -1224,41 +1327,18 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -1224,41 +1327,18 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1224 | break; | 1327 | break; |
| 1225 | case TargetSubsystemNative: | 1328 | case TargetSubsystemNative: |
| 1226 | lj->args.append("-SUBSYSTEM:native"); | 1329 | lj->args.append("-SUBSYSTEM:native"); |
| 1227 | add_nt_link_args(lj, is_library); | 1330 | add_win_link_args(lj, is_library); |
| 1228 | break; | 1331 | break; |
| 1229 | case TargetSubsystemPosix: | 1332 | case TargetSubsystemPosix: |
| 1230 | lj->args.append("-SUBSYSTEM:posix"); | 1333 | lj->args.append("-SUBSYSTEM:posix"); |
| 1231 | add_nt_link_args(lj, is_library); | 1334 | add_win_link_args(lj, is_library); |
| 1232 | break; | 1335 | break; |
| 1233 | case TargetSubsystemWindows: | 1336 | case TargetSubsystemWindows: |
| 1234 | lj->args.append("-SUBSYSTEM:windows"); | 1337 | lj->args.append("-SUBSYSTEM:windows"); |
| 1235 | add_nt_link_args(lj, is_library); | 1338 | add_win_link_args(lj, is_library); |
| 1236 | break; | 1339 | break; |
| 1237 | } | 1340 | } |
| 1238 | | 1341 | |
| 1239 | lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); | | |
| 1240 | | | |
| 1241 | if (g->libc_link_lib != nullptr) { | | |
| 1242 | assert(g->libc != nullptr); | | |
| 1243 | | | |
| 1244 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); | | |
| 1245 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); | | |
| 1246 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir)))); | | |
| 1247 | } | | |
| 1248 | | | |
| 1249 | if (is_library && g->is_dynamic) { | | |
| 1250 | lj->args.append("-DLL"); | | |
| 1251 | } | | |
| 1252 | | | |
| 1253 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | | |
| 1254 | const char *lib_dir = g->lib_dirs.at(i); | | |
| 1255 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); | | |
| 1256 | } | | |
| 1257 | | | |
| 1258 | for (size_t i = 0; i < g->link_objects.length; i += 1) { | | |
| 1259 | lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); | | |
| 1260 | } | | |
| 1261 | | | |
| 1262 | if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { | 1342 | if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { |
| 1263 | if (g->libc_link_lib == nullptr && !g->is_dummy_so) { | 1343 | if (g->libc_link_lib == nullptr && !g->is_dummy_so) { |
| 1264 | Buf *builtin_a_path = build_a(g, "builtin"); | 1344 | Buf *builtin_a_path = build_a(g, "builtin"); |
| ... | @@ -1278,11 +1358,19 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -1278,11 +1358,19 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1278 | continue; | 1358 | continue; |
| 1279 | } | 1359 | } |
| 1280 | if (link_lib->provided_explicitly) { | 1360 | if (link_lib->provided_explicitly) { |
| 1281 | if (lj->codegen->zig_target->abi == ZigLLVM_GNU) { | 1361 | if (target_abi_is_gnu(lj->codegen->zig_target->abi)) { |
| 1282 | Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); | 1362 | static const char *test_names[3] = { "lib%s.dll.a", "lib%s.a", nullptr }; |
| 1283 | lj->args.append(buf_ptr(arg)); | 1363 | |
| 1284 | } | 1364 | for (size_t i = 0; test_names[i] != nullptr; i++) { |
| 1285 | else { | 1365 | Buf *test_path = buf_sprintf(test_names[i], buf_ptr(link_lib->name)); |
| | 1366 | bool exists = false; |
| | 1367 | if (os_file_exists(test_path, &exists) != ErrorNone) { |
| | 1368 | zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path)); |
| | 1369 | } else if (exists) { |
| | 1370 | lj->args.append(buf_ptr(test_path)); |
| | 1371 | } |
| | 1372 | } |
| | 1373 | } else { |
| 1286 | lj->args.append(buf_ptr(link_lib->name)); | 1374 | lj->args.append(buf_ptr(link_lib->name)); |
| 1287 | } | 1375 | } |
| 1288 | } else { | 1376 | } else { |