[waffle] [PATCH v2 4/4] wayland: resolve wayland-client symbols at runtime (via libdl)
Emil Velikov
emil.l.velikov at gmail.com
Tue Mar 3 08:27:40 PST 2015
By doing so one can use waffle's other platforms, without having
wayland installed/available on their system.
This patch is based on a similar work by the SDL devs.
v2:
- Remove implementation details from commit message.
- Follow SDL's approach.
Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
---
.../Modules/WafflePrintConfigurationSummary.cmake | 1 -
src/waffle/CMakeLists.txt | 6 +-
src/waffle/wayland/wayland_display.c | 2 +-
src/waffle/wayland/wayland_platform.c | 6 ++
src/waffle/wayland/wayland_window.c | 1 +
src/waffle/wayland/wayland_wrapper.c | 115 +++++++++++++++++++++
src/waffle/wayland/wayland_wrapper.h | 97 +++++++++++++++++
7 files changed, 221 insertions(+), 7 deletions(-)
create mode 100644 src/waffle/wayland/wayland_wrapper.c
create mode 100644 src/waffle/wayland/wayland_wrapper.h
diff --git a/cmake/Modules/WafflePrintConfigurationSummary.cmake b/cmake/Modules/WafflePrintConfigurationSummary.cmake
index 27aa8dc..1199ea3 100644
--- a/cmake/Modules/WafflePrintConfigurationSummary.cmake
+++ b/cmake/Modules/WafflePrintConfigurationSummary.cmake
@@ -60,7 +60,6 @@ if(waffle_has_glx)
endif()
if(waffle_has_wayland)
message(" wayland-client_INCLUDE_DIRS: ${wayland-client_INCLUDE_DIRS}")
- message(" wayland-client_LDFLAGS: ${wayland-client_LDFLAGS}")
message(" wayland-egl_INCLUDE_DIRS: ${wayland-egl_INCLUDE_DIRS}")
endif()
if(waffle_has_x11)
diff --git a/src/waffle/CMakeLists.txt b/src/waffle/CMakeLists.txt
index 4a473be..4f1d5c7 100644
--- a/src/waffle/CMakeLists.txt
+++ b/src/waffle/CMakeLists.txt
@@ -41,11 +41,6 @@ list(APPEND waffle_libdeps
)
if(waffle_on_linux)
- if(waffle_has_wayland)
- list(APPEND waffle_libdeps
- ${wayland-client_LDFLAGS}
- )
- endif()
if(waffle_has_x11)
list(APPEND waffle_libdeps
${x11-xcb_LDFLAGS}
@@ -137,6 +132,7 @@ if(waffle_has_wayland)
wayland/wayland_display.c
wayland/wayland_platform.c
wayland/wayland_window.c
+ wayland/wayland_wrapper.c
)
endif()
diff --git a/src/waffle/wayland/wayland_display.c b/src/waffle/wayland/wayland_display.c
index e7c6e94..6fc4cd0 100644
--- a/src/waffle/wayland/wayland_display.c
+++ b/src/waffle/wayland/wayland_display.c
@@ -28,7 +28,7 @@
#include <stdlib.h>
#include <string.h>
-#include <wayland-client.h>
+#include "wayland_wrapper.h"
#undef container_of
#include "wcore_error.h"
diff --git a/src/waffle/wayland/wayland_platform.c b/src/waffle/wayland/wayland_platform.c
index 94c0010..2746ca1 100644
--- a/src/waffle/wayland/wayland_platform.c
+++ b/src/waffle/wayland/wayland_platform.c
@@ -43,6 +43,7 @@
#include "wayland_display.h"
#include "wayland_platform.h"
#include "wayland_window.h"
+#include "wayland_wrapper.h"
static const char *libwl_egl_filename = "libwayland-egl.so.1";
@@ -73,6 +74,7 @@ wayland_platform_destroy(struct wcore_platform *wc_self)
}
}
+ ok &= wayland_wrapper_teardown();
ok &= wegl_platform_teardown(&self->wegl);
free(self);
return ok;
@@ -92,6 +94,10 @@ wayland_platform_create(void)
if (!ok)
goto error;
+ ok = wayland_wrapper_init();
+ if (!ok)
+ goto error;
+
self->dl_wl_egl = dlopen(libwl_egl_filename, RTLD_LAZY | RTLD_LOCAL);
if (!self->dl_wl_egl) {
wcore_errorf(WAFFLE_ERROR_FATAL,
diff --git a/src/waffle/wayland/wayland_window.c b/src/waffle/wayland/wayland_window.c
index 2cdf8e6..acdc638 100644
--- a/src/waffle/wayland/wayland_window.c
+++ b/src/waffle/wayland/wayland_window.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
+#include "wayland_wrapper.h" // Must include this before wayland-egl.h
#include <wayland-egl.h>
#undef container_of
diff --git a/src/waffle/wayland/wayland_wrapper.c b/src/waffle/wayland/wayland_wrapper.c
new file mode 100644
index 0000000..6ffd5a9
--- /dev/null
+++ b/src/waffle/wayland/wayland_wrapper.c
@@ -0,0 +1,115 @@
+// Copyright 2015 Emil Velikov
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// @file
+/// @brief Wrappers for Wayland-client functions
+///
+/// Many of the wayland functions are defined as static inline within the
+/// public headers. In order to avoid the static(link-time) dependency, we
+/// provide the required symbols with this file.
+///
+/// This is achieved by declaring wrapper functions, around which we define the
+/// needed (base) wayland ones. After that we include the public header, at
+/// which point the pre-processor/compiler will use our defines.
+///
+/// Each wrapper is initialised via dlsym to retrieve the relevant symbol from
+/// the library libwayland-client.so.0
+
+
+#include <stdbool.h>
+#include <dlfcn.h>
+
+#include "wcore_error.h"
+
+#include "wayland_wrapper.h"
+
+// dlopen handle for libwayland-client.so.0
+static void *dl_wl_client;
+
+static const char *libwl_client_filename = "libwayland-client.so.0";
+
+bool
+wayland_wrapper_teardown(void)
+{
+ bool ok = true;
+ int error;
+
+ if (dl_wl_client) {
+ error = dlclose(dl_wl_client);
+ if (error) {
+ ok &= false;
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN,
+ "dlclose(\"%s\") failed: %s",
+ libwl_client_filename, dlerror());
+ }
+ }
+
+ return ok;
+}
+
+bool
+wayland_wrapper_init(void)
+{
+ bool ok = true;
+
+ dl_wl_client = dlopen(libwl_client_filename, RTLD_LAZY | RTLD_LOCAL);
+ if (!dl_wl_client) {
+ wcore_errorf(WAFFLE_ERROR_FATAL,
+ "dlopen(\"%s\") failed: %s",
+ libwl_client_filename, dlerror());
+ ok = false;
+ goto error;
+ }
+
+#define RETRIEVE_WL_CLIENT_SYMBOL(S) \
+ wfl_##S = (__typeof__(wfl_##S))dlsym(dl_wl_client, #S); \
+ if (!wfl_##S) { \
+ wcore_errorf(WAFFLE_ERROR_FATAL, \
+ "dlsym(\"%s\", \"" #S "\") failed: %s", \
+ libwl_client_filename, dlerror()); \
+ ok = false; \
+ goto error; \
+ }
+
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_compositor_interface);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_registry_interface);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_shell_interface);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_shell_surface_interface);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_surface_interface);
+
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_display_connect);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_display_disconnect);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_display_roundtrip);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_destroy);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_add_listener);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_marshal);
+ RETRIEVE_WL_CLIENT_SYMBOL(wl_proxy_marshal_constructor);
+#undef RETRIEVE_WL_CLIENT_SYMBOL
+
+error:
+ // On failure the caller of wayland_wrapper_init will trigger it's own
+ // destruction which will execute wayland_wrapper_teardown.
+ return ok;
+}
diff --git a/src/waffle/wayland/wayland_wrapper.h b/src/waffle/wayland/wayland_wrapper.h
new file mode 100644
index 0000000..de8ce2d
--- /dev/null
+++ b/src/waffle/wayland/wayland_wrapper.h
@@ -0,0 +1,97 @@
+// Copyright 2015 Emil Velikov
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// - Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma once
+
+#include <stdbool.h>
+#include "wayland-util.h"
+
+bool
+wayland_wrapper_init(void);
+
+bool
+wayland_wrapper_teardown(void);
+
+
+// Data symbols
+const struct wl_interface *wfl_wl_compositor_interface;
+const struct wl_interface *wfl_wl_registry_interface;
+const struct wl_interface *wfl_wl_shell_interface;
+const struct wl_interface *wfl_wl_shell_surface_interface;
+const struct wl_interface *wfl_wl_surface_interface;
+
+
+// Forward declaration of the structs required by the functions
+struct wl_proxy;
+struct wl_display;
+
+
+// Functions
+struct wl_display *
+(*wfl_wl_display_connect)(const char *name);
+
+void
+(*wfl_wl_display_disconnect)(struct wl_display *display);
+
+int
+(*wfl_wl_display_roundtrip)(struct wl_display *display);
+
+
+void
+(*wfl_wl_proxy_destroy)(struct wl_proxy *proxy);
+
+int
+(*wfl_wl_proxy_add_listener)(struct wl_proxy *proxy,
+ void (**implementation)(void), void *data);
+
+void
+(*wfl_wl_proxy_marshal)(struct wl_proxy *p, uint32_t opcode, ...);
+
+struct wl_proxy *
+(*wfl_wl_proxy_marshal_constructor)(struct wl_proxy *proxy,
+ uint32_t opcode,
+ const struct wl_interface *interface,
+ ...);
+
+#ifdef _WAYLAND_CLIENT_H
+#error Do not include wayland-client.h ahead of wayland_wrapper.h
+#endif
+
+#define wl_compositor_interface (*wfl_wl_compositor_interface)
+#define wl_registry_interface (*wfl_wl_registry_interface)
+#define wl_shell_interface (*wfl_wl_shell_interface)
+#define wl_shell_surface_interface (*wfl_wl_shell_surface_interface)
+#define wl_surface_interface (*wfl_wl_surface_interface)
+
+#define wl_display_connect (*wfl_wl_display_connect)
+#define wl_display_disconnect (*wfl_wl_display_disconnect)
+#define wl_display_roundtrip (*wfl_wl_display_roundtrip)
+#define wl_proxy_destroy (*wfl_wl_proxy_destroy)
+#define wl_proxy_add_listener (*wfl_wl_proxy_add_listener)
+#define wl_proxy_marshal (*wfl_wl_proxy_marshal)
+#define wl_proxy_marshal_constructor (*wfl_wl_proxy_marshal_constructor)
+
+
+#include <wayland-client.h>
--
2.3.1
More information about the waffle
mailing list