Commit 6cc443ee45

emekoi <emekankurumeh@outlook.com>
2019-03-30 02:37:15
added code for linking libc on mingw
1 parent ecd2332
Changed files (1)
src/link.cpp
@@ -1132,40 +1132,114 @@ static void add_uefi_link_args(LinkJob *lj) {
     lj->args.append("-SECTION:.xdata,D");
 }
 
-static void add_nt_link_args(LinkJob *lj, bool is_library) {
+static void add_msvc_link_args(LinkJob *lj, bool is_library) {
     CodeGen *g = lj->codegen;
 
-    if (lj->link_in_crt) {
-        // TODO: https://github.com/ziglang/zig/issues/2064
-        bool is_dynamic = true; // g->is_dynamic;
-        const char *lib_str = is_dynamic ? "" : "lib";
-        const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
-
-        if (!is_dynamic) {
-            Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
-            lj->args.append(buf_ptr(cmt_lib_name));
+    // TODO: https://github.com/ziglang/zig/issues/2064
+    bool is_dynamic = true; // g->is_dynamic;
+    const char *lib_str = is_dynamic ? "" : "lib";
+    const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
+
+    if (!is_dynamic) {
+        Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
+        lj->args.append(buf_ptr(cmt_lib_name));
+    } else {
+        Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
+        lj->args.append(buf_ptr(msvcrt_lib_name));
+    }
+
+    Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
+    lj->args.append(buf_ptr(vcruntime_lib_name));
+
+    Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
+    lj->args.append(buf_ptr(crt_lib_name));
+
+    //Visual C++ 2015 Conformance Changes
+    //https://msdn.microsoft.com/en-us/library/bb531344.aspx
+    lj->args.append("legacy_stdio_definitions.lib");
+
+    // msvcrt depends on kernel32 and ntdll
+    lj->args.append("kernel32.lib");
+    lj->args.append("ntdll.lib");
+}
+
+static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) {
+    Buf *out_buf = buf_alloc();
+    os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf);
+    return buf_ptr(out_buf);
+}
+
+static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) {
+    Buf *static_crt_dir = buf_alloc();
+    Buf *out_buf = buf_alloc();
+    if (zig_libc_cc_print_file_name(file, static_crt_dir, true, true) != ErrorNone) {
+        abort();
+    }
+    os_path_join(static_crt_dir, buf_create_from_str(file), out_buf);
+    return buf_ptr(out_buf);
+}
+
+static void add_gnu_link_args(LinkJob *lj, bool is_library) {
+    CodeGen *g = lj->codegen;
+
+    bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
+
+    if (g->zig_target->arch == ZigLLVM_x86) {
+        lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase");
+    } else {
+        lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase");
+    }
+
+    if (is_dll) {
+       lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
+    } else {
+       lj->args.append(get_libc_file(g->libc, "crt2.o"));
+    }
+
+    lj->args.append(get_libc_static_file(g->libc, "crtbegin.o"));
+
+    if (g->libc_link_lib != nullptr) {
+        lj->args.append("libmingw32.a");
+
+        if (is_dll) {
+            lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a"));
+            lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
         } else {
-            Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
-            lj->args.append(buf_ptr(msvcrt_lib_name));
+            lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
+            lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a"));
         }
 
-        Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
-        lj->args.append(buf_ptr(vcruntime_lib_name));
+        lj->args.append(get_libc_static_file(g->libc, "libssp.a"));
+        lj->args.append("libmoldname.a");
+        lj->args.append("libmingwex.a");
+        lj->args.append("libmsvcrt.a");
 
-        Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
-        lj->args.append(buf_ptr(crt_lib_name));
+        if (g->subsystem == TargetSubsystemWindows) {
+            lj->args.append("libgdi32.a");
+            lj->args.append("libcomdlg32.a");
+        }
 
-        //Visual C++ 2015 Conformance Changes
-        //https://msdn.microsoft.com/en-us/library/bb531344.aspx
-        lj->args.append("legacy_stdio_definitions.lib");
+        lj->args.append("libadvapi32.a");
+        lj->args.append("libadvapi32.a");
+        lj->args.append("libshell32.a");
+        lj->args.append("libuser32.a");
+        lj->args.append("libkernel32.a");
 
-        // msvcrt depends on kernel32 and ntdll
-        lj->args.append("kernel32.lib");
-        lj->args.append("ntdll.lib");
+        lj->args.append(get_libc_static_file(g->libc, "crtend.o"));
+    }
+}
+
+static void add_win_link_args(LinkJob *lj, bool is_library) {
+    if (lj->link_in_crt) {
+        if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
+            add_gnu_link_args(lj, is_library);
+        } else {
+            add_msvc_link_args(lj, is_library);
+        }
     } else {
         lj->args.append("-NODEFAULTLIB");
         if (!is_library) {
-            if (g->have_winmain) {
+            if (lj->codegen->have_winmain) {
                 lj->args.append("-ENTRY:WinMain");
             } else {
                 lj->args.append("-ENTRY:WinMainCRTStartup");
@@ -1194,17 +1268,46 @@ static void construct_linker_job_coff(LinkJob *lj) {
     coff_append_machine_arg(g, &lj->args);
 
     bool is_library = g->out_type == OutTypeLib;
+    if (is_library && g->is_dynamic) {
+        lj->args.append("-DLL");
+    }
+
+    lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
+
+    if (g->libc_link_lib != nullptr) {
+        assert(g->libc != nullptr);
+
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
+
+        if (target_abi_is_gnu(g->zig_target->abi)) {
+            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir))));
+            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir))));
+        } else {
+            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
+            lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
+        }
+    }
+
+    for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
+        const char *lib_dir = g->lib_dirs.at(i);
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
+    }
+
+    for (size_t i = 0; i < g->link_objects.length; i += 1) {
+        lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
+    }
+
     switch (g->subsystem) {
         case TargetSubsystemAuto:
             if (g->zig_target->os == OsUefi) {
                 add_uefi_link_args(lj);
             } else {
-                add_nt_link_args(lj, is_library);
+                add_win_link_args(lj, is_library);
             }
             break;
         case TargetSubsystemConsole:
             lj->args.append("-SUBSYSTEM:console");
-            add_nt_link_args(lj, is_library);
+            add_win_link_args(lj, is_library);
             break;
         case TargetSubsystemEfiApplication:
             lj->args.append("-SUBSYSTEM:efi_application");
@@ -1224,41 +1327,18 @@ static void construct_linker_job_coff(LinkJob *lj) {
             break;
         case TargetSubsystemNative:
             lj->args.append("-SUBSYSTEM:native");
-            add_nt_link_args(lj, is_library);
+            add_win_link_args(lj, is_library);
             break;
         case TargetSubsystemPosix:
             lj->args.append("-SUBSYSTEM:posix");
-            add_nt_link_args(lj, is_library);
+            add_win_link_args(lj, is_library);
             break;
         case TargetSubsystemWindows:
             lj->args.append("-SUBSYSTEM:windows");
-            add_nt_link_args(lj, is_library);
+            add_win_link_args(lj, is_library);
             break;
     }
 
-    lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
-
-    if (g->libc_link_lib != nullptr) {
-        assert(g->libc != nullptr);
-
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
-    }
-
-    if (is_library && g->is_dynamic) {
-        lj->args.append("-DLL");
-    }
-
-    for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
-        const char *lib_dir = g->lib_dirs.at(i);
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
-    }
-
-    for (size_t i = 0; i < g->link_objects.length; i += 1) {
-        lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
-    }
-
     if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
         if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
             Buf *builtin_a_path = build_a(g, "builtin");
@@ -1278,11 +1358,19 @@ static void construct_linker_job_coff(LinkJob *lj) {
             continue;
         }
         if (link_lib->provided_explicitly) {
-            if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {
-                Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
-                lj->args.append(buf_ptr(arg));
-            }
-            else {
+            if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
+                static const char *test_names[3] = { "lib%s.dll.a", "lib%s.a", nullptr };
+
+                for (size_t i = 0; test_names[i] != nullptr; i++) {
+                    Buf *test_path = buf_sprintf(test_names[i], buf_ptr(link_lib->name));
+                    bool exists = false;
+                    if (os_file_exists(test_path, &exists) != ErrorNone) {
+                        zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path));
+                    } else if (exists) {
+                        lj->args.append(buf_ptr(test_path));
+                    }
+                }
+            } else {
                 lj->args.append(buf_ptr(link_lib->name));
             }
         } else {