From 317c555a5cdc52612e998d8b4bcbaf730be1a6f1 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 2 Nov 2020 09:04:18 +0100 Subject: [PATCH 1/4] Fix linking issues on BigSur This commit fixes linking issue on macOS 11 BigSur by appending a prefix path to all lib and framework search paths known as `-syslibroot`. The reason this is needed is that in macOS 11, the system libraries and frameworks are no longer readily available in the filesystem. Instead, the new macOS ships with a built-in dynamic linker cache of all system-provided libraries, and hence, when linking with either `lld.ld64` or `ld64`, it is required to pass in `-syslibroot [dir]`. The latter can usually be obtained by invoking `xcrun --show-sdk-path`. With this commit, Zig will do this automatically when compiling natively on macOS. However, it also provides a flag `-syslibroot` which can be used to overwrite the automtically populated value. To summarise, with this change, the user of Zig is not required to generate and append their own syslibroot path. Standard invocations such as `zig build-exe hello.zig` or `zig build` for projects will work out of the box. The only missing bit is `zig cc` and `zig c++` since the addition of the `-syslibroot` option would be a mismatch between the values provided by `clang` itself and Zig's wrapper. --- lib/std/build.zig | 34 +++++++++++++++++++++++++++++----- lib/std/zig/system.zig | 2 ++ lib/std/zig/system/macos.zig | 24 ++++++++++++++++++++++++ src/Compilation.zig | 2 ++ src/link.zig | 2 ++ src/link/MachO.zig | 5 +++++ src/main.zig | 28 +++++++++++++++++++++++++++- 7 files changed, 91 insertions(+), 6 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index a1ac3f88f2589850241b1bdbbb2db44ccaac2dae..98f6730be09ac3430b484eaad76f39a3a071d7fa 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1207,6 +1207,7 @@ pub const LibExeObjStep = struct { name_only_filename: []const u8, strip: bool, lib_paths: ArrayList([]const u8), + syslibroot: ?[]const u8 = null, framework_dirs: ArrayList([]const u8), frameworks: BufSet, verbose_link: bool, @@ -1841,6 +1842,10 @@ pub const LibExeObjStep = struct { self.lib_paths.append(self.builder.dupe(path)) catch unreachable; } + pub fn addSyslibroot(self: *LibExeObjStep, path: []const u8) void { + self.syslibroot = path; + } + pub fn addFrameworkDir(self: *LibExeObjStep, dir_path: []const u8) void { self.framework_dirs.append(self.builder.dupe(dir_path)) catch unreachable; } @@ -1915,11 +1920,18 @@ pub const LibExeObjStep = struct { } } - // Inherit dependencies on darwin frameworks - if (self.target.isDarwin() and !other.isDynamicLibrary()) { - var it = other.frameworks.iterator(); - while (it.next()) |entry| { - self.frameworks.put(entry.key) catch unreachable; + if (self.target.isDarwin()) { + // Inherit syslibroot + if (other.syslibroot) |path| { + self.syslibroot = path; + } + + // Inherit dependencies on darwin frameworks + if (!other.isDynamicLibrary()) { + var it = other.frameworks.iterator(); + while (it.next()) |entry| { + self.frameworks.put(entry.key) catch unreachable; + } } } } @@ -2271,6 +2283,18 @@ pub const LibExeObjStep = struct { } if (self.target.isDarwin()) { + if (self.syslibroot) |path| { + try zig_args.append("-syslibroot"); + try zig_args.append(path); + } else { + if (self.target.isNative()) { + const syslibroot = try std.zig.system.getSDKPath(builder.allocator); + errdefer builder.allocator.free(syslibroot); + try zig_args.append("-syslibroot"); + try zig_args.append(syslibroot); + } + } + for (self.framework_dirs.span()) |dir| { try zig_args.append("-F"); try zig_args.append(dir); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 33ef137eb6c31b4aeab8c4a434c0c75a7309bb7a..b969fe8d96877ce8d1b658b52d8c1bb83e0f1b97 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -17,6 +17,8 @@ const macos = @import("system/macos.zig"); const is_windows = Target.current.os.tag == .windows; +pub const getSDKPath = macos.getSDKPath; + pub const NativePaths = struct { include_dirs: ArrayList([:0]u8), lib_dirs: ArrayList([:0]u8), diff --git a/lib/std/zig/system/macos.zig b/lib/std/zig/system/macos.zig index e0e69b6b8b40ad90061ee4354240aaf3b51a59f5..4347e1404a348264422ae5fdf1e7d1aad609fb58 100644 --- a/lib/std/zig/system/macos.zig +++ b/lib/std/zig/system/macos.zig @@ -4,6 +4,8 @@ // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; pub fn version_from_build(build: []const u8) !std.builtin.Version { // build format: @@ -452,3 +454,25 @@ test "version_from_build" { std.testing.expect(std.mem.eql(u8, sver, pair[1])); } } + +/// Detect SDK path on Darwin. +/// Calls `xcrun --show-sdk-path` which result can be used to specify +/// `-syslibroot` param of the linker. +/// The caller needs to free the resulting path slice. +pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 { + assert(std.Target.current.isDarwin()); + const argv = &[_][]const u8{ "/usr/bin/xcrun", "--show-sdk-path" }; + const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }); + defer { + allocator.free(result.stderr); + allocator.free(result.stdout); + } + if (result.stderr.len != 0) { + std.log.err("unexpected 'xcrun --show-sdk-path' stderr: {}", .{result.stderr}); + } + if (result.term.Exited != 0) { + return error.ProcessTerminated; + } + const syslibroot = mem.trimRight(u8, result.stdout, "\r\n"); + return mem.dupe(allocator, u8, syslibroot); +} diff --git a/src/Compilation.zig b/src/Compilation.zig index 472f367b91cedfa30cb10996400488416edda466..872eb1a78b971ae39410dfcfa67ac5675e886093 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -333,6 +333,7 @@ pub const InitOptions = struct { keep_source_files_loaded: bool = false, clang_argv: []const []const u8 = &[0][]const u8{}, lld_argv: []const []const u8 = &[0][]const u8{}, + syslibroot: ?[]const u8 = null, lib_dirs: []const []const u8 = &[0][]const u8{}, rpath_list: []const []const u8 = &[0][]const u8{}, c_source_files: []const CSourceFile = &[0]CSourceFile{}, @@ -773,6 +774,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, .system_libs = system_libs, + .syslibroot = options.syslibroot, .lib_dirs = options.lib_dirs, .rpath_list = options.rpath_list, .strip = strip, diff --git a/src/link.zig b/src/link.zig index 3f6ceb7ac3e911e100582d5760bb87ff9a5463dc..02433ecde7f9998c510c781e52b5b8bedd7c0f4a 100644 --- a/src/link.zig +++ b/src/link.zig @@ -88,6 +88,8 @@ pub const Options = struct { llvm_cpu_features: ?[*:0]const u8, /// Extra args passed directly to LLD. Ignored when not linking with LLD. extra_lld_args: []const []const u8, + /// Darwin-only. Set the root path to the system libraries and frameworks. + syslibroot: ?[]const u8, objects: []const []const u8, framework_dirs: []const []const u8, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 7344a698f91e33263fce02af9ab492e60d6d53ea..01830c1561333c2aad3eaa0fdece9d374fefe257 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -628,6 +628,11 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { } } + if (self.base.options.syslibroot) |dir| { + try argv.append("-syslibroot"); + try argv.append(dir); + } + for (self.base.options.lib_dirs) |lib_dir| { try argv.append("-L"); try argv.append(lib_dir); diff --git a/src/main.zig b/src/main.zig index 45fcb5ce61b49ee6455362fd44f8cfda84f779f6..87cd3e9dc7ae12a39ef035d461b124473fb4434b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -315,8 +315,9 @@ const usage_build_generic = \\ --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n" \\ --stack [size] Override default stack size \\ --image-base [addr] Set base address for executable image + \\ -syslibroot [dir] (darwin) prepend a prefix to all search paths \\ -framework [name] (darwin) link against framework - \\ -F[dir] (darwin) add search path for frameworks + \\ -F [dir] (darwin) add search path for frameworks \\ \\Test Options: \\ --test-filter [text] Skip tests that do not match filter @@ -492,6 +493,7 @@ fn buildOutputType( var main_pkg_path: ?[]const u8 = null; var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; + var syslibroot: ?[]const u8 = null; var system_libs = std.ArrayList([]const u8).init(gpa); defer system_libs.deinit(); @@ -682,6 +684,10 @@ fn buildOutputType( if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; try lib_dirs.append(args[i]); + } else if (mem.eql(u8, arg, "-syslibroot")) { + if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); + i += 1; + syslibroot = args[i]; } else if (mem.eql(u8, arg, "-F")) { if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; @@ -1380,6 +1386,12 @@ fn buildOutputType( } } + if (cross_target.isNativeOs() and std.Target.current.isDarwin()) { + if (syslibroot == null) { + syslibroot = try std.zig.system.getSDKPath(arena); + } + } + const object_format: std.Target.ObjectFormat = blk: { const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat(); if (mem.eql(u8, ofmt, "elf")) { @@ -1628,6 +1640,7 @@ fn buildOutputType( .rpath_list = rpath_list.items, .c_source_files = c_source_files.items, .link_objects = link_objects.items, + .syslibroot = syslibroot, .framework_dirs = framework_dirs.items, .frameworks = frameworks.items, .system_libs = system_libs.items, @@ -2159,6 +2172,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v var override_lib_dir: ?[]const u8 = null; var override_global_cache_dir: ?[]const u8 = null; var override_local_cache_dir: ?[]const u8 = null; + var syslibroot: ?[]const u8 = null; var child_argv = std.ArrayList([]const u8).init(arena); const argv_index_exe = child_argv.items.len; @@ -2200,6 +2214,11 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v override_global_cache_dir = args[i]; try child_argv.appendSlice(&[_][]const u8{ arg, args[i] }); continue; + } else if (mem.eql(u8, arg, "--syslibroot")) { + if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); + i += 1; + syslibroot = args[i]; + continue; } } try child_argv.append(arg); @@ -2305,6 +2324,12 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v const cross_target: std.zig.CrossTarget = .{}; const target_info = try detectNativeTargetInfo(gpa, cross_target); + if (cross_target.isNativeOs() and target_info.target.isDarwin()) { + if (syslibroot == null) { + syslibroot = try std.zig.system.getSDKPath(arena); + } + } + const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", .target = target_info.target, @@ -2328,6 +2353,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v .target = target_info.target, .is_native_os = cross_target.isNativeOs(), .dynamic_linker = target_info.dynamic_linker.get(), + .syslibroot = syslibroot, .output_mode = .Exe, .root_pkg = &root_pkg, .emit_bin = emit_bin, -- 2.54.0 From 7f5c96378d0fa91265aef7a2d5c33c7953c23b5b Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 2 Nov 2020 18:36:51 +0100 Subject: [PATCH 2/4] Refactor the code according to Andrew's suggestions --- lib/std/build.zig | 34 +++++----------------------------- lib/std/zig/system/macos.zig | 2 +- src/Compilation.zig | 8 ++++++-- src/main.zig | 28 +--------------------------- 4 files changed, 13 insertions(+), 59 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 98f6730be09ac3430b484eaad76f39a3a071d7fa..a1ac3f88f2589850241b1bdbbb2db44ccaac2dae 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1207,7 +1207,6 @@ pub const LibExeObjStep = struct { name_only_filename: []const u8, strip: bool, lib_paths: ArrayList([]const u8), - syslibroot: ?[]const u8 = null, framework_dirs: ArrayList([]const u8), frameworks: BufSet, verbose_link: bool, @@ -1842,10 +1841,6 @@ pub const LibExeObjStep = struct { self.lib_paths.append(self.builder.dupe(path)) catch unreachable; } - pub fn addSyslibroot(self: *LibExeObjStep, path: []const u8) void { - self.syslibroot = path; - } - pub fn addFrameworkDir(self: *LibExeObjStep, dir_path: []const u8) void { self.framework_dirs.append(self.builder.dupe(dir_path)) catch unreachable; } @@ -1920,18 +1915,11 @@ pub const LibExeObjStep = struct { } } - if (self.target.isDarwin()) { - // Inherit syslibroot - if (other.syslibroot) |path| { - self.syslibroot = path; - } - - // Inherit dependencies on darwin frameworks - if (!other.isDynamicLibrary()) { - var it = other.frameworks.iterator(); - while (it.next()) |entry| { - self.frameworks.put(entry.key) catch unreachable; - } + // Inherit dependencies on darwin frameworks + if (self.target.isDarwin() and !other.isDynamicLibrary()) { + var it = other.frameworks.iterator(); + while (it.next()) |entry| { + self.frameworks.put(entry.key) catch unreachable; } } } @@ -2283,18 +2271,6 @@ pub const LibExeObjStep = struct { } if (self.target.isDarwin()) { - if (self.syslibroot) |path| { - try zig_args.append("-syslibroot"); - try zig_args.append(path); - } else { - if (self.target.isNative()) { - const syslibroot = try std.zig.system.getSDKPath(builder.allocator); - errdefer builder.allocator.free(syslibroot); - try zig_args.append("-syslibroot"); - try zig_args.append(syslibroot); - } - } - for (self.framework_dirs.span()) |dir| { try zig_args.append("-F"); try zig_args.append(dir); diff --git a/lib/std/zig/system/macos.zig b/lib/std/zig/system/macos.zig index 4347e1404a348264422ae5fdf1e7d1aad609fb58..6895fa3f3a206d72e2227e42dd4776a23875c4a1 100644 --- a/lib/std/zig/system/macos.zig +++ b/lib/std/zig/system/macos.zig @@ -461,7 +461,7 @@ test "version_from_build" { /// The caller needs to free the resulting path slice. pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 { assert(std.Target.current.isDarwin()); - const argv = &[_][]const u8{ "/usr/bin/xcrun", "--show-sdk-path" }; + const argv = &[_][]const u8{ "xcrun", "--show-sdk-path" }; const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }); defer { allocator.free(result.stderr); diff --git a/src/Compilation.zig b/src/Compilation.zig index 872eb1a78b971ae39410dfcfa67ac5675e886093..55b1c0510417e5fbf7d926d2a42f3f4675fe82f8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -333,7 +333,6 @@ pub const InitOptions = struct { keep_source_files_loaded: bool = false, clang_argv: []const []const u8 = &[0][]const u8{}, lld_argv: []const []const u8 = &[0][]const u8{}, - syslibroot: ?[]const u8 = null, lib_dirs: []const []const u8 = &[0][]const u8{}, rpath_list: []const []const u8 = &[0][]const u8{}, c_source_files: []const CSourceFile = &[0]CSourceFile{}, @@ -473,6 +472,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :blk false; }; + const syslibroot = if (use_lld and options.is_native_os and options.target.isDarwin()) blk: { + const syslibroot_path = try std.zig.system.getSDKPath(arena); + break :blk syslibroot_path; + } else null; + const link_libc = options.link_libc or target_util.osRequiresLibC(options.target); const must_dynamic_link = dl: { @@ -774,7 +778,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .frameworks = options.frameworks, .framework_dirs = options.framework_dirs, .system_libs = system_libs, - .syslibroot = options.syslibroot, + .syslibroot = syslibroot, .lib_dirs = options.lib_dirs, .rpath_list = options.rpath_list, .strip = strip, diff --git a/src/main.zig b/src/main.zig index 87cd3e9dc7ae12a39ef035d461b124473fb4434b..45fcb5ce61b49ee6455362fd44f8cfda84f779f6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -315,9 +315,8 @@ const usage_build_generic = \\ --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n" \\ --stack [size] Override default stack size \\ --image-base [addr] Set base address for executable image - \\ -syslibroot [dir] (darwin) prepend a prefix to all search paths \\ -framework [name] (darwin) link against framework - \\ -F [dir] (darwin) add search path for frameworks + \\ -F[dir] (darwin) add search path for frameworks \\ \\Test Options: \\ --test-filter [text] Skip tests that do not match filter @@ -493,7 +492,6 @@ fn buildOutputType( var main_pkg_path: ?[]const u8 = null; var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; - var syslibroot: ?[]const u8 = null; var system_libs = std.ArrayList([]const u8).init(gpa); defer system_libs.deinit(); @@ -684,10 +682,6 @@ fn buildOutputType( if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; try lib_dirs.append(args[i]); - } else if (mem.eql(u8, arg, "-syslibroot")) { - if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); - i += 1; - syslibroot = args[i]; } else if (mem.eql(u8, arg, "-F")) { if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; @@ -1386,12 +1380,6 @@ fn buildOutputType( } } - if (cross_target.isNativeOs() and std.Target.current.isDarwin()) { - if (syslibroot == null) { - syslibroot = try std.zig.system.getSDKPath(arena); - } - } - const object_format: std.Target.ObjectFormat = blk: { const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat(); if (mem.eql(u8, ofmt, "elf")) { @@ -1640,7 +1628,6 @@ fn buildOutputType( .rpath_list = rpath_list.items, .c_source_files = c_source_files.items, .link_objects = link_objects.items, - .syslibroot = syslibroot, .framework_dirs = framework_dirs.items, .frameworks = frameworks.items, .system_libs = system_libs.items, @@ -2172,7 +2159,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v var override_lib_dir: ?[]const u8 = null; var override_global_cache_dir: ?[]const u8 = null; var override_local_cache_dir: ?[]const u8 = null; - var syslibroot: ?[]const u8 = null; var child_argv = std.ArrayList([]const u8).init(arena); const argv_index_exe = child_argv.items.len; @@ -2214,11 +2200,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v override_global_cache_dir = args[i]; try child_argv.appendSlice(&[_][]const u8{ arg, args[i] }); continue; - } else if (mem.eql(u8, arg, "--syslibroot")) { - if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); - i += 1; - syslibroot = args[i]; - continue; } } try child_argv.append(arg); @@ -2324,12 +2305,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v const cross_target: std.zig.CrossTarget = .{}; const target_info = try detectNativeTargetInfo(gpa, cross_target); - if (cross_target.isNativeOs() and target_info.target.isDarwin()) { - if (syslibroot == null) { - syslibroot = try std.zig.system.getSDKPath(arena); - } - } - const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", .target = target_info.target, @@ -2353,7 +2328,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v .target = target_info.target, .is_native_os = cross_target.isNativeOs(), .dynamic_linker = target_info.dynamic_linker.get(), - .syslibroot = syslibroot, .output_mode = .Exe, .root_pkg = &root_pkg, .emit_bin = emit_bin, -- 2.54.0 From f42ebd1b0a1394129e42847a694e2e55d17d4ca9 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 2 Nov 2020 18:56:08 +0100 Subject: [PATCH 3/4] Update src/Compilation.zig Co-authored-by: Andrew Kelley --- src/Compilation.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 55b1c0510417e5fbf7d926d2a42f3f4675fe82f8..8c7ec97b2d75b03c568c04c9dda915b669d9881e 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -472,7 +472,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :blk false; }; - const syslibroot = if (use_lld and options.is_native_os and options.target.isDarwin()) blk: { + const syslibroot = if (build_options.have_llvm and use_lld and options.is_native_os and options.target.isDarwin()) blk: { const syslibroot_path = try std.zig.system.getSDKPath(arena); break :blk syslibroot_path; } else null; -- 2.54.0 From 6ecefd590360be0484d766d18a23e19c6c7325e6 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 2 Nov 2020 19:06:23 +0100 Subject: [PATCH 4/4] Add std.Target.current.isDarwin() to exclude non-macs in comptime --- src/Compilation.zig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 8c7ec97b2d75b03c568c04c9dda915b669d9881e..d4289fad346cba294b01ef197cff19601a39fabb 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -472,9 +472,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :blk false; }; - const syslibroot = if (build_options.have_llvm and use_lld and options.is_native_os and options.target.isDarwin()) blk: { - const syslibroot_path = try std.zig.system.getSDKPath(arena); - break :blk syslibroot_path; + const syslibroot = if (build_options.have_llvm and comptime std.Target.current.isDarwin()) outer: { + const path = if (use_lld and options.is_native_os and options.target.isDarwin()) inner: { + const syslibroot_path = try std.zig.system.getSDKPath(arena); + break :inner syslibroot_path; + } else null; + break :outer path; } else null; const link_libc = options.link_libc or target_util.osRequiresLibC(options.target); -- 2.54.0