Commit cbb6d2239f

Andrew Kelley <superjoe30@gmail.com>
2017-10-16 16:20:52
look for libc at runtime on windows
See #539 before we close the issue we should also detect MSVC 2017 but this gets us started with supporting MSVC 2015
1 parent 8cfb0cf
src/all_types.hpp
@@ -1461,6 +1461,8 @@ struct CodeGen {
     Buf *libc_lib_dir;
     Buf *libc_static_lib_dir;
     Buf *libc_include_dir;
+    Buf *msvc_lib_dir;
+    Buf *kernel32_lib_dir;
     Buf *zig_lib_dir;
     Buf *zig_std_dir;
     Buf *zig_c_headers_dir;
src/analyze.cpp
@@ -3359,6 +3359,61 @@ void find_libc_include_path(CodeGen *g) {
 }
 
 void find_libc_lib_path(CodeGen *g) {
+#ifdef ZIG_OS_WINDOWS
+    if (!g->msvc_lib_dir && g->zig_target.os == ZigLLVM_Win32) {
+        Buf *msvc_lib_dir;
+        if (g->zig_target.arch.arch == ZigLLVM_arm) {
+            msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\arm");
+        } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
+            msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib\\amd64");
+        } else if (g->zig_target.arch.arch == ZigLLVM_x86) {
+            msvc_lib_dir = buf_create_from_str("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\lib");
+        } else {
+            zig_panic("unable to determine msvc lib path");
+        }
+        Buf *test_path = buf_alloc();
+        os_path_join(msvc_lib_dir, buf_create_from_str("vcruntime.lib"), test_path);
+        bool result;
+        int err;
+        if ((err = os_file_exists(test_path, &result))) {
+            result = false;
+        }
+        if (result) {
+            g->msvc_lib_dir = msvc_lib_dir;
+        } else {
+            zig_panic("Unable to determine msvc lib path.");
+        }
+    }
+
+    if (!g->kernel32_lib_dir && g->zig_target.os == ZigLLVM_Win32) {
+        Buf *kernel32_lib_dir;
+        if (g->zig_target.arch.arch == ZigLLVM_arm) {
+            kernel32_lib_dir = buf_create_from_str(
+                "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\arm");
+        } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
+            kernel32_lib_dir = buf_create_from_str(
+                "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x64");
+        } else if (g->zig_target.arch.arch == ZigLLVM_x86) {
+            kernel32_lib_dir = buf_create_from_str(
+                "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86");
+        } else {
+            zig_panic("unable to determine kernel32 lib path");
+        }
+        Buf *test_path = buf_alloc();
+        os_path_join(kernel32_lib_dir, buf_create_from_str("kernel32.lib"), test_path);
+        bool result;
+        int err;
+        if ((err = os_file_exists(test_path, &result))) {
+            result = false;
+        }
+        if (result) {
+            g->kernel32_lib_dir = kernel32_lib_dir;
+        } else {
+            zig_panic("Unable to determine kernel32 lib path.");
+        }
+    }
+#endif
+
     // later we can handle this better by reporting an error via the normal mechanism
     if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) {
         zig_panic("Unable to determine libc lib path.");
src/codegen.cpp
@@ -117,6 +117,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
         g->libc_lib_dir = buf_create_from_str("");
         g->libc_static_lib_dir = buf_create_from_str("");
         g->libc_include_dir = buf_create_from_str("");
+        g->msvc_lib_dir = nullptr;
+        g->kernel32_lib_dir = nullptr;
         g->each_lib_rpath = false;
     } else {
         // native compilation, we can rely on the configuration stuff
@@ -127,6 +129,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
         g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
         g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
         g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
+        g->msvc_lib_dir = nullptr; // find it at runtime
+        g->kernel32_lib_dir = nullptr; // find it at runtime
 #ifdef ZIG_EACH_LIB_RPATH
         g->each_lib_rpath = true;
 #endif
@@ -228,6 +232,14 @@ void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
     g->libc_include_dir = libc_include_dir;
 }
 
+void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) {
+    g->msvc_lib_dir = msvc_lib_dir;
+}
+
+void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) {
+    g->kernel32_lib_dir = kernel32_lib_dir;
+}
+
 void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
     g->dynamic_linker = dynamic_linker;
 }
src/codegen.hpp
@@ -31,6 +31,8 @@ void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
 void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
 void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
 void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
+void codegen_set_msvc_lib_dir(CodeGen *codegen, Buf *msvc_lib_dir);
+void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
 void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
 void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
 void codegen_set_windows_unicode(CodeGen *g, bool municode);
src/link.cpp
@@ -397,6 +397,14 @@ static void construct_linker_job_coff(LinkJob *lj) {
 
     lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file))));
 
+    if (g->libc_link_lib != nullptr) {
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
+
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
+    }
+
     if (lj->link_in_crt) {
         const char *lib_str = g->is_static ? "lib" : "";
         const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
@@ -441,11 +449,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
         lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
     }
 
-    if (g->libc_link_lib != nullptr) {
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
-        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_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)));
     }
src/main.cpp
@@ -59,6 +59,8 @@ static int usage(const char *arg0) {
         "  --each-lib-rpath             add rpath for each used dynamic library\n"
         "  --libc-lib-dir [path]        directory where libc crt1.o resides\n"
         "  --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
+        "  --msvc-lib-dir [path]        (windows) directory where vcruntime.lib resides\n"
+        "  --kernel32-lib-dir [path]    (windows) directory where kernel32.lib resides\n"
         "  --library [lib]              link against lib\n"
         "  --library-path [dir]         add a directory to the library search path\n"
         "  --linker-script [path]       use a custom linker script\n"
@@ -279,6 +281,8 @@ int main(int argc, char **argv) {
     const char *libc_lib_dir = nullptr;
     const char *libc_static_lib_dir = nullptr;
     const char *libc_include_dir = nullptr;
+    const char *msvc_lib_dir = nullptr;
+    const char *kernel32_lib_dir = nullptr;
     const char *zig_install_prefix = nullptr;
     const char *dynamic_linker = nullptr;
     ZigList<const char *> clang_argv = {0};
@@ -518,6 +522,10 @@ int main(int argc, char **argv) {
                     libc_static_lib_dir = argv[i];
                 } else if (strcmp(arg, "--libc-include-dir") == 0) {
                     libc_include_dir = argv[i];
+                } else if (strcmp(arg, "--msvc-lib-dir") == 0) {
+                    msvc_lib_dir = argv[i];
+                } else if (strcmp(arg, "--kernel32-lib-dir") == 0) {
+                    kernel32_lib_dir = argv[i];
                 } else if (strcmp(arg, "--zig-install-prefix") == 0) {
                     zig_install_prefix = argv[i];
                 } else if (strcmp(arg, "--dynamic-linker") == 0) {
@@ -728,6 +736,10 @@ int main(int argc, char **argv) {
                 codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir));
             if (libc_include_dir)
                 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
+            if (msvc_lib_dir)
+                codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir));
+            if (kernel32_lib_dir)
+                codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir));
             if (dynamic_linker)
                 codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
             codegen_set_verbose(g, verbose);