authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2020-06-04 16:20:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-24 20:01:18+00:00
log3b26e508638e96997aff3d5ef2c42a917bf86cc8
tree969d4867b78ae9fcc79db31a9c34bb27ab82c439
parentdf1a2ecd3bfea5506151f62780f442dbe487db96

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

6 files changed, 92 insertions(+), 46 deletions(-)

src-self-hosted/stage2.zig+2
...@@ -1271,3 +1271,5 @@ export fn stage2_clang_arg_next(it: *ClangArgIterator) Error {...@@ -1271,3 +1271,5 @@ export fn stage2_clang_arg_next(it: *ClangArgIterator) Error {
1271 };1271 };
1272 return .None;1272 return .None;
1273}1273}
1274
1275export const stage2_is_zig0 = false;
src/link.cpp+59-35
...@@ -2002,6 +2002,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -2002,6 +2002,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
2002 lj->args.append(buf_ptr(compiler_rt_o_path));2002 lj->args.append(buf_ptr(compiler_rt_o_path));
2003 }2003 }
20042004
2005 // libraries
2005 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {2006 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
2006 LinkLib *link_lib = g->link_libs_list.at(i);2007 LinkLib *link_lib = g->link_libs_list.at(i);
2007 if (buf_eql_str(link_lib->name, "c")) {2008 if (buf_eql_str(link_lib->name, "c")) {
...@@ -2662,8 +2663,8 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -2662,8 +2663,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
2662static void construct_linker_job_macho(LinkJob *lj) {2663static void construct_linker_job_macho(LinkJob *lj) {
2663 CodeGen *g = lj->codegen;2664 CodeGen *g = lj->codegen;
26642665
2665 // LLD MACH-O has no error limit option.2666 lj->args.append("-error-limit");
2666 //lj->args.append("-error-limit=0");2667 lj->args.append("0");
2667 lj->args.append("-demangle");2668 lj->args.append("-demangle");
26682669
2669 switch (g->linker_gc_sections) {2670 switch (g->linker_gc_sections) {
...@@ -2736,6 +2737,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -2736,6 +2737,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
2736 lj->args.append("-iphoneos_version_min");2737 lj->args.append("-iphoneos_version_min");
2737 }2738 }
2738 }2739 }
2740
2739 Buf *version_string = buf_sprintf("%d.%d.%d",2741 Buf *version_string = buf_sprintf("%d.%d.%d",
2740 g->zig_target->glibc_or_darwin_version->major,2742 g->zig_target->glibc_or_darwin_version->major,
2741 g->zig_target->glibc_or_darwin_version->minor,2743 g->zig_target->glibc_or_darwin_version->minor,
...@@ -2744,6 +2746,12 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -2744,6 +2746,12 @@ static void construct_linker_job_macho(LinkJob *lj) {
27442746
2745 lj->args.append("-sdk_version");2747 lj->args.append("-sdk_version");
2746 lj->args.append(buf_ptr(version_string));2748 lj->args.append(buf_ptr(version_string));
2749 } else if (stage2_is_zig0 && g->zig_target->os == OsMacOSX) {
2750 // running `zig0`; `-pie` requires versions >= 10.5; select 10.13
2751 lj->args.append("-macosx_version_min");
2752 lj->args.append("10.13");
2753 lj->args.append("-sdk_version");
2754 lj->args.append("10.13");
2747 }2755 }
27482756
2749 if (g->out_type == OutTypeExe) {2757 if (g->out_type == OutTypeExe) {
...@@ -2773,45 +2781,74 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -2773,45 +2781,74 @@ static void construct_linker_job_macho(LinkJob *lj) {
2773 lj->args.append(lib_dir);2781 lj->args.append(lib_dir);
2774 }2782 }
27752783
2784 // .o files
2776 for (size_t i = 0; i < g->link_objects.length; i += 1) {2785 for (size_t i = 0; i < g->link_objects.length; i += 1) {
2777 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));2786 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
2778 }2787 }
27792788
2780 // libc++ dep
2781 if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
2782 lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
2783 lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
2784 }
2785
2786 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce2789 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
2787 if (g->out_type == OutTypeExe || is_dyn_lib) {2790 if (g->out_type == OutTypeExe || is_dyn_lib) {
2788 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);2791 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
2789 lj->args.append(buf_ptr(compiler_rt_o_path));2792 lj->args.append(buf_ptr(compiler_rt_o_path));
2790 }2793 }
27912794
2792 if (g->zig_target->is_native_os) {2795 // libraries
2793 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {2796 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
2794 LinkLib *link_lib = g->link_libs_list.at(lib_i);2797 LinkLib *link_lib = g->link_libs_list.at(lib_i);
2795 if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {2798 if (buf_eql_str(link_lib->name, "c")) {
2796 // handled by libSystem2799 // libc is linked specially
2797 continue;2800 continue;
2798 }2801 }
2799 if (strchr(buf_ptr(link_lib->name), '/') == nullptr) {2802 if (target_is_libcpp_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
2800 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));2803 // libc++ is linked specially
2801 lj->args.append(buf_ptr(arg));2804 continue;
2802 } else {
2803 lj->args.append(buf_ptr(link_lib->name));
2804 }
2805 }2805 }
2806 if (g->zig_target->is_native_os && target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name))) {
2807 // libSystem is linked specially
2808 continue;
2809 }
2810
2811 Buf *arg;
2812 if (buf_starts_with_str(link_lib->name, "/") || buf_ends_with_str(link_lib->name, ".a") ||
2813 buf_ends_with_str(link_lib->name, ".dylib"))
2814 {
2815 arg = link_lib->name;
2816 } else {
2817 arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
2818 }
2819 lj->args.append(buf_ptr(arg));
2820 }
2821
2822 // libc++ dep
2823 if (g->libcpp_link_lib != nullptr && g->out_type != OutTypeObj) {
2824 lj->args.append(build_libcxxabi(g, lj->build_dep_prog_node));
2825 lj->args.append(build_libcxx(g, lj->build_dep_prog_node));
2826 }
2827
2828 // libc dep
2829 if (g->zig_target->is_native_os || stage2_is_zig0) {
2806 // on Darwin, libSystem has libc in it, but also you have to use it2830 // on Darwin, libSystem has libc in it, but also you have to use it
2807 // to make syscalls because the syscall numbers are not documented2831 // to make syscalls because the syscall numbers are not documented
2808 // and change between versions.2832 // and change between versions.
2809 // so we always link against libSystem2833 // so we always link against libSystem
2810 lj->args.append("-lSystem");2834 lj->args.append("-lSystem");
2811 }2835 }
2836
2837 for (size_t i = 0; i < g->framework_dirs.length; i += 1) {
2838 const char *framework_dir = g->framework_dirs.at(i);
2839 lj->args.append("-F");
2840 lj->args.append(framework_dir);
2841 }
2842
2843 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
2844 lj->args.append("-framework");
2845 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
2846 }
2847
2812 switch (g->linker_allow_shlib_undefined) {2848 switch (g->linker_allow_shlib_undefined) {
2813 case OptionalBoolNull:2849 case OptionalBoolNull:
2814 if (!g->zig_target->is_native_os) {2850 if (!g->zig_target->is_native_os && !stage2_is_zig0) {
2851 // TODO https://github.com/ziglang/zig/issues/5059
2815 lj->args.append("-undefined");2852 lj->args.append("-undefined");
2816 lj->args.append("dynamic_lookup");2853 lj->args.append("dynamic_lookup");
2817 }2854 }
...@@ -2831,18 +2868,6 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -2831,18 +2868,6 @@ static void construct_linker_job_macho(LinkJob *lj) {
2831 lj->args.append("-Bsymbolic");2868 lj->args.append("-Bsymbolic");
2832 break;2869 break;
2833 }2870 }
2834
2835 for (size_t i = 0; i < g->framework_dirs.length; i += 1) {
2836 const char *framework_dir = g->framework_dirs.at(i);
2837 lj->args.append("-F");
2838 lj->args.append(framework_dir);
2839 }
2840
2841 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
2842 lj->args.append("-framework");
2843 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
2844 }
2845
2846}2871}
28472872
2848static void construct_linker_job(LinkJob *lj) {2873static void construct_linker_job(LinkJob *lj) {
...@@ -2920,7 +2945,6 @@ void codegen_link(CodeGen *g) {...@@ -2920,7 +2945,6 @@ void codegen_link(CodeGen *g) {
29202945
2921 construct_linker_job(&lj);2946 construct_linker_job(&lj);
29222947
2923
2924 if (g->verbose_link) {2948 if (g->verbose_link) {
2925 for (size_t i = 0; i < lj.args.length; i += 1) {2949 for (size_t i = 0; i < lj.args.length; i += 1) {
2926 const char *space = (i != 0) ? " " : "";2950 const char *space = (i != 0) ? " " : "";
src/stage2.cpp+2
...@@ -322,3 +322,5 @@ enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it) {...@@ -322,3 +322,5 @@ enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it) {
322 const char *msg = "stage0 called stage2_clang_arg_next";322 const char *msg = "stage0 called stage2_clang_arg_next";
323 stage2_panic(msg, strlen(msg));323 stage2_panic(msg, strlen(msg));
324}324}
325
326const bool stage2_is_zig0 = true;
src/stage2.h+3
...@@ -379,4 +379,7 @@ ZIG_EXTERN_C void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,...@@ -379,4 +379,7 @@ ZIG_EXTERN_C void stage2_clang_arg_iterator(struct Stage2ClangArgIterator *it,
379// ABI warning379// ABI warning
380ZIG_EXTERN_C enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it);380ZIG_EXTERN_C enum Error stage2_clang_arg_next(struct Stage2ClangArgIterator *it);
381381
382// ABI warning
383ZIG_EXTERN_C const bool stage2_is_zig0;
384
382#endif385#endif
src/target.cpp+18-11
...@@ -1209,39 +1209,46 @@ const char *target_libc_generic_name(const ZigTarget *target) {...@@ -1209,39 +1209,46 @@ const char *target_libc_generic_name(const ZigTarget *target) {
1209}1209}
12101210
1211bool target_is_libc_lib_name(const ZigTarget *target, const char *name) {1211bool target_is_libc_lib_name(const ZigTarget *target, const char *name) {
1212 if (strcmp(name, "c") == 0)1212 auto equal = str_eql_str;
1213 if (target->os == OsMacOSX)
1214 equal = str_eql_str_ignore_case;
1215
1216 if (equal(name, "c"))
1213 return true;1217 return true;
12141218
1215 if (target_abi_is_gnu(target->abi) && target->os == OsWindows) {1219 if (target_abi_is_gnu(target->abi) && target->os == OsWindows) {
1216 // mingw-w641220 // mingw-w64
12171221
1218 if (strcmp(name, "m") == 0)1222 if (equal(name, "m"))
1219 return true;1223 return true;
12201224
1221 return false;1225 return false;
1222 }1226 }
12231227
1224 if (target_abi_is_gnu(target->abi) || target_abi_is_musl(target->abi) || target_os_is_darwin(target->os)) {1228 if (target_abi_is_gnu(target->abi) || target_abi_is_musl(target->abi) || target_os_is_darwin(target->os)) {
1225 if (strcmp(name, "m") == 0)1229 if (equal(name, "m"))
1226 return true;1230 return true;
1227 if (strcmp(name, "rt") == 0)1231 if (equal(name, "rt"))
1228 return true;1232 return true;
1229 if (strcmp(name, "pthread") == 0)1233 if (equal(name, "pthread"))
1230 return true;1234 return true;
1231 if (strcmp(name, "crypt") == 0)1235 if (equal(name, "crypt"))
1232 return true;1236 return true;
1233 if (strcmp(name, "util") == 0)1237 if (equal(name, "util"))
1234 return true;1238 return true;
1235 if (strcmp(name, "xnet") == 0)1239 if (equal(name, "xnet"))
1236 return true;1240 return true;
1237 if (strcmp(name, "resolv") == 0)1241 if (equal(name, "resolv"))
1238 return true;1242 return true;
1239 if (strcmp(name, "dl") == 0)1243 if (equal(name, "dl"))
1240 return true;1244 return true;
1241 if (strcmp(name, "util") == 0)1245 if (equal(name, "util"))
1242 return true;1246 return true;
1243 }1247 }
12441248
1249 if (target_os_is_darwin(target->os) && equal(name, "System"))
1250 return true;
1251
1245 return false;1252 return false;
1246}1253}
12471254
src/util.hpp+8
...@@ -96,6 +96,14 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str)...@@ -96,6 +96,14 @@ static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str)
96 return mem_eql_mem(mem, mem_len, str, strlen(str));96 return mem_eql_mem(mem, mem_len, str, strlen(str));
97}97}
9898
99static inline bool str_eql_str(const char *a, const char* b) {
100 return mem_eql_mem(a, strlen(a), b, strlen(b));
101}
102
103static inline bool str_eql_str_ignore_case(const char *a, const char* b) {
104 return mem_eql_mem_ignore_case(a, strlen(a), b, strlen(b));
105}
106
99static inline bool is_power_of_2(uint64_t x) {107static inline bool is_power_of_2(uint64_t x) {
100 return x != 0 && ((x & (~x + 1)) == x);108 return x != 0 && ((x & (~x + 1)) == x);
101}109}