mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
macOS: macho ld64.lld fixes
* bring `construct_linker_job_macho` to parity with `construct_linker_job_elf` * macho now sets `-error-limit` * macho on macOS now sets `-macosx_version_min` and `-sdk_version` to `10.13` when running `zig0` * macho now detects when `-l` prefix is not needed * macho on macOS detects system libraries in a case-insensitive manner * macho now ads user-specified libraries to linker command-line args when condition `is_native_os != true` * re-ordered some macho args positions to match elf positions closes #5059 closes #5067
This commit is contained in:
parent
df1a2ecd3b
commit
3b26e50863
@ -1271,3 +1271,5 @@ export fn stage2_clang_arg_next(it: *ClangArgIterator) Error {
|
||||
};
|
||||
return .None;
|
||||
}
|
||||
|
||||
export const stage2_is_zig0 = false;
|
||||
|
||||
94
src/link.cpp
94
src/link.cpp
@ -2002,6 +2002,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
||||
lj->args.append(buf_ptr(compiler_rt_o_path));
|
||||
}
|
||||
|
||||
// libraries
|
||||
for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
|
||||
LinkLib *link_lib = g->link_libs_list.at(i);
|
||||
if (buf_eql_str(link_lib->name, "c")) {
|
||||
@ -2662,8 +2663,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
||||
static void construct_linker_job_macho(LinkJob *lj) {
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
// LLD MACH-O has no error limit option.
|
||||
//lj->args.append("-error-limit=0");
|
||||
lj->args.append("-error-limit");
|
||||
lj->args.append("0");
|
||||
lj->args.append("-demangle");
|
||||
|
||||
switch (g->linker_gc_sections) {
|
||||
@ -2736,6 +2737,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
lj->args.append("-iphoneos_version_min");
|
||||
}
|
||||
}
|
||||
|
||||
Buf *version_string = buf_sprintf("%d.%d.%d",
|
||||
g->zig_target->glibc_or_darwin_version->major,
|
||||
g->zig_target->glibc_or_darwin_version->minor,
|
||||
@ -2744,6 +2746,12 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
|
||||
lj->args.append("-sdk_version");
|
||||
lj->args.append(buf_ptr(version_string));
|
||||
} else if (stage2_is_zig0 && g->zig_target->os == OsMacOSX) {
|
||||
// running `zig0`; `-pie` requires versions >= 10.5; select 10.13
|
||||
lj->args.append("-macosx_version_min");
|
||||
lj->args.append("10.13");
|
||||
lj->args.append("-sdk_version");
|
||||
lj->args.append("10.13");
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeExe) {
|
||||
@ -2773,45 +2781,74 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
lj->args.append(lib_dir);
|
||||
}
|
||||
|
||||
// .o files
|
||||
for (size_t i = 0; i < g->link_objects.length; i += 1) {
|
||||
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
|
||||
lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
|
||||
lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
|
||||
}
|
||||
|
||||
// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
|
||||
if (g->out_type == OutTypeExe || is_dyn_lib) {
|
||||
Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
|
||||
lj->args.append(buf_ptr(compiler_rt_o_path));
|
||||
}
|
||||
|
||||
if (g->zig_target->is_native_os) {
|
||||
for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
|
||||
LinkLib *link_lib = g->link_libs_list.at(lib_i);
|
||||
if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
|
||||
// handled by libSystem
|
||||
continue;
|
||||
}
|
||||
if (strchr(buf_ptr(link_lib->name), '/') == nullptr) {
|
||||
Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
|
||||
lj->args.append(buf_ptr(arg));
|
||||
} else {
|
||||
lj->args.append(buf_ptr(link_lib->name));
|
||||
}
|
||||
// libraries
|
||||
for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
|
||||
LinkLib *link_lib = g->link_libs_list.at(lib_i);
|
||||
if (buf_eql_str(link_lib->name, "c")) {
|
||||
// libc is linked specially
|
||||
continue;
|
||||
}
|
||||
if (target_is_libcpp_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
|
||||
// libc++ is linked specially
|
||||
continue;
|
||||
}
|
||||
if (g->zig_target->is_native_os && target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
|
||||
// libSystem is linked specially
|
||||
continue;
|
||||
}
|
||||
|
||||
Buf *arg;
|
||||
if (buf_starts_with_str(link_lib->name, "/") || buf_ends_with_str(link_lib->name, ".a") ||
|
||||
buf_ends_with_str(link_lib->name, ".dylib"))
|
||||
{
|
||||
arg = link_lib->name;
|
||||
} else {
|
||||
arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
|
||||
}
|
||||
lj->args.append(buf_ptr(arg));
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
|
||||
lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
|
||||
lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
|
||||
}
|
||||
|
||||
// libc dep
|
||||
if (g->zig_target->is_native_os || stage2_is_zig0) {
|
||||
// on Darwin, libSystem has libc in it, but also you have to use it
|
||||
// to make syscalls because the syscall numbers are not documented
|
||||
// and change between versions.
|
||||
// so we always link against libSystem
|
||||
lj->args.append("-lSystem");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g->framework_dirs.length; i += 1) {
|
||||
const char *framework_dir = g->framework_dirs.at(i);
|
||||
lj->args.append("-F");
|
||||
lj->args.append(framework_dir);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
|
||||
lj->args.append("-framework");
|
||||
lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
|
||||
}
|
||||
|
||||
switch (g->linker_allow_shlib_undefined) {
|
||||
case OptionalBoolNull:
|
||||
if (!g->zig_target->is_native_os) {
|
||||
if (!g->zig_target->is_native_os && !stage2_is_zig0) {
|
||||
// TODO https://github.com/ziglang/zig/issues/5059
|
||||
lj->args.append("-undefined");
|
||||
lj->args.append("dynamic_lookup");
|
||||
}
|
||||
@ -2831,18 +2868,6 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
lj->args.append("-Bsymbolic");
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g->framework_dirs.length; i += 1) {
|
||||
const char *framework_dir = g->framework_dirs.at(i);
|
||||
lj->args.append("-F");
|
||||
lj->args.append(framework_dir);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
|
||||
lj->args.append("-framework");
|
||||
lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void construct_linker_job(LinkJob *lj) {
|
||||
@ -2920,7 +2945,6 @@ void codegen_link(CodeGen *g) {
|
||||
|
||||
construct_linker_job(&lj);
|
||||
|
||||
|
||||
if (g->verbose_link) {
|
||||
for (size_t i = 0; i < lj.args.length; i += 1) {
|
||||
const char *space = (i != 0) ? " " : "";
|
||||
|
||||
@ -322,3 +322,5 @@ enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it) {
|
||||
const char *msg = "stage0 called stage2_clang_arg_next";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
|
||||
const bool stage2_is_zig0 = true;
|
||||
|
||||
@ -379,4 +379,7 @@ ZIG_EXTERN_C void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C const bool stage2_is_zig0;
|
||||
|
||||
#endif
|
||||
|
||||
@ -1209,39 +1209,46 @@ const char *target_libc_generic_name(const ZigTarget *target) {
|
||||
}
|
||||
|
||||
bool target_is_libc_lib_name(const ZigTarget *target, const char *name) {
|
||||
if (strcmp(name, "c") == 0)
|
||||
auto equal = str_eql_str;
|
||||
if (target->os == OsMacOSX)
|
||||
equal = str_eql_str_ignore_case;
|
||||
|
||||
if (equal(name, "c"))
|
||||
return true;
|
||||
|
||||
if (target_abi_is_gnu(target->abi) && target->os == OsWindows) {
|
||||
// mingw-w64
|
||||
|
||||
if (strcmp(name, "m") == 0)
|
||||
if (equal(name, "m"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target_abi_is_gnu(target->abi) || target_abi_is_musl(target->abi) || target_os_is_darwin(target->os)) {
|
||||
if (strcmp(name, "m") == 0)
|
||||
if (equal(name, "m"))
|
||||
return true;
|
||||
if (strcmp(name, "rt") == 0)
|
||||
if (equal(name, "rt"))
|
||||
return true;
|
||||
if (strcmp(name, "pthread") == 0)
|
||||
if (equal(name, "pthread"))
|
||||
return true;
|
||||
if (strcmp(name, "crypt") == 0)
|
||||
if (equal(name, "crypt"))
|
||||
return true;
|
||||
if (strcmp(name, "util") == 0)
|
||||
if (equal(name, "util"))
|
||||
return true;
|
||||
if (strcmp(name, "xnet") == 0)
|
||||
if (equal(name, "xnet"))
|
||||
return true;
|
||||
if (strcmp(name, "resolv") == 0)
|
||||
if (equal(name, "resolv"))
|
||||
return true;
|
||||
if (strcmp(name, "dl") == 0)
|
||||
if (equal(name, "dl"))
|
||||
return true;
|
||||
if (strcmp(name, "util") == 0)
|
||||
if (equal(name, "util"))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target_os_is_darwin(target->os) && equal(name, "System"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -96,6 +96,14 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str)
|
||||
return mem_eql_mem(mem, mem_len, str, strlen(str));
|
||||
}
|
||||
|
||||
static inline bool str_eql_str(const char *a, const char* b) {
|
||||
return mem_eql_mem(a, strlen(a), b, strlen(b));
|
||||
}
|
||||
|
||||
static inline bool str_eql_str_ignore_case(const char *a, const char* b) {
|
||||
return mem_eql_mem_ignore_case(a, strlen(a), b, strlen(b));
|
||||
}
|
||||
|
||||
static inline bool is_power_of_2(uint64_t x) {
|
||||
return x != 0 && ((x & (~x + 1)) == x);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user