From 0d10ab0680c8cd0c75bf6f6cc7d4a153ac742db8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 Mar 2019 14:37:32 -0500 Subject: stop linking against gcc files --- src/libc_installation.cpp | 55 +++-------------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) (limited to 'src/libc_installation.cpp') diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp index 8be704887a..49c969d704 100644 --- a/src/libc_installation.cpp +++ b/src/libc_installation.cpp @@ -14,8 +14,6 @@ static const char *zig_libc_keys[] = { "include_dir", "sys_include_dir", "crt_dir", - "lib_dir", - "static_lib_dir", "msvc_lib_dir", "kernel32_lib_dir", "dynamic_linker_path", @@ -37,8 +35,6 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) { buf_init_from_str(&libc->include_dir, ""); buf_init_from_str(&libc->sys_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, ""); buf_init_from_str(&libc->kernel32_lib_dir, ""); buf_init_from_str(&libc->dynamic_linker_path, ""); @@ -80,11 +76,9 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget 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->sys_include_dir); match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir); - match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->lib_dir); - match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->static_lib_dir); - match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->msvc_lib_dir); - match = match || zig_libc_match_key(name, value, found_keys, 6, &libc->kernel32_lib_dir); - match = match || zig_libc_match_key(name, value, found_keys, 7, &libc->dynamic_linker_path); + 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); } for (size_t i = 0; i < zig_libc_keys_len; i += 1) { @@ -119,24 +113,6 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget } } - 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", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - - if (buf_len(&libc->static_lib_dir) == 0) { - if (!target_is_darwin(target) && target->os != OsWindows) { - if (verbose) { - fprintf(stderr, "static_lib_dir may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - if (buf_len(&libc->msvc_lib_dir) == 0) { if (target->os == OsWindows) { if (verbose) { @@ -363,13 +339,6 @@ static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want 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("libgcc_s.so", &self->lib_dir, true, verbose); -} - -static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) { - return zig_libc_cc_print_file_name("crtbegin.o", &self->static_lib_dir, true, verbose); -} #endif static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) { @@ -414,16 +383,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) { "# 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 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" "# The directory that contains `vcruntime.lib`.\n" "# Only needed when targeting Windows.\n" "msvc_lib_dir=%s\n" @@ -440,8 +399,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) { buf_ptr(&self->include_dir), buf_ptr(&self->sys_include_dir), buf_ptr(&self->crt_dir), - buf_ptr(&self->lib_dir), - buf_ptr(&self->static_lib_dir), buf_ptr(&self->msvc_lib_dir), buf_ptr(&self->kernel32_lib_dir), buf_ptr(&self->dynamic_linker_path) @@ -481,15 +438,9 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool 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))) - return err; #endif if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose))) return err; -- cgit v1.2.3 From 55a0016221e459c49b9f04a4b57ba84be27bba72 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 Mar 2019 15:54:08 -0500 Subject: dynamic linker path is independent from libc installation --- src/all_types.hpp | 1 + src/codegen.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++- src/codegen.hpp | 1 + src/compiler.cpp | 16 +++++++++++++- src/compiler.hpp | 9 ++++---- src/libc_installation.cpp | 53 ++++------------------------------------------- src/libc_installation.hpp | 5 ++++- src/link.cpp | 12 +++-------- src/main.cpp | 7 ++++++- 9 files changed, 90 insertions(+), 66 deletions(-) (limited to 'src/libc_installation.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index f3069cad07..0cf3504ce9 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1851,6 +1851,7 @@ struct CodeGen { ZigPackage *root_package; Buf *zig_lib_dir; Buf *zig_std_dir; + Buf *dynamic_linker_path; const char **llvm_argv; size_t llvm_argv_len; diff --git a/src/codegen.cpp b/src/codegen.cpp index 2edc0a2fec..ad4ecce857 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -257,6 +257,10 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { g->root_out_name = out_name; } +void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker_path) { + g->dynamic_linker_path = dynamic_linker_path; +} + void codegen_add_lib_dir(CodeGen *g, const char *dir) { g->lib_dirs.append(dir); } @@ -7908,6 +7912,51 @@ static void init(CodeGen *g) { } } +static void detect_dynamic_linker(CodeGen *g) { + if (g->dynamic_linker_path != nullptr) + return; + + if (g->zig_target->is_native) { + // target_dynamic_linker is usually correct. However on some systems, such as NixOS + // it will be incorrect. See if we can do better by looking at what zig's own + // dynamic linker path is. + g->dynamic_linker_path = get_self_dynamic_linker_path(); + if (g->dynamic_linker_path != nullptr) + return; + + // If Zig is statically linked, such as via distributed binary static builds, the above + // trick won't work. What are we left with? Try to run the system C compiler and get + // it to tell us the dynamic linker path +#if defined(ZIG_OS_LINUX) + { + Error err; + static const char *dyn_tests[] = { +#if defined(ZIG_ARCH_X86_64) + "ld-linux-x86-64.so.2", + "ld-musl-x86_64.so.1", +#endif + }; + Buf *result = buf_alloc(); + for (size_t i = 0; i < array_length(dyn_tests); i += 1) { + const char *lib_name = dyn_tests[i]; + if ((err = zig_libc_cc_print_file_name(lib_name, result, false, true))) { + if (err != ErrorCCompilerCannotFindFile) { + fprintf(stderr, "Unable to detect native dynamic linker: %s\n", err_str(err)); + exit(1); + } + continue; + } + g->dynamic_linker_path = result; + return; + } + } +#endif + } + + // Otherwise go with the standard linker path. + g->dynamic_linker_path = buf_create_from_str(target_dynamic_linker(g->zig_target)); +} + static void detect_libc(CodeGen *g) { Error err; @@ -9029,8 +9078,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_buf(ch, &g->libc->crt_dir); cache_buf(ch, &g->libc->msvc_lib_dir); cache_buf(ch, &g->libc->kernel32_lib_dir); - cache_buf(ch, &g->libc->dynamic_linker_path); } + cache_buf(ch, g->dynamic_linker_path); gen_c_objects(g); @@ -9132,6 +9181,7 @@ void codegen_build_and_link(CodeGen *g) { assert(g->out_type != OutTypeUnknown); detect_libc(g); + detect_dynamic_linker(g); Buf *artifact_dir = buf_alloc(); Buf digest = BUF_INIT; diff --git a/src/codegen.hpp b/src/codegen.hpp index c9316fda83..90aaff3508 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -29,6 +29,7 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static); void codegen_set_strip(CodeGen *codegen, bool strip); void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); void codegen_set_out_name(CodeGen *codegen, Buf *out_name); +void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); void codegen_add_lib_dir(CodeGen *codegen, const char *dir); void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); diff --git a/src/compiler.cpp b/src/compiler.cpp index 8c2f9cdf60..27e4c57be5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,4 +1,5 @@ #include "cache_hash.hpp" +#include "os.hpp" #include @@ -8,8 +9,9 @@ static Buf saved_stage1_path = BUF_INIT; static Buf saved_lib_dir = BUF_INIT; static Buf saved_special_dir = BUF_INIT; static Buf saved_std_dir = BUF_INIT; +static Buf saved_dynamic_linker_path = BUF_INIT; -Buf *get_stage1_cache_path() { +Buf *get_stage1_cache_path(void) { if (saved_stage1_path.list.length != 0) { return &saved_stage1_path; } @@ -57,6 +59,13 @@ Error get_compiler_id(Buf **result) { Buf *lib_path = lib_paths.at(i); if ((err = cache_add_file(ch, lib_path))) return err; +#if defined(ZIG_OS_LINUX) && defined(ZIG_ARCH_X86_64) + if (buf_ends_with_str(lib_path, "ld-linux-x86-64.so.2")) { + buf_init_from_buf(&saved_dynamic_linker_path, lib_path); + } else if (buf_ends_with_str(lib_path, "ld-musl-x86-64.so.1")) { + buf_init_from_buf(&saved_dynamic_linker_path, lib_path); + } +#endif } if ((err = cache_final(ch, &saved_compiler_id))) return err; @@ -67,6 +76,11 @@ Error get_compiler_id(Buf **result) { return ErrorNone; } +Buf *get_self_dynamic_linker_path(void) { + Buf *dontcare; + (void)get_compiler_id(&dontcare); // for the side-effects of caching the dynamic linker path + return (saved_dynamic_linker_path.list.length == 0) ? nullptr : &saved_dynamic_linker_path; +} static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) { Buf lib_buf = BUF_INIT; diff --git a/src/compiler.hpp b/src/compiler.hpp index ffdd1cefbb..f2788b9998 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -11,11 +11,12 @@ #include "buffer.hpp" #include "error.hpp" -Buf *get_stage1_cache_path(); +Buf *get_stage1_cache_path(void); Error get_compiler_id(Buf **result); +Buf *get_self_dynamic_linker_path(void); -Buf *get_zig_lib_dir(); -Buf *get_zig_special_dir(); -Buf *get_zig_std_dir(); +Buf *get_zig_lib_dir(void); +Buf *get_zig_special_dir(void); +Buf *get_zig_std_dir(void); #endif diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp index 49c969d704..8a293af82a 100644 --- a/src/libc_installation.cpp +++ b/src/libc_installation.cpp @@ -16,7 +16,6 @@ static const char *zig_libc_keys[] = { "crt_dir", "msvc_lib_dir", "kernel32_lib_dir", - "dynamic_linker_path", }; static const size_t zig_libc_keys_len = array_length(zig_libc_keys); @@ -37,7 +36,6 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) { buf_init_from_str(&libc->crt_dir, ""); buf_init_from_str(&libc->msvc_lib_dir, ""); buf_init_from_str(&libc->kernel32_lib_dir, ""); - buf_init_from_str(&libc->dynamic_linker_path, ""); } Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) { @@ -78,7 +76,6 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_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); } for (size_t i = 0; i < zig_libc_keys_len; i += 1) { @@ -131,15 +128,6 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget } } - if (buf_len(&libc->dynamic_linker_path) == 0) { - if (!target_is_darwin(target) && target->os != OsWindows) { - if (verbose) { - fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", target_os_name(target->os)); - } - return ErrorSemanticAnalyzeFail; - } - } - return ErrorNone; } @@ -301,8 +289,8 @@ static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, b } return ErrorFileNotFound; } -#if !defined(ZIG_OS_DARWIN) && !defined(ZIG_OS_FREEBSD) && !defined(ZIG_OS_NETBSD) -static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) { +#if defined(ZIG_OS_LINUX) +Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) { const char *cc_exe = getenv("CC"); cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; ZigList args = {}; @@ -340,32 +328,6 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose); } #endif - -static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) { -#if defined(ZIG_OS_LINUX) - Error err; - static const char *dyn_tests[] = { - "ld-linux-x86-64.so.2", - "ld-musl-x86_64.so.1", - }; - for (size_t i = 0; i < array_length(dyn_tests); i += 1) { - const char *lib_name = dyn_tests[i]; - if ((err = zig_libc_cc_print_file_name(lib_name, &self->dynamic_linker_path, false, true))) { - if (err != ErrorCCompilerCannotFindFile) - return err; - continue; - } - return ErrorNone; - } -#endif - ZigTarget native_target; - get_native_target(&native_target); - const char *dynamic_linker_path = target_dynamic_linker(&native_target); - if (dynamic_linker_path != nullptr) { - buf_init_from_str(&self->dynamic_linker_path, dynamic_linker_path); - } - return ErrorNone; -} #endif void zig_libc_render(ZigLibCInstallation *self, FILE *file) { @@ -391,17 +353,12 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) { "# Only needed when targeting Windows.\n" "kernel32_lib_dir=%s\n" "\n" - "# The full path to the dynamic linker, on the target system.\n" - "# Not needed when targeting MacOS or Windows.\n" - "dynamic_linker_path=%s\n" - "\n" , buf_ptr(&self->include_dir), buf_ptr(&self->sys_include_dir), buf_ptr(&self->crt_dir), buf_ptr(&self->msvc_lib_dir), - buf_ptr(&self->kernel32_lib_dir), - buf_ptr(&self->dynamic_linker_path) + buf_ptr(&self->kernel32_lib_dir) ); } @@ -438,12 +395,10 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { return err; #if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) buf_init_from_str(&self->crt_dir, "/usr/lib"); -#elif !defined(ZIG_OS_DARWIN) +#elif defined(ZIG_OS_LINUX) if ((err = zig_libc_find_native_crt_dir_posix(self, verbose))) return err; #endif - if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose))) - return err; return ErrorNone; #endif } diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp index a7e18e6d8a..8bcbac68c6 100644 --- a/src/libc_installation.hpp +++ b/src/libc_installation.hpp @@ -21,7 +21,6 @@ struct ZigLibCInstallation { Buf crt_dir; Buf msvc_lib_dir; Buf kernel32_lib_dir; - Buf dynamic_linker_path; }; Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, @@ -30,4 +29,8 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file); Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose); +#if defined(ZIG_OS_LINUX) +Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose); +#endif + #endif diff --git a/src/link.cpp b/src/link.cpp index f7df0112db..320d1204d2 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -517,14 +517,9 @@ static void construct_linker_job_elf(LinkJob *lj) { } if (!g->is_static) { - if (g->libc != nullptr) { - assert(buf_len(&g->libc->dynamic_linker_path) != 0); - lj->args.append("-dynamic-linker"); - lj->args.append(buf_ptr(&g->libc->dynamic_linker_path)); - } else { - lj->args.append("-dynamic-linker"); - lj->args.append(target_dynamic_linker(g->zig_target)); - } + assert(g->dynamic_linker_path != nullptr); + lj->args.append("-dynamic-linker"); + lj->args.append(buf_ptr(g->dynamic_linker_path)); } } @@ -545,7 +540,6 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append(buf_ptr(builtin_a_path)); } - // sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage Buf *compiler_rt_o_path = build_compiler_rt(g); lj->args.append(buf_ptr(compiler_rt_o_path)); } diff --git a/src/main.cpp b/src/main.cpp index de54633a79..7d2c5cf029 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,7 +166,7 @@ static int print_target_list(FILE *f) { SubArchList sub_arch_list = target_subarch_list(arch); size_t sub_count = target_subarch_count(sub_arch_list); const char *arch_native_str = (native.arch == arch) ? " (native)" : ""; - fprintf(stderr, " %s%s\n", arch_name, arch_native_str); + fprintf(f, " %s%s\n", arch_name, arch_native_str); for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); const char *sub_name = target_subarch_name(sub); @@ -406,6 +406,7 @@ int main(int argc, char **argv) { bool verbose_cc = false; ErrColor color = ErrColorAuto; CacheOpt enable_cache = CacheOptAuto; + const char *dynamic_linker = nullptr; const char *libc_txt = nullptr; ZigList clang_argv = {0}; ZigList llvm_argv = {0}; @@ -715,6 +716,8 @@ int main(int argc, char **argv) { } } else if (strcmp(arg, "--name") == 0) { out_name = argv[i]; + } else if (strcmp(arg, "--dynamic-linker") == 0) { + dynamic_linker = argv[i]; } else if (strcmp(arg, "--libc") == 0) { libc_txt = argv[i]; } else if (strcmp(arg, "-isystem") == 0) { @@ -1027,6 +1030,8 @@ int main(int argc, char **argv) { codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length); codegen_set_strip(g, strip); codegen_set_is_static(g, is_static); + if (dynamic_linker != nullptr) + codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); g->verbose_tokenize = verbose_tokenize; g->verbose_ast = verbose_ast; g->verbose_link = verbose_link; -- cgit v1.2.3