| author | |
| committer | |
| log | 16228e87d6d7d8929305083e8c76168603780f5f |
| tree | f535e98a621b25ca4d0e271c1ae61fcf028125c5 |
| parent | 3e4f3a1924150e22e0ca87e906681ebadcf8433e |
| signature |
This feature is necessary for cross-compiling code that dynamically
links system libraries, at least with the current feature set of lld.5 files changed, 46 insertions(+), 24 deletions(-)
src/Compilation.zig+25-17| ... | ... | @@ -612,6 +612,7 @@ pub const InitOptions = struct { |
| 612 | 612 | output_mode: std.builtin.OutputMode, |
| 613 | 613 | thread_pool: *ThreadPool, |
| 614 | 614 | dynamic_linker: ?[]const u8 = null, |
| 615 | sysroot: ?[]const u8 = null, | |
| 615 | 616 | /// `null` means to not emit a binary file. |
| 616 | 617 | emit_bin: ?EmitLoc, |
| 617 | 618 | /// `null` means to not emit a C header file. |
| ... | ... | @@ -868,25 +869,32 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 868 | 869 | break :blk false; |
| 869 | 870 | }; |
| 870 | 871 | |
| 871 | const DarwinOptions = struct { | |
| 872 | syslibroot: ?[]const u8 = null, | |
| 873 | system_linker_hack: bool = false, | |
| 872 | const darwin_can_use_system_linker_and_sdk = | |
| 873 | // comptime conditions | |
| 874 | ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and | |
| 875 | // runtime conditions | |
| 876 | (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin())); | |
| 877 | ||
| 878 | const darwin_system_linker_hack = blk: { | |
| 879 | if (darwin_can_use_system_linker_and_sdk) { | |
| 880 | break :blk std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null; | |
| 881 | } else { | |
| 882 | break :blk false; | |
| 883 | } | |
| 874 | 884 | }; |
| 875 | 885 | |
| 876 | const darwin_options: DarwinOptions = if (build_options.have_llvm and comptime std.Target.current.isDarwin()) outer: { | |
| 877 | const opts: DarwinOptions = if (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin()) inner: { | |
| 886 | const sysroot = blk: { | |
| 887 | if (options.sysroot) |sysroot| { | |
| 888 | break :blk sysroot; | |
| 889 | } else if (darwin_can_use_system_linker_and_sdk) { | |
| 878 | 890 | // TODO Revisit this targeting versions lower than macOS 11 when LLVM 12 is out. |
| 879 | 891 | // See https://github.com/ziglang/zig/issues/6996 |
| 880 | 892 | const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11; |
| 881 | const syslibroot = if (at_least_big_sur) try std.zig.system.getSDKPath(arena) else null; | |
| 882 | const system_linker_hack = std.os.getenv("ZIG_SYSTEM_LINKER_HACK") != null; | |
| 883 | break :inner .{ | |
| 884 | .syslibroot = syslibroot, | |
| 885 | .system_linker_hack = system_linker_hack, | |
| 886 | }; | |
| 887 | } else .{}; | |
| 888 | break :outer opts; | |
| 889 | } else .{}; | |
| 893 | break :blk if (at_least_big_sur) try std.zig.system.getSDKPath(arena) else null; | |
| 894 | } else { | |
| 895 | break :blk null; | |
| 896 | } | |
| 897 | }; | |
| 890 | 898 | |
| 891 | 899 | const lto = blk: { |
| 892 | 900 | if (options.want_lto) |explicit| { |
| ... | ... | @@ -897,7 +905,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 897 | 905 | break :blk false; |
| 898 | 906 | } else if (options.c_source_files.len == 0) { |
| 899 | 907 | break :blk false; |
| 900 | } else if (darwin_options.system_linker_hack) { | |
| 908 | } else if (darwin_system_linker_hack) { | |
| 901 | 909 | break :blk false; |
| 902 | 910 | } else switch (options.output_mode) { |
| 903 | 911 | .Lib, .Obj => break :blk false, |
| ... | ... | @@ -1273,13 +1281,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1273 | 1281 | .module = module, |
| 1274 | 1282 | .target = options.target, |
| 1275 | 1283 | .dynamic_linker = options.dynamic_linker, |
| 1284 | .sysroot = sysroot, | |
| 1276 | 1285 | .output_mode = options.output_mode, |
| 1277 | 1286 | .link_mode = link_mode, |
| 1278 | 1287 | .object_format = ofmt, |
| 1279 | 1288 | .optimize_mode = options.optimize_mode, |
| 1280 | 1289 | .use_lld = use_lld, |
| 1281 | 1290 | .use_llvm = use_llvm, |
| 1282 | .system_linker_hack = darwin_options.system_linker_hack, | |
| 1291 | .system_linker_hack = darwin_system_linker_hack, | |
| 1283 | 1292 | .link_libc = link_libc, |
| 1284 | 1293 | .link_libcpp = link_libcpp, |
| 1285 | 1294 | .link_libunwind = link_libunwind, |
| ... | ... | @@ -1287,7 +1296,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1287 | 1296 | .frameworks = options.frameworks, |
| 1288 | 1297 | .framework_dirs = options.framework_dirs, |
| 1289 | 1298 | .system_libs = system_libs, |
| 1290 | .syslibroot = darwin_options.syslibroot, | |
| 1291 | 1299 | .lib_dirs = options.lib_dirs, |
| 1292 | 1300 | .rpath_list = options.rpath_list, |
| 1293 | 1301 | .strip = strip, |
src/link.zig+2-2| ... | ... | @@ -37,6 +37,8 @@ pub const Options = struct { |
| 37 | 37 | /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. |
| 38 | 38 | module: ?*Module, |
| 39 | 39 | dynamic_linker: ?[]const u8, |
| 40 | /// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin) | |
| 41 | sysroot: ?[]const u8, | |
| 40 | 42 | /// Used for calculating how much space to reserve for symbols in case the binary file |
| 41 | 43 | /// does not already have a symbol table. |
| 42 | 44 | symbol_count_hint: u64 = 32, |
| ... | ... | @@ -103,8 +105,6 @@ pub const Options = struct { |
| 103 | 105 | llvm_cpu_features: ?[*:0]const u8, |
| 104 | 106 | /// Extra args passed directly to LLD. Ignored when not linking with LLD. |
| 105 | 107 | extra_lld_args: []const []const u8, |
| 106 | /// Darwin-only. Set the root path to the system libraries and frameworks. | |
| 107 | syslibroot: ?[]const u8, | |
| 108 | 108 | |
| 109 | 109 | objects: []const []const u8, |
| 110 | 110 | framework_dirs: []const []const u8, |
src/link/Elf.zig+5| ... | ... | @@ -1354,6 +1354,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1354 | 1354 | man.hash.add(allow_shlib_undefined); |
| 1355 | 1355 | man.hash.add(self.base.options.bind_global_refs_locally); |
| 1356 | 1356 | man.hash.add(self.base.options.tsan); |
| 1357 | man.hash.addOptionalBytes(self.base.options.sysroot); | |
| 1357 | 1358 | |
| 1358 | 1359 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 1359 | 1360 | _ = try man.hit(); |
| ... | ... | @@ -1423,6 +1424,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1423 | 1424 | |
| 1424 | 1425 | try argv.append("-error-limit=0"); |
| 1425 | 1426 | |
| 1427 | if (self.base.options.sysroot) |sysroot| { | |
| 1428 | try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot})); | |
| 1429 | } | |
| 1430 | ||
| 1426 | 1431 | if (self.base.options.lto) { |
| 1427 | 1432 | switch (self.base.options.optimize_mode) { |
| 1428 | 1433 | .Debug => {}, |
src/link/MachO.zig+4-4| ... | ... | @@ -590,7 +590,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 590 | 590 | man.hash.add(allow_shlib_undefined); |
| 591 | 591 | man.hash.add(self.base.options.bind_global_refs_locally); |
| 592 | 592 | man.hash.add(self.base.options.system_linker_hack); |
| 593 | man.hash.addOptionalBytes(self.base.options.syslibroot); | |
| 593 | man.hash.addOptionalBytes(self.base.options.sysroot); | |
| 594 | 594 | |
| 595 | 595 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 596 | 596 | _ = try man.hit(); |
| ... | ... | @@ -720,7 +720,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 720 | 720 | for (self.base.options.lib_dirs) |path| { |
| 721 | 721 | if (fs.path.isAbsolute(path)) { |
| 722 | 722 | var candidates = std.ArrayList([]const u8).init(arena); |
| 723 | if (self.base.options.syslibroot) |syslibroot| { | |
| 723 | if (self.base.options.sysroot) |syslibroot| { | |
| 724 | 724 | const full_path = try fs.path.join(arena, &[_][]const u8{ syslibroot, path }); |
| 725 | 725 | try candidates.append(full_path); |
| 726 | 726 | } |
| ... | ... | @@ -813,7 +813,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 813 | 813 | try argv.append("zig"); |
| 814 | 814 | try argv.append("ld"); |
| 815 | 815 | |
| 816 | if (self.base.options.syslibroot) |syslibroot| { | |
| 816 | if (self.base.options.sysroot) |syslibroot| { | |
| 817 | 817 | try argv.append("-syslibroot"); |
| 818 | 818 | try argv.append(syslibroot); |
| 819 | 819 | } |
| ... | ... | @@ -959,7 +959,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 959 | 959 | } |
| 960 | 960 | } |
| 961 | 961 | |
| 962 | if (self.base.options.syslibroot) |dir| { | |
| 962 | if (self.base.options.sysroot) |dir| { | |
| 963 | 963 | try argv.append("-syslibroot"); |
| 964 | 964 | try argv.append(dir); |
| 965 | 965 | } |
src/main.zig+10-1| ... | ... | @@ -377,6 +377,7 @@ const usage_build_generic = |
| 377 | 377 | \\ -T[script], --script [script] Use a custom linker script |
| 378 | 378 | \\ --version-script [path] Provide a version .map file |
| 379 | 379 | \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) |
| 380 | \\ --sysroot [path] Set the system root directory (usually /) | |
| 380 | 381 | \\ --version [ver] Dynamic library semver |
| 381 | 382 | \\ -fsoname[=name] (Linux) Override the default SONAME value |
| 382 | 383 | \\ -fno-soname (Linux) Disable emitting a SONAME |
| ... | ... | @@ -602,6 +603,7 @@ fn buildOutputType( |
| 602 | 603 | var link_eh_frame_hdr = false; |
| 603 | 604 | var link_emit_relocs = false; |
| 604 | 605 | var each_lib_rpath: ?bool = null; |
| 606 | var sysroot: ?[]const u8 = null; | |
| 605 | 607 | var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC"); |
| 606 | 608 | var machine_code_model: std.builtin.CodeModel = .default; |
| 607 | 609 | var runtime_args_start: ?usize = null; |
| ... | ... | @@ -859,6 +861,10 @@ fn buildOutputType( |
| 859 | 861 | if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); |
| 860 | 862 | i += 1; |
| 861 | 863 | target_dynamic_linker = args[i]; |
| 864 | } else if (mem.eql(u8, arg, "--sysroot")) { | |
| 865 | if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); | |
| 866 | i += 1; | |
| 867 | sysroot = args[i]; | |
| 862 | 868 | } else if (mem.eql(u8, arg, "--libc")) { |
| 863 | 869 | if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); |
| 864 | 870 | i += 1; |
| ... | ... | @@ -1621,7 +1627,9 @@ fn buildOutputType( |
| 1621 | 1627 | want_native_include_dirs = true; |
| 1622 | 1628 | } |
| 1623 | 1629 | |
| 1624 | if (cross_target.isNativeOs() and (system_libs.items.len != 0 or want_native_include_dirs)) { | |
| 1630 | if (sysroot == null and cross_target.isNativeOs() and | |
| 1631 | (system_libs.items.len != 0 or want_native_include_dirs)) | |
| 1632 | { | |
| 1625 | 1633 | const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { |
| 1626 | 1634 | fatal("unable to detect native system paths: {s}", .{@errorName(err)}); |
| 1627 | 1635 | }; |
| ... | ... | @@ -1898,6 +1906,7 @@ fn buildOutputType( |
| 1898 | 1906 | .is_native_os = cross_target.isNativeOs(), |
| 1899 | 1907 | .is_native_abi = cross_target.isNativeAbi(), |
| 1900 | 1908 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 1909 | .sysroot = sysroot, | |
| 1901 | 1910 | .output_mode = output_mode, |
| 1902 | 1911 | .root_pkg = root_pkg, |
| 1903 | 1912 | .emit_bin = emit_bin_loc, |