Commit 55a0016221
Changed files (9)
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;
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;
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);
src/compiler.cpp
@@ -1,4 +1,5 @@
#include "cache_hash.hpp"
+#include "os.hpp"
#include <stdio.h>
@@ -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;
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
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<const char *> 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
}
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
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));
}
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<const char *> clang_argv = {0};
ZigList<const char *> 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;