[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