Commit 0f54728cf0

Andrew Kelley <andrew@ziglang.org>
2019-02-26 01:10:48
fix not finding libgcc_s when looking for native libc
closes #2011
1 parent aab8e13
src/codegen.cpp
@@ -8815,6 +8815,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
     cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
     if (g->libc) {
         cache_buf(ch, &g->libc->include_dir);
+        cache_buf(ch, &g->libc->crt_dir);
         cache_buf(ch, &g->libc->lib_dir);
         cache_buf(ch, &g->libc->static_lib_dir);
         cache_buf(ch, &g->libc->msvc_lib_dir);
src/libc_installation.cpp
@@ -10,10 +10,9 @@
 #include "windows_sdk.h"
 #include "target.hpp"
 
-static const size_t zig_libc_keys_len = 6;
-
 static const char *zig_libc_keys[] = {
     "include_dir",
+    "crt_dir",
     "lib_dir",
     "static_lib_dir",
     "msvc_lib_dir",
@@ -21,6 +20,8 @@ static const char *zig_libc_keys[] = {
     "dynamic_linker_path",
 };
 
+static const size_t zig_libc_keys_len = array_length(zig_libc_keys);
+
 static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *found_keys,
         size_t index, Buf *field_ptr)
 {
@@ -33,6 +34,7 @@ static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *
 static void zig_libc_init_empty(ZigLibCInstallation *libc) {
     *libc = {};
     buf_init_from_str(&libc->include_dir, "");
+    buf_init_from_str(&libc->crt_dir, "");
     buf_init_from_str(&libc->lib_dir, "");
     buf_init_from_str(&libc->static_lib_dir, "");
     buf_init_from_str(&libc->msvc_lib_dir, "");
@@ -44,7 +46,7 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
     Error err;
     zig_libc_init_empty(libc);
 
-    bool found_keys[6] = {}; // zig_libc_keys_len
+    bool found_keys[array_length(zig_libc_keys)] = {}; // zig_libc_keys_len
 
     Buf *contents = buf_alloc();
     if ((err = os_fetch_file_path(libc_file, contents, false))) {
@@ -74,11 +76,12 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
         Slice<uint8_t> value = SplitIterator_rest(&line_it);
         bool match = false;
         match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
-        match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->lib_dir);
-        match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->static_lib_dir);
-        match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->msvc_lib_dir);
-        match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir);
-        match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->dynamic_linker_path);
+        match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->crt_dir);
+        match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->lib_dir);
+        match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_lib_dir);
+        match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
+        match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
+        match = match || zig_libc_match_key(name, value, found_keys, 6, &libc->dynamic_linker_path);
     }
 
     for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
@@ -97,8 +100,17 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
         return ErrorSemanticAnalyzeFail;
     }
 
-    if (buf_len(&libc->lib_dir) == 0) {
+    if (buf_len(&libc->crt_dir) == 0) {
         if (!target_is_darwin(target)) {
+            if (verbose) {
+                fprintf(stderr, "crt_dir may not be empty for %s\n", get_target_os_name(target->os));
+            }
+            return ErrorSemanticAnalyzeFail;
+        }
+    }
+
+    if (buf_len(&libc->lib_dir) == 0) {
+        if (!target_is_darwin(target) && target->os != OsWindows) {
             if (verbose) {
                 fprintf(stderr, "lib_dir may not be empty for %s\n", get_target_os_name(target->os));
             }
@@ -134,7 +146,7 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
     }
 
     if (buf_len(&libc->dynamic_linker_path) == 0) {
-        if (target->os == OsLinux) {
+        if (!target_is_darwin(target) && target->os != OsWindows) {
             if (verbose) {
                 fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", get_target_os_name(target->os));
             }
@@ -156,11 +168,11 @@ static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self,
     }
     return ErrorNone;
 }
-static Error zig_libc_find_lib_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
+static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
         bool verbose)
 {
     Error err;
-    if ((err = os_get_win32_ucrt_lib_path(sdk, &self->lib_dir, target->arch.arch))) {
+    if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch.arch))) {
         if (verbose) {
             fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err));
         }
@@ -291,8 +303,11 @@ static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want
     }
     return ErrorNone;
 }
+static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
+    return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose);
+}
 static Error zig_libc_find_native_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
-    return zig_libc_cc_print_file_name("crt1.o", &self->lib_dir, true, verbose);
+    return zig_libc_cc_print_file_name("libgcc_s.so", &self->lib_dir, true, verbose);
 }
 
 static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
@@ -328,16 +343,21 @@ static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self
 void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
     fprintf(file,
         "# The directory that contains `stdlib.h`.\n"
-        "# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`\n"
+        "# On POSIX, can be found with: `cc -E -Wp,-v -xc /dev/null`\n"
         "include_dir=%s\n"
         "\n"
         "# The directory that contains `crt1.o`.\n"
-        "# On Linux, can be found with `cc -print-file-name=crt1.o`.\n"
+        "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
         "# Not needed when targeting MacOS.\n"
+        "crt_dir=%s\n"
+        "\n"
+        "# The directory that contains `libgcc_s.so`.\n"
+        "# On POSIX, can be found with `cc -print-file-name=libgcc_s.so`.\n"
+        "# Not needed when targeting MacOS or Windows.\n"
         "lib_dir=%s\n"
         "\n"
         "# The directory that contains `crtbegin.o`.\n"
-        "# On Linux, can be found with `cc -print-file-name=crtbegin.o`.\n"
+        "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
         "# Not needed when targeting MacOS or Windows.\n"
         "static_lib_dir=%s\n"
         "\n"
@@ -350,11 +370,12 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
         "kernel32_lib_dir=%s\n"
         "\n"
         "# The full path to the dynamic linker, on the target system.\n"
-        "# Only needed when targeting Linux.\n"
+        "# Not needed when targeting MacOS or Windows.\n"
         "dynamic_linker_path=%s\n"
         "\n"
     ,
         buf_ptr(&self->include_dir),
+        buf_ptr(&self->crt_dir),
         buf_ptr(&self->lib_dir),
         buf_ptr(&self->static_lib_dir),
         buf_ptr(&self->msvc_lib_dir),
@@ -378,7 +399,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
                 return err;
             if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
                 return err;
-            if ((err = zig_libc_find_lib_dir_windows(self, sdk, &native_target, verbose)))
+            if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose)))
                 return err;
             return ErrorNone;
         case ZigFindWindowsSdkErrorOutOfMemory:
@@ -393,9 +414,12 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
     if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
         return err;
 #if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
+    buf_init_from_str(&self->crt_dir, "/usr/lib");
     buf_init_from_str(&self->lib_dir, "/usr/lib");
     buf_init_from_str(&self->static_lib_dir, "/usr/lib");
 #elif !defined(ZIG_OS_DARWIN)
+    if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
+        return err;
     if ((err = zig_libc_find_native_lib_dir_posix(self, verbose)))
         return err;
     if ((err = zig_libc_find_native_static_lib_dir_posix(self, verbose)))
src/libc_installation.hpp
@@ -17,6 +17,7 @@
 // Must be synchronized with zig_libc_keys
 struct ZigLibCInstallation {
     Buf include_dir;
+    Buf crt_dir;
     Buf lib_dir;
     Buf static_lib_dir;
     Buf msvc_lib_dir;
src/link.cpp
@@ -17,10 +17,10 @@ struct LinkJob {
     HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
 };
 
-static const char *get_libc_file(CodeGen *g, const char *file) {
+static const char *get_libc_crt_file(CodeGen *g, const char *file) {
     assert(g->libc != nullptr);
     Buf *out_buf = buf_alloc();
-    os_path_join(&g->libc->lib_dir, buf_create_from_str(file), out_buf);
+    os_path_join(&g->libc->crt_dir, buf_create_from_str(file), out_buf);
     return buf_ptr(out_buf);
 }
 
@@ -224,8 +224,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
             crt1o = "Scrt1.o";
             crtbegino = "crtbegin.o";
         }
-        lj->args.append(get_libc_file(g, crt1o));
-        lj->args.append(get_libc_file(g, "crti.o"));
+        lj->args.append(get_libc_crt_file(g, crt1o));
+        lj->args.append(get_libc_crt_file(g, "crti.o"));
         lj->args.append(get_libc_static_file(g, crtbegino));
     }
 
@@ -263,7 +263,12 @@ static void construct_linker_job_elf(LinkJob *lj) {
     if (g->libc_link_lib != nullptr) {
         assert(g->libc != nullptr);
         lj->args.append("-L");
-        lj->args.append(buf_ptr(&g->libc->lib_dir));
+        lj->args.append(buf_ptr(&g->libc->crt_dir));
+
+        if (!buf_eql_buf(&g->libc->crt_dir, &g->libc->lib_dir)) {
+            lj->args.append("-L");
+            lj->args.append(buf_ptr(&g->libc->lib_dir));
+        }
 
         lj->args.append("-L");
         lj->args.append(buf_ptr(&g->libc->static_lib_dir));
@@ -340,7 +345,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
     // crt end
     if (lj->link_in_crt) {
         lj->args.append(get_libc_static_file(g, "crtend.o"));
-        lj->args.append(get_libc_file(g, "crtn.o"));
+        lj->args.append(get_libc_crt_file(g, "crtn.o"));
     }
 
     if (!g->zig_target->is_native) {
@@ -597,7 +602,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
 
         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->lib_dir))));
+        lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
     }
 
     if (is_library && !g->is_static) {