diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-02 09:04:18 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-02 17:06:09 +0100 |
| commit | 317c555a5cdc52612e998d8b4bcbaf730be1a6f1 (patch) | |
| tree | 0c414e11cfb2de91e0c7ee6485d784f61dc4330a /lib/std | |
| parent | 909aae8153e7ac71197bc9f864e4ceb2793317f2 (diff) | |
| download | zig-317c555a5cdc52612e998d8b4bcbaf730be1a6f1.tar.gz zig-317c555a5cdc52612e998d8b4bcbaf730be1a6f1.zip | |
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.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/build.zig | 34 | ||||
| -rw-r--r-- | lib/std/zig/system.zig | 2 | ||||
| -rw-r--r-- | lib/std/zig/system/macos.zig | 24 |
3 files changed, 55 insertions, 5 deletions
diff --git a/lib/std/build.zig b/lib/std/build.zig index a1ac3f88f2..98f6730be0 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 33ef137eb6..b969fe8d96 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 e0e69b6b8b..4347e1404a 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); +} |
