From 5a851a2a28dd78e7df3323c4f69d490fafeacfde Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Wed, 26 Oct 2022 18:29:26 +0330 Subject: [PATCH] system_sdk: better target check --- libs/glfw/system_sdk.zig | 322 +++++++++++++++++-------------- libs/gpu-dawn/src/dawn/dummy.zig | 0 2 files changed, 179 insertions(+), 143 deletions(-) delete mode 100644 libs/gpu-dawn/src/dawn/dummy.zig diff --git a/libs/glfw/system_sdk.zig b/libs/glfw/system_sdk.zig index c32bd8b9..8833f4b1 100644 --- a/libs/glfw/system_sdk.zig +++ b/libs/glfw/system_sdk.zig @@ -33,28 +33,88 @@ const std = @import("std"); const Builder = std.build.Builder; pub const Options = struct { - /// The github org to find repositories in. - github_org: []const u8 = "hexops", + pub const Sdk = struct { + name: []const u8, + git_addr: []const u8, + git_revision: []const u8, + cpu_arch: []const std.Target.Cpu.Arch, + os_tag: std.Target.Os.Tag, + os_version: std.Target.Os.TaggedVersionRange, + }; - /// The MacOS 12 SDK repository name. - macos_sdk_12: []const u8 = "sdk-macos-12.0", - macos_sdk_12_revision: []const u8 = "14613b4917c7059dad8f3789f55bb13a2548f83d", - - /// The MacOS 11 SDK repository name. - macos_sdk_11: []const u8 = "sdk-macos-11.3", - macos_sdk_11_revision: []const u8 = "ccbaae84cc39469a6792108b24480a4806e09d59", - - /// The Linux x86-64 SDK repository name. - linux_x86_64: []const u8 = "sdk-linux-x86_64", - linux_x86_64_revision: []const u8 = "b65ab8630839c2f6cf016e1ab1debcc155c7cd52", - - /// The Linux aarch64 SDK repository name. - linux_aarch64: []const u8 = "sdk-linux-aarch64", - linux_aarch64_revision: []const u8 = "555b6cfa32447a88f2439d144f13f56f8c88cb5a", - - /// The Windows x86-64 SDK repository name. - windows_x86_64: []const u8 = "sdk-windows-x86_64", - windows_x86_64_revision: []const u8 = "13dcda7fe3f1aec0fc6130527226ad7ae0f4b792", + sdk_list: []const Sdk = &.{ + .{ + .name = "sdk-macos-12.0", + .git_addr = "https://github.com/hexops/sdk-macos-12.0", + .git_revision = "14613b4917c7059dad8f3789f55bb13a2548f83d", + .cpu_arch = &.{ .aarch64, .x86_64 }, + .os_tag = .macos, + .os_version = .{ + .semver = .{ + .min = .{ .major = 12, .minor = 0 }, + .max = .{ .major = 12, .minor = std.math.maxInt(u32) }, + }, + }, + }, + .{ + .name = "sdk-macos-11.3", + .git_addr = "https://github.com/hexops/sdk-macos-11.3", + .git_revision = "ccbaae84cc39469a6792108b24480a4806e09d59", + .cpu_arch = &.{ .aarch64, .x86_64 }, + .os_tag = .macos, + .os_version = .{ + .semver = .{ + .min = .{ .major = 11, .minor = 3 }, + .max = .{ .major = 11, .minor = std.math.maxInt(u32) }, + }, + }, + }, + .{ + .name = "sdk-linux-x86_64", + .git_addr = "https://github.com/hexops/sdk-linux-x86_64", + .git_revision = "b65ab8630839c2f6cf016e1ab1debcc155c7cd52", + .cpu_arch = &.{.x86_64}, + .os_tag = .linux, + .os_version = .{ + .linux = .{ + .range = .{ + .min = .{ .major = 3, .minor = 16 }, + .max = .{ .major = 5, .minor = std.math.maxInt(u32) }, + }, + .glibc = .{ .major = 0, .minor = 0 }, + }, + }, + }, + .{ + .name = "sdk-linux-aarch64", + .git_addr = "https://github.com/hexops/sdk-linux-aarch64", + .git_revision = "555b6cfa32447a88f2439d144f13f56f8c88cb5a", + .cpu_arch = &.{.aarch64}, + .os_tag = .linux, + .os_version = .{ + .linux = .{ + .range = .{ + .min = .{ .major = 3, .minor = 16 }, + .max = .{ .major = 5, .minor = std.math.maxInt(u32) }, + }, + .glibc = .{ .major = 0, .minor = 0 }, + }, + }, + }, + .{ + .name = "sdk-windows-x86_64", + .git_addr = "https://github.com/hexops/sdk-windows-x86_64", + .git_revision = "13dcda7fe3f1aec0fc6130527226ad7ae0f4b792", + .cpu_arch = &.{.x86_64}, + .os_tag = .windows, + .os_version = .{ + .windows = .{ + .min = .win7, + .max = std.Target.Os.WindowsVersion.latest, + }, + }, + }, + }, /// If true, the Builder.sysroot will set to the SDK path. This has the drawback of preventing /// you from including headers, libraries, etc. from outside the SDK generally. However, it can @@ -64,128 +124,104 @@ pub const Options = struct { }; pub fn include(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void { - const target = (std.zig.system.NativeTargetInfo.detect(step.target) catch unreachable).target; - switch (target.os.tag) { - .windows => includeSdkWindowsX8664(b, step, options), - .macos => includeSdkMacOS(b, step, options), - else => switch (target.cpu.arch) { // Assume Linux-like for now - .aarch64 => includeSdkLinuxAarch64(b, step, options), - else => includeSdkLinuxX8664(b, step, options), // Assume x86-64 for now - }, + const target = step.target_info.target; + // var best_sdk: ?Options.Sdk = null; + for (options.sdk_list) |sdk| { + if (!std.mem.containsAtLeast(std.Target.Cpu.Arch, sdk.cpu_arch, 1, &.{target.cpu.arch})) + continue; + if (sdk.os_tag != target.os.tag) continue; + + const version_ok = switch (sdk.os_version) { + .semver => |vr| vr.includesVersion(target.os.version_range.semver.min) or vr.includesVersion(target.os.version_range.semver.max), + .linux => |vr| vr.includesVersion(target.os.version_range.linux.range.min) or vr.includesVersion(target.os.version_range.linux.range.max), + .windows => |vr| vr.includesVersion(target.os.version_range.windows.min) or vr.includesVersion(target.os.version_range.windows.max), + .none => false, + }; + if (!version_ok) continue; + + const sdk_root_dir = getSdkRoot(b.allocator, sdk) catch unreachable; + if (options.set_sysroot) { + // We have no sysroot for Windows, but we still set one to prevent inclusion of other system + // libs (if set_sysroot is set, don't want to accidentally depend on system libs.) + b.sysroot = sdk_root_dir; + } + return switch (target.os.tag) { + .windows => { + const sdk_includes = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "include" }) catch unreachable; + const sdk_libs = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "lib" }) catch unreachable; + defer { + b.allocator.free(sdk_includes); + b.allocator.free(sdk_libs); + } + step.addIncludePath(sdk_includes); + step.addLibraryPath(sdk_libs); + }, + .macos => { + if (options.set_sysroot) { + step.addFrameworkPath("/System/Library/Frameworks"); + step.addSystemIncludePath("/usr/include"); + step.addLibraryPath("/usr/lib"); + return; + } + + const sdk_framework_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/System/Library/Frameworks" }) catch unreachable; + const sdk_include_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/include" }) catch unreachable; + const sdk_lib_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib" }) catch unreachable; + defer { + b.allocator.free(sdk_framework_dir); + b.allocator.free(sdk_include_dir); + b.allocator.free(sdk_lib_dir); + } + step.addFrameworkPath(sdk_framework_dir); + step.addSystemIncludePath(sdk_include_dir); + step.addLibraryPath(sdk_lib_dir); + }, + .linux => { + if (options.set_sysroot) return; + + const sdk_root_includes = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/include" }) catch unreachable; + const wayland_protocols_include = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/share/wayland-generated" }) catch unreachable; + const sdk_root_libs = switch (target.cpu.arch) { + .x86_64 => std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib/x86_64-linux-gnu" }) catch unreachable, + .aarch64 => std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib/aarch64-linux-gnu" }) catch unreachable, + else => break, + }; + defer { + b.allocator.free(sdk_root_includes); + b.allocator.free(wayland_protocols_include); + b.allocator.free(sdk_root_libs); + } + step.addSystemIncludePath(sdk_root_includes); + step.addSystemIncludePath(wayland_protocols_include); + step.addLibraryPath(sdk_root_libs); + }, + else => unreachable, + }; } + + // TODO(error_handling) + std.debug.print("Unsupported Target!\n", .{}); + unreachable; } -fn includeSdkMacOS(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void { - const target = (std.zig.system.NativeTargetInfo.detect(step.target) catch unreachable).target; - const mac_12 = target.os.version_range.semver.isAtLeast(.{ .major = 12, .minor = 0 }) orelse false; - const sdk_name = if (mac_12) options.macos_sdk_12 else options.macos_sdk_11; - const sdk_revision = if (mac_12) options.macos_sdk_12_revision else options.macos_sdk_11_revision; - const sdk_root_dir = getSdkRoot(b.allocator, step, options.github_org, sdk_name, sdk_revision) catch unreachable; - - if (options.set_sysroot) { - step.addFrameworkPath("/System/Library/Frameworks"); - step.addSystemIncludePath("/usr/include"); - step.addLibraryPath("/usr/lib"); - - var sdk_sysroot = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/" }) catch unreachable; - b.sysroot = sdk_sysroot; - return; - } - - var sdk_framework_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/System/Library/Frameworks" }) catch unreachable; - step.addFrameworkPath(sdk_framework_dir); - - var sdk_include_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/include" }) catch unreachable; - step.addSystemIncludePath(sdk_include_dir); - - var sdk_lib_dir = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib" }) catch unreachable; - step.addLibraryPath(sdk_lib_dir); -} - -fn includeSdkLinuxX8664(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void { - const sdk_root_dir = getSdkRoot(b.allocator, step, options.github_org, options.linux_x86_64, options.linux_x86_64_revision) catch unreachable; - - if (options.set_sysroot) { - var sdk_sysroot = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/" }) catch unreachable; - b.sysroot = sdk_sysroot; - return; - } - - var sdk_root_includes = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/include" }) catch unreachable; - var wayland_protocols_include = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/share/wayland-generated" }) catch unreachable; - var sdk_root_libs = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib/x86_64-linux-gnu" }) catch unreachable; - defer { - b.allocator.free(sdk_root_includes); - b.allocator.free(wayland_protocols_include); - b.allocator.free(sdk_root_libs); - } - step.addSystemIncludePath(sdk_root_includes); - step.addSystemIncludePath(wayland_protocols_include); - step.addLibraryPath(sdk_root_libs); -} - -fn includeSdkLinuxAarch64(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void { - const sdk_root_dir = getSdkRoot(b.allocator, step, options.github_org, options.linux_aarch64, options.linux_aarch64_revision) catch unreachable; - - if (options.set_sysroot) { - var sdk_sysroot = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/" }) catch unreachable; - b.sysroot = sdk_sysroot; - return; - } - - var sdk_root_includes = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/include" }) catch unreachable; - var wayland_protocols_include = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/share/wayland-generated" }) catch unreachable; - var sdk_root_libs = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "root/usr/lib/aarch64-linux-gnu" }) catch unreachable; - defer { - b.allocator.free(sdk_root_includes); - b.allocator.free(wayland_protocols_include); - b.allocator.free(sdk_root_libs); - } - step.addSystemIncludePath(sdk_root_includes); - step.addSystemIncludePath(wayland_protocols_include); - step.addLibraryPath(sdk_root_libs); -} - -fn includeSdkWindowsX8664(b: *Builder, step: *std.build.LibExeObjStep, options: Options) void { - const sdk_root_dir = getSdkRoot(b.allocator, step, options.github_org, options.windows_x86_64, options.windows_x86_64_revision) catch unreachable; - - if (options.set_sysroot) { - // We have no sysroot for Windows, but we still set one to prevent inclusion of other system - // libs (if set_sysroot is set, don't want to accidentally depend on system libs.) - var sdk_sysroot = std.fs.path.join(b.allocator, &.{sdk_root_dir}) catch unreachable; - b.sysroot = sdk_sysroot; - } - - var sdk_includes = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "include" }) catch unreachable; - var sdk_libs = std.fs.path.join(b.allocator, &.{ sdk_root_dir, "lib" }) catch unreachable; - defer { - b.allocator.free(sdk_includes); - b.allocator.free(sdk_libs); - } - - step.addIncludePath(sdk_includes); - step.addLibraryPath(sdk_libs); -} - -var cached_sdk_roots: ?std.AutoHashMap(*std.build.LibExeObjStep, []const u8) = null; +var cached_sdk_roots: ?std.AutoHashMap(*const Options.Sdk, []const u8) = null; /// returns the SDK root path, determining it iff necessary. In a real application, this may be /// tens or hundreds of times and so the result is cached in-memory (this also means the result /// cannot be freed until the result will never be used again, which is fine as the Zig build system /// Builder.allocator is an arena, you don't need to free.) -fn getSdkRoot(allocator: std.mem.Allocator, step: *std.build.LibExeObjStep, org: []const u8, name: []const u8, revision: []const u8) ![]const u8 { - if (cached_sdk_roots == null) { - cached_sdk_roots = std.AutoHashMap(*std.build.LibExeObjStep, []const u8).init(allocator); - } +fn getSdkRoot(allocator: std.mem.Allocator, sdk: Options.Sdk) ![]const u8 { + if (cached_sdk_roots == null) + cached_sdk_roots = std.AutoHashMap(*const Options.Sdk, []const u8).init(allocator); - var entry = try cached_sdk_roots.?.getOrPut(step); + var entry = try cached_sdk_roots.?.getOrPut(&sdk); if (entry.found_existing) return entry.value_ptr.*; - const sdk_root = try determineSdkRoot(allocator, org, name, revision); + const sdk_root = try determineSdkRoot(allocator, sdk); entry.value_ptr.* = sdk_root; return sdk_root; } -fn determineSdkRoot(allocator: std.mem.Allocator, org: []const u8, name: []const u8, revision: []const u8) ![]const u8 { +fn determineSdkRoot(allocator: std.mem.Allocator, sdk: Options.Sdk) ![]const u8 { // Find the directory where the SDK should be located. We'll consider two locations: // // 1. $SDK_PATH/ (if set, e.g. for testing changes to SDKs easily) @@ -198,11 +234,11 @@ fn determineSdkRoot(allocator: std.mem.Allocator, org: []const u8, name: []const if (std.process.getEnvVarOwned(allocator, "MACH_SDK_PATH")) |sdk_path| { custom_sdk_path = true; sdk_path_dir = sdk_path; - sdk_root_dir = try std.fs.path.join(allocator, &.{ sdk_path, name }); + sdk_root_dir = try std.fs.path.join(allocator, &.{ sdk_path, sdk.name }); } else |err| switch (err) { error.EnvironmentVariableNotFound => { - sdk_path_dir = try std.fs.getAppDataDir(allocator, org); - sdk_root_dir = try std.fs.path.join(allocator, &.{ sdk_path_dir, name }); + sdk_path_dir = try std.fs.getAppDataDir(allocator, "mach"); + sdk_root_dir = try std.fs.path.join(allocator, &.{ sdk_path_dir, sdk.name }); }, else => |e| return e, } @@ -212,29 +248,29 @@ fn determineSdkRoot(allocator: std.mem.Allocator, org: []const u8, name: []const // If the SDK exists, return it. Otherwise, clone it. if (std.fs.openDirAbsolute(sdk_root_dir, .{})) |_| { const current_revision = try getCurrentGitRevision(allocator, sdk_root_dir); - if (!std.mem.eql(u8, current_revision, revision)) { + if (!std.mem.eql(u8, current_revision, sdk.git_revision)) { // Update the SDK to the target revision. This may be either forward or backwards in // history (e.g. if building an old project) and so we use a hard reset. // // No reset is performed if specifying a custom SDK_PATH, as that is a development/debug // option and could wipe out dev history. - exec(allocator, &[_][]const u8{ "git", "fetch" }, sdk_root_dir) catch |err| std.debug.print("warning: failed to check for updates to {s}/{s}: {s}\n", .{ org, name, @errorName(err) }); - if (!custom_sdk_path) try exec(allocator, &[_][]const u8{ "git", "reset", "--quiet", "--hard", revision }, sdk_root_dir); + exec(allocator, &[_][]const u8{ "git", "fetch" }, sdk_root_dir) catch |err| std.debug.print("warning: failed to check for updates to {s}: {s}\n", .{ sdk.name, @errorName(err) }); + if (!custom_sdk_path) + try exec(allocator, &[_][]const u8{ "git", "reset", "--quiet", "--hard", sdk.git_revision }, sdk_root_dir); } return sdk_root_dir; } else |err| return switch (err) { error.FileNotFound => { - std.log.info("cloning required sdk..\ngit clone https://github.com/{s}/{s} '{s}'..\n", .{ org, name, sdk_root_dir }); - if (std.mem.startsWith(u8, name, "sdk-macos-")) { - if (!try confirmAppleSDKAgreement(allocator)) @panic("cannot continue"); + std.log.info("cloning required sdk..\ngit clone {s} '{s}'..\n", .{ sdk.git_addr, sdk_root_dir }); + switch (sdk.os_tag) { + .macos, .ios, .watchos, .tvos => { + if (!try confirmAppleSDKAgreement(allocator)) @panic("cannot continue"); + }, + else => {}, } try std.fs.cwd().makePath(sdk_path_dir); - var buf: [1000]u8 = undefined; - var repo_url_fbs = std.io.fixedBufferStream(&buf); - try std.fmt.format(repo_url_fbs.writer(), "https://github.com/{s}/{s}", .{ org, name }); - - try exec(allocator, &[_][]const u8{ "git", "clone", "-c", "core.longpaths=true", repo_url_fbs.getWritten() }, sdk_path_dir); + try exec(allocator, &[_][]const u8{ "git", "clone", "-c", "core.longpaths=true", sdk.git_addr }, sdk_path_dir); return sdk_root_dir; }, else => err, diff --git a/libs/gpu-dawn/src/dawn/dummy.zig b/libs/gpu-dawn/src/dawn/dummy.zig deleted file mode 100644 index e69de29b..00000000