From 91a35e1a922e865ca0e9beb43a2be2c5552fc494 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 20 Dec 2020 11:45:48 +0100 Subject: [PATCH] Detect native iframework dirs on macOS This commit adds default search paths for system frameworks on macOS while also adding `-isysroot` for OS versions at least BigSur. Since BigSur (11.0.1), neither headers nor libs exist in standard root locations (`/usr/include`, `/System/Library/Frameworks`). Instead, they are now exclusively part of the installed developer toolchain (either via XCode.app or CLT), and specifying `-isysroot` allows us to keep using universal search paths such as `/System/Library/Frameworks` while only changing the include flag from `-iframework` to `-iframeworkwithsysroot`. --- lib/std/zig/system.zig | 29 +++++++++++++++++++++++++++-- src/Compilation.zig | 7 +------ src/main.zig | 26 +++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 574ccfb32d80..09fc15c8bafa 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -22,6 +22,7 @@ pub const getSDKPath = macos.getSDKPath; pub const NativePaths = struct { include_dirs: ArrayList([:0]u8), lib_dirs: ArrayList([:0]u8), + framework_dirs: ArrayList([:0]u8), rpaths: ArrayList([:0]u8), warnings: ArrayList([:0]u8), @@ -29,6 +30,7 @@ pub const NativePaths = struct { var self: NativePaths = .{ .include_dirs = ArrayList([:0]u8).init(allocator), .lib_dirs = ArrayList([:0]u8).init(allocator), + .framework_dirs = ArrayList([:0]u8).init(allocator), .rpaths = ArrayList([:0]u8).init(allocator), .warnings = ArrayList([:0]u8).init(allocator), }; @@ -88,6 +90,19 @@ pub const NativePaths = struct { return self; } + if (comptime Target.current.isDarwin()) { + try self.addIncludeDir("/usr/include"); + try self.addIncludeDir("/usr/local/include"); + + try self.addLibDir("/usr/lib"); + try self.addLibDir("/usr/local/lib"); + + try self.addFrameworkDir("/Library/Frameworks"); + try self.addFrameworkDir("/System/Library/Frameworks"); + + return self; + } + if (!is_windows) { const triple = try Target.current.linuxTriple(allocator); const qual = Target.current.cpu.arch.ptrBitWidth(); @@ -122,6 +137,7 @@ pub const NativePaths = struct { pub fn deinit(self: *NativePaths) void { deinitArray(&self.include_dirs); deinitArray(&self.lib_dirs); + deinitArray(&self.framework_dirs); deinitArray(&self.rpaths); deinitArray(&self.warnings); self.* = undefined; @@ -158,6 +174,16 @@ pub const NativePaths = struct { return self.appendArray(&self.warnings, s); } + pub fn addFrameworkDir(self: *NativePaths, s: []const u8) !void { + return self.appendArray(&self.framework_dirs, s); + } + + pub fn addFrameworkDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { + const item = try std.fmt.allocPrint0(self.framework_dirs.allocator, fmt, args); + errdefer self.framework_dirs.allocator.free(item); + try self.framework_dirs.append(item); + } + pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args); errdefer self.warnings.allocator.free(item); @@ -237,8 +263,7 @@ pub const NativeTargetInfo = struct { // `---` `` ``--> Sub-version (Starting from Windows 10 onwards) // \ `--> Service pack (Always zero in the constants defined) // `--> OS version (Major & minor) - const os_ver: u16 = - @intCast(u16, version_info.dwMajorVersion & 0xff) << 8 | + const os_ver: u16 = @intCast(u16, version_info.dwMajorVersion & 0xff) << 8 | @intCast(u16, version_info.dwMinorVersion & 0xff); const sp_ver: u8 = 0; const sub_ver: u8 = if (os_ver >= 0x0A00) subver: { diff --git a/src/Compilation.zig b/src/Compilation.zig index cd3db84ec286..4fd0e54aa8d3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2079,12 +2079,6 @@ pub fn addCCArgs( try argv.append("-ffunction-sections"); } - try argv.ensureCapacity(argv.items.len + comp.bin_file.options.framework_dirs.len * 2); - for (comp.bin_file.options.framework_dirs) |framework_dir| { - argv.appendAssumeCapacity("-iframework"); - argv.appendAssumeCapacity(framework_dir); - } - if (comp.bin_file.options.link_libcpp) { const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "libcxx", "include", @@ -2894,6 +2888,7 @@ fn buildOutputFromZig( .directory = null, // Put it in the cache directory. .basename = bin_basename, }; + const sub_compilation = try Compilation.create(comp.gpa, .{ .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, diff --git a/src/main.zig b/src/main.zig index 247f8327f0f9..096fa86c75af 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1436,11 +1436,35 @@ fn buildOutputType( for (paths.warnings.items) |warning| { warn("{}", .{warning}); } + + const has_sysroot = if (comptime std.Target.current.isDarwin()) outer: { + const at_least_big_sur = target_info.target.os.getVersionRange().semver.min.major >= 11; + if (at_least_big_sur) { + const sdk_path = try std.zig.system.getSDKPath(arena); + try clang_argv.ensureCapacity(clang_argv.items.len + 2); + clang_argv.appendAssumeCapacity("-isysroot"); + clang_argv.appendAssumeCapacity(sdk_path); + break :outer true; + } + break :outer false; + } else false; + try clang_argv.ensureCapacity(clang_argv.items.len + paths.include_dirs.items.len * 2); + const isystem_flag = if (has_sysroot) "-iwithsysroot" else "-isystem"; for (paths.include_dirs.items) |include_dir| { - clang_argv.appendAssumeCapacity("-isystem"); + clang_argv.appendAssumeCapacity(isystem_flag); clang_argv.appendAssumeCapacity(include_dir); } + + try clang_argv.ensureCapacity(clang_argv.items.len + paths.framework_dirs.items.len * 2); + try framework_dirs.ensureCapacity(framework_dirs.items.len + paths.framework_dirs.items.len); + const iframework_flag = if (has_sysroot) "-iframeworkwithsysroot" else "-iframework"; + for (paths.framework_dirs.items) |framework_dir| { + clang_argv.appendAssumeCapacity(iframework_flag); + clang_argv.appendAssumeCapacity(framework_dir); + framework_dirs.appendAssumeCapacity(framework_dir); + } + for (paths.lib_dirs.items) |lib_dir| { try lib_dirs.append(lib_dir); }