| author | |
| committer | |
| log | c2898c436f0c858d10367b7631091f5a52cce76f |
| tree | bf2ca1d0dd9b02b530cb70545111091c916727b5 |
| parent | 5ca54036ca0bc292ead681c03c8ac57e27a127db |
10 files changed, 282 insertions(+), 425 deletions(-)
lib/std/zig/target.zig+2-2| ... | @@ -25,7 +25,7 @@ pub const available_libcs = [_]ArchOsAbi{ | ... | @@ -25,7 +25,7 @@ pub const available_libcs = [_]ArchOsAbi{ |
| 25 | .{ .arch = .thumbeb, .os = .linux, .abi = .musleabihf }, | 25 | .{ .arch = .thumbeb, .os = .linux, .abi = .musleabihf }, |
| 26 | .{ .arch = .aarch64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, | 26 | .{ .arch = .aarch64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, |
| 27 | .{ .arch = .aarch64, .os = .linux, .abi = .musl }, | 27 | .{ .arch = .aarch64, .os = .linux, .abi = .musl }, |
| 28 | .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 11, .minor = 0, .patch = 0 } }, | 28 | .{ .arch = .aarch64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } }, |
| 29 | .{ .arch = .aarch64, .os = .windows, .abi = .gnu }, | 29 | .{ .arch = .aarch64, .os = .windows, .abi = .gnu }, |
| 30 | .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, | 30 | .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, |
| 31 | .{ .arch = .aarch64_be, .os = .linux, .abi = .musl }, | 31 | .{ .arch = .aarch64_be, .os = .linux, .abi = .musl }, |
| ... | @@ -74,7 +74,7 @@ pub const available_libcs = [_]ArchOsAbi{ | ... | @@ -74,7 +74,7 @@ pub const available_libcs = [_]ArchOsAbi{ |
| 74 | .{ .arch = .x86_64, .os = .linux, .abi = .gnu }, | 74 | .{ .arch = .x86_64, .os = .linux, .abi = .gnu }, |
| 75 | .{ .arch = .x86_64, .os = .linux, .abi = .gnux32 }, | 75 | .{ .arch = .x86_64, .os = .linux, .abi = .gnux32 }, |
| 76 | .{ .arch = .x86_64, .os = .linux, .abi = .musl }, | 76 | .{ .arch = .x86_64, .os = .linux, .abi = .musl }, |
| 77 | .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, | 77 | .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 13, .minor = 0, .patch = 0 } }, |
| 78 | .{ .arch = .x86_64, .os = .windows, .abi = .gnu }, | 78 | .{ .arch = .x86_64, .os = .windows, .abi = .gnu }, |
| 79 | }; | 79 | }; |
| 80 | 80 |
src/Compilation.zig+148-152| ... | @@ -49,6 +49,8 @@ pub const Config = @import("Compilation/Config.zig"); | ... | @@ -49,6 +49,8 @@ pub const Config = @import("Compilation/Config.zig"); |
| 49 | gpa: Allocator, | 49 | gpa: Allocator, |
| 50 | /// Arena-allocated memory, mostly used during initialization. However, it can | 50 | /// Arena-allocated memory, mostly used during initialization. However, it can |
| 51 | /// be used for other things requiring the same lifetime as the `Compilation`. | 51 | /// be used for other things requiring the same lifetime as the `Compilation`. |
| 52 | /// Not thread-safe - lock `mutex` if potentially accessing from multiple | ||
| 53 | /// threads at once. | ||
| 52 | arena: Allocator, | 54 | arena: Allocator, |
| 53 | /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. | 55 | /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. |
| 54 | zcu: ?*Zcu, | 56 | zcu: ?*Zcu, |
| ... | @@ -1760,172 +1762,166 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1760,172 +1762,166 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1760 | .incremental => comp.bin_file != null, | 1762 | .incremental => comp.bin_file != null, |
| 1761 | }; | 1763 | }; |
| 1762 | 1764 | ||
| 1763 | if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) { | 1765 | if (have_bin_emit and target.ofmt != .c) { |
| 1764 | if (target.isDarwin()) { | 1766 | if (!comp.skip_linker_dependencies) { |
| 1765 | switch (target.abi) { | 1767 | // If we need to build libc for the target, add work items for it. |
| 1766 | .none, | 1768 | // We go through the work queue so that building can be done in parallel. |
| 1767 | .simulator, | 1769 | // If linking against host libc installation, instead queue up jobs |
| 1768 | .macabi, | 1770 | // for loading those files in the linker. |
| 1769 | => {}, | 1771 | if (comp.config.link_libc and is_exe_or_dyn_lib) { |
| 1770 | else => return error.LibCUnavailable, | 1772 | if (comp.libc_installation) |lci| { |
| 1771 | } | 1773 | const basenames = LibCInstallation.CrtBasenames.get(.{ |
| 1772 | } | 1774 | .target = target, |
| 1773 | // If we need to build glibc for the target, add work items for it. | 1775 | .link_libc = comp.config.link_libc, |
| 1774 | // We go through the work queue so that building can be done in parallel. | 1776 | .output_mode = comp.config.output_mode, |
| 1775 | // If linking against host libc installation, instead queue up jobs | 1777 | .link_mode = comp.config.link_mode, |
| 1776 | // for loading those files in the linker. | 1778 | .pie = comp.config.pie, |
| 1777 | if (comp.config.link_libc and is_exe_or_dyn_lib and target.ofmt != .c) { | 1779 | }); |
| 1778 | if (comp.libc_installation) |lci| { | 1780 | const paths = try lci.resolveCrtPaths(arena, basenames, target); |
| 1779 | const basenames = LibCInstallation.CrtBasenames.get(.{ | ||
| 1780 | .target = target, | ||
| 1781 | .link_libc = comp.config.link_libc, | ||
| 1782 | .output_mode = comp.config.output_mode, | ||
| 1783 | .link_mode = comp.config.link_mode, | ||
| 1784 | .pie = comp.config.pie, | ||
| 1785 | }); | ||
| 1786 | const paths = try lci.resolveCrtPaths(arena, basenames, target); | ||
| 1787 | 1781 | ||
| 1788 | const fields = @typeInfo(@TypeOf(paths)).@"struct".fields; | 1782 | const fields = @typeInfo(@TypeOf(paths)).@"struct".fields; |
| 1789 | try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, fields.len); | 1783 | try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, fields.len); |
| 1790 | inline for (fields) |field| { | 1784 | inline for (fields) |field| { |
| 1791 | if (@field(paths, field.name)) |path| { | 1785 | if (@field(paths, field.name)) |path| { |
| 1792 | comp.link_task_queue.shared.appendAssumeCapacity(.{ .load_object = path }); | 1786 | comp.link_task_queue.shared.appendAssumeCapacity(.{ .load_object = path }); |
| 1787 | } | ||
| 1793 | } | 1788 | } |
| 1794 | } | ||
| 1795 | 1789 | ||
| 1796 | const flags = target_util.libcFullLinkFlags(target); | 1790 | const flags = target_util.libcFullLinkFlags(target); |
| 1797 | try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, flags.len); | 1791 | try comp.link_task_queue.shared.ensureUnusedCapacity(gpa, flags.len); |
| 1798 | for (flags) |flag| { | 1792 | for (flags) |flag| { |
| 1799 | assert(mem.startsWith(u8, flag, "-l")); | 1793 | assert(mem.startsWith(u8, flag, "-l")); |
| 1800 | const lib_name = flag["-l".len..]; | 1794 | const lib_name = flag["-l".len..]; |
| 1801 | const suffix = switch (comp.config.link_mode) { | 1795 | const suffix = switch (comp.config.link_mode) { |
| 1802 | .static => target.staticLibSuffix(), | 1796 | .static => target.staticLibSuffix(), |
| 1803 | .dynamic => target.dynamicLibSuffix(), | 1797 | .dynamic => target.dynamicLibSuffix(), |
| 1804 | }; | 1798 | }; |
| 1805 | const sep = std.fs.path.sep_str; | 1799 | const sep = std.fs.path.sep_str; |
| 1806 | const lib_path = try std.fmt.allocPrint(arena, "{s}" ++ sep ++ "lib{s}{s}", .{ | 1800 | const lib_path = try std.fmt.allocPrint(arena, "{s}" ++ sep ++ "lib{s}{s}", .{ |
| 1807 | lci.crt_dir.?, lib_name, suffix, | 1801 | lci.crt_dir.?, lib_name, suffix, |
| 1808 | }); | 1802 | }); |
| 1809 | const resolved_path = Path.initCwd(lib_path); | 1803 | const resolved_path = Path.initCwd(lib_path); |
| 1810 | comp.link_task_queue.shared.appendAssumeCapacity(switch (comp.config.link_mode) { | 1804 | comp.link_task_queue.shared.appendAssumeCapacity(switch (comp.config.link_mode) { |
| 1811 | .static => .{ .load_archive = resolved_path }, | 1805 | .static => .{ .load_archive = resolved_path }, |
| 1812 | .dynamic => .{ .load_dso = resolved_path }, | 1806 | .dynamic => .{ .load_dso = resolved_path }, |
| 1807 | }); | ||
| 1808 | } | ||
| 1809 | } else if (target.isMusl() and !target.isWasm()) { | ||
| 1810 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; | ||
| 1811 | |||
| 1812 | if (musl.needsCrtiCrtn(target)) { | ||
| 1813 | try comp.queueJobs(&[_]Job{ | ||
| 1814 | .{ .musl_crt_file = .crti_o }, | ||
| 1815 | .{ .musl_crt_file = .crtn_o }, | ||
| 1816 | }); | ||
| 1817 | } | ||
| 1818 | try comp.queueJobs(&[_]Job{ | ||
| 1819 | .{ .musl_crt_file = .crt1_o }, | ||
| 1820 | .{ .musl_crt_file = .scrt1_o }, | ||
| 1821 | .{ .musl_crt_file = .rcrt1_o }, | ||
| 1822 | switch (comp.config.link_mode) { | ||
| 1823 | .static => .{ .musl_crt_file = .libc_a }, | ||
| 1824 | .dynamic => .{ .musl_crt_file = .libc_so }, | ||
| 1825 | }, | ||
| 1813 | }); | 1826 | }); |
| 1814 | } | 1827 | } else if (target.isGnuLibC()) { |
| 1815 | } else if (target.isMusl() and !target.isWasm()) { | 1828 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; |
| 1816 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; | 1829 | |
| 1817 | 1830 | if (glibc.needsCrtiCrtn(target)) { | |
| 1818 | if (musl.needsCrtiCrtn(target)) { | 1831 | try comp.queueJobs(&[_]Job{ |
| 1832 | .{ .glibc_crt_file = .crti_o }, | ||
| 1833 | .{ .glibc_crt_file = .crtn_o }, | ||
| 1834 | }); | ||
| 1835 | } | ||
| 1819 | try comp.queueJobs(&[_]Job{ | 1836 | try comp.queueJobs(&[_]Job{ |
| 1820 | .{ .musl_crt_file = .crti_o }, | 1837 | .{ .glibc_crt_file = .scrt1_o }, |
| 1821 | .{ .musl_crt_file = .crtn_o }, | 1838 | .{ .glibc_crt_file = .libc_nonshared_a }, |
| 1839 | .{ .glibc_shared_objects = {} }, | ||
| 1822 | }); | 1840 | }); |
| 1823 | } | 1841 | } else if (target.isWasm() and target.os.tag == .wasi) { |
| 1824 | try comp.queueJobs(&[_]Job{ | 1842 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; |
| 1825 | .{ .musl_crt_file = .crt1_o }, | ||
| 1826 | .{ .musl_crt_file = .scrt1_o }, | ||
| 1827 | .{ .musl_crt_file = .rcrt1_o }, | ||
| 1828 | switch (comp.config.link_mode) { | ||
| 1829 | .static => .{ .musl_crt_file = .libc_a }, | ||
| 1830 | .dynamic => .{ .musl_crt_file = .libc_so }, | ||
| 1831 | }, | ||
| 1832 | }); | ||
| 1833 | } else if (target.isGnuLibC()) { | ||
| 1834 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; | ||
| 1835 | 1843 | ||
| 1836 | if (glibc.needsCrtiCrtn(target)) { | 1844 | for (comp.wasi_emulated_libs) |crt_file| { |
| 1845 | try comp.queueJob(.{ | ||
| 1846 | .wasi_libc_crt_file = crt_file, | ||
| 1847 | }); | ||
| 1848 | } | ||
| 1837 | try comp.queueJobs(&[_]Job{ | 1849 | try comp.queueJobs(&[_]Job{ |
| 1838 | .{ .glibc_crt_file = .crti_o }, | 1850 | .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) }, |
| 1839 | .{ .glibc_crt_file = .crtn_o }, | 1851 | .{ .wasi_libc_crt_file = .libc_a }, |
| 1840 | }); | 1852 | }); |
| 1841 | } | 1853 | } else if (target.isMinGW()) { |
| 1842 | try comp.queueJobs(&[_]Job{ | 1854 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; |
| 1843 | .{ .glibc_crt_file = .scrt1_o }, | ||
| 1844 | .{ .glibc_crt_file = .libc_nonshared_a }, | ||
| 1845 | .{ .glibc_shared_objects = {} }, | ||
| 1846 | }); | ||
| 1847 | } else if (target.isWasm() and target.os.tag == .wasi) { | ||
| 1848 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; | ||
| 1849 | 1855 | ||
| 1850 | for (comp.wasi_emulated_libs) |crt_file| { | 1856 | const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o }; |
| 1851 | try comp.queueJob(.{ | 1857 | try comp.queueJobs(&.{ |
| 1852 | .wasi_libc_crt_file = crt_file, | 1858 | .{ .mingw_crt_file = .mingw32_lib }, |
| 1859 | crt_job, | ||
| 1853 | }); | 1860 | }); |
| 1854 | } | ||
| 1855 | try comp.queueJobs(&[_]Job{ | ||
| 1856 | .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) }, | ||
| 1857 | .{ .wasi_libc_crt_file = .libc_a }, | ||
| 1858 | }); | ||
| 1859 | } else if (target.isMinGW()) { | ||
| 1860 | if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; | ||
| 1861 | 1861 | ||
| 1862 | const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o }; | 1862 | // When linking mingw-w64 there are some import libs we always need. |
| 1863 | try comp.queueJobs(&.{ | 1863 | try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len); |
| 1864 | .{ .mingw_crt_file = .mingw32_lib }, | 1864 | for (mingw.always_link_libs) |name| comp.windows_libs.putAssumeCapacity(name, {}); |
| 1865 | crt_job, | 1865 | } else if (target.isDarwin()) { |
| 1866 | }); | 1866 | switch (target.abi) { |
| 1867 | 1867 | .none, .simulator, .macabi => {}, | |
| 1868 | // When linking mingw-w64 there are some import libs we always need. | 1868 | else => return error.LibCUnavailable, |
| 1869 | try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len); | 1869 | } |
| 1870 | for (mingw.always_link_libs) |name| comp.windows_libs.putAssumeCapacity(name, {}); | 1870 | } else if (target.os.tag == .freestanding and capable_of_building_zig_libc) { |
| 1871 | } else { | 1871 | try comp.queueJob(.{ .zig_libc = {} }); |
| 1872 | return error.LibCUnavailable; | 1872 | } else { |
| 1873 | return error.LibCUnavailable; | ||
| 1874 | } | ||
| 1873 | } | 1875 | } |
| 1874 | } | ||
| 1875 | 1876 | ||
| 1876 | // Generate Windows import libs. | 1877 | // Generate Windows import libs. |
| 1877 | if (target.os.tag == .windows) { | 1878 | if (target.os.tag == .windows) { |
| 1878 | const count = comp.windows_libs.count(); | 1879 | const count = comp.windows_libs.count(); |
| 1879 | for (0..count) |i| { | 1880 | for (0..count) |i| { |
| 1880 | try comp.queueJob(.{ .windows_import_lib = i }); | 1881 | try comp.queueJob(.{ .windows_import_lib = i }); |
| 1882 | } | ||
| 1883 | } | ||
| 1884 | if (comp.wantBuildLibUnwindFromSource()) { | ||
| 1885 | try comp.queueJob(.{ .libunwind = {} }); | ||
| 1886 | } | ||
| 1887 | if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) { | ||
| 1888 | try comp.queueJob(.libcxx); | ||
| 1889 | try comp.queueJob(.libcxxabi); | ||
| 1890 | } | ||
| 1891 | if (build_options.have_llvm and comp.config.any_sanitize_thread) { | ||
| 1892 | try comp.queueJob(.libtsan); | ||
| 1881 | } | 1893 | } |
| 1882 | } | ||
| 1883 | if (comp.wantBuildLibUnwindFromSource()) { | ||
| 1884 | try comp.queueJob(.{ .libunwind = {} }); | ||
| 1885 | } | ||
| 1886 | if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) { | ||
| 1887 | try comp.queueJob(.libcxx); | ||
| 1888 | try comp.queueJob(.libcxxabi); | ||
| 1889 | } | ||
| 1890 | if (build_options.have_llvm and comp.config.any_sanitize_thread) { | ||
| 1891 | try comp.queueJob(.libtsan); | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | if (target.isMinGW() and comp.config.any_non_single_threaded) { | ||
| 1895 | // LLD might drop some symbols as unused during LTO and GCing, therefore, | ||
| 1896 | // we force mark them for resolution here. | ||
| 1897 | 1894 | ||
| 1898 | const tls_index_sym = switch (target.cpu.arch) { | 1895 | if (target.isMinGW() and comp.config.any_non_single_threaded) { |
| 1899 | .x86 => "__tls_index", | 1896 | // LLD might drop some symbols as unused during LTO and GCing, therefore, |
| 1900 | else => "_tls_index", | 1897 | // we force mark them for resolution here. |
| 1901 | }; | ||
| 1902 | 1898 | ||
| 1903 | try comp.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); | 1899 | const tls_index_sym = switch (target.cpu.arch) { |
| 1904 | } | 1900 | .x86 => "__tls_index", |
| 1901 | else => "_tls_index", | ||
| 1902 | }; | ||
| 1905 | 1903 | ||
| 1906 | if (comp.include_compiler_rt and capable_of_building_compiler_rt) { | 1904 | try comp.force_undefined_symbols.put(comp.gpa, tls_index_sym, {}); |
| 1907 | if (is_exe_or_dyn_lib) { | ||
| 1908 | log.debug("queuing a job to build compiler_rt_lib", .{}); | ||
| 1909 | comp.job_queued_compiler_rt_lib = true; | ||
| 1910 | } else if (output_mode != .Obj) { | ||
| 1911 | log.debug("queuing a job to build compiler_rt_obj", .{}); | ||
| 1912 | // In this case we are making a static library, so we ask | ||
| 1913 | // for a compiler-rt object to put in it. | ||
| 1914 | comp.job_queued_compiler_rt_obj = true; | ||
| 1915 | } | 1905 | } |
| 1916 | } | ||
| 1917 | 1906 | ||
| 1918 | if (comp.config.any_fuzz and capable_of_building_compiler_rt) { | 1907 | if (comp.include_compiler_rt and capable_of_building_compiler_rt) { |
| 1919 | if (is_exe_or_dyn_lib) { | 1908 | if (is_exe_or_dyn_lib) { |
| 1920 | log.debug("queuing a job to build libfuzzer", .{}); | 1909 | log.debug("queuing a job to build compiler_rt_lib", .{}); |
| 1921 | comp.job_queued_fuzzer_lib = true; | 1910 | comp.job_queued_compiler_rt_lib = true; |
| 1911 | } else if (output_mode != .Obj) { | ||
| 1912 | log.debug("queuing a job to build compiler_rt_obj", .{}); | ||
| 1913 | // In this case we are making a static library, so we ask | ||
| 1914 | // for a compiler-rt object to put in it. | ||
| 1915 | comp.job_queued_compiler_rt_obj = true; | ||
| 1916 | } | ||
| 1922 | } | 1917 | } |
| 1923 | } | ||
| 1924 | 1918 | ||
| 1925 | if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and | 1919 | if (comp.config.any_fuzz and capable_of_building_compiler_rt) { |
| 1926 | !comp.config.link_libc and capable_of_building_zig_libc) | 1920 | if (is_exe_or_dyn_lib) { |
| 1927 | { | 1921 | log.debug("queuing a job to build libfuzzer", .{}); |
| 1928 | try comp.queueJob(.{ .zig_libc = {} }); | 1922 | comp.job_queued_fuzzer_lib = true; |
| 1923 | } | ||
| 1924 | } | ||
| 1929 | } | 1925 | } |
| 1930 | 1926 | ||
| 1931 | try comp.link_task_queue.shared.append(gpa, .load_explicitly_provided); | 1927 | try comp.link_task_queue.shared.append(gpa, .load_explicitly_provided); |
| ... | @@ -3521,7 +3517,7 @@ fn performAllTheWorkInner( | ... | @@ -3521,7 +3517,7 @@ fn performAllTheWorkInner( |
| 3521 | defer work_queue_wait_group.wait(); | 3517 | defer work_queue_wait_group.wait(); |
| 3522 | 3518 | ||
| 3523 | if (comp.bin_file) |lf| { | 3519 | if (comp.bin_file) |lf| { |
| 3524 | if (try comp.link_task_queue.enqueue(comp.gpa, &.{.load_explicitly_provided})) { | 3520 | if (comp.link_task_queue.start()) { |
| 3525 | comp.thread_pool.spawnWg(work_queue_wait_group, link.File.flushTaskQueue, .{ lf, main_progress_node }); | 3521 | comp.thread_pool.spawnWg(work_queue_wait_group, link.File.flushTaskQueue, .{ lf, main_progress_node }); |
| 3526 | } | 3522 | } |
| 3527 | } | 3523 | } |
| ... | @@ -4980,7 +4976,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr | ... | @@ -4980,7 +4976,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr |
| 4980 | }, | 4976 | }, |
| 4981 | }; | 4977 | }; |
| 4982 | 4978 | ||
| 4983 | comp.enqueueLinkTasks(&.{.{ .load_object = c_object.status.success.object_path }}); | 4979 | comp.queueLinkTasks(&.{.{ .load_object = c_object.status.success.object_path }}); |
| 4984 | } | 4980 | } |
| 4985 | 4981 | ||
| 4986 | fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void { | 4982 | fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void { |
| ... | @@ -6114,7 +6110,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { | ... | @@ -6114,7 +6110,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| 6114 | return is_exe_or_dyn_lib and comp.config.link_libunwind and ofmt != .c; | 6110 | return is_exe_or_dyn_lib and comp.config.link_libunwind and ofmt != .c; |
| 6115 | } | 6111 | } |
| 6116 | 6112 | ||
| 6117 | fn setAllocFailure(comp: *Compilation) void { | 6113 | pub fn setAllocFailure(comp: *Compilation) void { |
| 6118 | @branchHint(.cold); | 6114 | @branchHint(.cold); |
| 6119 | log.debug("memory allocation failure", .{}); | 6115 | log.debug("memory allocation failure", .{}); |
| 6120 | comp.alloc_failure_occurred = true; | 6116 | comp.alloc_failure_occurred = true; |
| ... | @@ -6355,7 +6351,7 @@ fn buildOutputFromZig( | ... | @@ -6355,7 +6351,7 @@ fn buildOutputFromZig( |
| 6355 | assert(out.* == null); | 6351 | assert(out.* == null); |
| 6356 | out.* = crt_file; | 6352 | out.* = crt_file; |
| 6357 | 6353 | ||
| 6358 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 6354 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 6359 | } | 6355 | } |
| 6360 | 6356 | ||
| 6361 | pub fn build_crt_file( | 6357 | pub fn build_crt_file( |
| ... | @@ -6463,7 +6459,7 @@ pub fn build_crt_file( | ... | @@ -6463,7 +6459,7 @@ pub fn build_crt_file( |
| 6463 | try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); | 6459 | try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); |
| 6464 | 6460 | ||
| 6465 | const crt_file = try sub_compilation.toCrtFile(); | 6461 | const crt_file = try sub_compilation.toCrtFile(); |
| 6466 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 6462 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 6467 | 6463 | ||
| 6468 | { | 6464 | { |
| 6469 | comp.mutex.lock(); | 6465 | comp.mutex.lock(); |
| ... | @@ -6473,8 +6469,8 @@ pub fn build_crt_file( | ... | @@ -6473,8 +6469,8 @@ pub fn build_crt_file( |
| 6473 | } | 6469 | } |
| 6474 | } | 6470 | } |
| 6475 | 6471 | ||
| 6476 | pub fn enqueueLinkTaskMode(comp: *Compilation, path: Path, output_mode: std.builtin.OutputMode) void { | 6472 | pub fn queueLinkTaskMode(comp: *Compilation, path: Path, output_mode: std.builtin.OutputMode) void { |
| 6477 | comp.enqueueLinkTasks(switch (output_mode) { | 6473 | comp.queueLinkTasks(switch (output_mode) { |
| 6478 | .Exe => unreachable, | 6474 | .Exe => unreachable, |
| 6479 | .Obj => &.{.{ .load_object = path }}, | 6475 | .Obj => &.{.{ .load_object = path }}, |
| 6480 | .Lib => &.{.{ .load_archive = path }}, | 6476 | .Lib => &.{.{ .load_archive = path }}, |
| ... | @@ -6483,7 +6479,7 @@ pub fn enqueueLinkTaskMode(comp: *Compilation, path: Path, output_mode: std.buil | ... | @@ -6483,7 +6479,7 @@ pub fn enqueueLinkTaskMode(comp: *Compilation, path: Path, output_mode: std.buil |
| 6483 | 6479 | ||
| 6484 | /// Only valid to call during `update`. Automatically handles queuing up a | 6480 | /// Only valid to call during `update`. Automatically handles queuing up a |
| 6485 | /// linker worker task if there is not already one. | 6481 | /// linker worker task if there is not already one. |
| 6486 | fn enqueueLinkTasks(comp: *Compilation, tasks: []const link.File.Task) void { | 6482 | pub fn queueLinkTasks(comp: *Compilation, tasks: []const link.File.Task) void { |
| 6487 | const use_lld = build_options.have_llvm and comp.config.use_lld; | 6483 | const use_lld = build_options.have_llvm and comp.config.use_lld; |
| 6488 | if (use_lld) return; | 6484 | if (use_lld) return; |
| 6489 | const target = comp.root_mod.resolved_target.result; | 6485 | const target = comp.root_mod.resolved_target.result; |
src/ThreadSafeQueue.zig+8| ... | @@ -59,5 +59,13 @@ pub fn ThreadSafeQueue(comptime T: type) type { | ... | @@ -59,5 +59,13 @@ pub fn ThreadSafeQueue(comptime T: type) type { |
| 59 | self.state = .run; | 59 | self.state = .run; |
| 60 | return was_waiting; | 60 | return was_waiting; |
| 61 | } | 61 | } |
| 62 | |||
| 63 | /// Safe only to call exactly once when initially starting the worker. | ||
| 64 | pub fn start(self: *Self) bool { | ||
| 65 | assert(self.state == .wait); | ||
| 66 | if (self.shared.items.len == 0) return false; | ||
| 67 | self.state = .run; | ||
| 68 | return true; | ||
| 69 | } | ||
| 62 | }; | 70 | }; |
| 63 | } | 71 | } |
src/glibc.zig+54-17| ... | @@ -6,12 +6,14 @@ const fs = std.fs; | ... | @@ -6,12 +6,14 @@ const fs = std.fs; |
| 6 | const path = fs.path; | 6 | const path = fs.path; |
| 7 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 8 | const Version = std.SemanticVersion; | 8 | const Version = std.SemanticVersion; |
| 9 | const Path = std.Build.Cache.Path; | ||
| 9 | 10 | ||
| 10 | const Compilation = @import("Compilation.zig"); | 11 | const Compilation = @import("Compilation.zig"); |
| 11 | const build_options = @import("build_options"); | 12 | const build_options = @import("build_options"); |
| 12 | const trace = @import("tracy.zig").trace; | 13 | const trace = @import("tracy.zig").trace; |
| 13 | const Cache = std.Build.Cache; | 14 | const Cache = std.Build.Cache; |
| 14 | const Module = @import("Package/Module.zig"); | 15 | const Module = @import("Package/Module.zig"); |
| 16 | const link = @import("link.zig"); | ||
| 15 | 17 | ||
| 16 | pub const Lib = struct { | 18 | pub const Lib = struct { |
| 17 | name: []const u8, | 19 | name: []const u8, |
| ... | @@ -717,11 +719,11 @@ fn lib_path(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const | ... | @@ -717,11 +719,11 @@ fn lib_path(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const |
| 717 | 719 | ||
| 718 | pub const BuiltSharedObjects = struct { | 720 | pub const BuiltSharedObjects = struct { |
| 719 | lock: Cache.Lock, | 721 | lock: Cache.Lock, |
| 720 | dir_path: []u8, | 722 | dir_path: Path, |
| 721 | 723 | ||
| 722 | pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator) void { | 724 | pub fn deinit(self: *BuiltSharedObjects, gpa: Allocator) void { |
| 723 | self.lock.release(); | 725 | self.lock.release(); |
| 724 | gpa.free(self.dir_path); | 726 | gpa.free(self.dir_path.sub_path); |
| 725 | self.* = undefined; | 727 | self.* = undefined; |
| 726 | } | 728 | } |
| 727 | }; | 729 | }; |
| ... | @@ -742,7 +744,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -742,7 +744,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 742 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | 744 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 743 | } | 745 | } |
| 744 | 746 | ||
| 745 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | 747 | const gpa = comp.gpa; |
| 748 | |||
| 749 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | ||
| 746 | defer arena_allocator.deinit(); | 750 | defer arena_allocator.deinit(); |
| 747 | const arena = arena_allocator.allocator(); | 751 | const arena = arena_allocator.allocator(); |
| 748 | 752 | ||
| ... | @@ -751,7 +755,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -751,7 +755,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 751 | 755 | ||
| 752 | // Use the global cache directory. | 756 | // Use the global cache directory. |
| 753 | var cache: Cache = .{ | 757 | var cache: Cache = .{ |
| 754 | .gpa = comp.gpa, | 758 | .gpa = gpa, |
| 755 | .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), | 759 | .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), |
| 756 | }; | 760 | }; |
| 757 | cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); | 761 | cache.addPrefix(.{ .path = null, .handle = fs.cwd() }); |
| ... | @@ -772,12 +776,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -772,12 +776,13 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 772 | if (try man.hit()) { | 776 | if (try man.hit()) { |
| 773 | const digest = man.final(); | 777 | const digest = man.final(); |
| 774 | 778 | ||
| 775 | assert(comp.glibc_so_files == null); | 779 | return queueSharedObjects(comp, .{ |
| 776 | comp.glibc_so_files = BuiltSharedObjects{ | ||
| 777 | .lock = man.toOwnedLock(), | 780 | .lock = man.toOwnedLock(), |
| 778 | .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }), | 781 | .dir_path = .{ |
| 779 | }; | 782 | .root_dir = comp.global_cache_directory, |
| 780 | return; | 783 | .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), |
| 784 | }, | ||
| 785 | }); | ||
| 781 | } | 786 | } |
| 782 | 787 | ||
| 783 | const digest = man.final(); | 788 | const digest = man.final(); |
| ... | @@ -790,8 +795,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -790,8 +795,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 790 | defer o_directory.handle.close(); | 795 | defer o_directory.handle.close(); |
| 791 | 796 | ||
| 792 | const abilists_contents = man.files.keys()[abilists_index].contents.?; | 797 | const abilists_contents = man.files.keys()[abilists_index].contents.?; |
| 793 | const metadata = try loadMetaData(comp.gpa, abilists_contents); | 798 | const metadata = try loadMetaData(gpa, abilists_contents); |
| 794 | defer metadata.destroy(comp.gpa); | 799 | defer metadata.destroy(gpa); |
| 795 | 800 | ||
| 796 | const target_targ_index = for (metadata.all_targets, 0..) |targ, i| { | 801 | const target_targ_index = for (metadata.all_targets, 0..) |targ, i| { |
| 797 | if (targ.arch == target.cpu.arch and | 802 | if (targ.arch == target.cpu.arch and |
| ... | @@ -835,7 +840,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -835,7 +840,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 835 | map_contents.deinit(); // The most recent allocation of an arena can be freed :) | 840 | map_contents.deinit(); // The most recent allocation of an arena can be freed :) |
| 836 | } | 841 | } |
| 837 | 842 | ||
| 838 | var stubs_asm = std.ArrayList(u8).init(comp.gpa); | 843 | var stubs_asm = std.ArrayList(u8).init(gpa); |
| 839 | defer stubs_asm.deinit(); | 844 | defer stubs_asm.deinit(); |
| 840 | 845 | ||
| 841 | for (libs, 0..) |lib, lib_i| { | 846 | for (libs, 0..) |lib, lib_i| { |
| ... | @@ -1195,7 +1200,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -1195,7 +1200,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 1195 | var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. | 1200 | var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. |
| 1196 | const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; | 1201 | const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; |
| 1197 | try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items }); | 1202 | try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items }); |
| 1198 | |||
| 1199 | try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib, prog_node); | 1203 | try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib, prog_node); |
| 1200 | } | 1204 | } |
| 1201 | 1205 | ||
| ... | @@ -1203,11 +1207,44 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi | ... | @@ -1203,11 +1207,44 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) !voi |
| 1203 | log.warn("failed to write cache manifest for glibc stubs: {s}", .{@errorName(err)}); | 1207 | log.warn("failed to write cache manifest for glibc stubs: {s}", .{@errorName(err)}); |
| 1204 | }; | 1208 | }; |
| 1205 | 1209 | ||
| 1206 | assert(comp.glibc_so_files == null); | 1210 | return queueSharedObjects(comp, .{ |
| 1207 | comp.glibc_so_files = .{ | ||
| 1208 | .lock = man.toOwnedLock(), | 1211 | .lock = man.toOwnedLock(), |
| 1209 | .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }), | 1212 | .dir_path = .{ |
| 1210 | }; | 1213 | .root_dir = comp.global_cache_directory, |
| 1214 | .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest), | ||
| 1215 | }, | ||
| 1216 | }); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { | ||
| 1220 | const target_version = comp.getTarget().os.version_range.linux.glibc; | ||
| 1221 | |||
| 1222 | assert(comp.glibc_so_files == null); | ||
| 1223 | comp.glibc_so_files = so_files; | ||
| 1224 | |||
| 1225 | var task_buffer: [libs.len]link.File.Task = undefined; | ||
| 1226 | var task_buffer_i: usize = 0; | ||
| 1227 | |||
| 1228 | { | ||
| 1229 | comp.mutex.lock(); // protect comp.arena | ||
| 1230 | defer comp.mutex.unlock(); | ||
| 1231 | |||
| 1232 | for (libs) |lib| { | ||
| 1233 | if (lib.removed_in) |rem_in| { | ||
| 1234 | if (target_version.order(rem_in) != .lt) continue; | ||
| 1235 | } | ||
| 1236 | const so_path: Path = .{ | ||
| 1237 | .root_dir = so_files.dir_path.root_dir, | ||
| 1238 | .sub_path = std.fmt.allocPrint(comp.arena, "{s}{c}lib{s}.so.{d}", .{ | ||
| 1239 | so_files.dir_path.sub_path, fs.path.sep, lib.name, lib.sover, | ||
| 1240 | }) catch return comp.setAllocFailure(), | ||
| 1241 | }; | ||
| 1242 | task_buffer[task_buffer_i] = .{ .load_dso = so_path }; | ||
| 1243 | task_buffer_i += 1; | ||
| 1244 | } | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | comp.queueLinkTasks(task_buffer[0..task_buffer_i]); | ||
| 1211 | } | 1248 | } |
| 1212 | 1249 | ||
| 1213 | fn buildSharedLib( | 1250 | fn buildSharedLib( |
src/libcxx.zig+2-2| ... | @@ -357,7 +357,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError! | ... | @@ -357,7 +357,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError! |
| 357 | assert(comp.libcxx_static_lib == null); | 357 | assert(comp.libcxx_static_lib == null); |
| 358 | const crt_file = try sub_compilation.toCrtFile(); | 358 | const crt_file = try sub_compilation.toCrtFile(); |
| 359 | comp.libcxx_static_lib = crt_file; | 359 | comp.libcxx_static_lib = crt_file; |
| 360 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 360 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { | 363 | pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { |
| ... | @@ -588,7 +588,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -588,7 +588,7 @@ pub fn buildLibCXXABI(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 588 | assert(comp.libcxxabi_static_lib == null); | 588 | assert(comp.libcxxabi_static_lib == null); |
| 589 | const crt_file = try sub_compilation.toCrtFile(); | 589 | const crt_file = try sub_compilation.toCrtFile(); |
| 590 | comp.libcxxabi_static_lib = crt_file; | 590 | comp.libcxxabi_static_lib = crt_file; |
| 591 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 591 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 592 | } | 592 | } |
| 593 | 593 | ||
| 594 | pub fn hardeningModeFlag(optimize_mode: std.builtin.OptimizeMode) []const u8 { | 594 | pub fn hardeningModeFlag(optimize_mode: std.builtin.OptimizeMode) []const u8 { |
src/libtsan.zig+1-1| ... | @@ -343,7 +343,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo | ... | @@ -343,7 +343,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo |
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| 345 | const crt_file = try sub_compilation.toCrtFile(); | 345 | const crt_file = try sub_compilation.toCrtFile(); |
| 346 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 346 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 347 | assert(comp.tsan_lib == null); | 347 | assert(comp.tsan_lib == null); |
| 348 | comp.tsan_lib = crt_file; | 348 | comp.tsan_lib = crt_file; |
| 349 | } | 349 | } |
src/libunwind.zig+1-1| ... | @@ -200,7 +200,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -200,7 +200,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 200 | }; | 200 | }; |
| 201 | 201 | ||
| 202 | const crt_file = try sub_compilation.toCrtFile(); | 202 | const crt_file = try sub_compilation.toCrtFile(); |
| 203 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 203 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 204 | assert(comp.libunwind_static_lib == null); | 204 | assert(comp.libunwind_static_lib == null); |
| 205 | comp.libunwind_static_lib = crt_file; | 205 | comp.libunwind_static_lib = crt_file; |
| 206 | } | 206 | } |
src/link.zig+5-27| ... | @@ -1349,12 +1349,14 @@ pub const File = struct { | ... | @@ -1349,12 +1349,14 @@ pub const File = struct { |
| 1349 | /// Does all the tasks in the queue. Runs in exactly one separate thread | 1349 | /// Does all the tasks in the queue. Runs in exactly one separate thread |
| 1350 | /// from the rest of compilation. All tasks performed here are | 1350 | /// from the rest of compilation. All tasks performed here are |
| 1351 | /// single-threaded with respect to one another. | 1351 | /// single-threaded with respect to one another. |
| 1352 | pub fn flushTaskQueue(base: *File, prog_node: std.Progress.Node) void { | 1352 | pub fn flushTaskQueue(base: *File, parent_prog_node: std.Progress.Node) void { |
| 1353 | const comp = base.comp; | 1353 | const comp = base.comp; |
| 1354 | base.task_queue_safety.lock(); | 1354 | base.task_queue_safety.lock(); |
| 1355 | defer base.task_queue_safety.unlock(); | 1355 | defer base.task_queue_safety.unlock(); |
| 1356 | const prog_node = parent_prog_node.start("Parse Linker Inputs", 0); | ||
| 1357 | defer prog_node.end(); | ||
| 1356 | while (comp.link_task_queue.check()) |tasks| { | 1358 | while (comp.link_task_queue.check()) |tasks| { |
| 1357 | for (tasks) |task| doTask(base, prog_node, task); | 1359 | for (tasks) |task| doTask(base, task); |
| 1358 | } | 1360 | } |
| 1359 | } | 1361 | } |
| 1360 | 1362 | ||
| ... | @@ -1374,16 +1376,11 @@ pub const File = struct { | ... | @@ -1374,16 +1376,11 @@ pub const File = struct { |
| 1374 | load_input: Input, | 1376 | load_input: Input, |
| 1375 | }; | 1377 | }; |
| 1376 | 1378 | ||
| 1377 | fn doTask(base: *File, parent_prog_node: std.Progress.Node, task: Task) void { | 1379 | fn doTask(base: *File, task: Task) void { |
| 1378 | const comp = base.comp; | 1380 | const comp = base.comp; |
| 1379 | switch (task) { | 1381 | switch (task) { |
| 1380 | .load_explicitly_provided => { | 1382 | .load_explicitly_provided => { |
| 1381 | const prog_node = parent_prog_node.start("Linker Parse Input", comp.link_inputs.len); | ||
| 1382 | defer prog_node.end(); | ||
| 1383 | |||
| 1384 | for (comp.link_inputs) |input| { | 1383 | for (comp.link_inputs) |input| { |
| 1385 | const sub_node = prog_node.start(input.taskName(), 0); | ||
| 1386 | defer sub_node.end(); | ||
| 1387 | base.loadInput(input) catch |err| switch (err) { | 1384 | base.loadInput(input) catch |err| switch (err) { |
| 1388 | error.LinkFailure => return, // error reported via link_diags | 1385 | error.LinkFailure => return, // error reported via link_diags |
| 1389 | else => |e| { | 1386 | else => |e| { |
| ... | @@ -1397,33 +1394,18 @@ pub const File = struct { | ... | @@ -1397,33 +1394,18 @@ pub const File = struct { |
| 1397 | } | 1394 | } |
| 1398 | }, | 1395 | }, |
| 1399 | .load_object => |path| { | 1396 | .load_object => |path| { |
| 1400 | const prog_node = parent_prog_node.start("Linker Parse Object", 0); | ||
| 1401 | defer prog_node.end(); | ||
| 1402 | const sub_node = prog_node.start(path.basename(), 0); | ||
| 1403 | defer sub_node.end(); | ||
| 1404 | |||
| 1405 | base.openLoadObject(path) catch |err| switch (err) { | 1397 | base.openLoadObject(path) catch |err| switch (err) { |
| 1406 | error.LinkFailure => return, // error reported via link_diags | 1398 | error.LinkFailure => return, // error reported via link_diags |
| 1407 | else => |e| comp.link_diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}), | 1399 | else => |e| comp.link_diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}), |
| 1408 | }; | 1400 | }; |
| 1409 | }, | 1401 | }, |
| 1410 | .load_archive => |path| { | 1402 | .load_archive => |path| { |
| 1411 | const prog_node = parent_prog_node.start("Linker Parse Archive", 0); | ||
| 1412 | defer prog_node.end(); | ||
| 1413 | const sub_node = prog_node.start(path.basename(), 0); | ||
| 1414 | defer sub_node.end(); | ||
| 1415 | |||
| 1416 | base.openLoadArchive(path) catch |err| switch (err) { | 1403 | base.openLoadArchive(path) catch |err| switch (err) { |
| 1417 | error.LinkFailure => return, // error reported via link_diags | 1404 | error.LinkFailure => return, // error reported via link_diags |
| 1418 | else => |e| comp.link_diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), | 1405 | else => |e| comp.link_diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), |
| 1419 | }; | 1406 | }; |
| 1420 | }, | 1407 | }, |
| 1421 | .load_dso => |path| { | 1408 | .load_dso => |path| { |
| 1422 | const prog_node = parent_prog_node.start("Linker Parse Shared Library", 0); | ||
| 1423 | defer prog_node.end(); | ||
| 1424 | const sub_node = prog_node.start(path.basename(), 0); | ||
| 1425 | defer sub_node.end(); | ||
| 1426 | |||
| 1427 | base.openLoadDso(path, .{ | 1409 | base.openLoadDso(path, .{ |
| 1428 | .preferred_mode = .dynamic, | 1410 | .preferred_mode = .dynamic, |
| 1429 | .search_strategy = .paths_first, | 1411 | .search_strategy = .paths_first, |
| ... | @@ -1433,10 +1415,6 @@ pub const File = struct { | ... | @@ -1433,10 +1415,6 @@ pub const File = struct { |
| 1433 | }; | 1415 | }; |
| 1434 | }, | 1416 | }, |
| 1435 | .load_input => |input| { | 1417 | .load_input => |input| { |
| 1436 | const prog_node = parent_prog_node.start("Linker Parse Input", 0); | ||
| 1437 | defer prog_node.end(); | ||
| 1438 | const sub_node = prog_node.start(input.taskName(), 0); | ||
| 1439 | defer sub_node.end(); | ||
| 1440 | base.loadInput(input) catch |err| switch (err) { | 1418 | base.loadInput(input) catch |err| switch (err) { |
| 1441 | error.LinkFailure => return, // error reported via link_diags | 1419 | error.LinkFailure => return, // error reported via link_diags |
| 1442 | else => |e| { | 1420 | else => |e| { |
src/link/Elf.zig+60-222| ... | @@ -114,6 +114,10 @@ comment_merge_section_index: ?Merge.Section.Index = null, | ... | @@ -114,6 +114,10 @@ comment_merge_section_index: ?Merge.Section.Index = null, |
| 114 | 114 | ||
| 115 | first_eflags: ?elf.Word = null, | 115 | first_eflags: ?elf.Word = null, |
| 116 | 116 | ||
| 117 | /// `--verbose-link` output. | ||
| 118 | /// Initialized on creation, appended to as inputs are added, printed during `flush`. | ||
| 119 | dump_argv_list: std.ArrayListUnmanaged([]const u8), | ||
| 120 | |||
| 117 | const SectionIndexes = struct { | 121 | const SectionIndexes = struct { |
| 118 | copy_rel: ?u32 = null, | 122 | copy_rel: ?u32 = null, |
| 119 | dynamic: ?u32 = null, | 123 | dynamic: ?u32 = null, |
| ... | @@ -338,6 +342,7 @@ pub fn createEmpty( | ... | @@ -338,6 +342,7 @@ pub fn createEmpty( |
| 338 | .enable_new_dtags = options.enable_new_dtags, | 342 | .enable_new_dtags = options.enable_new_dtags, |
| 339 | .print_icf_sections = options.print_icf_sections, | 343 | .print_icf_sections = options.print_icf_sections, |
| 340 | .print_map = options.print_map, | 344 | .print_map = options.print_map, |
| 345 | .dump_argv_list = .empty, | ||
| 341 | }; | 346 | }; |
| 342 | if (use_llvm and comp.config.have_zcu) { | 347 | if (use_llvm and comp.config.have_zcu) { |
| 343 | self.llvm_object = try LlvmObject.create(arena, comp); | 348 | self.llvm_object = try LlvmObject.create(arena, comp); |
| ... | @@ -350,7 +355,7 @@ pub fn createEmpty( | ... | @@ -350,7 +355,7 @@ pub fn createEmpty( |
| 350 | } | 355 | } |
| 351 | 356 | ||
| 352 | // --verbose-link | 357 | // --verbose-link |
| 353 | if (comp.verbose_link) try self.dumpArgv(comp); | 358 | if (comp.verbose_link) try dumpArgvInit(self, arena); |
| 354 | 359 | ||
| 355 | const is_obj = output_mode == .Obj; | 360 | const is_obj = output_mode == .Obj; |
| 356 | const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static); | 361 | const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .static); |
| ... | @@ -501,6 +506,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -501,6 +506,7 @@ pub fn deinit(self: *Elf) void { |
| 501 | self.rela_dyn.deinit(gpa); | 506 | self.rela_dyn.deinit(gpa); |
| 502 | self.rela_plt.deinit(gpa); | 507 | self.rela_plt.deinit(gpa); |
| 503 | self.comdat_group_sections.deinit(gpa); | 508 | self.comdat_group_sections.deinit(gpa); |
| 509 | self.dump_argv_list.deinit(gpa); | ||
| 504 | } | 510 | } |
| 505 | 511 | ||
| 506 | pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { | 512 | pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 { |
| ... | @@ -753,12 +759,23 @@ pub fn allocateChunk(self: *Elf, args: struct { | ... | @@ -753,12 +759,23 @@ pub fn allocateChunk(self: *Elf, args: struct { |
| 753 | } | 759 | } |
| 754 | 760 | ||
| 755 | pub fn loadInput(self: *Elf, input: link.Input) !void { | 761 | pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 756 | const gpa = self.base.comp.gpa; | 762 | const comp = self.base.comp; |
| 757 | const diags = &self.base.comp.link_diags; | 763 | const gpa = comp.gpa; |
| 764 | const diags = &comp.link_diags; | ||
| 758 | const target = self.getTarget(); | 765 | const target = self.getTarget(); |
| 759 | const debug_fmt_strip = self.base.comp.config.debug_format == .strip; | 766 | const debug_fmt_strip = comp.config.debug_format == .strip; |
| 760 | const default_sym_version = self.default_sym_version; | 767 | const default_sym_version = self.default_sym_version; |
| 761 | 768 | ||
| 769 | if (comp.verbose_link) { | ||
| 770 | const argv = &self.dump_argv_list; | ||
| 771 | switch (input) { | ||
| 772 | .res => unreachable, | ||
| 773 | .dso_exact => |dso_exact| try argv.appendSlice(gpa, &.{ "-l", dso_exact.name }), | ||
| 774 | .object, .archive => |obj| try argv.append(gpa, try obj.path.toString(comp.arena)), | ||
| 775 | .dso => |dso| try argv.append(gpa, try dso.path.toString(comp.arena)), | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 762 | switch (input) { | 779 | switch (input) { |
| 763 | .res => unreachable, | 780 | .res => unreachable, |
| 764 | .dso_exact => @panic("TODO"), | 781 | .dso_exact => @panic("TODO"), |
| ... | @@ -790,6 +807,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -790,6 +807,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 790 | if (use_lld) return; | 807 | if (use_lld) return; |
| 791 | } | 808 | } |
| 792 | 809 | ||
| 810 | if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items); | ||
| 811 | |||
| 793 | const sub_prog_node = prog_node.start("ELF Flush", 0); | 812 | const sub_prog_node = prog_node.start("ELF Flush", 0); |
| 794 | defer sub_prog_node.end(); | 813 | defer sub_prog_node.end(); |
| 795 | 814 | ||
| ... | @@ -965,291 +984,110 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -965,291 +984,110 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 965 | if (diags.hasErrors()) return error.FlushFailure; | 984 | if (diags.hasErrors()) return error.FlushFailure; |
| 966 | } | 985 | } |
| 967 | 986 | ||
| 968 | /// --verbose-link output | 987 | fn dumpArgvInit(self: *Elf, arena: Allocator) !void { |
| 969 | fn dumpArgv(self: *Elf, comp: *Compilation) !void { | 988 | const comp = self.base.comp; |
| 970 | const gpa = self.base.comp.gpa; | 989 | const gpa = comp.gpa; |
| 971 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | ||
| 972 | defer arena_allocator.deinit(); | ||
| 973 | const arena = arena_allocator.allocator(); | ||
| 974 | |||
| 975 | const target = self.getTarget(); | 990 | const target = self.getTarget(); |
| 976 | const link_mode = self.base.comp.config.link_mode; | 991 | const full_out_path = try self.base.emit.root_dir.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 977 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | ||
| 978 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | ||
| 979 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | ||
| 980 | if (fs.path.dirname(full_out_path)) |dirname| { | ||
| 981 | break :blk try fs.path.join(arena, &.{ dirname, path }); | ||
| 982 | } else { | ||
| 983 | break :blk path; | ||
| 984 | } | ||
| 985 | } else null; | ||
| 986 | 992 | ||
| 987 | const crt_basenames = std.zig.LibCInstallation.CrtBasenames.get(.{ | 993 | const argv = &self.dump_argv_list; |
| 988 | .target = target, | ||
| 989 | .link_libc = comp.config.link_libc, | ||
| 990 | .output_mode = comp.config.output_mode, | ||
| 991 | .link_mode = link_mode, | ||
| 992 | .pie = comp.config.pie, | ||
| 993 | }); | ||
| 994 | const crt_paths: std.zig.LibCInstallation.CrtPaths = if (comp.libc_installation) |lci| | ||
| 995 | try lci.resolveCrtPaths(arena, crt_basenames, target) | ||
| 996 | else | ||
| 997 | .{}; | ||
| 998 | const compiler_rt_path: ?[]const u8 = blk: { | ||
| 999 | if (comp.compiler_rt_lib) |x| break :blk try x.full_object_path.toString(arena); | ||
| 1000 | if (comp.compiler_rt_obj) |x| break :blk try x.full_object_path.toString(arena); | ||
| 1001 | break :blk null; | ||
| 1002 | }; | ||
| 1003 | 994 | ||
| 1004 | var argv = std.ArrayList([]const u8).init(arena); | 995 | try argv.append(gpa, "zig"); |
| 1005 | |||
| 1006 | try argv.append("zig"); | ||
| 1007 | 996 | ||
| 1008 | if (self.base.isStaticLib()) { | 997 | if (self.base.isStaticLib()) { |
| 1009 | try argv.append("ar"); | 998 | try argv.append(gpa, "ar"); |
| 1010 | } else { | 999 | } else { |
| 1011 | try argv.append("ld"); | 1000 | try argv.append(gpa, "ld"); |
| 1012 | } | 1001 | } |
| 1013 | 1002 | ||
| 1014 | if (self.base.isObject()) { | 1003 | if (self.base.isObject()) { |
| 1015 | try argv.append("-r"); | 1004 | try argv.append(gpa, "-r"); |
| 1016 | } | 1005 | } |
| 1017 | 1006 | ||
| 1018 | try argv.append("-o"); | 1007 | try argv.append(gpa, "-o"); |
| 1019 | try argv.append(full_out_path); | 1008 | try argv.append(gpa, full_out_path); |
| 1020 | |||
| 1021 | if (self.base.isRelocatable()) { | ||
| 1022 | for (self.base.comp.link_inputs) |link_input| switch (link_input) { | ||
| 1023 | .res => unreachable, | ||
| 1024 | .dso => |dso| try argv.append(try dso.path.toString(arena)), | ||
| 1025 | .object, .archive => |obj| try argv.append(try obj.path.toString(arena)), | ||
| 1026 | .dso_exact => |dso_exact| { | ||
| 1027 | assert(dso_exact.name[0] == ':'); | ||
| 1028 | try argv.appendSlice(&.{ "-l", dso_exact.name }); | ||
| 1029 | }, | ||
| 1030 | }; | ||
| 1031 | |||
| 1032 | for (comp.c_object_table.keys()) |key| { | ||
| 1033 | try argv.append(try key.status.success.object_path.toString(arena)); | ||
| 1034 | } | ||
| 1035 | 1009 | ||
| 1036 | if (module_obj_path) |p| { | 1010 | if (!self.base.isRelocatable()) { |
| 1037 | try argv.append(p); | ||
| 1038 | } | ||
| 1039 | } else { | ||
| 1040 | if (!self.base.isStatic()) { | 1011 | if (!self.base.isStatic()) { |
| 1041 | if (target.dynamic_linker.get()) |path| { | 1012 | if (target.dynamic_linker.get()) |path| { |
| 1042 | try argv.append("-dynamic-linker"); | 1013 | try argv.appendSlice(gpa, &.{ "-dynamic-linker", try arena.dupe(u8, path) }); |
| 1043 | try argv.append(path); | ||
| 1044 | } | 1014 | } |
| 1045 | } | 1015 | } |
| 1046 | 1016 | ||
| 1047 | if (self.base.isDynLib()) { | 1017 | if (self.base.isDynLib()) { |
| 1048 | if (self.soname) |name| { | 1018 | if (self.soname) |name| { |
| 1049 | try argv.append("-soname"); | 1019 | try argv.append(gpa, "-soname"); |
| 1050 | try argv.append(name); | 1020 | try argv.append(gpa, name); |
| 1051 | } | 1021 | } |
| 1052 | } | 1022 | } |
| 1053 | 1023 | ||
| 1054 | if (self.entry_name) |name| { | 1024 | if (self.entry_name) |name| { |
| 1055 | try argv.appendSlice(&.{ "--entry", name }); | 1025 | try argv.appendSlice(gpa, &.{ "--entry", name }); |
| 1056 | } | 1026 | } |
| 1057 | 1027 | ||
| 1058 | for (self.rpath_table.keys()) |rpath| { | 1028 | for (self.rpath_table.keys()) |rpath| { |
| 1059 | try argv.appendSlice(&.{ "-rpath", rpath }); | 1029 | try argv.appendSlice(gpa, &.{ "-rpath", rpath }); |
| 1060 | } | 1030 | } |
| 1061 | 1031 | ||
| 1062 | try argv.appendSlice(&.{ | 1032 | try argv.appendSlice(gpa, &.{ |
| 1063 | "-z", | 1033 | "-z", |
| 1064 | try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), | 1034 | try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), |
| 1065 | }); | 1035 | }); |
| 1066 | 1036 | ||
| 1067 | try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); | 1037 | try argv.append(gpa, try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); |
| 1068 | 1038 | ||
| 1069 | if (self.base.gc_sections) { | 1039 | if (self.base.gc_sections) { |
| 1070 | try argv.append("--gc-sections"); | 1040 | try argv.append(gpa, "--gc-sections"); |
| 1071 | } | 1041 | } |
| 1072 | 1042 | ||
| 1073 | if (self.base.print_gc_sections) { | 1043 | if (self.base.print_gc_sections) { |
| 1074 | try argv.append("--print-gc-sections"); | 1044 | try argv.append(gpa, "--print-gc-sections"); |
| 1075 | } | 1045 | } |
| 1076 | 1046 | ||
| 1077 | if (comp.link_eh_frame_hdr) { | 1047 | if (comp.link_eh_frame_hdr) { |
| 1078 | try argv.append("--eh-frame-hdr"); | 1048 | try argv.append(gpa, "--eh-frame-hdr"); |
| 1079 | } | 1049 | } |
| 1080 | 1050 | ||
| 1081 | if (comp.config.rdynamic) { | 1051 | if (comp.config.rdynamic) { |
| 1082 | try argv.append("--export-dynamic"); | 1052 | try argv.append(gpa, "--export-dynamic"); |
| 1083 | } | 1053 | } |
| 1084 | 1054 | ||
| 1085 | if (self.z_notext) { | 1055 | if (self.z_notext) { |
| 1086 | try argv.append("-z"); | 1056 | try argv.append(gpa, "-z"); |
| 1087 | try argv.append("notext"); | 1057 | try argv.append(gpa, "notext"); |
| 1088 | } | 1058 | } |
| 1089 | 1059 | ||
| 1090 | if (self.z_nocopyreloc) { | 1060 | if (self.z_nocopyreloc) { |
| 1091 | try argv.append("-z"); | 1061 | try argv.append(gpa, "-z"); |
| 1092 | try argv.append("nocopyreloc"); | 1062 | try argv.append(gpa, "nocopyreloc"); |
| 1093 | } | 1063 | } |
| 1094 | 1064 | ||
| 1095 | if (self.z_now) { | 1065 | if (self.z_now) { |
| 1096 | try argv.append("-z"); | 1066 | try argv.append(gpa, "-z"); |
| 1097 | try argv.append("now"); | 1067 | try argv.append(gpa, "now"); |
| 1098 | } | 1068 | } |
| 1099 | 1069 | ||
| 1100 | if (self.base.isStatic()) { | 1070 | if (self.base.isStatic()) { |
| 1101 | try argv.append("-static"); | 1071 | try argv.append(gpa, "-static"); |
| 1102 | } else if (self.isEffectivelyDynLib()) { | 1072 | } else if (self.isEffectivelyDynLib()) { |
| 1103 | try argv.append("-shared"); | 1073 | try argv.append(gpa, "-shared"); |
| 1104 | } | 1074 | } |
| 1105 | 1075 | ||
| 1106 | if (comp.config.pie and self.base.isExe()) { | 1076 | if (comp.config.pie and self.base.isExe()) { |
| 1107 | try argv.append("-pie"); | 1077 | try argv.append(gpa, "-pie"); |
| 1108 | } | 1078 | } |
| 1109 | 1079 | ||
| 1110 | if (comp.config.debug_format == .strip) { | 1080 | if (comp.config.debug_format == .strip) { |
| 1111 | try argv.append("-s"); | 1081 | try argv.append(gpa, "-s"); |
| 1112 | } | 1082 | } |
| 1113 | 1083 | ||
| 1114 | if (crt_paths.crt0) |path| try argv.append(try path.toString(arena)); | ||
| 1115 | if (crt_paths.crti) |path| try argv.append(try path.toString(arena)); | ||
| 1116 | if (crt_paths.crtbegin) |path| try argv.append(try path.toString(arena)); | ||
| 1117 | |||
| 1118 | if (comp.config.link_libc) { | 1084 | if (comp.config.link_libc) { |
| 1119 | if (self.base.comp.libc_installation) |libc_installation| { | 1085 | if (self.base.comp.libc_installation) |lci| { |
| 1120 | try argv.append("-L"); | 1086 | try argv.append(gpa, "-L"); |
| 1121 | try argv.append(libc_installation.crt_dir.?); | 1087 | try argv.append(gpa, lci.crt_dir.?); |
| 1122 | } | 1088 | } |
| 1123 | } | 1089 | } |
| 1124 | |||
| 1125 | var whole_archive = false; | ||
| 1126 | |||
| 1127 | for (self.base.comp.link_inputs) |link_input| switch (link_input) { | ||
| 1128 | .res => unreachable, | ||
| 1129 | .dso => continue, | ||
| 1130 | .object, .archive => |obj| { | ||
| 1131 | if (obj.must_link and !whole_archive) { | ||
| 1132 | try argv.append("-whole-archive"); | ||
| 1133 | whole_archive = true; | ||
| 1134 | } else if (!obj.must_link and whole_archive) { | ||
| 1135 | try argv.append("-no-whole-archive"); | ||
| 1136 | whole_archive = false; | ||
| 1137 | } | ||
| 1138 | try argv.append(try obj.path.toString(arena)); | ||
| 1139 | }, | ||
| 1140 | .dso_exact => |dso_exact| { | ||
| 1141 | assert(dso_exact.name[0] == ':'); | ||
| 1142 | try argv.appendSlice(&.{ "-l", dso_exact.name }); | ||
| 1143 | }, | ||
| 1144 | }; | ||
| 1145 | |||
| 1146 | if (whole_archive) { | ||
| 1147 | try argv.append("-no-whole-archive"); | ||
| 1148 | whole_archive = false; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | for (comp.c_object_table.keys()) |key| { | ||
| 1152 | try argv.append(try key.status.success.object_path.toString(arena)); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | if (module_obj_path) |p| { | ||
| 1156 | try argv.append(p); | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | if (comp.config.any_sanitize_thread) { | ||
| 1160 | try argv.append(try comp.tsan_lib.?.full_object_path.toString(arena)); | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | if (comp.config.any_fuzz) { | ||
| 1164 | try argv.append(try comp.fuzzer_lib.?.full_object_path.toString(arena)); | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | // libc | ||
| 1168 | if (!comp.skip_linker_dependencies and !comp.config.link_libc) { | ||
| 1169 | if (comp.libc_static_lib) |lib| { | ||
| 1170 | try argv.append(try lib.full_object_path.toString(arena)); | ||
| 1171 | } | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | // Shared libraries. | ||
| 1175 | // Worst-case, we need an --as-needed argument for every lib, as well | ||
| 1176 | // as one before and one after. | ||
| 1177 | argv.appendAssumeCapacity("--as-needed"); | ||
| 1178 | var as_needed = true; | ||
| 1179 | |||
| 1180 | for (self.base.comp.link_inputs) |link_input| switch (link_input) { | ||
| 1181 | .object, .archive, .dso_exact => continue, | ||
| 1182 | .dso => |dso| { | ||
| 1183 | const lib_as_needed = !dso.needed; | ||
| 1184 | switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { | ||
| 1185 | 0b00, 0b11 => {}, | ||
| 1186 | 0b01 => { | ||
| 1187 | try argv.append("--no-as-needed"); | ||
| 1188 | as_needed = false; | ||
| 1189 | }, | ||
| 1190 | 0b10 => { | ||
| 1191 | try argv.append("--as-needed"); | ||
| 1192 | as_needed = true; | ||
| 1193 | }, | ||
| 1194 | } | ||
| 1195 | argv.appendAssumeCapacity(try dso.path.toString(arena)); | ||
| 1196 | }, | ||
| 1197 | .res => unreachable, | ||
| 1198 | }; | ||
| 1199 | |||
| 1200 | if (!as_needed) { | ||
| 1201 | argv.appendAssumeCapacity("--as-needed"); | ||
| 1202 | as_needed = true; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | // libc++ dep | ||
| 1206 | if (comp.config.link_libcpp) { | ||
| 1207 | try argv.append(try comp.libcxxabi_static_lib.?.full_object_path.toString(arena)); | ||
| 1208 | try argv.append(try comp.libcxx_static_lib.?.full_object_path.toString(arena)); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | // libunwind dep | ||
| 1212 | if (comp.config.link_libunwind) { | ||
| 1213 | try argv.append(try comp.libunwind_static_lib.?.full_object_path.toString(arena)); | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | // libc dep | ||
| 1217 | if (comp.config.link_libc) { | ||
| 1218 | if (self.base.comp.libc_installation != null) { | ||
| 1219 | const needs_grouping = link_mode == .static; | ||
| 1220 | if (needs_grouping) try argv.append("--start-group"); | ||
| 1221 | try argv.appendSlice(target_util.libcFullLinkFlags(target)); | ||
| 1222 | if (needs_grouping) try argv.append("--end-group"); | ||
| 1223 | } else if (target.isGnuLibC()) { | ||
| 1224 | for (glibc.libs) |lib| { | ||
| 1225 | if (lib.removed_in) |rem_in| { | ||
| 1226 | if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ | ||
| 1230 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, | ||
| 1231 | }); | ||
| 1232 | try argv.append(lib_path); | ||
| 1233 | } | ||
| 1234 | try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a")); | ||
| 1235 | } else if (target.isMusl()) { | ||
| 1236 | try argv.append(try comp.crtFileAsString(arena, switch (link_mode) { | ||
| 1237 | .static => "libc.a", | ||
| 1238 | .dynamic => "libc.so", | ||
| 1239 | })); | ||
| 1240 | } | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | // compiler-rt | ||
| 1244 | if (compiler_rt_path) |p| { | ||
| 1245 | try argv.append(p); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | if (crt_paths.crtend) |path| try argv.append(try path.toString(arena)); | ||
| 1249 | if (crt_paths.crtn) |path| try argv.append(try path.toString(arena)); | ||
| 1250 | } | 1090 | } |
| 1251 | |||
| 1252 | Compilation.dump_argv(argv.items); | ||
| 1253 | } | 1091 | } |
| 1254 | 1092 | ||
| 1255 | pub const ParseError = error{ | 1093 | pub const ParseError = error{ |
| ... | @@ -2177,7 +2015,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2177,7 +2015,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2177 | if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue; | 2015 | if (target.os.version_range.linux.glibc.order(rem_in) != .lt) continue; |
| 2178 | } | 2016 | } |
| 2179 | 2017 | ||
| 2180 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ | 2018 | const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{ |
| 2181 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, | 2019 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| 2182 | }); | 2020 | }); |
| 2183 | try argv.append(lib_path); | 2021 | try argv.append(lib_path); |
src/musl.zig+1-1| ... | @@ -281,7 +281,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro | ... | @@ -281,7 +281,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 281 | errdefer comp.gpa.free(basename); | 281 | errdefer comp.gpa.free(basename); |
| 282 | 282 | ||
| 283 | const crt_file = try sub_compilation.toCrtFile(); | 283 | const crt_file = try sub_compilation.toCrtFile(); |
| 284 | comp.enqueueLinkTaskMode(crt_file.full_object_path, output_mode); | 284 | comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); |
| 285 | { | 285 | { |
| 286 | comp.mutex.lock(); | 286 | comp.mutex.lock(); |
| 287 | defer comp.mutex.unlock(); | 287 | defer comp.mutex.unlock(); |