From ad56adfcb163bf2dd56a07ab5535253480ff4fe9 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 7 May 2026 20:55:53 +0200 Subject: [PATCH] cmake: add SDL_LIBURING_SHARED option --- CMakeLists.txt | 12 +-- cmake/sdlchecks.cmake | 35 ++++++++ include/build_config/SDL_build_config.h.cmake | 1 + src/io/io_uring/SDL_asyncio_liburing.c | 90 ++++++++++--------- 4 files changed, 88 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e591a011c1..4b6888a28f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,6 +324,7 @@ set_option(SDL_LIBICONV "Prefer iconv() from libiconv, if available, set_option(SDL_GCC_ATOMICS "Use gcc builtin atomics" ${SDL_GCC_ATOMICS_DEFAULT}) dep_option(SDL_DBUS "Enable D-Bus support" ON "${UNIX_SYS}" OFF) dep_option(SDL_LIBURING "Enable liburing support" ON "${UNIX_SYS}" OFF) +dep_option(SDL_LIBURING_SHARED "Dynamically load liburing support" ON "SDL_LIBURING;SDL_DEPS_SHARED" OFF) dep_option(SDL_DISKAUDIO "Support the disk writer audio driver" ON "SDL_AUDIO" OFF) dep_option(SDL_DUMMYAUDIO "Support the dummy audio driver" ON "SDL_AUDIO" OFF) dep_option(SDL_DUMMYVIDEO "Use dummy video driver" ON "SDL_VIDEO" OFF) @@ -2001,15 +2002,8 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) set(SDL_USE_IME 1) endif() - if(SDL_LIBURING) - pkg_search_module(LIBURING liburing-ffi) - find_path(HAVE_LIBURING_H NAMES liburing.h) - if(LIBURING_FOUND AND HAVE_LIBURING_H) - set(HAVE_LIBURING_LIBURING_H TRUE) - sdl_include_directories(PRIVATE SYSTEM ${LIBURING_INCLUDE_DIRS}) - set(HAVE_LIBURING TRUE) - endif() - endif() + CheckLiburing() + if((FREEBSD OR NETBSD) AND NOT HAVE_INOTIFY) set(LibInotify_PKG_CONFIG_SPEC libinotify) pkg_check_modules(PC_LIBINOTIFY IMPORTED_TARGET ${LibInotify_PKG_CONFIG_SPEC}) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 055781dde3..2b2b2c15f3 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -1485,3 +1485,38 @@ macro(CheckLibUnwind) endif() endif() endmacro() + +macro(CheckLiburing) + set(HAVE_LIBURING_H FALSE) + set(HAVE_LIBURING_SHARED OFF) + set(HAVE_LIBURING OFF) + if(SDL_LIBURING) + find_path(LIBURING_H_INCLUDE_PATH NAMES liburing.h) + if(LIBURING_H_INCLUDE_PATH) + if(SDL_LIBURING_SHARED) + if(NOT HAVE_SDL_LOADSO) + message(WARNING "You must have SDL_LoadObject() support for dynamic liburing support") + else() + FindLibraryAndSONAME(uring-ffi) + if(URING_FFI_LIB_SONAME) + sdl_include_directories(PRIVATE SYSTEM ${LIBURING_H_INCLUDE_PATH}) + set(SDL_LIBURING_DYNAMIC "\"${URING_FFI_LIB_SONAME}\"") + set(HAVE_LIBURING TRUE) + set(HAVE_LIBURING_SHARED TRUE) + endif() + endif() + endif() + if(NOT HAVE_LIBURING) + set(liburing_PKG_CONFIG_SPEC liburing) + pkg_check_modules(PC_LIBURING IMPORTED_TARGET ${liburing_PKG_CONFIG_SPEC}) + if(PC_LIBURING_FOUND) + set(HAVE_LIBURING TRUE) + sdl_link_dependency(liburing LIBS PkgConfig::PC_LIBURING PKG_CONFIG_PREFIX PC_LIBURING PKG_CONFIG_SPECS ${liburing_PKG_CONFIG_SPEC}) + endif() + endif() + endif() + if(HAVE_LIBURING) + set(HAVE_LIBURING_H TRUE) + endif() + endif() +endmacro() diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index e7d0b34f42..f11d18d152 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -218,6 +218,7 @@ #cmakedefine HAVE_LIBUDEV_H 1 #cmakedefine HAVE_LIBDECOR_H 1 #cmakedefine HAVE_LIBURING_H 1 +#cmakedefine SDL_LIBURING_DYNAMIC @SDL_LIBURING_DYNAMIC@ #cmakedefine HAVE_FRIBIDI_H 1 #cmakedefine SDL_FRIBIDI_DYNAMIC @SDL_FRIBIDI_DYNAMIC@ #cmakedefine HAVE_LIBTHAI_H 1 diff --git a/src/io/io_uring/SDL_asyncio_liburing.c b/src/io/io_uring/SDL_asyncio_liburing.c index a15218a1e3..31b2f76820 100644 --- a/src/io/io_uring/SDL_asyncio_liburing.c +++ b/src/io/io_uring/SDL_asyncio_liburing.c @@ -41,19 +41,17 @@ static bool (*CreateAsyncIOQueue)(SDL_AsyncIOQueue *queue); static void (*QuitAsyncIO)(void); static bool (*AsyncIOFromFile)(const char *file, const char *mode, SDL_AsyncIO *asyncio); -// we never link directly to liburing. -// (this says "-ffi" which sounds like a scripting language binding thing, but the non-ffi version -// is static-inline code we can't lookup with dlsym. This is by design.) -#define SDL_DRIVER_LIBURING_DYNAMIC "liburing-ffi.so.2" -static const char *liburing_library = SDL_DRIVER_LIBURING_DYNAMIC; +#ifdef SDL_LIBURING_DYNAMIC +static const char liburing_library[] = SDL_LIBURING_DYNAMIC; static void *liburing_handle = NULL; SDL_ELF_NOTE_DLOPEN( "io-io_uring", "Support for async IO through liburing", SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, - SDL_DRIVER_LIBURING_DYNAMIC + SDL_LIBURING_DYNAMIC ) +#endif #define SDL_LIBURING_FUNCS \ SDL_LIBURING_FUNC(int, io_uring_queue_init, (unsigned entries, struct io_uring *ring, unsigned flags)) \ @@ -65,8 +63,8 @@ SDL_ELF_NOTE_DLOPEN( SDL_LIBURING_FUNC(void, io_uring_prep_write,(struct io_uring_sqe *sqe, int fd, const void *buf, unsigned nbytes, __u64 offset)) \ SDL_LIBURING_FUNC(void, io_uring_prep_close, (struct io_uring_sqe *sqe, int fd)) \ SDL_LIBURING_FUNC(void, io_uring_prep_fsync, (struct io_uring_sqe *sqe, int fd, unsigned fsync_flags)) \ - SDL_LIBURING_FUNC(void, io_uring_prep_cancel, (struct io_uring_sqe *sqe, void *user_data, int flags)) \ - SDL_LIBURING_FUNC(void, io_uring_prep_timeout, (struct io_uring_sqe *sqe, struct __kernel_timespec *ts, unsigned count, unsigned flags)) \ + SDL_LIBURING_FUNC(void, io_uring_prep_cancel, (struct io_uring_sqe *sqe, const void *user_data, int flags)) \ + SDL_LIBURING_FUNC(void, io_uring_prep_timeout, (struct io_uring_sqe *sqe, const struct __kernel_timespec *ts, unsigned count, unsigned flags)) \ SDL_LIBURING_FUNC(void, io_uring_prep_nop, (struct io_uring_sqe *sqe)) \ SDL_LIBURING_FUNC(void, io_uring_sqe_set_data, (struct io_uring_sqe *sqe, void *data)) \ SDL_LIBURING_FUNC(void, io_uring_sqe_set_flags, (struct io_uring_sqe *sqe, unsigned flags)) \ @@ -103,21 +101,28 @@ typedef struct LibUringAsyncIOQueueData static void UnloadLibUringLibrary(void) { - if (liburing_library) { +#ifdef SDL_LIBURING_DYNAMIC + if (liburing_handle) { SDL_UnloadObject(liburing_handle); - liburing_library = NULL; + liburing_handle = NULL; } +#endif SDL_zero(liburing); } static bool LoadLibUringSyms(void) { +#ifdef SDL_LIBURING_DYNAMIC #define SDL_LIBURING_FUNC(ret, fn, args) { \ liburing.fn = (SDL_fntype_##fn) SDL_LoadFunction(liburing_handle, #fn); \ if (!liburing.fn) { \ return false; \ } \ } +#else + #define SDL_LIBURING_FUNC(ret, fn, args) \ + liburing.fn = fn; +#endif SDL_LIBURING_FUNCS #undef SDL_LIBURING_FUNC return true; @@ -130,43 +135,46 @@ static bool LoadLibUring(void) { bool result = true; +#ifdef SDL_LIBURING_DYNAMIC if (!liburing_handle) { liburing_handle = SDL_LoadObject(liburing_library); if (!liburing_handle) { - result = false; // Don't call SDL_SetError(): SDL_LoadObject already did. - } else { - result = LoadLibUringSyms(); - if (result) { - static const int needed_ops[] = { - IORING_OP_NOP, - IORING_OP_FSYNC, - IORING_OP_TIMEOUT, - IORING_OP_CLOSE, - IORING_OP_READ, - IORING_OP_WRITE, - IORING_OP_ASYNC_CANCEL - }; - - struct io_uring_probe *probe = liburing.io_uring_get_probe(); - if (!probe) { - result = false; - } else { - for (int i = 0; i < SDL_arraysize(needed_ops); i++) { - if (!io_uring_opcode_supported(probe, needed_ops[i])) { - result = false; - break; - } - } - liburing.io_uring_free_probe(probe); - } - } - - if (!result) { - UnloadLibUringLibrary(); - } + return false; } } +#endif + result = LoadLibUringSyms(); + if (result) { + static const int needed_ops[] = { + IORING_OP_NOP, + IORING_OP_FSYNC, + IORING_OP_TIMEOUT, + IORING_OP_CLOSE, + IORING_OP_READ, + IORING_OP_WRITE, + IORING_OP_ASYNC_CANCEL + }; + + struct io_uring_probe *probe = liburing.io_uring_get_probe(); + if (!probe) { + result = false; + } else { + for (int i = 0; i < SDL_arraysize(needed_ops); i++) { + if (!io_uring_opcode_supported(probe, needed_ops[i])) { + result = false; + break; + } + } + liburing.io_uring_free_probe(probe); + } + } + +#ifdef SDL_LIBURING_DYNAMIC + if (!result) { + UnloadLibUringLibrary(); + } +#endif return result; }