| ... | @@ -527,11 +527,11 @@ const usage_build_generic = | ... | @@ -527,11 +527,11 @@ const usage_build_generic = |
| 527 | \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker | 527 | \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker |
| 528 | \\ --stack [size] Override default stack size | 528 | \\ --stack [size] Override default stack size |
| 529 | \\ --image-base [addr] Set base address for executable image | 529 | \\ --image-base [addr] Set base address for executable image |
| 530 | \\ -weak-l[lib] (Darwin) link against system library and mark it and all referenced symbols as weak | 530 | \\ -weak-l[lib] link against system library and mark it and all referenced symbols as weak |
| 531 | \\ -weak_library [lib] | 531 | \\ -weak_library [lib] |
| 532 | \\ -framework [name] (Darwin) link against framework | 532 | \\ -framework [name] (Darwin) link against framework |
| 533 | \\ -needed_framework [name] (Darwin) link against framework (even if unused) | 533 | \\ -needed_framework [name] (Darwin) link against framework (even if unused) |
| 534 | \\ -needed_library [lib] (Darwin) link against system library (even if unused) | 534 | \\ -needed_library [lib] link against system library (even if unused) |
| 535 | \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak | 535 | \\ -weak_framework [name] (Darwin) link against framework and mark it and all referenced symbols as weak |
| 536 | \\ -F[dir] (Darwin) add search path for frameworks | 536 | \\ -F[dir] (Darwin) add search path for frameworks |
| 537 | \\ -install_name=[value] (Darwin) add dylib's install name | 537 | \\ -install_name=[value] (Darwin) add dylib's install name |
| ... | @@ -716,6 +716,27 @@ const ArgsIterator = struct { | ... | @@ -716,6 +716,27 @@ const ArgsIterator = struct { |
| 716 | } | 716 | } |
| 717 | }; | 717 | }; |
| 718 | | 718 | |
| | 719 | /// In contrast to `link.SystemLib`, this stores arguments that may need to be |
| | 720 | /// resolved into static libraries so that we can pass only dynamic libraries |
| | 721 | /// as system libs to `Compilation`. |
| | 722 | const SystemLib = struct { |
| | 723 | needed: bool, |
| | 724 | weak: bool, |
| | 725 | |
| | 726 | preferred_mode: std.builtin.LinkMode, |
| | 727 | search_strategy: SearchStrategy, |
| | 728 | |
| | 729 | const SearchStrategy = enum { paths_first, mode_first, no_fallback }; |
| | 730 | |
| | 731 | fn fallbackMode(this: SystemLib) std.builtin.LinkMode { |
| | 732 | assert(this.search_strategy != .no_fallback); |
| | 733 | return switch (this.preferred_mode) { |
| | 734 | .Dynamic => .Static, |
| | 735 | .Static => .Dynamic, |
| | 736 | }; |
| | 737 | } |
| | 738 | }; |
| | 739 | |
| 719 | fn buildOutputType( | 740 | fn buildOutputType( |
| 720 | gpa: Allocator, | 741 | gpa: Allocator, |
| 721 | arena: Allocator, | 742 | arena: Allocator, |
| ... | @@ -854,7 +875,8 @@ fn buildOutputType( | ... | @@ -854,7 +875,8 @@ fn buildOutputType( |
| 854 | var hash_style: link.HashStyle = .both; | 875 | var hash_style: link.HashStyle = .both; |
| 855 | var entitlements: ?[]const u8 = null; | 876 | var entitlements: ?[]const u8 = null; |
| 856 | var pagezero_size: ?u64 = null; | 877 | var pagezero_size: ?u64 = null; |
| 857 | var search_strategy: ?link.File.MachO.SearchStrategy = null; | 878 | var lib_search_strategy: ?SystemLib.SearchStrategy = null; |
| | 879 | var lib_preferred_mode: ?std.builtin.LinkMode = null; |
| 858 | var headerpad_size: ?u32 = null; | 880 | var headerpad_size: ?u32 = null; |
| 859 | var headerpad_max_install_names: bool = false; | 881 | var headerpad_max_install_names: bool = false; |
| 860 | var dead_strip_dylibs: bool = false; | 882 | var dead_strip_dylibs: bool = false; |
| ... | @@ -869,11 +891,7 @@ fn buildOutputType( | ... | @@ -869,11 +891,7 @@ fn buildOutputType( |
| 869 | var llvm_m_args = std.ArrayList([]const u8).init(gpa); | 891 | var llvm_m_args = std.ArrayList([]const u8).init(gpa); |
| 870 | defer llvm_m_args.deinit(); | 892 | defer llvm_m_args.deinit(); |
| 871 | | 893 | |
| 872 | var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa); | 894 | var system_libs = std.StringArrayHashMap(SystemLib).init(arena); |
| 873 | defer system_libs.deinit(); | | |
| 874 | | | |
| 875 | var static_libs = std.ArrayList([]const u8).init(gpa); | | |
| 876 | defer static_libs.deinit(); | | |
| 877 | | 895 | |
| 878 | var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa); | 896 | var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa); |
| 879 | defer wasi_emulated_libs.deinit(); | 897 | defer wasi_emulated_libs.deinit(); |
| ... | @@ -884,8 +902,8 @@ fn buildOutputType( | ... | @@ -884,8 +902,8 @@ fn buildOutputType( |
| 884 | var extra_cflags = std.ArrayList([]const u8).init(gpa); | 902 | var extra_cflags = std.ArrayList([]const u8).init(gpa); |
| 885 | defer extra_cflags.deinit(); | 903 | defer extra_cflags.deinit(); |
| 886 | | 904 | |
| 887 | var lib_dirs = std.ArrayList([]const u8).init(gpa); | 905 | // These are before resolving sysroot. |
| 888 | defer lib_dirs.deinit(); | 906 | var lib_dir_args = std.ArrayList([]const u8).init(arena); |
| 889 | | 907 | |
| 890 | var rpath_list = std.ArrayList([]const u8).init(gpa); | 908 | var rpath_list = std.ArrayList([]const u8).init(gpa); |
| 891 | defer rpath_list.deinit(); | 909 | defer rpath_list.deinit(); |
| ... | @@ -901,7 +919,7 @@ fn buildOutputType( | ... | @@ -901,7 +919,7 @@ fn buildOutputType( |
| 901 | var framework_dirs = std.ArrayList([]const u8).init(gpa); | 919 | var framework_dirs = std.ArrayList([]const u8).init(gpa); |
| 902 | defer framework_dirs.deinit(); | 920 | defer framework_dirs.deinit(); |
| 903 | | 921 | |
| 904 | var frameworks: std.StringArrayHashMapUnmanaged(Compilation.SystemLib) = .{}; | 922 | var frameworks: std.StringArrayHashMapUnmanaged(Compilation.Framework) = .{}; |
| 905 | | 923 | |
| 906 | // null means replace with the test executable binary | 924 | // null means replace with the test executable binary |
| 907 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); | 925 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); |
| ... | @@ -1061,7 +1079,7 @@ fn buildOutputType( | ... | @@ -1061,7 +1079,7 @@ fn buildOutputType( |
| 1061 | } else if (mem.eql(u8, arg, "-rpath")) { | 1079 | } else if (mem.eql(u8, arg, "-rpath")) { |
| 1062 | try rpath_list.append(args_iter.nextOrFatal()); | 1080 | try rpath_list.append(args_iter.nextOrFatal()); |
| 1063 | } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { | 1081 | } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) { |
| 1064 | try lib_dirs.append(args_iter.nextOrFatal()); | 1082 | try lib_dir_args.append(args_iter.nextOrFatal()); |
| 1065 | } else if (mem.eql(u8, arg, "-F")) { | 1083 | } else if (mem.eql(u8, arg, "-F")) { |
| 1066 | try framework_dirs.append(args_iter.nextOrFatal()); | 1084 | try framework_dirs.append(args_iter.nextOrFatal()); |
| 1067 | } else if (mem.eql(u8, arg, "-framework")) { | 1085 | } else if (mem.eql(u8, arg, "-framework")) { |
| ... | @@ -1085,9 +1103,11 @@ fn buildOutputType( | ... | @@ -1085,9 +1103,11 @@ fn buildOutputType( |
| 1085 | fatal("unable to parse pagezero size'{s}': {s}", .{ next_arg, @errorName(err) }); | 1103 | fatal("unable to parse pagezero size'{s}': {s}", .{ next_arg, @errorName(err) }); |
| 1086 | }; | 1104 | }; |
| 1087 | } else if (mem.eql(u8, arg, "-search_paths_first")) { | 1105 | } else if (mem.eql(u8, arg, "-search_paths_first")) { |
| 1088 | search_strategy = .paths_first; | 1106 | lib_search_strategy = .paths_first; |
| | 1107 | lib_preferred_mode = .Dynamic; |
| 1089 | } else if (mem.eql(u8, arg, "-search_dylibs_first")) { | 1108 | } else if (mem.eql(u8, arg, "-search_dylibs_first")) { |
| 1090 | search_strategy = .dylibs_first; | 1109 | lib_search_strategy = .mode_first; |
| | 1110 | lib_preferred_mode = .Dynamic; |
| 1091 | } else if (mem.eql(u8, arg, "-headerpad")) { | 1111 | } else if (mem.eql(u8, arg, "-headerpad")) { |
| 1092 | const next_arg = args_iter.nextOrFatal(); | 1112 | const next_arg = args_iter.nextOrFatal(); |
| 1093 | headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { | 1113 | headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { |
| ... | @@ -1104,17 +1124,36 @@ fn buildOutputType( | ... | @@ -1104,17 +1124,36 @@ fn buildOutputType( |
| 1104 | } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) { | 1124 | } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) { |
| 1105 | version_script = args_iter.nextOrFatal(); | 1125 | version_script = args_iter.nextOrFatal(); |
| 1106 | } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { | 1126 | } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) { |
| 1107 | // We don't know whether this library is part of libc or libc++ until | 1127 | // We don't know whether this library is part of libc |
| 1108 | // we resolve the target, so we simply append to the list for now. | 1128 | // or libc++ until we resolve the target, so we append |
| 1109 | try system_libs.put(args_iter.nextOrFatal(), .{}); | 1129 | // to the list for now. |
| | 1130 | try system_libs.put(args_iter.nextOrFatal(), .{ |
| | 1131 | .needed = false, |
| | 1132 | .weak = false, |
| | 1133 | // -l always dynamic links. For static libraries, |
| | 1134 | // users are expected to use positional arguments |
| | 1135 | // which are always unambiguous. |
| | 1136 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1137 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1138 | }); |
| 1110 | } else if (mem.eql(u8, arg, "--needed-library") or | 1139 | } else if (mem.eql(u8, arg, "--needed-library") or |
| 1111 | mem.eql(u8, arg, "-needed-l") or | 1140 | mem.eql(u8, arg, "-needed-l") or |
| 1112 | mem.eql(u8, arg, "-needed_library")) | 1141 | mem.eql(u8, arg, "-needed_library")) |
| 1113 | { | 1142 | { |
| 1114 | const next_arg = args_iter.nextOrFatal(); | 1143 | const next_arg = args_iter.nextOrFatal(); |
| 1115 | try system_libs.put(next_arg, .{ .needed = true }); | 1144 | try system_libs.put(next_arg, .{ |
| | 1145 | .needed = true, |
| | 1146 | .weak = false, |
| | 1147 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1148 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1149 | }); |
| 1116 | } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) { | 1150 | } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) { |
| 1117 | try system_libs.put(args_iter.nextOrFatal(), .{ .weak = true }); | 1151 | try system_libs.put(args_iter.nextOrFatal(), .{ |
| | 1152 | .needed = false, |
| | 1153 | .weak = true, |
| | 1154 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1155 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1156 | }); |
| 1118 | } else if (mem.eql(u8, arg, "-D")) { | 1157 | } else if (mem.eql(u8, arg, "-D")) { |
| 1119 | try clang_argv.append(arg); | 1158 | try clang_argv.append(arg); |
| 1120 | try clang_argv.append(args_iter.nextOrFatal()); | 1159 | try clang_argv.append(args_iter.nextOrFatal()); |
| ... | @@ -1486,17 +1525,36 @@ fn buildOutputType( | ... | @@ -1486,17 +1525,36 @@ fn buildOutputType( |
| 1486 | } else if (mem.startsWith(u8, arg, "-T")) { | 1525 | } else if (mem.startsWith(u8, arg, "-T")) { |
| 1487 | linker_script = arg[2..]; | 1526 | linker_script = arg[2..]; |
| 1488 | } else if (mem.startsWith(u8, arg, "-L")) { | 1527 | } else if (mem.startsWith(u8, arg, "-L")) { |
| 1489 | try lib_dirs.append(arg[2..]); | 1528 | try lib_dir_args.append(arg[2..]); |
| 1490 | } else if (mem.startsWith(u8, arg, "-F")) { | 1529 | } else if (mem.startsWith(u8, arg, "-F")) { |
| 1491 | try framework_dirs.append(arg[2..]); | 1530 | try framework_dirs.append(arg[2..]); |
| 1492 | } else if (mem.startsWith(u8, arg, "-l")) { | 1531 | } else if (mem.startsWith(u8, arg, "-l")) { |
| 1493 | // We don't know whether this library is part of libc or libc++ until | 1532 | // We don't know whether this library is part of libc |
| 1494 | // we resolve the target, so we simply append to the list for now. | 1533 | // or libc++ until we resolve the target, so we append |
| 1495 | try system_libs.put(arg["-l".len..], .{}); | 1534 | // to the list for now. |
| | 1535 | try system_libs.put(arg["-l".len..], .{ |
| | 1536 | .needed = false, |
| | 1537 | .weak = false, |
| | 1538 | // -l always dynamic links. For static libraries, |
| | 1539 | // users are expected to use positional arguments |
| | 1540 | // which are always unambiguous. |
| | 1541 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1542 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1543 | }); |
| 1496 | } else if (mem.startsWith(u8, arg, "-needed-l")) { | 1544 | } else if (mem.startsWith(u8, arg, "-needed-l")) { |
| 1497 | try system_libs.put(arg["-needed-l".len..], .{ .needed = true }); | 1545 | try system_libs.put(arg["-needed-l".len..], .{ |
| | 1546 | .needed = true, |
| | 1547 | .weak = false, |
| | 1548 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1549 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1550 | }); |
| 1498 | } else if (mem.startsWith(u8, arg, "-weak-l")) { | 1551 | } else if (mem.startsWith(u8, arg, "-weak-l")) { |
| 1499 | try system_libs.put(arg["-weak-l".len..], .{ .weak = true }); | 1552 | try system_libs.put(arg["-weak-l".len..], .{ |
| | 1553 | .needed = false, |
| | 1554 | .weak = true, |
| | 1555 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1556 | .search_strategy = lib_search_strategy orelse .no_fallback, |
| | 1557 | }); |
| 1500 | } else if (mem.startsWith(u8, arg, "-D")) { | 1558 | } else if (mem.startsWith(u8, arg, "-D")) { |
| 1501 | try clang_argv.append(arg); | 1559 | try clang_argv.append(arg); |
| 1502 | } else if (mem.startsWith(u8, arg, "-I")) { | 1560 | } else if (mem.startsWith(u8, arg, "-I")) { |
| ... | @@ -1642,9 +1700,22 @@ fn buildOutputType( | ... | @@ -1642,9 +1700,22 @@ fn buildOutputType( |
| 1642 | .loption = true, | 1700 | .loption = true, |
| 1643 | }); | 1701 | }); |
| 1644 | } else if (force_static_libs) { | 1702 | } else if (force_static_libs) { |
| 1645 | try static_libs.append(it.only_arg); | 1703 | try system_libs.put(it.only_arg, .{ |
| | 1704 | .needed = false, |
| | 1705 | .weak = false, |
| | 1706 | .preferred_mode = .Static, |
| | 1707 | .search_strategy = .no_fallback, |
| | 1708 | }); |
| 1646 | } else { | 1709 | } else { |
| 1647 | try system_libs.put(it.only_arg, .{ .needed = needed }); | 1710 | // C compilers are traditionally expected to look |
| | 1711 | // first for dynamic libraries and then fall back |
| | 1712 | // to static libraries. |
| | 1713 | try system_libs.put(it.only_arg, .{ |
| | 1714 | .needed = needed, |
| | 1715 | .weak = false, |
| | 1716 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1717 | .search_strategy = lib_search_strategy orelse .paths_first, |
| | 1718 | }); |
| 1648 | } | 1719 | } |
| 1649 | }, | 1720 | }, |
| 1650 | .ignore => {}, | 1721 | .ignore => {}, |
| ... | @@ -1748,9 +1819,11 @@ fn buildOutputType( | ... | @@ -1748,9 +1819,11 @@ fn buildOutputType( |
| 1748 | { | 1819 | { |
| 1749 | force_static_libs = true; | 1820 | force_static_libs = true; |
| 1750 | } else if (mem.eql(u8, linker_arg, "-search_paths_first")) { | 1821 | } else if (mem.eql(u8, linker_arg, "-search_paths_first")) { |
| 1751 | search_strategy = .paths_first; | 1822 | lib_search_strategy = .paths_first; |
| | 1823 | lib_preferred_mode = .Dynamic; |
| 1752 | } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) { | 1824 | } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) { |
| 1753 | search_strategy = .dylibs_first; | 1825 | lib_search_strategy = .mode_first; |
| | 1826 | lib_preferred_mode = .Dynamic; |
| 1754 | } else { | 1827 | } else { |
| 1755 | try linker_args.append(linker_arg); | 1828 | try linker_args.append(linker_arg); |
| 1756 | } | 1829 | } |
| ... | @@ -1828,7 +1901,7 @@ fn buildOutputType( | ... | @@ -1828,7 +1901,7 @@ fn buildOutputType( |
| 1828 | try linker_args.append("-z"); | 1901 | try linker_args.append("-z"); |
| 1829 | try linker_args.append(it.only_arg); | 1902 | try linker_args.append(it.only_arg); |
| 1830 | }, | 1903 | }, |
| 1831 | .lib_dir => try lib_dirs.append(it.only_arg), | 1904 | .lib_dir => try lib_dir_args.append(it.only_arg), |
| 1832 | .mcpu => target_mcpu = it.only_arg, | 1905 | .mcpu => target_mcpu = it.only_arg, |
| 1833 | .m => try llvm_m_args.append(it.only_arg), | 1906 | .m => try llvm_m_args.append(it.only_arg), |
| 1834 | .dep_file => { | 1907 | .dep_file => { |
| ... | @@ -1860,7 +1933,12 @@ fn buildOutputType( | ... | @@ -1860,7 +1933,12 @@ fn buildOutputType( |
| 1860 | .force_undefined_symbol => { | 1933 | .force_undefined_symbol => { |
| 1861 | try force_undefined_symbols.put(gpa, it.only_arg, {}); | 1934 | try force_undefined_symbols.put(gpa, it.only_arg, {}); |
| 1862 | }, | 1935 | }, |
| 1863 | .weak_library => try system_libs.put(it.only_arg, .{ .weak = true }), | 1936 | .weak_library => try system_libs.put(it.only_arg, .{ |
| | 1937 | .needed = false, |
| | 1938 | .weak = true, |
| | 1939 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 1940 | .search_strategy = lib_search_strategy orelse .paths_first, |
| | 1941 | }), |
| 1864 | .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), | 1942 | .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), |
| 1865 | .headerpad_max_install_names => headerpad_max_install_names = true, | 1943 | .headerpad_max_install_names => headerpad_max_install_names = true, |
| 1866 | .compress_debug_sections => { | 1944 | .compress_debug_sections => { |
| ... | @@ -2156,11 +2234,26 @@ fn buildOutputType( | ... | @@ -2156,11 +2234,26 @@ fn buildOutputType( |
| 2156 | } else if (mem.eql(u8, arg, "-needed_framework")) { | 2234 | } else if (mem.eql(u8, arg, "-needed_framework")) { |
| 2157 | try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .needed = true }); | 2235 | try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .needed = true }); |
| 2158 | } else if (mem.eql(u8, arg, "-needed_library")) { | 2236 | } else if (mem.eql(u8, arg, "-needed_library")) { |
| 2159 | try system_libs.put(linker_args_it.nextOrFatal(), .{ .needed = true }); | 2237 | try system_libs.put(linker_args_it.nextOrFatal(), .{ |
| | 2238 | .weak = false, |
| | 2239 | .needed = true, |
| | 2240 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 2241 | .search_strategy = lib_search_strategy orelse .paths_first, |
| | 2242 | }); |
| 2160 | } else if (mem.startsWith(u8, arg, "-weak-l")) { | 2243 | } else if (mem.startsWith(u8, arg, "-weak-l")) { |
| 2161 | try system_libs.put(arg["-weak-l".len..], .{ .weak = true }); | 2244 | try system_libs.put(arg["-weak-l".len..], .{ |
| | 2245 | .weak = true, |
| | 2246 | .needed = false, |
| | 2247 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 2248 | .search_strategy = lib_search_strategy orelse .paths_first, |
| | 2249 | }); |
| 2162 | } else if (mem.eql(u8, arg, "-weak_library")) { | 2250 | } else if (mem.eql(u8, arg, "-weak_library")) { |
| 2163 | try system_libs.put(linker_args_it.nextOrFatal(), .{ .weak = true }); | 2251 | try system_libs.put(linker_args_it.nextOrFatal(), .{ |
| | 2252 | .weak = true, |
| | 2253 | .needed = false, |
| | 2254 | .preferred_mode = lib_preferred_mode orelse .Dynamic, |
| | 2255 | .search_strategy = lib_search_strategy orelse .paths_first, |
| | 2256 | }); |
| 2164 | } else if (mem.eql(u8, arg, "-compatibility_version")) { | 2257 | } else if (mem.eql(u8, arg, "-compatibility_version")) { |
| 2165 | const compat_version = linker_args_it.nextOrFatal(); | 2258 | const compat_version = linker_args_it.nextOrFatal(); |
| 2166 | compatibility_version = std.SemanticVersion.parse(compat_version) catch |err| { | 2259 | compatibility_version = std.SemanticVersion.parse(compat_version) catch |err| { |
| ... | @@ -2458,40 +2551,63 @@ fn buildOutputType( | ... | @@ -2458,40 +2551,63 @@ fn buildOutputType( |
| 2458 | } | 2551 | } |
| 2459 | } | 2552 | } |
| 2460 | | 2553 | |
| | 2554 | // Resolve the library path arguments with respect to sysroot. |
| | 2555 | var lib_dirs = std.ArrayList([]const u8).init(arena); |
| | 2556 | if (sysroot) |root| { |
| | 2557 | for (lib_dir_args.items) |dir| { |
| | 2558 | if (fs.path.isAbsolute(dir)) { |
| | 2559 | const stripped_dir = dir[fs.path.diskDesignator(dir).len..]; |
| | 2560 | const full_path = try fs.path.join(arena, &[_][]const u8{ root, stripped_dir }); |
| | 2561 | try lib_dirs.append(full_path); |
| | 2562 | } |
| | 2563 | try lib_dirs.append(dir); |
| | 2564 | } |
| | 2565 | } else { |
| | 2566 | lib_dirs = lib_dir_args; |
| | 2567 | } |
| | 2568 | lib_dir_args = undefined; // From here we use lib_dirs instead. |
| | 2569 | |
| 2461 | // Now that we have target info, we can find out if any of the system libraries | 2570 | // Now that we have target info, we can find out if any of the system libraries |
| 2462 | // are part of libc or libc++. We remove them from the list and communicate their | 2571 | // are part of libc or libc++. We remove them from the list and communicate their |
| 2463 | // existence via flags instead. | 2572 | // existence via flags instead. |
| | 2573 | // Similarly, if any libs in this list are statically provided, we omit |
| | 2574 | // them from the resolved list and populate the link_objects array instead. |
| | 2575 | var resolved_system_libs: std.MultiArrayList(struct { |
| | 2576 | name: []const u8, |
| | 2577 | lib: Compilation.SystemLib, |
| | 2578 | }) = .{}; |
| | 2579 | |
| 2464 | { | 2580 | { |
| 2465 | // Similarly, if any libs in this list are statically provided, we remove | | |
| 2466 | // them from this list and populate the link_objects array instead. | | |
| 2467 | const sep = fs.path.sep_str; | | |
| 2468 | var test_path = std.ArrayList(u8).init(gpa); | 2581 | var test_path = std.ArrayList(u8).init(gpa); |
| 2469 | defer test_path.deinit(); | 2582 | defer test_path.deinit(); |
| 2470 | | 2583 | |
| 2471 | var i: usize = 0; | 2584 | var checked_paths = std.ArrayList(u8).init(gpa); |
| 2472 | syslib: while (i < system_libs.count()) { | 2585 | defer checked_paths.deinit(); |
| 2473 | const lib_name = system_libs.keys()[i]; | | |
| 2474 | | 2586 | |
| | 2587 | var failed_libs = std.ArrayList(struct { |
| | 2588 | name: []const u8, |
| | 2589 | strategy: SystemLib.SearchStrategy, |
| | 2590 | checked_paths: []const u8, |
| | 2591 | preferred_mode: std.builtin.LinkMode, |
| | 2592 | }).init(arena); |
| | 2593 | |
| | 2594 | syslib: for (system_libs.keys(), system_libs.values()) |lib_name, info| { |
| 2475 | if (target_util.is_libc_lib_name(target_info.target, lib_name)) { | 2595 | if (target_util.is_libc_lib_name(target_info.target, lib_name)) { |
| 2476 | link_libc = true; | 2596 | link_libc = true; |
| 2477 | system_libs.orderedRemoveAt(i); | | |
| 2478 | continue; | 2597 | continue; |
| 2479 | } | 2598 | } |
| 2480 | if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { | 2599 | if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { |
| 2481 | link_libcpp = true; | 2600 | link_libcpp = true; |
| 2482 | system_libs.orderedRemoveAt(i); | | |
| 2483 | continue; | 2601 | continue; |
| 2484 | } | 2602 | } |
| 2485 | switch (target_util.classifyCompilerRtLibName(target_info.target, lib_name)) { | 2603 | switch (target_util.classifyCompilerRtLibName(target_info.target, lib_name)) { |
| 2486 | .none => {}, | 2604 | .none => {}, |
| 2487 | .only_libunwind, .both => { | 2605 | .only_libunwind, .both => { |
| 2488 | link_libunwind = true; | 2606 | link_libunwind = true; |
| 2489 | system_libs.orderedRemoveAt(i); | | |
| 2490 | continue; | 2607 | continue; |
| 2491 | }, | 2608 | }, |
| 2492 | .only_compiler_rt => { | 2609 | .only_compiler_rt => { |
| 2493 | std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); | 2610 | std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); |
| 2494 | system_libs.orderedRemoveAt(i); | | |
| 2495 | continue; | 2611 | continue; |
| 2496 | }, | 2612 | }, |
| 2497 | } | 2613 | } |
| ... | @@ -2503,53 +2619,150 @@ fn buildOutputType( | ... | @@ -2503,53 +2619,150 @@ fn buildOutputType( |
| 2503 | if (target_info.target.os.tag == .wasi) { | 2619 | if (target_info.target.os.tag == .wasi) { |
| 2504 | if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { | 2620 | if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { |
| 2505 | try wasi_emulated_libs.append(crt_file); | 2621 | try wasi_emulated_libs.append(crt_file); |
| 2506 | system_libs.orderedRemoveAt(i); | | |
| 2507 | continue; | 2622 | continue; |
| 2508 | } | 2623 | } |
| 2509 | } | 2624 | } |
| 2510 | | 2625 | |
| 2511 | for (lib_dirs.items) |lib_dir_path| { | 2626 | checked_paths.clearRetainingCapacity(); |
| 2512 | if (cross_target.isDarwin()) break; // Targeting Darwin we let the linker resolve the libraries in the correct order | 2627 | |
| 2513 | test_path.clearRetainingCapacity(); | 2628 | switch (info.search_strategy) { |
| 2514 | try test_path.writer().print("{s}" ++ sep ++ "{s}{s}{s}", .{ | 2629 | .mode_first, .no_fallback => { |
| 2515 | lib_dir_path, | 2630 | // check for preferred mode |
| 2516 | target_info.target.libPrefix(), | 2631 | for (lib_dirs.items) |lib_dir_path| { |
| 2517 | lib_name, | 2632 | if (try accessLibPath( |
| 2518 | target_info.target.staticLibSuffix(), | 2633 | &test_path, |
| 2519 | }); | 2634 | &checked_paths, |
| 2520 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { | 2635 | lib_dir_path, |
| 2521 | error.FileNotFound => continue, | 2636 | lib_name, |
| 2522 | else => |e| fatal("unable to search for static library '{s}': {s}", .{ | 2637 | target_info.target, |
| 2523 | test_path.items, @errorName(e), | 2638 | info.preferred_mode, |
| 2524 | }), | 2639 | )) { |
| 2525 | }; | 2640 | const path = try arena.dupe(u8, test_path.items); |
| 2526 | try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) }); | 2641 | switch (info.preferred_mode) { |
| 2527 | system_libs.orderedRemoveAt(i); | 2642 | .Static => try link_objects.append(.{ .path = path }), |
| 2528 | continue :syslib; | 2643 | .Dynamic => try resolved_system_libs.append(arena, .{ |
| 2529 | } | 2644 | .name = lib_name, |
| | 2645 | .lib = .{ |
| | 2646 | .needed = info.needed, |
| | 2647 | .weak = info.weak, |
| | 2648 | .path = path, |
| | 2649 | }, |
| | 2650 | }), |
| | 2651 | } |
| | 2652 | continue :syslib; |
| | 2653 | } |
| | 2654 | } |
| | 2655 | // check for fallback mode |
| | 2656 | if (info.search_strategy == .no_fallback) { |
| | 2657 | try failed_libs.append(.{ |
| | 2658 | .name = lib_name, |
| | 2659 | .strategy = info.search_strategy, |
| | 2660 | .checked_paths = try arena.dupe(u8, checked_paths.items), |
| | 2661 | .preferred_mode = info.preferred_mode, |
| | 2662 | }); |
| | 2663 | continue :syslib; |
| | 2664 | } |
| | 2665 | for (lib_dirs.items) |lib_dir_path| { |
| | 2666 | if (try accessLibPath( |
| | 2667 | &test_path, |
| | 2668 | &checked_paths, |
| | 2669 | lib_dir_path, |
| | 2670 | lib_name, |
| | 2671 | target_info.target, |
| | 2672 | info.fallbackMode(), |
| | 2673 | )) { |
| | 2674 | const path = try arena.dupe(u8, test_path.items); |
| | 2675 | switch (info.preferred_mode) { |
| | 2676 | .Static => try link_objects.append(.{ .path = path }), |
| | 2677 | .Dynamic => try resolved_system_libs.append(arena, .{ |
| | 2678 | .name = lib_name, |
| | 2679 | .lib = .{ |
| | 2680 | .needed = info.needed, |
| | 2681 | .weak = info.weak, |
| | 2682 | .path = path, |
| | 2683 | }, |
| | 2684 | }), |
| | 2685 | } |
| | 2686 | continue :syslib; |
| | 2687 | } |
| | 2688 | } |
| | 2689 | try failed_libs.append(.{ |
| | 2690 | .name = lib_name, |
| | 2691 | .strategy = info.search_strategy, |
| | 2692 | .checked_paths = try arena.dupe(u8, checked_paths.items), |
| | 2693 | .preferred_mode = info.preferred_mode, |
| | 2694 | }); |
| | 2695 | continue :syslib; |
| | 2696 | }, |
| | 2697 | .paths_first => { |
| | 2698 | for (lib_dirs.items) |lib_dir_path| { |
| | 2699 | // check for preferred mode |
| | 2700 | if (try accessLibPath( |
| | 2701 | &test_path, |
| | 2702 | &checked_paths, |
| | 2703 | lib_dir_path, |
| | 2704 | lib_name, |
| | 2705 | target_info.target, |
| | 2706 | info.preferred_mode, |
| | 2707 | )) { |
| | 2708 | const path = try arena.dupe(u8, test_path.items); |
| | 2709 | switch (info.preferred_mode) { |
| | 2710 | .Static => try link_objects.append(.{ .path = path }), |
| | 2711 | .Dynamic => try resolved_system_libs.append(arena, .{ |
| | 2712 | .name = lib_name, |
| | 2713 | .lib = .{ |
| | 2714 | .needed = info.needed, |
| | 2715 | .weak = info.weak, |
| | 2716 | .path = path, |
| | 2717 | }, |
| | 2718 | }), |
| | 2719 | } |
| | 2720 | continue :syslib; |
| | 2721 | } |
| 2530 | | 2722 | |
| 2531 | // Unfortunately, in the case of MinGW we also need to look for `libfoo.a`. | 2723 | // check for fallback mode |
| 2532 | if (target_info.target.isMinGW()) { | 2724 | if (try accessLibPath( |
| 2533 | for (lib_dirs.items) |lib_dir_path| { | 2725 | &test_path, |
| 2534 | test_path.clearRetainingCapacity(); | 2726 | &checked_paths, |
| 2535 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}.a", .{ | 2727 | lib_dir_path, |
| 2536 | lib_dir_path, lib_name, | 2728 | lib_name, |
| | 2729 | target_info.target, |
| | 2730 | info.fallbackMode(), |
| | 2731 | )) { |
| | 2732 | const path = try arena.dupe(u8, test_path.items); |
| | 2733 | switch (info.preferred_mode) { |
| | 2734 | .Static => try link_objects.append(.{ .path = path }), |
| | 2735 | .Dynamic => try resolved_system_libs.append(arena, .{ |
| | 2736 | .name = lib_name, |
| | 2737 | .lib = .{ |
| | 2738 | .needed = info.needed, |
| | 2739 | .weak = info.weak, |
| | 2740 | .path = path, |
| | 2741 | }, |
| | 2742 | }), |
| | 2743 | } |
| | 2744 | continue :syslib; |
| | 2745 | } |
| | 2746 | } |
| | 2747 | try failed_libs.append(.{ |
| | 2748 | .name = lib_name, |
| | 2749 | .strategy = info.search_strategy, |
| | 2750 | .checked_paths = try arena.dupe(u8, checked_paths.items), |
| | 2751 | .preferred_mode = info.preferred_mode, |
| 2537 | }); | 2752 | }); |
| 2538 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { | | |
| 2539 | error.FileNotFound => continue, | | |
| 2540 | else => |e| fatal("unable to search for static library '{s}': {s}", .{ | | |
| 2541 | test_path.items, @errorName(e), | | |
| 2542 | }), | | |
| 2543 | }; | | |
| 2544 | try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) }); | | |
| 2545 | system_libs.orderedRemoveAt(i); | | |
| 2546 | continue :syslib; | 2753 | continue :syslib; |
| 2547 | } | 2754 | }, |
| 2548 | } | 2755 | } |
| | 2756 | @compileError("unreachable"); |
| | 2757 | } |
| 2549 | | 2758 | |
| 2550 | std.log.scoped(.cli).debug("depending on system for -l{s}", .{lib_name}); | 2759 | if (failed_libs.items.len > 0) { |
| 2551 | | 2760 | for (failed_libs.items) |f| { |
| 2552 | i += 1; | 2761 | std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{ |
| | 2762 | @tagName(f.preferred_mode), f.name, @tagName(f.strategy), f.checked_paths, |
| | 2763 | }); |
| | 2764 | } |
| | 2765 | process.exit(1); |
| 2553 | } | 2766 | } |
| 2554 | } | 2767 | } |
| 2555 | // libc++ depends on libc | 2768 | // libc++ depends on libc |
| ... | @@ -2576,7 +2789,7 @@ fn buildOutputType( | ... | @@ -2576,7 +2789,7 @@ fn buildOutputType( |
| 2576 | } | 2789 | } |
| 2577 | | 2790 | |
| 2578 | if (sysroot == null and cross_target.isNativeOs() and | 2791 | if (sysroot == null and cross_target.isNativeOs() and |
| 2579 | (system_libs.count() != 0 or want_native_include_dirs)) | 2792 | (resolved_system_libs.len != 0 or want_native_include_dirs)) |
| 2580 | { | 2793 | { |
| 2581 | const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { | 2794 | const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { |
| 2582 | fatal("unable to detect native system paths: {s}", .{@errorName(err)}); | 2795 | fatal("unable to detect native system paths: {s}", .{@errorName(err)}); |
| ... | @@ -2613,54 +2826,8 @@ fn buildOutputType( | ... | @@ -2613,54 +2826,8 @@ fn buildOutputType( |
| 2613 | framework_dirs.appendAssumeCapacity(framework_dir); | 2826 | framework_dirs.appendAssumeCapacity(framework_dir); |
| 2614 | } | 2827 | } |
| 2615 | | 2828 | |
| 2616 | for (paths.lib_dirs.items) |lib_dir| { | 2829 | try lib_dirs.appendSlice(paths.lib_dirs.items); |
| 2617 | try lib_dirs.append(lib_dir); | 2830 | try rpath_list.appendSlice(paths.rpaths.items); |
| 2618 | } | | |
| 2619 | for (paths.rpaths.items) |rpath| { | | |
| 2620 | try rpath_list.append(rpath); | | |
| 2621 | } | | |
| 2622 | } | | |
| 2623 | | | |
| 2624 | { | | |
| 2625 | // Resolve static libraries into full paths. | | |
| 2626 | const sep = fs.path.sep_str; | | |
| 2627 | | | |
| 2628 | var test_path = std.ArrayList(u8).init(gpa); | | |
| 2629 | defer test_path.deinit(); | | |
| 2630 | | | |
| 2631 | for (static_libs.items) |static_lib| { | | |
| 2632 | for (lib_dirs.items) |lib_dir_path| { | | |
| 2633 | test_path.clearRetainingCapacity(); | | |
| 2634 | try test_path.writer().print("{s}" ++ sep ++ "{s}{s}{s}", .{ | | |
| 2635 | lib_dir_path, | | |
| 2636 | target_info.target.libPrefix(), | | |
| 2637 | static_lib, | | |
| 2638 | target_info.target.staticLibSuffix(), | | |
| 2639 | }); | | |
| 2640 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { | | |
| 2641 | error.FileNotFound => continue, | | |
| 2642 | else => |e| fatal("unable to search for static library '{s}': {s}", .{ | | |
| 2643 | test_path.items, @errorName(e), | | |
| 2644 | }), | | |
| 2645 | }; | | |
| 2646 | try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) }); | | |
| 2647 | break; | | |
| 2648 | } else { | | |
| 2649 | var search_paths = std.ArrayList(u8).init(arena); | | |
| 2650 | for (lib_dirs.items) |lib_dir_path| { | | |
| 2651 | try search_paths.writer().print("\n {s}" ++ sep ++ "{s}{s}{s}", .{ | | |
| 2652 | lib_dir_path, | | |
| 2653 | target_info.target.libPrefix(), | | |
| 2654 | static_lib, | | |
| 2655 | target_info.target.staticLibSuffix(), | | |
| 2656 | }); | | |
| 2657 | } | | |
| 2658 | try search_paths.appendSlice("\n suggestion: use full paths to static libraries on the command line rather than using -l and -L arguments"); | | |
| 2659 | fatal("static library '{s}' not found. search paths: {s}", .{ | | |
| 2660 | static_lib, search_paths.items, | | |
| 2661 | }); | | |
| 2662 | } | | |
| 2663 | } | | |
| 2664 | } | 2831 | } |
| 2665 | | 2832 | |
| 2666 | const object_format = target_info.target.ofmt; | 2833 | const object_format = target_info.target.ofmt; |
| ... | @@ -3086,8 +3253,8 @@ fn buildOutputType( | ... | @@ -3086,8 +3253,8 @@ fn buildOutputType( |
| 3086 | .link_objects = link_objects.items, | 3253 | .link_objects = link_objects.items, |
| 3087 | .framework_dirs = framework_dirs.items, | 3254 | .framework_dirs = framework_dirs.items, |
| 3088 | .frameworks = frameworks, | 3255 | .frameworks = frameworks, |
| 3089 | .system_lib_names = system_libs.keys(), | 3256 | .system_lib_names = resolved_system_libs.items(.name), |
| 3090 | .system_lib_infos = system_libs.values(), | 3257 | .system_lib_infos = resolved_system_libs.items(.lib), |
| 3091 | .wasi_emulated_libs = wasi_emulated_libs.items, | 3258 | .wasi_emulated_libs = wasi_emulated_libs.items, |
| 3092 | .link_libc = link_libc, | 3259 | .link_libc = link_libc, |
| 3093 | .link_libcpp = link_libcpp, | 3260 | .link_libcpp = link_libcpp, |
| ... | @@ -3196,7 +3363,6 @@ fn buildOutputType( | ... | @@ -3196,7 +3363,6 @@ fn buildOutputType( |
| 3196 | .install_name = install_name, | 3363 | .install_name = install_name, |
| 3197 | .entitlements = entitlements, | 3364 | .entitlements = entitlements, |
| 3198 | .pagezero_size = pagezero_size, | 3365 | .pagezero_size = pagezero_size, |
| 3199 | .search_strategy = search_strategy, | | |
| 3200 | .headerpad_size = headerpad_size, | 3366 | .headerpad_size = headerpad_size, |
| 3201 | .headerpad_max_install_names = headerpad_max_install_names, | 3367 | .headerpad_max_install_names = headerpad_max_install_names, |
| 3202 | .dead_strip_dylibs = dead_strip_dylibs, | 3368 | .dead_strip_dylibs = dead_strip_dylibs, |
| ... | @@ -6068,3 +6234,84 @@ fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { | ... | @@ -6068,3 +6234,84 @@ fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { |
| 6068 | .include_reference_trace = ttyconf != .no_color, | 6234 | .include_reference_trace = ttyconf != .no_color, |
| 6069 | }; | 6235 | }; |
| 6070 | } | 6236 | } |
| | 6237 | |
| | 6238 | fn accessLibPath( |
| | 6239 | test_path: *std.ArrayList(u8), |
| | 6240 | checked_paths: *std.ArrayList(u8), |
| | 6241 | lib_dir_path: []const u8, |
| | 6242 | lib_name: []const u8, |
| | 6243 | target: std.Target, |
| | 6244 | link_mode: std.builtin.LinkMode, |
| | 6245 | ) !bool { |
| | 6246 | const sep = fs.path.sep_str; |
| | 6247 | |
| | 6248 | if (target.isDarwin() and link_mode == .Dynamic) tbd: { |
| | 6249 | // Prefer .tbd over .dylib. |
| | 6250 | test_path.clearRetainingCapacity(); |
| | 6251 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}.tbd", .{ lib_dir_path, lib_name }); |
| | 6252 | try checked_paths.writer().print("\n {s}", .{test_path.items}); |
| | 6253 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| | 6254 | error.FileNotFound => break :tbd, |
| | 6255 | else => |e| fatal("unable to search for tbd library '{s}': {s}", .{ |
| | 6256 | test_path.items, @errorName(e), |
| | 6257 | }), |
| | 6258 | }; |
| | 6259 | return true; |
| | 6260 | } |
| | 6261 | |
| | 6262 | main_check: { |
| | 6263 | test_path.clearRetainingCapacity(); |
| | 6264 | try test_path.writer().print("{s}" ++ sep ++ "{s}{s}{s}", .{ |
| | 6265 | lib_dir_path, |
| | 6266 | target.libPrefix(), |
| | 6267 | lib_name, |
| | 6268 | switch (link_mode) { |
| | 6269 | .Static => target.staticLibSuffix(), |
| | 6270 | .Dynamic => target.dynamicLibSuffix(), |
| | 6271 | }, |
| | 6272 | }); |
| | 6273 | try checked_paths.writer().print("\n {s}", .{test_path.items}); |
| | 6274 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| | 6275 | error.FileNotFound => break :main_check, |
| | 6276 | else => |e| fatal("unable to search for {s} library '{s}': {s}", .{ |
| | 6277 | @tagName(link_mode), test_path.items, @errorName(e), |
| | 6278 | }), |
| | 6279 | }; |
| | 6280 | return true; |
| | 6281 | } |
| | 6282 | |
| | 6283 | // In the case of Darwin, the main check will be .dylib, so here we |
| | 6284 | // additionally check for .so files. |
| | 6285 | if (target.isDarwin() and link_mode == .Dynamic) so: { |
| | 6286 | // Prefer .tbd over .dylib. |
| | 6287 | test_path.clearRetainingCapacity(); |
| | 6288 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{ lib_dir_path, lib_name }); |
| | 6289 | try checked_paths.writer().print("\n {s}", .{test_path.items}); |
| | 6290 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| | 6291 | error.FileNotFound => break :so, |
| | 6292 | else => |e| fatal("unable to search for tbd library '{s}': {s}", .{ |
| | 6293 | test_path.items, @errorName(e), |
| | 6294 | }), |
| | 6295 | }; |
| | 6296 | return true; |
| | 6297 | } |
| | 6298 | |
| | 6299 | // In the case of MinGW, the main check will be .lib but we also need to |
| | 6300 | // look for `libfoo.a`. |
| | 6301 | if (target.isMinGW() and link_mode == .Static) mingw: { |
| | 6302 | test_path.clearRetainingCapacity(); |
| | 6303 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}.a", .{ |
| | 6304 | lib_dir_path, lib_name, |
| | 6305 | }); |
| | 6306 | try checked_paths.writer().print("\n {s}", .{test_path.items}); |
| | 6307 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| | 6308 | error.FileNotFound => break :mingw, |
| | 6309 | else => |e| fatal("unable to search for static library '{s}': {s}", .{ |
| | 6310 | test_path.items, @errorName(e), |
| | 6311 | }), |
| | 6312 | }; |
| | 6313 | return true; |
| | 6314 | } |
| | 6315 | |
| | 6316 | return false; |
| | 6317 | } |