| ... | @@ -478,6 +478,7 @@ const usage_build_generic = | ... | @@ -478,6 +478,7 @@ const usage_build_generic = |
| 478 | \\ --sysroot [path] Set the system root directory (usually /) | 478 | \\ --sysroot [path] Set the system root directory (usually /) |
| 479 | \\ --version [ver] Dynamic library semver | 479 | \\ --version [ver] Dynamic library semver |
| 480 | \\ --entry [name] Set the entrypoint symbol name | 480 | \\ --entry [name] Set the entrypoint symbol name |
| | 481 | \\ --force_undefined [name] Specify the symbol must be defined for the link to succeed |
| 481 | \\ -fsoname[=name] Override the default SONAME value | 482 | \\ -fsoname[=name] Override the default SONAME value |
| 482 | \\ -fno-soname Disable emitting a SONAME | 483 | \\ -fno-soname Disable emitting a SONAME |
| 483 | \\ -fLLD Force using LLD as the linker | 484 | \\ -fLLD Force using LLD as the linker |
| ... | @@ -680,6 +681,28 @@ const Listen = union(enum) { | ... | @@ -680,6 +681,28 @@ const Listen = union(enum) { |
| 680 | stdio, | 681 | stdio, |
| 681 | }; | 682 | }; |
| 682 | | 683 | |
| | 684 | const ArgsIterator = struct { |
| | 685 | resp_file: ?ArgIteratorResponseFile = null, |
| | 686 | args: []const []const u8, |
| | 687 | i: usize = 0, |
| | 688 | fn next(it: *@This()) ?[]const u8 { |
| | 689 | if (it.i >= it.args.len) { |
| | 690 | if (it.resp_file) |*resp| return resp.next(); |
| | 691 | return null; |
| | 692 | } |
| | 693 | defer it.i += 1; |
| | 694 | return it.args[it.i]; |
| | 695 | } |
| | 696 | fn nextOrFatal(it: *@This()) []const u8 { |
| | 697 | if (it.i >= it.args.len) { |
| | 698 | if (it.resp_file) |*resp| if (resp.next()) |ret| return ret; |
| | 699 | fatal("expected parameter after {s}", .{it.args[it.i - 1]}); |
| | 700 | } |
| | 701 | defer it.i += 1; |
| | 702 | return it.args[it.i]; |
| | 703 | } |
| | 704 | }; |
| | 705 | |
| 683 | fn buildOutputType( | 706 | fn buildOutputType( |
| 684 | gpa: Allocator, | 707 | gpa: Allocator, |
| 685 | arena: Allocator, | 708 | arena: Allocator, |
| ... | @@ -784,6 +807,7 @@ fn buildOutputType( | ... | @@ -784,6 +807,7 @@ fn buildOutputType( |
| 784 | var test_evented_io = false; | 807 | var test_evented_io = false; |
| 785 | var test_no_exec = false; | 808 | var test_no_exec = false; |
| 786 | var entry: ?[]const u8 = null; | 809 | var entry: ?[]const u8 = null; |
| | 810 | var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; |
| 787 | var stack_size_override: ?u64 = null; | 811 | var stack_size_override: ?u64 = null; |
| 788 | var image_base_override: ?u64 = null; | 812 | var image_base_override: ?u64 = null; |
| 789 | var use_llvm: ?bool = null; | 813 | var use_llvm: ?bool = null; |
| ... | @@ -917,28 +941,7 @@ fn buildOutputType( | ... | @@ -917,28 +941,7 @@ fn buildOutputType( |
| 917 | | 941 | |
| 918 | soname = .yes_default_value; | 942 | soname = .yes_default_value; |
| 919 | | 943 | |
| 920 | const Iterator = struct { | 944 | var args_iter = ArgsIterator{ |
| 921 | resp_file: ?ArgIteratorResponseFile = null, | | |
| 922 | args: []const []const u8, | | |
| 923 | i: usize = 0, | | |
| 924 | fn next(it: *@This()) ?[]const u8 { | | |
| 925 | if (it.i >= it.args.len) { | | |
| 926 | if (it.resp_file) |*resp| return resp.next(); | | |
| 927 | return null; | | |
| 928 | } | | |
| 929 | defer it.i += 1; | | |
| 930 | return it.args[it.i]; | | |
| 931 | } | | |
| 932 | fn nextOrFatal(it: *@This()) []const u8 { | | |
| 933 | if (it.i >= it.args.len) { | | |
| 934 | if (it.resp_file) |*resp| if (resp.next()) |ret| return ret; | | |
| 935 | fatal("expected parameter after {s}", .{it.args[it.i - 1]}); | | |
| 936 | } | | |
| 937 | defer it.i += 1; | | |
| 938 | return it.args[it.i]; | | |
| 939 | } | | |
| 940 | }; | | |
| 941 | var args_iter = Iterator{ | | |
| 942 | .args = all_args[2..], | 945 | .args = all_args[2..], |
| 943 | }; | 946 | }; |
| 944 | | 947 | |
| ... | @@ -1029,6 +1032,8 @@ fn buildOutputType( | ... | @@ -1029,6 +1032,8 @@ fn buildOutputType( |
| 1029 | optimize_mode_string = args_iter.nextOrFatal(); | 1032 | optimize_mode_string = args_iter.nextOrFatal(); |
| 1030 | } else if (mem.eql(u8, arg, "--entry")) { | 1033 | } else if (mem.eql(u8, arg, "--entry")) { |
| 1031 | entry = args_iter.nextOrFatal(); | 1034 | entry = args_iter.nextOrFatal(); |
| | 1035 | } else if (mem.eql(u8, arg, "--force_undefined")) { |
| | 1036 | try force_undefined_symbols.put(gpa, args_iter.nextOrFatal(), {}); |
| 1032 | } else if (mem.eql(u8, arg, "--stack")) { | 1037 | } else if (mem.eql(u8, arg, "--stack")) { |
| 1033 | const next_arg = args_iter.nextOrFatal(); | 1038 | const next_arg = args_iter.nextOrFatal(); |
| 1034 | stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { | 1039 | stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { |
| ... | @@ -1816,6 +1821,9 @@ fn buildOutputType( | ... | @@ -1816,6 +1821,9 @@ fn buildOutputType( |
| 1816 | .entry => { | 1821 | .entry => { |
| 1817 | entry = it.only_arg; | 1822 | entry = it.only_arg; |
| 1818 | }, | 1823 | }, |
| | 1824 | .force_undefined_symbol => { |
| | 1825 | try force_undefined_symbols.put(gpa, it.only_arg, {}); |
| | 1826 | }, |
| 1819 | .weak_library => try system_libs.put(it.only_arg, .{ .weak = true }), | 1827 | .weak_library => try system_libs.put(it.only_arg, .{ .weak = true }), |
| 1820 | .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), | 1828 | .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), |
| 1821 | .headerpad_max_install_names => headerpad_max_install_names = true, | 1829 | .headerpad_max_install_names => headerpad_max_install_names = true, |
| ... | @@ -1843,17 +1851,14 @@ fn buildOutputType( | ... | @@ -1843,17 +1851,14 @@ fn buildOutputType( |
| 1843 | } | 1851 | } |
| 1844 | } | 1852 | } |
| 1845 | // Parse linker args. | 1853 | // Parse linker args. |
| 1846 | var i: usize = 0; | 1854 | var linker_args_it = ArgsIterator{ |
| 1847 | while (i < linker_args.items.len) : (i += 1) { | 1855 | .args = linker_args.items, |
| 1848 | const arg = linker_args.items[i]; | 1856 | }; |
| | 1857 | while (linker_args_it.next()) |arg| { |
| 1849 | if (mem.eql(u8, arg, "-soname") or | 1858 | if (mem.eql(u8, arg, "-soname") or |
| 1850 | mem.eql(u8, arg, "--soname")) | 1859 | mem.eql(u8, arg, "--soname")) |
| 1851 | { | 1860 | { |
| 1852 | i += 1; | 1861 | const name = linker_args_it.nextOrFatal(); |
| 1853 | if (i >= linker_args.items.len) { | | |
| 1854 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1855 | } | | |
| 1856 | const name = linker_args.items[i]; | | |
| 1857 | soname = .{ .yes = name }; | 1862 | soname = .{ .yes = name }; |
| 1858 | // Use it as --name. | 1863 | // Use it as --name. |
| 1859 | // Example: libsoundio.so.2 | 1864 | // Example: libsoundio.so.2 |
| ... | @@ -1881,64 +1886,37 @@ fn buildOutputType( | ... | @@ -1881,64 +1886,37 @@ fn buildOutputType( |
| 1881 | } | 1886 | } |
| 1882 | provided_name = name[prefix..end]; | 1887 | provided_name = name[prefix..end]; |
| 1883 | } else if (mem.eql(u8, arg, "-rpath")) { | 1888 | } else if (mem.eql(u8, arg, "-rpath")) { |
| 1884 | i += 1; | 1889 | try rpath_list.append(linker_args_it.nextOrFatal()); |
| 1885 | if (i >= linker_args.items.len) { | | |
| 1886 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1887 | } | | |
| 1888 | try rpath_list.append(linker_args.items[i]); | | |
| 1889 | } else if (mem.eql(u8, arg, "--subsystem")) { | 1890 | } else if (mem.eql(u8, arg, "--subsystem")) { |
| 1890 | i += 1; | 1891 | subsystem = try parseSubSystem(linker_args_it.nextOrFatal()); |
| 1891 | if (i >= linker_args.items.len) { | | |
| 1892 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1893 | } | | |
| 1894 | subsystem = try parseSubSystem(linker_args.items[i]); | | |
| 1895 | } else if (mem.eql(u8, arg, "-I") or | 1892 | } else if (mem.eql(u8, arg, "-I") or |
| 1896 | mem.eql(u8, arg, "--dynamic-linker") or | 1893 | mem.eql(u8, arg, "--dynamic-linker") or |
| 1897 | mem.eql(u8, arg, "-dynamic-linker")) | 1894 | mem.eql(u8, arg, "-dynamic-linker")) |
| 1898 | { | 1895 | { |
| 1899 | i += 1; | 1896 | target_dynamic_linker = linker_args_it.nextOrFatal(); |
| 1900 | if (i >= linker_args.items.len) { | | |
| 1901 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1902 | } | | |
| 1903 | target_dynamic_linker = linker_args.items[i]; | | |
| 1904 | } else if (mem.eql(u8, arg, "-E") or | 1897 | } else if (mem.eql(u8, arg, "-E") or |
| 1905 | mem.eql(u8, arg, "--export-dynamic") or | 1898 | mem.eql(u8, arg, "--export-dynamic") or |
| 1906 | mem.eql(u8, arg, "-export-dynamic")) | 1899 | mem.eql(u8, arg, "-export-dynamic")) |
| 1907 | { | 1900 | { |
| 1908 | rdynamic = true; | 1901 | rdynamic = true; |
| 1909 | } else if (mem.eql(u8, arg, "--version-script")) { | 1902 | } else if (mem.eql(u8, arg, "--version-script")) { |
| 1910 | i += 1; | 1903 | version_script = linker_args_it.nextOrFatal(); |
| 1911 | if (i >= linker_args.items.len) { | | |
| 1912 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1913 | } | | |
| 1914 | version_script = linker_args.items[i]; | | |
| 1915 | } else if (mem.eql(u8, arg, "-O")) { | 1904 | } else if (mem.eql(u8, arg, "-O")) { |
| 1916 | i += 1; | 1905 | const opt = linker_args_it.nextOrFatal(); |
| 1917 | if (i >= linker_args.items.len) { | 1906 | linker_optimization = std.fmt.parseUnsigned(u8, opt, 10) catch |err| { |
| 1918 | fatal("expected linker arg after '{s}'", .{arg}); | 1907 | fatal("unable to parse optimization level '{s}': {s}", .{ opt, @errorName(err) }); |
| 1919 | } | | |
| 1920 | linker_optimization = std.fmt.parseUnsigned(u8, linker_args.items[i], 10) catch |err| { | | |
| 1921 | fatal("unable to parse optimization level '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 1922 | }; | 1908 | }; |
| 1923 | } else if (mem.startsWith(u8, arg, "-O")) { | 1909 | } else if (mem.startsWith(u8, arg, "-O")) { |
| 1924 | linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| { | 1910 | linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| { |
| 1925 | fatal("unable to parse optimization level '{s}': {s}", .{ arg, @errorName(err) }); | 1911 | fatal("unable to parse optimization level '{s}': {s}", .{ arg, @errorName(err) }); |
| 1926 | }; | 1912 | }; |
| 1927 | } else if (mem.eql(u8, arg, "-pagezero_size")) { | 1913 | } else if (mem.eql(u8, arg, "-pagezero_size")) { |
| 1928 | i += 1; | 1914 | const next_arg = linker_args_it.nextOrFatal(); |
| 1929 | if (i >= linker_args.items.len) { | | |
| 1930 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1931 | } | | |
| 1932 | const next_arg = linker_args.items[i]; | | |
| 1933 | pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { | 1915 | pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { |
| 1934 | fatal("unable to parse pagezero size '{s}': {s}", .{ next_arg, @errorName(err) }); | 1916 | fatal("unable to parse pagezero size '{s}': {s}", .{ next_arg, @errorName(err) }); |
| 1935 | }; | 1917 | }; |
| 1936 | } else if (mem.eql(u8, arg, "-headerpad")) { | 1918 | } else if (mem.eql(u8, arg, "-headerpad")) { |
| 1937 | i += 1; | 1919 | const next_arg = linker_args_it.nextOrFatal(); |
| 1938 | if (i >= linker_args.items.len) { | | |
| 1939 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1940 | } | | |
| 1941 | const next_arg = linker_args.items[i]; | | |
| 1942 | headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { | 1920 | headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { |
| 1943 | fatal("unable to parse headerpad size '{s}': {s}", .{ next_arg, @errorName(err) }); | 1921 | fatal("unable to parse headerpad size '{s}': {s}", .{ next_arg, @errorName(err) }); |
| 1944 | }; | 1922 | }; |
| ... | @@ -1961,11 +1939,7 @@ fn buildOutputType( | ... | @@ -1961,11 +1939,7 @@ fn buildOutputType( |
| 1961 | } else if (mem.eql(u8, arg, "--print-map")) { | 1939 | } else if (mem.eql(u8, arg, "--print-map")) { |
| 1962 | linker_print_map = true; | 1940 | linker_print_map = true; |
| 1963 | } else if (mem.eql(u8, arg, "--sort-section")) { | 1941 | } else if (mem.eql(u8, arg, "--sort-section")) { |
| 1964 | i += 1; | 1942 | const arg1 = linker_args_it.nextOrFatal(); |
| 1965 | if (i >= linker_args.items.len) { | | |
| 1966 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 1967 | } | | |
| 1968 | const arg1 = linker_args.items[i]; | | |
| 1969 | linker_sort_section = std.meta.stringToEnum(link.SortSection, arg1) orelse { | 1943 | linker_sort_section = std.meta.stringToEnum(link.SortSection, arg1) orelse { |
| 1970 | fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1}); | 1944 | fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1}); |
| 1971 | }; | 1945 | }; |
| ... | @@ -1998,28 +1972,16 @@ fn buildOutputType( | ... | @@ -1998,28 +1972,16 @@ fn buildOutputType( |
| 1998 | } else if (mem.startsWith(u8, arg, "--export=")) { | 1972 | } else if (mem.startsWith(u8, arg, "--export=")) { |
| 1999 | try linker_export_symbol_names.append(arg["--export=".len..]); | 1973 | try linker_export_symbol_names.append(arg["--export=".len..]); |
| 2000 | } else if (mem.eql(u8, arg, "--export")) { | 1974 | } else if (mem.eql(u8, arg, "--export")) { |
| 2001 | i += 1; | 1975 | try linker_export_symbol_names.append(linker_args_it.nextOrFatal()); |
| 2002 | if (i >= linker_args.items.len) { | | |
| 2003 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2004 | } | | |
| 2005 | try linker_export_symbol_names.append(linker_args.items[i]); | | |
| 2006 | } else if (mem.eql(u8, arg, "--compress-debug-sections")) { | 1976 | } else if (mem.eql(u8, arg, "--compress-debug-sections")) { |
| 2007 | i += 1; | 1977 | const arg1 = linker_args_it.nextOrFatal(); |
| 2008 | if (i >= linker_args.items.len) { | | |
| 2009 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2010 | } | | |
| 2011 | const arg1 = linker_args.items[i]; | | |
| 2012 | linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse { | 1978 | linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse { |
| 2013 | fatal("expected [none|zlib] after --compress-debug-sections, found '{s}'", .{arg1}); | 1979 | fatal("expected [none|zlib] after --compress-debug-sections, found '{s}'", .{arg1}); |
| 2014 | }; | 1980 | }; |
| 2015 | } else if (mem.startsWith(u8, arg, "-z")) { | 1981 | } else if (mem.startsWith(u8, arg, "-z")) { |
| 2016 | var z_arg = arg[2..]; | 1982 | var z_arg = arg[2..]; |
| 2017 | if (z_arg.len == 0) { | 1983 | if (z_arg.len == 0) { |
| 2018 | i += 1; | 1984 | z_arg = linker_args_it.nextOrFatal(); |
| 2019 | if (i >= linker_args.items.len) { | | |
| 2020 | fatal("expected linker extension flag after '{s}'", .{arg}); | | |
| 2021 | } | | |
| 2022 | z_arg = linker_args.items[i]; | | |
| 2023 | } | 1985 | } |
| 2024 | if (mem.eql(u8, z_arg, "nodelete")) { | 1986 | if (mem.eql(u8, z_arg, "nodelete")) { |
| 2025 | linker_z_nodelete = true; | 1987 | linker_z_nodelete = true; |
| ... | @@ -2056,51 +2018,33 @@ fn buildOutputType( | ... | @@ -2056,51 +2018,33 @@ fn buildOutputType( |
| 2056 | fatal("unsupported linker extension flag: -z {s}", .{z_arg}); | 2018 | fatal("unsupported linker extension flag: -z {s}", .{z_arg}); |
| 2057 | } | 2019 | } |
| 2058 | } else if (mem.eql(u8, arg, "--major-image-version")) { | 2020 | } else if (mem.eql(u8, arg, "--major-image-version")) { |
| 2059 | i += 1; | 2021 | const major = linker_args_it.nextOrFatal(); |
| 2060 | if (i >= linker_args.items.len) { | 2022 | version.major = std.fmt.parseUnsigned(u32, major, 10) catch |err| { |
| 2061 | fatal("expected linker arg after '{s}'", .{arg}); | 2023 | fatal("unable to parse major image version '{s}': {s}", .{ major, @errorName(err) }); |
| 2062 | } | | |
| 2063 | version.major = std.fmt.parseUnsigned(u32, linker_args.items[i], 10) catch |err| { | | |
| 2064 | fatal("unable to parse major image version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2065 | }; | 2024 | }; |
| 2066 | have_version = true; | 2025 | have_version = true; |
| 2067 | } else if (mem.eql(u8, arg, "--minor-image-version")) { | 2026 | } else if (mem.eql(u8, arg, "--minor-image-version")) { |
| 2068 | i += 1; | 2027 | const minor = linker_args_it.nextOrFatal(); |
| 2069 | if (i >= linker_args.items.len) { | 2028 | version.minor = std.fmt.parseUnsigned(u32, minor, 10) catch |err| { |
| 2070 | fatal("expected linker arg after '{s}'", .{arg}); | 2029 | fatal("unable to parse minor image version '{s}': {s}", .{ minor, @errorName(err) }); |
| 2071 | } | | |
| 2072 | version.minor = std.fmt.parseUnsigned(u32, linker_args.items[i], 10) catch |err| { | | |
| 2073 | fatal("unable to parse minor image version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2074 | }; | 2030 | }; |
| 2075 | have_version = true; | 2031 | have_version = true; |
| 2076 | } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { | 2032 | } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) { |
| 2077 | i += 1; | 2033 | entry = linker_args_it.nextOrFatal(); |
| 2078 | if (i >= linker_args.items.len) { | 2034 | } else if (mem.eql(u8, arg, "-u")) { |
| 2079 | fatal("expected linker arg after '{s}'", .{arg}); | 2035 | try force_undefined_symbols.put(gpa, linker_args_it.nextOrFatal(), {}); |
| 2080 | } | | |
| 2081 | entry = linker_args.items[i]; | | |
| 2082 | } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { | 2036 | } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { |
| 2083 | i += 1; | 2037 | const stack_size = linker_args_it.nextOrFatal(); |
| 2084 | if (i >= linker_args.items.len) { | 2038 | stack_size_override = std.fmt.parseUnsigned(u64, stack_size, 0) catch |err| { |
| 2085 | fatal("expected linker arg after '{s}'", .{arg}); | 2039 | fatal("unable to parse stack size override '{s}': {s}", .{ stack_size, @errorName(err) }); |
| 2086 | } | | |
| 2087 | stack_size_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| { | | |
| 2088 | fatal("unable to parse stack size override '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2089 | }; | 2040 | }; |
| 2090 | } else if (mem.eql(u8, arg, "--image-base")) { | 2041 | } else if (mem.eql(u8, arg, "--image-base")) { |
| 2091 | i += 1; | 2042 | const image_base = linker_args_it.nextOrFatal(); |
| 2092 | if (i >= linker_args.items.len) { | 2043 | image_base_override = std.fmt.parseUnsigned(u64, image_base, 0) catch |err| { |
| 2093 | fatal("expected linker arg after '{s}'", .{arg}); | 2044 | fatal("unable to parse image base override '{s}': {s}", .{ image_base, @errorName(err) }); |
| 2094 | } | | |
| 2095 | image_base_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| { | | |
| 2096 | fatal("unable to parse image base override '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2097 | }; | 2045 | }; |
| 2098 | } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { | 2046 | } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { |
| 2099 | i += 1; | 2047 | linker_script = linker_args_it.nextOrFatal(); |
| 2100 | if (i >= linker_args.items.len) { | | |
| 2101 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2102 | } | | |
| 2103 | linker_script = linker_args.items[i]; | | |
| 2104 | } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { | 2048 | } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { |
| 2105 | link_eh_frame_hdr = true; | 2049 | link_eh_frame_hdr = true; |
| 2106 | } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { | 2050 | } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { |
| ... | @@ -2138,130 +2082,74 @@ fn buildOutputType( | ... | @@ -2138,130 +2082,74 @@ fn buildOutputType( |
| 2138 | } else if (mem.eql(u8, arg, "--major-os-version") or | 2082 | } else if (mem.eql(u8, arg, "--major-os-version") or |
| 2139 | mem.eql(u8, arg, "--minor-os-version")) | 2083 | mem.eql(u8, arg, "--minor-os-version")) |
| 2140 | { | 2084 | { |
| 2141 | i += 1; | | |
| 2142 | if (i >= linker_args.items.len) { | | |
| 2143 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2144 | } | | |
| 2145 | // This option does not do anything. | 2085 | // This option does not do anything. |
| | 2086 | _ = linker_args_it.nextOrFatal(); |
| 2146 | } else if (mem.eql(u8, arg, "--major-subsystem-version")) { | 2087 | } else if (mem.eql(u8, arg, "--major-subsystem-version")) { |
| 2147 | i += 1; | 2088 | const major = linker_args_it.nextOrFatal(); |
| 2148 | if (i >= linker_args.items.len) { | | |
| 2149 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2150 | } | | |
| 2151 | | | |
| 2152 | major_subsystem_version = std.fmt.parseUnsigned( | 2089 | major_subsystem_version = std.fmt.parseUnsigned( |
| 2153 | u32, | 2090 | u32, |
| 2154 | linker_args.items[i], | 2091 | major, |
| 2155 | 10, | 2092 | 10, |
| 2156 | ) catch |err| { | 2093 | ) catch |err| { |
| 2157 | fatal("unable to parse major subsystem version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | 2094 | fatal("unable to parse major subsystem version '{s}': {s}", .{ major, @errorName(err) }); |
| 2158 | }; | 2095 | }; |
| 2159 | } else if (mem.eql(u8, arg, "--minor-subsystem-version")) { | 2096 | } else if (mem.eql(u8, arg, "--minor-subsystem-version")) { |
| 2160 | i += 1; | 2097 | const minor = linker_args_it.nextOrFatal(); |
| 2161 | if (i >= linker_args.items.len) { | | |
| 2162 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2163 | } | | |
| 2164 | | | |
| 2165 | minor_subsystem_version = std.fmt.parseUnsigned( | 2098 | minor_subsystem_version = std.fmt.parseUnsigned( |
| 2166 | u32, | 2099 | u32, |
| 2167 | linker_args.items[i], | 2100 | minor, |
| 2168 | 10, | 2101 | 10, |
| 2169 | ) catch |err| { | 2102 | ) catch |err| { |
| 2170 | fatal("unable to parse minor subsystem version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | 2103 | fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) }); |
| 2171 | }; | 2104 | }; |
| 2172 | } else if (mem.eql(u8, arg, "-framework")) { | 2105 | } else if (mem.eql(u8, arg, "-framework")) { |
| 2173 | i += 1; | 2106 | try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{}); |
| 2174 | if (i >= linker_args.items.len) { | | |
| 2175 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2176 | } | | |
| 2177 | try frameworks.put(gpa, linker_args.items[i], .{}); | | |
| 2178 | } else if (mem.eql(u8, arg, "-weak_framework")) { | 2107 | } else if (mem.eql(u8, arg, "-weak_framework")) { |
| 2179 | i += 1; | 2108 | try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .weak = true }); |
| 2180 | if (i >= linker_args.items.len) { | | |
| 2181 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2182 | } | | |
| 2183 | try frameworks.put(gpa, linker_args.items[i], .{ .weak = true }); | | |
| 2184 | } else if (mem.eql(u8, arg, "-needed_framework")) { | 2109 | } else if (mem.eql(u8, arg, "-needed_framework")) { |
| 2185 | i += 1; | 2110 | try frameworks.put(gpa, linker_args_it.nextOrFatal(), .{ .needed = true }); |
| 2186 | if (i >= linker_args.items.len) { | | |
| 2187 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2188 | } | | |
| 2189 | try frameworks.put(gpa, linker_args.items[i], .{ .needed = true }); | | |
| 2190 | } else if (mem.eql(u8, arg, "-needed_library")) { | 2111 | } else if (mem.eql(u8, arg, "-needed_library")) { |
| 2191 | i += 1; | 2112 | try system_libs.put(linker_args_it.nextOrFatal(), .{ .needed = true }); |
| 2192 | if (i >= linker_args.items.len) { | | |
| 2193 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2194 | } | | |
| 2195 | try system_libs.put(linker_args.items[i], .{ .needed = true }); | | |
| 2196 | } else if (mem.startsWith(u8, arg, "-weak-l")) { | 2113 | } else if (mem.startsWith(u8, arg, "-weak-l")) { |
| 2197 | try system_libs.put(arg["-weak-l".len..], .{ .weak = true }); | 2114 | try system_libs.put(arg["-weak-l".len..], .{ .weak = true }); |
| 2198 | } else if (mem.eql(u8, arg, "-weak_library")) { | 2115 | } else if (mem.eql(u8, arg, "-weak_library")) { |
| 2199 | i += 1; | 2116 | try system_libs.put(linker_args_it.nextOrFatal(), .{ .weak = true }); |
| 2200 | if (i >= linker_args.items.len) { | | |
| 2201 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2202 | } | | |
| 2203 | try system_libs.put(linker_args.items[i], .{ .weak = true }); | | |
| 2204 | } else if (mem.eql(u8, arg, "-compatibility_version")) { | 2117 | } else if (mem.eql(u8, arg, "-compatibility_version")) { |
| 2205 | i += 1; | 2118 | const compat_version = linker_args_it.nextOrFatal(); |
| 2206 | if (i >= linker_args.items.len) { | 2119 | compatibility_version = std.builtin.Version.parse(compat_version) catch |err| { |
| 2207 | fatal("expected linker arg after '{s}'", .{arg}); | 2120 | fatal("unable to parse -compatibility_version '{s}': {s}", .{ compat_version, @errorName(err) }); |
| 2208 | } | | |
| 2209 | compatibility_version = std.builtin.Version.parse(linker_args.items[i]) catch |err| { | | |
| 2210 | fatal("unable to parse -compatibility_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2211 | }; | 2121 | }; |
| 2212 | } else if (mem.eql(u8, arg, "-current_version")) { | 2122 | } else if (mem.eql(u8, arg, "-current_version")) { |
| 2213 | i += 1; | 2123 | const curr_version = linker_args_it.nextOrFatal(); |
| 2214 | if (i >= linker_args.items.len) { | 2124 | version = std.builtin.Version.parse(curr_version) catch |err| { |
| 2215 | fatal("expected linker arg after '{s}'", .{arg}); | 2125 | fatal("unable to parse -current_version '{s}': {s}", .{ curr_version, @errorName(err) }); |
| 2216 | } | | |
| 2217 | version = std.builtin.Version.parse(linker_args.items[i]) catch |err| { | | |
| 2218 | fatal("unable to parse -current_version '{s}': {s}", .{ linker_args.items[i], @errorName(err) }); | | |
| 2219 | }; | 2126 | }; |
| 2220 | have_version = true; | 2127 | have_version = true; |
| 2221 | } else if (mem.eql(u8, arg, "--out-implib") or | 2128 | } else if (mem.eql(u8, arg, "--out-implib") or |
| 2222 | mem.eql(u8, arg, "-implib")) | 2129 | mem.eql(u8, arg, "-implib")) |
| 2223 | { | 2130 | { |
| 2224 | i += 1; | 2131 | emit_implib = .{ .yes = linker_args_it.nextOrFatal() }; |
| 2225 | if (i >= linker_args.items.len) { | | |
| 2226 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2227 | } | | |
| 2228 | emit_implib = .{ .yes = linker_args.items[i] }; | | |
| 2229 | emit_implib_arg_provided = true; | 2132 | emit_implib_arg_provided = true; |
| 2230 | } else if (mem.eql(u8, arg, "-undefined")) { | 2133 | } else if (mem.eql(u8, arg, "-undefined")) { |
| 2231 | i += 1; | 2134 | const lookup_type = linker_args_it.nextOrFatal(); |
| 2232 | if (i >= linker_args.items.len) { | 2135 | if (mem.eql(u8, "dynamic_lookup", lookup_type)) { |
| 2233 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2234 | } | | |
| 2235 | if (mem.eql(u8, "dynamic_lookup", linker_args.items[i])) { | | |
| 2236 | linker_allow_shlib_undefined = true; | 2136 | linker_allow_shlib_undefined = true; |
| 2237 | } else if (mem.eql(u8, "error", linker_args.items[i])) { | 2137 | } else if (mem.eql(u8, "error", lookup_type)) { |
| 2238 | linker_allow_shlib_undefined = false; | 2138 | linker_allow_shlib_undefined = false; |
| 2239 | } else { | 2139 | } else { |
| 2240 | fatal("unsupported -undefined option '{s}'", .{linker_args.items[i]}); | 2140 | fatal("unsupported -undefined option '{s}'", .{lookup_type}); |
| 2241 | } | 2141 | } |
| 2242 | } else if (mem.eql(u8, arg, "-install_name")) { | 2142 | } else if (mem.eql(u8, arg, "-install_name")) { |
| 2243 | i += 1; | 2143 | install_name = linker_args_it.nextOrFatal(); |
| 2244 | if (i >= linker_args.items.len) { | | |
| 2245 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2246 | } | | |
| 2247 | install_name = linker_args.items[i]; | | |
| 2248 | } else if (mem.eql(u8, arg, "-force_load")) { | 2144 | } else if (mem.eql(u8, arg, "-force_load")) { |
| 2249 | i += 1; | | |
| 2250 | if (i >= linker_args.items.len) { | | |
| 2251 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2252 | } | | |
| 2253 | try link_objects.append(.{ | 2145 | try link_objects.append(.{ |
| 2254 | .path = linker_args.items[i], | 2146 | .path = linker_args_it.nextOrFatal(), |
| 2255 | .must_link = true, | 2147 | .must_link = true, |
| 2256 | }); | 2148 | }); |
| 2257 | } else if (mem.eql(u8, arg, "-hash-style") or | 2149 | } else if (mem.eql(u8, arg, "-hash-style") or |
| 2258 | mem.eql(u8, arg, "--hash-style")) | 2150 | mem.eql(u8, arg, "--hash-style")) |
| 2259 | { | 2151 | { |
| 2260 | i += 1; | 2152 | const next_arg = linker_args_it.nextOrFatal(); |
| 2261 | if (i >= linker_args.items.len) { | | |
| 2262 | fatal("expected linker arg after '{s}'", .{arg}); | | |
| 2263 | } | | |
| 2264 | const next_arg = linker_args.items[i]; | | |
| 2265 | hash_style = std.meta.stringToEnum(link.HashStyle, next_arg) orelse { | 2153 | hash_style = std.meta.stringToEnum(link.HashStyle, next_arg) orelse { |
| 2266 | fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{ | 2154 | fatal("expected [sysv|gnu|both] after --hash-style, found '{s}'", .{ |
| 2267 | next_arg, | 2155 | next_arg, |
| ... | @@ -3219,6 +3107,7 @@ fn buildOutputType( | ... | @@ -3219,6 +3107,7 @@ fn buildOutputType( |
| 3219 | .link_eh_frame_hdr = link_eh_frame_hdr, | 3107 | .link_eh_frame_hdr = link_eh_frame_hdr, |
| 3220 | .link_emit_relocs = link_emit_relocs, | 3108 | .link_emit_relocs = link_emit_relocs, |
| 3221 | .entry = entry, | 3109 | .entry = entry, |
| | 3110 | .force_undefined_symbols = force_undefined_symbols, |
| 3222 | .stack_size_override = stack_size_override, | 3111 | .stack_size_override = stack_size_override, |
| 3223 | .image_base_override = image_base_override, | 3112 | .image_base_override = image_base_override, |
| 3224 | .strip = strip, | 3113 | .strip = strip, |
| ... | @@ -5295,6 +5184,7 @@ pub const ClangArgIterator = struct { | ... | @@ -5295,6 +5184,7 @@ pub const ClangArgIterator = struct { |
| 5295 | emit_llvm, | 5184 | emit_llvm, |
| 5296 | sysroot, | 5185 | sysroot, |
| 5297 | entry, | 5186 | entry, |
| | 5187 | force_undefined_symbol, |
| 5298 | weak_library, | 5188 | weak_library, |
| 5299 | weak_framework, | 5189 | weak_framework, |
| 5300 | headerpad_max_install_names, | 5190 | headerpad_max_install_names, |