diff --git a/src/core/linux/Wayland.zig b/src/core/linux/Wayland.zig index e5a615ca13..288eb44080 100644 --- a/src/core/linux/Wayland.zig +++ b/src/core/linux/Wayland.zig @@ -274,7 +274,7 @@ const LibXkbCommon = struct { pub fn load() !LibXkbCommon { var lib: LibXkbCommon = undefined; - lib.handle = std.DynLib.open("libxkbcommon.so.0") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libxkbcommon.so.0"); inline for (@typeInfo(LibXkbCommon).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); @@ -327,7 +327,7 @@ const LibWaylandClient = struct { pub fn load() !LibWaylandClient { var lib: LibWaylandClient = undefined; - lib.handle = std.DynLib.open("libwayland-client.so.0") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libwayland-client.so.0"); inline for (@typeInfo(LibWaylandClient).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/core/linux/X11.zig b/src/core/linux/X11.zig index 6a8a7d7296..8189c68d06 100644 --- a/src/core/linux/X11.zig +++ b/src/core/linux/X11.zig @@ -439,7 +439,7 @@ const LibX11 = struct { XFree: *const @TypeOf(c.XFree), pub fn load() !LibX11 { var lib: LibX11 = undefined; - lib.handle = std.DynLib.open("libX11.so.6") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libX11.so.6"); inline for (@typeInfo(LibX11).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); @@ -459,7 +459,7 @@ const LibXCursor = struct { XcursorLibraryLoadImage: *const @TypeOf(c.XcursorLibraryLoadImage), pub fn load() !LibXCursor { var lib: LibXCursor = undefined; - lib.handle = std.DynLib.open("libXcursor.so.1") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libXcursor.so.1"); inline for (@typeInfo(LibXCursor).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); @@ -475,7 +475,7 @@ const LibXRR = struct { XRRConfigCurrentRate: *const @TypeOf(c.XRRConfigCurrentRate), pub fn load() !LibXRR { var lib: LibXRR = undefined; - lib.handle = std.DynLib.open("libXrandr.so.1") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libXrandr.so.1"); inline for (@typeInfo(LibXRR).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); @@ -506,7 +506,7 @@ const LibGL = struct { glXSwapBuffers: *const fn (*c.Display, Drawable) callconv(.C) bool, pub fn load() !LibGL { var lib: LibGL = undefined; - lib.handle = std.DynLib.open("libGL.so.1") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libGL.so.1"); inline for (@typeInfo(LibGL).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); @@ -538,7 +538,7 @@ const LibXkbCommon = struct { pub fn load() !LibXkbCommon { var lib: LibXkbCommon = undefined; - lib.handle = std.DynLib.open("libxkbcommon.so.0") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libxkbcommon.so.0"); inline for (@typeInfo(LibXkbCommon).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/gamemode.zig b/src/gamemode.zig index 928d55a120..6e6865822a 100644 --- a/src/gamemode.zig +++ b/src/gamemode.zig @@ -1,5 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); +const mach = @import("main.zig"); const log = std.log.scoped(.gamemode); @@ -100,9 +101,9 @@ const linux_impl = struct { pub fn tryInit() LoadError!void { if (state == .init) return; - var dl = std.DynLib.open("libgamemode.so.0") catch |e| switch (e) { + var dl = mach.dynLibOpen("libgamemode.so.0") catch |e| switch (e) { // backwards-compatibility for old gamemode versions - error.FileNotFound => try std.DynLib.open("libgamemode.so"), + error.LibraryNotFound => try mach.dynLibOpen("libgamemode.so"), else => return e, }; errdefer dl.close(); @@ -128,7 +129,7 @@ const linux_impl = struct { .failed => return false, .uninit => { tryInit() catch |e| { - if (e != error.FileNotFound) { + if (e != error.LibraryNotFound) { log.warn("Loading gamemode: '{}'. Disabling libgamemode support.", .{e}); } state = .failed; diff --git a/src/main.zig b/src/main.zig index 0124e81cf4..c3d1ef4a21 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,6 +4,8 @@ const build_options = @import("build-options"); const builtin = @import("builtin"); const std = @import("std"); +const log = std.log.scoped(.mach); + pub const is_debug = builtin.mode == .Debug; // Core @@ -35,6 +37,20 @@ pub fn schedule(v: anytype) @TypeOf(v) { return v; } +// Instrumented function to load system libraries and print nicer error +// messages. +pub inline fn dynLibOpen(libName: []const u8) !std.DynLib { + return std.DynLib.open(libName) catch |err| { + switch (err) { + error.FileNotFound => { + log.err("Missing system library: '{s}'!", .{libName}); + return error.LibraryNotFound; + }, + else => return err, + } + }; +} + test { // TODO: refactor code so we can use this here: // std.testing.refAllDeclsRecursive(@This()); diff --git a/src/sysaudio/alsa.zig b/src/sysaudio/alsa.zig index d08708e161..b65e227958 100644 --- a/src/sysaudio/alsa.zig +++ b/src/sysaudio/alsa.zig @@ -3,6 +3,8 @@ const c = @cImport(@cInclude("alsa/asoundlib.h")); const main = @import("main.zig"); const backends = @import("backends.zig"); const util = @import("util.zig"); +const mach = @import("../main.zig"); + const inotify_event = std.os.linux.inotify_event; const is_little = @import("builtin").cpu.arch.endian() == .little; @@ -69,7 +71,7 @@ const Lib = struct { snd_mixer_selem_has_capture_channel: *const fn (?*c.snd_mixer_elem_t, c.snd_mixer_selem_channel_id_t) callconv(.C) c_int, pub fn load() !void { - lib.handle = std.DynLib.open("libasound.so") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libasound.so"); inline for (@typeInfo(Lib).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/sysaudio/jack.zig b/src/sysaudio/jack.zig index cac94fa339..f42dc6a419 100644 --- a/src/sysaudio/jack.zig +++ b/src/sysaudio/jack.zig @@ -3,6 +3,7 @@ const c = @cImport(@cInclude("jack/jack.h")); const main = @import("main.zig"); const backends = @import("backends.zig"); const util = @import("util.zig"); +const mach = @import("../main.zig"); var lib: Lib = undefined; const Lib = struct { @@ -33,7 +34,7 @@ const Lib = struct { jack_port_type_size: *const fn () c_int, pub fn load() !void { - lib.handle = std.DynLib.open("libjack.so") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libjack.so"); inline for (@typeInfo(Lib).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/sysaudio/pipewire.zig b/src/sysaudio/pipewire.zig index 4014220753..022da16ed7 100644 --- a/src/sysaudio/pipewire.zig +++ b/src/sysaudio/pipewire.zig @@ -6,6 +6,7 @@ const c = @cImport({ const main = @import("main.zig"); const backends = @import("backends.zig"); const util = @import("util.zig"); +const mach = @import("../main.zig"); const default_sample_rate = 44_100; // Hz @@ -33,7 +34,7 @@ const Lib = struct { pw_stream_get_state: *const fn (?*c.pw_stream, [*c][*c]const u8) callconv(.C) c.pw_stream_state, pub fn load() !void { - lib.handle = std.DynLib.open("libpipewire-0.3.so") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libpipewire-0.3.so"); inline for (@typeInfo(Lib).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/sysaudio/pulseaudio.zig b/src/sysaudio/pulseaudio.zig index 3431f4284a..c8aa5763fa 100644 --- a/src/sysaudio/pulseaudio.zig +++ b/src/sysaudio/pulseaudio.zig @@ -3,6 +3,8 @@ const c = @cImport(@cInclude("pulse/pulseaudio.h")); const main = @import("main.zig"); const backends = @import("backends.zig"); const util = @import("util.zig"); +const mach = @import("../main.zig"); + const is_little = @import("builtin").cpu.arch.endian() == .little; const default_sample_rate = 44_100; // Hz @@ -61,7 +63,7 @@ const Lib = struct { pa_stream_get_sample_spec: *const fn (s: ?*c.pa_stream) [*c]const c.pa_sample_spec, pub fn load() !void { - lib.handle = std.DynLib.open("libpulse.so") catch return error.LibraryNotFound; + lib.handle = try mach.dynLibOpen("libpulse.so"); inline for (@typeInfo(Lib).@"struct".fields[1..]) |field| { const name = std.fmt.comptimePrint("{s}\x00", .{field.name}); const name_z: [:0]const u8 = @ptrCast(name[0 .. name.len - 1]); diff --git a/src/sysgpu/opengl/proc.zig b/src/sysgpu/opengl/proc.zig index e4e70b463e..7170ed97f7 100644 --- a/src/sysgpu/opengl/proc.zig +++ b/src/sysgpu/opengl/proc.zig @@ -1,5 +1,6 @@ const std = @import("std"); const c = @import("c.zig"); +const mach = @import("../../main.zig"); var libgl: std.DynLib = undefined; @@ -16,7 +17,7 @@ fn getProcAddress(name_ptr: [*:0]const u8) c.PROC { } pub fn init() !void { - libgl = try std.DynLib.open("opengl32.dll"); + libgl = try mach.dynLibOpen("opengl32.dll"); } pub fn deinit() void { diff --git a/src/sysgpu/vulkan.zig b/src/sysgpu/vulkan.zig index 8356cb9238..5b384fed96 100644 --- a/src/sysgpu/vulkan.zig +++ b/src/sysgpu/vulkan.zig @@ -7,6 +7,7 @@ const shader = @import("shader.zig"); const utils = @import("utils.zig"); const conv = @import("vulkan/conv.zig"); const proc = @import("vulkan/proc.zig"); +const mach = @import("../main.zig"); const log = std.log.scoped(.vulkan); const api_version = vk.makeApiVersion(0, 1, 1, 0); @@ -28,7 +29,7 @@ pub fn init(alloc: std.mem.Allocator, options: InitOptions) !void { if (options.baseLoader) |baseLoader| { vkb = try proc.loadBase(baseLoader); } else { - libvulkan = try std.DynLib.open(switch (builtin.target.os.tag) { + libvulkan = try mach.dynLibOpen(switch (builtin.target.os.tag) { .windows => "vulkan-1.dll", .linux => "libvulkan.so.1", .macos => "libvulkan.1.dylib",