1
0
Fork 0

Optional library loading on Linux with Implib

This commit is contained in:
Ilya Fedin 2023-05-31 06:15:33 +04:00 committed by John Preston
parent 92e35993aa
commit 8316cfd167
12 changed files with 109 additions and 771 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "external/glib/cppgir"] [submodule "external/glib/cppgir"]
path = external/glib/cppgir path = external/glib/cppgir
url = https://gitlab.com/mnauw/cppgir.git url = https://gitlab.com/mnauw/cppgir.git
[submodule "external/Implib.so"]
path = external/Implib.so
url = https://github.com/yugr/Implib.so.git

View file

@ -8,12 +8,6 @@ add_subdirectory(external)
if (LINUX AND NOT DESKTOP_APP_DISABLE_JEMALLOC) if (LINUX AND NOT DESKTOP_APP_DISABLE_JEMALLOC)
add_subdirectory(linux_jemalloc_helper) add_subdirectory(linux_jemalloc_helper)
endif() 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) if (DESKTOP_APP_USE_ALLOCATION_TRACER)
add_subdirectory(linux_allocation_tracer) add_subdirectory(linux_allocation_tracer)
endif() endif()

1
external/Implib.so vendored Submodule

@ -0,0 +1 @@
Subproject commit 340e5d32a8a3fcc7ac71136abeeb80b4d7dfb9fc

View file

@ -306,28 +306,31 @@ if (LINUX)
xcb-keysyms xcb-keysyms
) )
if (TARGET Qt::WaylandClient) if (TARGET Qt::WaylandClient)
target_link_libraries(external_qt target_link_optional_libraries(external_qt
INTERFACE INTERFACE
desktop-app::linux_wayland_helper wayland-egl
wayland-cursor
wayland-client
) )
endif() endif()
if (TARGET Qt::WaylandCompositor) if (TARGET Qt::WaylandCompositor)
target_link_static_libraries(external_qt target_link_optional_libraries(external_qt
INTERFACE INTERFACE
wayland-server wayland-server
ffi
) )
endif() endif()
target_link_libraries(external_qt target_link_optional_libraries(external_qt
INTERFACE INTERFACE
desktop-app::linux_xcb_helper
fontconfig
freetype
EGL EGL
GL GL
xcb
X11
X11-xcb X11-xcb
xcb
)
target_link_libraries(external_qt
INTERFACE
fontconfig
freetype
X11
glib-2.0 glib-2.0
) )
endif() endif()

View file

@ -12,5 +12,5 @@ if (DESKTOP_APP_USE_PACKAGED)
pkg_check_modules(WAYLAND_CLIENT REQUIRED IMPORTED_TARGET wayland-client) pkg_check_modules(WAYLAND_CLIENT REQUIRED IMPORTED_TARGET wayland-client)
target_link_libraries(external_wayland_client INTERFACE PkgConfig::WAYLAND_CLIENT) target_link_libraries(external_wayland_client INTERFACE PkgConfig::WAYLAND_CLIENT)
else() else()
target_link_libraries(external_wayland_client INTERFACE desktop-app::linux_wayland_helper) target_link_optional_libraries(external_wayland_client INTERFACE wayland-client)
endif() endif()

View file

@ -16,5 +16,5 @@ if (DESKTOP_APP_USE_PACKAGED)
pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb) pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb)
target_link_libraries(external_xcb INTERFACE PkgConfig::XCB) target_link_libraries(external_xcb INTERFACE PkgConfig::XCB)
else() else()
target_link_libraries(external_xcb INTERFACE xcb) target_link_optional_libraries(external_xcb INTERFACE xcb)
endif() endif()

View file

@ -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
)

View file

@ -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 <dlfcn.h>
#include <errno.h>
#include <gsl/gsl>
#include <wayland-egl.h>
#include <wayland-cursor.h>
#include <iostream>
#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<void, HandleDeleter>;
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 <typename Function>
inline bool LoadSymbol(
const Handle &handle,
const char *name,
Function &func,
bool silent = false) {
func = handle
? reinterpret_cast<Function>(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"

View file

@ -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
)

View file

@ -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 <dlfcn.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/xcbext.h>
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<unsigned int(*)(
xcb_connection_t*,
int,
struct iovec*,
const xcb_protocol_request_t*,
unsigned int,
int*)>(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<void(*)(xcb_connection_t*, int)>(
dlsym(RTLD_NEXT, "xcb_send_fd"));
if (dlerror()) {
abort();
}
const auto send_request = reinterpret_cast<unsigned int(*)(
xcb_connection_t*,
int,
struct iovec*,
const xcb_protocol_request_t*)>(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);
}

View file

@ -48,6 +48,10 @@ if (DESKTOP_APP_SPECIAL_TARGET)
endif() endif()
if (NOT DESKTOP_APP_USE_PACKAGED) if (NOT DESKTOP_APP_USE_PACKAGED)
target_link_options(common_options
INTERFACE
-Wl,-z,muldefs
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_options(common_options target_link_options(common_options
INTERFACE INTERFACE

View file

@ -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
$<LINK_ONLY:implib_${entry_identifier}>
$<TARGET_FILE:implib_${entry_identifier}>
)
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()