From 9b230dfb36d21f6c0133ecadcb4860ebefe6b1a2 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Thu, 7 May 2026 16:21:41 +0200
Subject: [PATCH] cmake: add SDL_LIBUDEV_SHARED option
---
CMakeLists.txt | 3 ++-
cmake/sdlchecks.cmake | 21 +++++++++++++++++----
src/core/linux/SDL_udev.c | 18 +++++++++++++++---
src/core/linux/SDL_udev.h | 8 ++++----
4 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2fd4c0db652e3..a86cfb187e07c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -400,7 +400,8 @@ dep_option(SDL_HIDAPI_LIBUSB "Use libusb for low level joystick drivers" O
dep_option(SDL_HIDAPI_LIBUSB_SHARED "Dynamically load libusb support" ON "SDL_HIDAPI_LIBUSB;SDL_DEPS_SHARED" OFF)
dep_option(SDL_HIDAPI_JOYSTICK "Use HIDAPI for low level joystick drivers" ON SDL_HIDAPI OFF)
dep_option(SDL_VIRTUAL_JOYSTICK "Enable the virtual-joystick driver" ON SDL_HIDAPI OFF)
-set_option(SDL_LIBUDEV "Enable libudev support" ON)
+dep_option(SDL_LIBUDEV "Enable libudev support" ON ${UNIX_SYS} OFF)
+dep_option(SDL_LIBUDEV_SHARED "Dynamically load libudev support" ON "SDL_LIBUDEV;SDL_DEPS_SHARED" OFF)
set_option(SDL_ASAN "Use AddressSanitizer to detect memory errors" OFF)
set_option(SDL_CCACHE "Use Ccache to speed up build" OFF)
set_option(SDL_CLANG_TIDY "Run clang-tidy static analysis" OFF)
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
index 8ed5f19d17be0..0365ddba7584c 100644
--- a/cmake/sdlchecks.cmake
+++ b/cmake/sdlchecks.cmake
@@ -1408,14 +1408,27 @@ macro(CheckKMSDRM)
endmacro()
macro(CheckLibUDev)
+ set(HAVE_LIBUDEV_H FALSE)
+ set(HAVE_LIBUDEV FALSE)
+ set(HAVE_LIBUDEV_SHARED OFF)
if(SDL_LIBUDEV)
check_include_file("libudev.h" HAVE_LIBUDEV_HEADER)
if(HAVE_LIBUDEV_HEADER)
set(HAVE_LIBUDEV_H TRUE)
- FindLibraryAndSONAME(udev)
- if(UDEV_LIB_SONAME)
- set(SDL_UDEV_DYNAMIC "\"${UDEV_LIB_SONAME}\"")
- set(HAVE_LIBUDEV TRUE)
+ set(HAVE_LIBUDEV TRUE)
+ if(SDL_LIBUDEV_SHARED)
+ if(NOT HAVE_SDL_LOADSO)
+ message(WARNING "You must have SDL_LoadObject() support for dynamic libudev support")
+ else()
+ FindLibraryAndSONAME(udev)
+ if(UDEV_LIB_SONAME)
+ set(SDL_UDEV_DYNAMIC "\"${UDEV_LIB_SONAME}\"")
+ set(HAVE_LIBUDEV_SHARED TRUE)
+ endif()
+ endif()
+ endif()
+ if(NOT HAVE_LIBUDEV_SHARED)
+ sdl_link_dependency(udev PRIVATE LIBS udev)
endif()
endif()
endif()
diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c
index 73071410ae401..35db562cdd6e7 100644
--- a/src/core/linux/SDL_udev.c
+++ b/src/core/linux/SDL_udev.c
@@ -41,10 +41,8 @@
static const char *SDL_UDEV_LIBS[] = { SDL_UDEV_FALLBACK_LIBS };
#ifdef SDL_UDEV_DYNAMIC
+
#define SDL_UDEV_DLNOTE_LIBS SDL_UDEV_DYNAMIC, SDL_UDEV_FALLBACK_LIBS
-#else
-#define SDL_UDEV_DLNOTE_LIBS SDL_UDEV_FALLBACK_LIBS
-#endif
SDL_ELF_NOTE_DLOPEN(
"events-udev",
@@ -52,17 +50,21 @@ SDL_ELF_NOTE_DLOPEN(
SDL_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
SDL_UDEV_DLNOTE_LIBS
)
+#endif
static SDL_UDEV_PrivateData *_this = NULL;
+#ifdef SDL_UDEV_DYNAMIC
static bool SDL_UDEV_load_sym(const char *fn, void **addr);
static bool SDL_UDEV_load_syms(void);
+#endif
static bool SDL_UDEV_hotplug_update_available(void);
static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len);
static int guess_device_class(struct udev_device *dev);
static int device_class(struct udev_device *dev);
static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev);
+#ifdef SDL_UDEV_DYNAMIC
static bool SDL_UDEV_load_sym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(_this->udev_handle, fn);
@@ -73,9 +75,12 @@ static bool SDL_UDEV_load_sym(const char *fn, void **addr)
return true;
}
+#endif
static bool SDL_UDEV_load_syms(void)
{
+
+#ifdef SDL_UDEV_DYNAMIC
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_UDEV_SYM(x) \
if (!SDL_UDEV_load_sym(#x, (void **)(char *)&_this->syms.x)) \
@@ -83,6 +88,13 @@ static bool SDL_UDEV_load_syms(void)
#define SDL_UDEV_SYM_OPTIONAL(x) \
SDL_UDEV_load_sym(#x, (void **)(char *)&_this->syms.x);
+#else
+#define SDL_UDEV_SYM(x) \
+ _this->syms.x = x;
+
+#define SDL_UDEV_SYM_OPTIONAL(x) \
+ _this->syms.x = x;
+#endif
SDL_UDEV_SYM(udev_device_get_action);
SDL_UDEV_SYM(udev_device_get_devnode);
diff --git a/src/core/linux/SDL_udev.h b/src/core/linux/SDL_udev.h
index d4f737c07cabc..8fe273d15d428 100644
--- a/src/core/linux/SDL_udev.h
+++ b/src/core/linux/SDL_udev.h
@@ -64,13 +64,13 @@ typedef struct SDL_UDEV_Symbols
const char *(*udev_device_get_property_value)(struct udev_device *, const char *);
const char *(*udev_device_get_sysattr_value)(struct udev_device *udev_device, const char *sysattr);
struct udev_device *(*udev_device_new_from_syspath)(struct udev *, const char *);
- void (*udev_device_unref)(struct udev_device *);
+ struct udev_device *(*udev_device_unref)(struct udev_device *);
int (*udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *);
int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *);
struct udev_list_entry *(*udev_enumerate_get_list_entry)(struct udev_enumerate *);
struct udev_enumerate *(*udev_enumerate_new)(struct udev *);
int (*udev_enumerate_scan_devices)(struct udev_enumerate *);
- void (*udev_enumerate_unref)(struct udev_enumerate *);
+ struct udev_enumerate *(*udev_enumerate_unref)(struct udev_enumerate *);
const char *(*udev_list_entry_get_name)(struct udev_list_entry *);
const char *(*udev_list_entry_get_value)(struct udev_list_entry *);
struct udev_list_entry *(*udev_list_entry_get_next)(struct udev_list_entry *);
@@ -79,9 +79,9 @@ typedef struct SDL_UDEV_Symbols
int (*udev_monitor_get_fd)(struct udev_monitor *);
struct udev_monitor *(*udev_monitor_new_from_netlink)(struct udev *, const char *);
struct udev_device *(*udev_monitor_receive_device)(struct udev_monitor *);
- void (*udev_monitor_unref)(struct udev_monitor *);
+ struct udev_monitor *(*udev_monitor_unref)(struct udev_monitor *);
struct udev *(*udev_new)(void);
- void (*udev_unref)(struct udev *);
+ struct udev *(*udev_unref)(struct udev *);
struct udev_device *(*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum);
dev_t (*udev_device_get_devnum)(struct udev_device *udev_device);