diff --git a/src/codegen.cpp b/src/codegen.cpp index 4a8b376e2..99fffa449 100644 --- a/src/codegen.cpp +++ b/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); diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp index 9228ea95b..04459d78e 100644 --- a/src/libc_installation.cpp +++ b/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 name, Slice value, bool *found_keys, size_t index, Buf *field_ptr) { @@ -33,6 +34,7 @@ static bool zig_libc_match_key(Slice name, Slice 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 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))) diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp index 4cb77f145..7a1fb37d6 100644 --- a/src/libc_installation.hpp +++ b/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; diff --git a/src/link.cpp b/src/link.cpp index 5f611ae5a..f52eaa137 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -17,10 +17,10 @@ struct LinkJob { HashMap 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) {