mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 22:09:49 +00:00
dynamic linker path is independent from libc installation
This commit is contained in:
parent
0d10ab0680
commit
55a0016221
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
12
src/link.cpp
12
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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user