From 8316cfd1672b56f74f5dd4fa28b0695fcfdcb528 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 31 May 2023 06:15:33 +0400 Subject: [PATCH] Optional library loading on Linux with Implib --- .gitmodules | 3 + CMakeLists.txt | 6 - external/Implib.so | 1 + external/qt/CMakeLists.txt | 23 +- external/wayland_client/CMakeLists.txt | 2 +- external/xcb/CMakeLists.txt | 2 +- linux_wayland_helper/CMakeLists.txt | 19 - linux_wayland_helper/linux_wayland_helper.cpp | 667 ------------------ linux_xcb_helper/CMakeLists.txt | 14 - linux_xcb_helper/linux_xcb_helper.cpp | 53 -- options_linux.cmake | 4 + target_link_optional_libraries.cmake | 86 +++ 12 files changed, 109 insertions(+), 771 deletions(-) create mode 160000 external/Implib.so delete mode 100644 linux_wayland_helper/CMakeLists.txt delete mode 100644 linux_wayland_helper/linux_wayland_helper.cpp delete mode 100644 linux_xcb_helper/CMakeLists.txt delete mode 100644 linux_xcb_helper/linux_xcb_helper.cpp create mode 100644 target_link_optional_libraries.cmake diff --git a/.gitmodules b/.gitmodules index c92fbea..3d3dbe7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/glib/cppgir"] path = external/glib/cppgir url = https://gitlab.com/mnauw/cppgir.git +[submodule "external/Implib.so"] + path = external/Implib.so + url = https://github.com/yugr/Implib.so.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a896fb..bb8789c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,6 @@ add_subdirectory(external) if (LINUX AND NOT DESKTOP_APP_DISABLE_JEMALLOC) add_subdirectory(linux_jemalloc_helper) endif() -if (LINUX AND NOT DESKTOP_APP_USE_PACKAGED) - add_subdirectory(linux_xcb_helper) -endif() -if (LINUX AND NOT DESKTOP_APP_USE_PACKAGED) - add_subdirectory(linux_wayland_helper) -endif() if (DESKTOP_APP_USE_ALLOCATION_TRACER) add_subdirectory(linux_allocation_tracer) endif() diff --git a/external/Implib.so b/external/Implib.so new file mode 160000 index 0000000..340e5d3 --- /dev/null +++ b/external/Implib.so @@ -0,0 +1 @@ +Subproject commit 340e5d32a8a3fcc7ac71136abeeb80b4d7dfb9fc diff --git a/external/qt/CMakeLists.txt b/external/qt/CMakeLists.txt index 78e9d51..cd7ab5e 100644 --- a/external/qt/CMakeLists.txt +++ b/external/qt/CMakeLists.txt @@ -306,28 +306,31 @@ if (LINUX) xcb-keysyms ) if (TARGET Qt::WaylandClient) - target_link_libraries(external_qt + target_link_optional_libraries(external_qt INTERFACE - desktop-app::linux_wayland_helper + wayland-egl + wayland-cursor + wayland-client ) endif() if (TARGET Qt::WaylandCompositor) - target_link_static_libraries(external_qt + target_link_optional_libraries(external_qt INTERFACE wayland-server - ffi ) endif() - target_link_libraries(external_qt + target_link_optional_libraries(external_qt INTERFACE - desktop-app::linux_xcb_helper - fontconfig - freetype EGL GL - xcb - X11 X11-xcb + xcb + ) + target_link_libraries(external_qt + INTERFACE + fontconfig + freetype + X11 glib-2.0 ) endif() diff --git a/external/wayland_client/CMakeLists.txt b/external/wayland_client/CMakeLists.txt index cda9899..e310fae 100644 --- a/external/wayland_client/CMakeLists.txt +++ b/external/wayland_client/CMakeLists.txt @@ -12,5 +12,5 @@ if (DESKTOP_APP_USE_PACKAGED) pkg_check_modules(WAYLAND_CLIENT REQUIRED IMPORTED_TARGET wayland-client) target_link_libraries(external_wayland_client INTERFACE PkgConfig::WAYLAND_CLIENT) else() - target_link_libraries(external_wayland_client INTERFACE desktop-app::linux_wayland_helper) + target_link_optional_libraries(external_wayland_client INTERFACE wayland-client) endif() diff --git a/external/xcb/CMakeLists.txt b/external/xcb/CMakeLists.txt index 0f16bf3..c6ee5b3 100644 --- a/external/xcb/CMakeLists.txt +++ b/external/xcb/CMakeLists.txt @@ -16,5 +16,5 @@ if (DESKTOP_APP_USE_PACKAGED) pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb) target_link_libraries(external_xcb INTERFACE PkgConfig::XCB) else() - target_link_libraries(external_xcb INTERFACE xcb) + target_link_optional_libraries(external_xcb INTERFACE xcb) endif() diff --git a/linux_wayland_helper/CMakeLists.txt b/linux_wayland_helper/CMakeLists.txt deleted file mode 100644 index c554e94..0000000 --- a/linux_wayland_helper/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# This file is part of Desktop App Toolkit, -# a set of libraries for developing nice desktop applications. -# -# For license and copyright information please follow this link: -# https://github.com/desktop-app/legal/blob/master/LEGAL - -add_library(linux_wayland_helper STATIC) -init_target(linux_wayland_helper "(external)") -add_library(desktop-app::linux_wayland_helper ALIAS linux_wayland_helper) - -nice_target_sources(linux_wayland_helper ${CMAKE_CURRENT_SOURCE_DIR} -PRIVATE - linux_wayland_helper.cpp -) - -target_link_libraries(linux_wayland_helper -PRIVATE - desktop-app::external_gsl -) diff --git a/linux_wayland_helper/linux_wayland_helper.cpp b/linux_wayland_helper/linux_wayland_helper.cpp deleted file mode 100644 index 3c95a3b..0000000 --- a/linux_wayland_helper/linux_wayland_helper.cpp +++ /dev/null @@ -1,667 +0,0 @@ -// This file is part of Desktop App Toolkit, -// a set of libraries for developing nice desktop applications. -// -// For license and copyright information please follow this link: -// https://github.com/desktop-app/legal/blob/master/LEGAL -// -#include -#include -#include -#include -#include -#include - -#define LOAD_SYMBOL(handle, func) LoadSymbol(handle, #func, func) -#define LOAD_SYMBOL_SILENT(handle, func) LoadSymbol(handle, #func, func, true) - -namespace Wayland { -namespace { - -constexpr auto WL_CLOSURE_MAX_ARGS = 20; - -struct wl_egl_window *(*wl_egl_window_create)( - struct wl_surface *surface, - int width, - int height); -void (*wl_egl_window_destroy)(struct wl_egl_window *egl_window); -void (*wl_egl_window_resize)( - struct wl_egl_window *egl_window, - int width, - int height, - int dx, - int dy); -void (*wl_egl_window_get_attached_size)( - struct wl_egl_window *egl_window, - int *width, - int *height); - -struct wl_buffer *(*wl_cursor_image_get_buffer)( - struct wl_cursor_image *image); -struct wl_cursor_theme *(*wl_cursor_theme_load)( - const char *name, - int size, - struct wl_shm *shm); -void (*wl_cursor_theme_destroy)(struct wl_cursor_theme *theme); -struct wl_cursor *(*wl_cursor_theme_get_cursor)( - struct wl_cursor_theme *theme, - const char *name); - -int (*wl_cursor_frame_and_duration)( - struct wl_cursor *cursor, - uint32_t time, - uint32_t *duration); - -void (*wl_proxy_destroy)(struct wl_proxy *proxy); -uint32_t (*wl_proxy_get_version)(struct wl_proxy *proxy); -int (*wl_proxy_add_listener)( - struct wl_proxy *proxy, - void (**implementation)(void), - void *data); -void (*wl_proxy_set_user_data)(struct wl_proxy *proxy, void *user_data); -void *(*wl_proxy_get_user_data)(struct wl_proxy *proxy); -int (*wl_display_get_fd)(struct wl_display *display); -int (*wl_display_get_error)(struct wl_display *display); -int (*wl_display_dispatch)(struct wl_display *display); -struct wl_event_queue *(*wl_display_create_queue)(struct wl_display *display); -int (*wl_display_dispatch_queue_pending)( - struct wl_display *display, - struct wl_event_queue *queue); -int (*wl_display_prepare_read_queue)( - struct wl_display *display, - struct wl_event_queue *queue); -int (*wl_display_flush)(struct wl_display *display); -void (*wl_display_cancel_read)(struct wl_display *display); -int (*wl_display_read_events)(struct wl_display *display); -void (*wl_event_queue_destroy)(struct wl_event_queue *queue); -int (*wl_display_prepare_read)(struct wl_display *display); -int (*wl_display_dispatch_pending)(struct wl_display *display); -struct wl_display *(*wl_display_connect)(const char *name); -void (*wl_display_disconnect)(struct wl_display *display); -void *(*wl_proxy_create_wrapper)(void *proxy); -void (*wl_proxy_wrapper_destroy)(void *proxy_wrapper); -void (*wl_proxy_set_queue)(struct wl_proxy *proxy, struct wl_event_queue *queue); -int (*wl_display_roundtrip)(struct wl_display *display); -struct wl_proxy *(*wl_proxy_marshal_array_constructor)( - struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface); -struct wl_proxy *(*wl_proxy_marshal_array_constructor_versioned)( - struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface, - uint32_t version); -struct wl_proxy *(*wl_proxy_marshal_array_flags)( - struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - uint32_t flags, - union wl_argument *args); -uint32_t (*wl_proxy_get_id)(struct wl_proxy *proxy); -const void *(*wl_proxy_get_listener)(struct wl_proxy *proxy); - -struct argument_details { - char type; - int nullable; -}; - -const char *get_next_argument( - const char *signature, - struct argument_details *details) { - details->nullable = 0; - for(; *signature; ++signature) { - switch(*signature) { - case 'i': - case 'u': - case 'f': - case 's': - case 'o': - case 'n': - case 'a': - case 'h': - details->type = *signature; - return signature + 1; - case '?': - details->nullable = 1; - } - } - details->type = '\0'; - return signature; -} - -void wl_argument_from_va_list( - const char *signature, - union wl_argument *args, - int count, - va_list ap) { - int i; - const char *sig_iter; - struct argument_details arg; - - sig_iter = signature; - for (i = 0; i < count; i++) { - sig_iter = get_next_argument(sig_iter, &arg); - - switch(arg.type) { - case 'i': - args[i].i = va_arg(ap, int32_t); - break; - case 'u': - args[i].u = va_arg(ap, uint32_t); - break; - case 'f': - args[i].f = va_arg(ap, wl_fixed_t); - break; - case 's': - args[i].s = va_arg(ap, const char *); - break; - case 'o': - args[i].o = va_arg(ap, struct wl_object *); - break; - case 'n': - args[i].o = va_arg(ap, struct wl_object *); - break; - case 'a': - args[i].a = va_arg(ap, struct wl_array *); - break; - case 'h': - args[i].h = va_arg(ap, int32_t); - break; - case '\0': - return; - } - } -} - -struct HandleDeleter { - void operator()(void *handle) { - dlclose(handle); - } -}; - -using Handle = std::unique_ptr; - -bool LoadLibrary(Handle &handle, const char *name) { - handle = Handle(dlopen(name, RTLD_LAZY | RTLD_NODELETE)); - if (handle) { - return true; - } - std::cerr << dlerror() << std::endl; - return false; -} - -template -inline bool LoadSymbol( - const Handle &handle, - const char *name, - Function &func, - bool silent = false) { - func = handle - ? reinterpret_cast(dlsym(handle.get(), name)) - : nullptr; - if (const auto error = dlerror(); error && !silent) { - std::cerr << error << std::endl; - } - return (func != nullptr); -} - -bool Resolve() { - static const auto loaded = [] { - auto egl = Handle(); - auto cursor = Handle(); - auto client = Handle(); - const auto required = LoadLibrary(egl, "libwayland-egl.so.1") - && LOAD_SYMBOL(egl, wl_egl_window_create) - && LOAD_SYMBOL(egl, wl_egl_window_destroy) - && LOAD_SYMBOL(egl, wl_egl_window_resize) - && LOAD_SYMBOL(egl, wl_egl_window_get_attached_size) - && LoadLibrary(cursor, "libwayland-cursor.so.0") - && LOAD_SYMBOL(cursor, wl_cursor_image_get_buffer) - && LOAD_SYMBOL(cursor, wl_cursor_theme_load) - && LOAD_SYMBOL(cursor, wl_cursor_theme_destroy) - && LOAD_SYMBOL(cursor, wl_cursor_theme_get_cursor) - && LOAD_SYMBOL(cursor, wl_cursor_frame_and_duration) - && LoadLibrary(client, "libwayland-client.so.0") - && LOAD_SYMBOL(client, wl_proxy_destroy) - && LOAD_SYMBOL(client, wl_proxy_get_version) - && LOAD_SYMBOL(client, wl_proxy_add_listener) - && LOAD_SYMBOL(client, wl_proxy_set_user_data) - && LOAD_SYMBOL(client, wl_proxy_get_user_data) - && LOAD_SYMBOL(client, wl_display_get_fd) - && LOAD_SYMBOL(client, wl_display_get_error) - && LOAD_SYMBOL(client, wl_display_dispatch) - && LOAD_SYMBOL(client, wl_display_create_queue) - && LOAD_SYMBOL(client, wl_display_dispatch_queue_pending) - && LOAD_SYMBOL(client, wl_display_prepare_read_queue) - && LOAD_SYMBOL(client, wl_display_flush) - && LOAD_SYMBOL(client, wl_display_cancel_read) - && LOAD_SYMBOL(client, wl_display_read_events) - && LOAD_SYMBOL(client, wl_event_queue_destroy) - && LOAD_SYMBOL(client, wl_display_prepare_read) - && LOAD_SYMBOL(client, wl_display_dispatch_pending) - && LOAD_SYMBOL(client, wl_display_connect) - && LOAD_SYMBOL(client, wl_display_disconnect) - && LOAD_SYMBOL(client, wl_proxy_create_wrapper) - && LOAD_SYMBOL(client, wl_proxy_wrapper_destroy) - && LOAD_SYMBOL(client, wl_proxy_set_queue) - && LOAD_SYMBOL(client, wl_display_roundtrip) - && LOAD_SYMBOL(client, wl_proxy_marshal_array_constructor) - && LOAD_SYMBOL(client, wl_proxy_marshal_array_constructor_versioned) - && LOAD_SYMBOL(client, wl_proxy_get_id) - && LOAD_SYMBOL(client, wl_proxy_get_listener); - LOAD_SYMBOL_SILENT(client, wl_proxy_marshal_array_flags); - return required; - }(); - return loaded; -} - -} // namespace -} // namespace Wayland - -namespace W = Wayland; - -extern "C" { - -struct wl_egl_window *wl_egl_window_create( - struct wl_surface *surface, - int width, - int height) { - Expects(W::wl_egl_window_create != nullptr); - - return W::wl_egl_window_create(surface, width, height); -} - -void wl_egl_window_destroy(struct wl_egl_window *egl_window) { - Expects(W::wl_egl_window_destroy != nullptr); - - W::wl_egl_window_destroy(egl_window); -} - -void wl_egl_window_resize( - struct wl_egl_window *egl_window, - int width, - int height, - int dx, - int dy) { - Expects(W::wl_egl_window_resize != nullptr); - - W::wl_egl_window_resize(egl_window, width, height, dx, dy); -} - -void wl_egl_window_get_attached_size( - struct wl_egl_window *egl_window, - int *width, - int *height) { - Expects(W::wl_egl_window_get_attached_size != nullptr); - - W::wl_egl_window_get_attached_size(egl_window, width, height); -} - -struct wl_buffer *wl_cursor_image_get_buffer(struct wl_cursor_image *image) { - Expects(W::wl_cursor_image_get_buffer != nullptr); - - return W::wl_cursor_image_get_buffer(image); -} - -struct wl_cursor_theme *wl_cursor_theme_load( - const char *name, - int size, - struct wl_shm *shm) { - Expects(W::wl_cursor_theme_load != nullptr); - - return W::wl_cursor_theme_load(name, size, shm); -} - -void wl_cursor_theme_destroy(struct wl_cursor_theme *theme) { - Expects(W::wl_cursor_theme_destroy != nullptr); - - W::wl_cursor_theme_destroy(theme); -} - -struct wl_cursor *wl_cursor_theme_get_cursor( - struct wl_cursor_theme *theme, - const char *name) { - Expects(W::wl_cursor_theme_get_cursor != nullptr); - - return W::wl_cursor_theme_get_cursor(theme, name); -} - -int wl_cursor_frame_and_duration( - struct wl_cursor *cursor, - uint32_t time, - uint32_t *duration) { - Expects(W::wl_cursor_frame_and_duration != nullptr); - - return W::wl_cursor_frame_and_duration(cursor, time, duration); -} - -void wl_proxy_destroy(struct wl_proxy *proxy) { - Expects(W::wl_proxy_destroy != nullptr); - - W::wl_proxy_destroy(proxy); -} - -uint32_t wl_proxy_get_version(struct wl_proxy *proxy) { - Expects(W::wl_proxy_get_version != nullptr); - - return W::wl_proxy_get_version(proxy); -} - -int wl_proxy_add_listener( - struct wl_proxy *proxy, - void (**implementation)(void), - void *data) { - Expects(W::wl_proxy_add_listener != nullptr); - - return W::wl_proxy_add_listener(proxy, implementation, data); -} - -void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data) { - Expects(W::wl_proxy_set_user_data != nullptr); - - W::wl_proxy_set_user_data(proxy, user_data); -} - -void *wl_proxy_get_user_data(struct wl_proxy *proxy) { - Expects(W::wl_proxy_get_user_data != nullptr); - - return W::wl_proxy_get_user_data(proxy); -} - -int wl_display_get_fd(struct wl_display *display) { - Expects(W::wl_display_get_fd != nullptr); - - return W::wl_display_get_fd(display); -} - -int wl_display_get_error(struct wl_display *display) { - Expects(W::wl_display_get_error != nullptr); - - return W::wl_display_get_error(display); -} - -int wl_display_dispatch(struct wl_display *display) { - Expects(W::wl_display_dispatch != nullptr); - - return W::wl_display_dispatch(display); -} - -struct wl_event_queue *wl_display_create_queue(struct wl_display *display) { - Expects(W::wl_display_create_queue != nullptr); - - return W::wl_display_create_queue(display); -} - -int wl_display_dispatch_queue_pending( - struct wl_display *display, - struct wl_event_queue *queue) { - Expects(W::wl_display_dispatch_queue_pending != nullptr); - - return W::wl_display_dispatch_queue_pending(display, queue); -} - -int wl_display_prepare_read_queue( - struct wl_display *display, - struct wl_event_queue *queue) { - Expects(W::wl_display_prepare_read_queue != nullptr); - - return W::wl_display_prepare_read_queue(display, queue); -} - -int wl_display_flush(struct wl_display *display) { - Expects(W::wl_display_flush != nullptr); - - return W::wl_display_flush(display); -} - -void wl_display_cancel_read(struct wl_display *display) { - Expects(W::wl_display_cancel_read != nullptr); - - W::wl_display_cancel_read(display); -} - -int wl_display_read_events(struct wl_display *display) { - Expects(W::wl_display_read_events != nullptr); - - return W::wl_display_read_events(display); -} - -void wl_event_queue_destroy(struct wl_event_queue *queue) { - Expects(W::wl_event_queue_destroy != nullptr); - - W::wl_event_queue_destroy(queue); -} - -int wl_display_prepare_read(struct wl_display *display) { - Expects(W::wl_display_prepare_read != nullptr); - - return W::wl_display_prepare_read(display); -} - -int wl_display_dispatch_pending(struct wl_display *display) { - Expects(W::wl_display_dispatch_pending != nullptr); - - return W::wl_display_dispatch_pending(display); -} - -struct wl_display *wl_display_connect(const char *name) { - if (!W::Resolve()) { - errno = ENOENT; - return nullptr; - } - return W::wl_display_connect(name); -} - -void wl_display_disconnect(struct wl_display *display) { - Expects(W::wl_display_disconnect != nullptr); - - W::wl_display_disconnect(display); -} - -void *wl_proxy_create_wrapper(void *proxy) { - Expects(W::wl_proxy_create_wrapper != nullptr); - - return W::wl_proxy_create_wrapper(proxy); -} - -void wl_proxy_wrapper_destroy(void *proxy_wrapper) { - Expects(W::wl_proxy_wrapper_destroy != nullptr); - - W::wl_proxy_wrapper_destroy(proxy_wrapper); -} - -void wl_proxy_set_queue( - struct wl_proxy *proxy, - struct wl_event_queue *queue) { - Expects(W::wl_proxy_set_queue != nullptr); - - W::wl_proxy_set_queue(proxy, queue); -} - -int wl_display_roundtrip(struct wl_display *display) { - Expects(W::wl_display_roundtrip != nullptr); - - return W::wl_display_roundtrip(display); -} - -struct wl_proxy *wl_proxy_marshal_array_constructor( - struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface) { - Expects(W::wl_proxy_marshal_array_constructor != nullptr); - - return W::wl_proxy_marshal_array_constructor( - proxy, - opcode, - args, - interface); -} - -struct wl_proxy *wl_proxy_marshal_array_constructor_versioned( - struct wl_proxy *proxy, - uint32_t opcode, - union wl_argument *args, - const struct wl_interface *interface, - uint32_t version) { - Expects(W::wl_proxy_marshal_array_constructor_versioned != nullptr); - - return W::wl_proxy_marshal_array_constructor_versioned( - proxy, - opcode, - args, - interface, - version); -} - -struct wl_proxy *wl_proxy_marshal_array_flags( - struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - uint32_t flags, - union wl_argument *args) { - Expects(W::wl_proxy_marshal_array_flags != nullptr); - - return W::wl_proxy_marshal_array_flags( - proxy, - opcode, - interface, - version, - flags, - args); -} - -uint32_t wl_proxy_get_id(struct wl_proxy *proxy) { - Expects(W::wl_proxy_get_id != nullptr); - - return W::wl_proxy_get_id(proxy); -} - -const void *wl_proxy_get_listener(struct wl_proxy *proxy) { - Expects(W::wl_proxy_get_listener != nullptr); - - return W::wl_proxy_get_listener(proxy); -} - -void wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) { - union wl_argument args[W::WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, opcode); - - // wl_proxy { wl_object { wl_interface *, ... }, ... } - struct wl_object *object = (struct wl_object*)proxy; - struct wl_interface *interface = *((struct wl_interface**)object); - W::wl_argument_from_va_list( - interface->methods[opcode].signature, - args, - W::WL_CLOSURE_MAX_ARGS, - ap); - - va_end(ap); - - wl_proxy_marshal_array_constructor(proxy, opcode, args, nullptr); -} - -struct wl_proxy *wl_proxy_marshal_constructor( - struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - ...) { - union wl_argument args[W::WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, interface); - - // wl_proxy { wl_object { wl_interface *, ... }, ... } - struct wl_object *object = (struct wl_object*)proxy; - struct wl_interface *i = *((struct wl_interface**)object); - W::wl_argument_from_va_list( - i->methods[opcode].signature, - args, - W::WL_CLOSURE_MAX_ARGS, - ap); - - va_end(ap); - - return wl_proxy_marshal_array_constructor(proxy, opcode, args, interface); -} - -struct wl_proxy *wl_proxy_marshal_constructor_versioned( - struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - ...) { - union wl_argument args[W::WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, version); - - // wl_proxy { wl_object { wl_interface *, ... }, ... } - struct wl_object *object = (struct wl_object*)proxy; - struct wl_interface *i = *((struct wl_interface**)object); - W::wl_argument_from_va_list( - i->methods[opcode].signature, - args, - W::WL_CLOSURE_MAX_ARGS, - ap); - - va_end(ap); - - return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, - args, interface, - version); -} - -struct wl_proxy *wl_proxy_marshal_flags( - struct wl_proxy *proxy, - uint32_t opcode, - const struct wl_interface *interface, - uint32_t version, - uint32_t flags, - ...) { - union wl_argument args[W::WL_CLOSURE_MAX_ARGS]; - va_list ap; - - va_start(ap, flags); - - // wl_proxy { wl_object { wl_interface *, ... }, ... } - struct wl_object *object = (struct wl_object*)proxy; - struct wl_interface *i = *((struct wl_interface**)object); - W::wl_argument_from_va_list( - i->methods[opcode].signature, - args, - W::WL_CLOSURE_MAX_ARGS, - ap); - - va_end(ap); - - if (W::wl_proxy_marshal_array_flags == nullptr) { - const auto result = wl_proxy_marshal_array_constructor_versioned( - proxy, - opcode, - args, - interface, - version); - - if (flags & WL_MARSHAL_FLAG_DESTROY) { - wl_proxy_destroy(proxy); - } - - return result; - } - - return wl_proxy_marshal_array_flags( - proxy, - opcode, - interface, - version, - flags, - args); -} - -} // extern "C" diff --git a/linux_xcb_helper/CMakeLists.txt b/linux_xcb_helper/CMakeLists.txt deleted file mode 100644 index 8344d6b..0000000 --- a/linux_xcb_helper/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# This file is part of Desktop App Toolkit, -# a set of libraries for developing nice desktop applications. -# -# For license and copyright information please follow this link: -# https://github.com/desktop-app/legal/blob/master/LEGAL - -add_library(linux_xcb_helper STATIC) -init_target(linux_xcb_helper "(external)") -add_library(desktop-app::linux_xcb_helper ALIAS linux_xcb_helper) - -nice_target_sources(linux_xcb_helper ${CMAKE_CURRENT_SOURCE_DIR} -PRIVATE - linux_xcb_helper.cpp -) diff --git a/linux_xcb_helper/linux_xcb_helper.cpp b/linux_xcb_helper/linux_xcb_helper.cpp deleted file mode 100644 index e056830..0000000 --- a/linux_xcb_helper/linux_xcb_helper.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of Desktop App Toolkit, -// a set of libraries for developing nice desktop applications. -// -// For license and copyright information please follow this link: -// https://github.com/desktop-app/legal/blob/master/LEGAL -// -#include -#include -#include -#include - -unsigned int xcb_send_request_with_fds( - xcb_connection_t *c, - int flags, - struct iovec *vector, - const xcb_protocol_request_t *req, - unsigned int num_fds, - int *fds) { - const auto send_request_with_fds = reinterpret_cast(dlsym(RTLD_NEXT, "xcb_send_request_with_fds")); - - if (!dlerror()) { - return send_request_with_fds(c, flags, vector, req, num_fds, fds); - } - - const auto send_fd = reinterpret_cast( - dlsym(RTLD_NEXT, "xcb_send_fd")); - - if (dlerror()) { - abort(); - } - - const auto send_request = reinterpret_cast(dlsym(RTLD_NEXT, "xcb_send_request")); - - if (dlerror()) { - abort(); - } - - for (int i = 0; i != num_fds; ++i) { - send_fd(c, fds[i]); - } - - return send_request(c, flags, vector, req); -} diff --git a/options_linux.cmake b/options_linux.cmake index eca8149..0d38ef0 100644 --- a/options_linux.cmake +++ b/options_linux.cmake @@ -48,6 +48,10 @@ if (DESKTOP_APP_SPECIAL_TARGET) endif() if (NOT DESKTOP_APP_USE_PACKAGED) + target_link_options(common_options + INTERFACE + -Wl,-z,muldefs + ) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_link_options(common_options INTERFACE diff --git a/target_link_optional_libraries.cmake b/target_link_optional_libraries.cmake new file mode 100644 index 0000000..59b7641 --- /dev/null +++ b/target_link_optional_libraries.cmake @@ -0,0 +1,86 @@ +# This file is part of Desktop App Toolkit, +# a set of libraries for developing nice desktop applications. +# +# For license and copyright information please follow this link: +# https://github.com/desktop-app/legal/blob/master/LEGAL + +function(generate_implib) + find_package(Python3 REQUIRED) + + set(gen_dst ${CMAKE_CURRENT_BINARY_DIR}/gen) + file(MAKE_DIRECTORY ${gen_dst}) + + foreach (lib ${ARGN}) + string(MAKE_C_IDENTIFIER ${lib} lib_identifier) + find_library(DESKTOP_APP_${lib_identifier}_PATH ${lib} REQUIRED) + get_filename_component(lib_file ${DESKTOP_APP_${lib_identifier}_PATH} NAME) + + set(gen_timestamp ${gen_dst}/implib_${lib_identifier}.timestamp) + set(gen_files + ${gen_dst}/${lib_file}.init.c + ${gen_dst}/${lib_file}.tramp.S + ) + + add_custom_command( + OUTPUT + ${gen_timestamp} + BYPRODUCTS + ${gen_files} + COMMAND + ${Python3_EXECUTABLE} + ${cmake_helpers_loc}/external/Implib.so/implib-gen.py + -o + ${gen_dst} + ${DESKTOP_APP_${lib_identifier}_PATH} + COMMAND + echo 1> ${gen_timestamp} + COMMENT "Generating dlopen helper for ${lib_file}" + DEPENDS + ${DESKTOP_APP_${lib_identifier}_PATH} + ) + + add_library(implib_${lib_identifier} STATIC) + init_target(implib_${lib_identifier} "(gen)") + generate_target(implib_${lib_identifier} timestamp ${gen_timestamp} "${gen_files}" ${gen_dst}) + endforeach() +endfunction() + +function(target_link_optional_libraries target_name) + set(writing_now "") + set(private_libs "") + set(public_libs "") + set(interface_libs "") + foreach (entry ${ARGN}) + if (${entry} STREQUAL "PRIVATE" OR ${entry} STREQUAL "PUBLIC" OR ${entry} STREQUAL "INTERFACE") + set(writing_now ${entry}) + else() + string(MAKE_C_IDENTIFIER ${entry} entry_identifier) + if (NOT TARGET implib_${entry_identifier}) + generate_implib(${entry}) + endif() + set(result + $ + $ + ) + if ("${writing_now}" STREQUAL "PRIVATE") + list(APPEND private_libs ${result}) + elseif ("${writing_now}" STREQUAL "PUBLIC") + list(APPEND public_libs ${result}) + elseif ("${writing_now}" STREQUAL "INTERFACE") + list(APPEND interface_libs ${result}) + else() + message(FATAL_ERROR "Unknown libraries scope for target ${target_name}") + endif() + endif() + endforeach() + + if (NOT "${public_libs}" STREQUAL "") + target_link_libraries(${target_name} PUBLIC ${public_libs}) + endif() + if (NOT "${private_libs}" STREQUAL "") + target_link_libraries(${target_name} PRIVATE ${private_libs}) + endif() + if (NOT "${interface_libs}" STREQUAL "") + target_link_libraries(${target_name} INTERFACE ${interface_libs}) + endif() +endfunction()