[waffle] [PATCH 4/4] wayland: resolve wayland-client symbols at runtime (via libdl)

Emil Velikov emil.l.velikov at gmail.com
Mon Feb 23 12:32:28 PST 2015


As the wayland public headers define some functions as static inline,
it's not straight forward if one we want to remove the link-time
dependency of the library (libwayland-client.so.0).

To do so, we define the symbols within the wayland "wrapper", which
makes sure that the symbols are retrieved as usable, as we dlopen/dlsym
the library early within the setup process (wayland_platform_create).

Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
---
 .../Modules/WafflePrintConfigurationSummary.cmake  |   1 -
 src/waffle/CMakeLists.txt                          |   6 +-
 src/waffle/wayland/wayland_platform.c              |   6 +
 src/waffle/wayland/wayland_wrapper.c               | 152 +++++++++++++++++++++
 src/waffle/wayland/wayland_wrapper.h               |  32 +++++
 5 files changed, 191 insertions(+), 6 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_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_wrapper.c b/src/waffle/wayland/wayland_wrapper.c
new file mode 100644
index 0000000..cb4b0cc
--- /dev/null
+++ b/src/waffle/wayland/wayland_wrapper.c
@@ -0,0 +1,152 @@
+// 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.
+///
+/// Each "wrapper" uses dlsym to retrieve the relevant symbol from the library.
+/// Then we use the object file at link-time, in order to satisfy the
+/// dependencies.
+
+
+#include <stdbool.h>
+#include <dlfcn.h>
+
+#include <wayland-util.h> // for struct wl_interface
+
+#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";
+
+// Data symbols
+const struct wl_interface *wl_compositor_interface;
+const struct wl_interface *wl_registry_interface;
+const struct wl_interface *wl_shell_interface;
+const struct wl_interface *wl_shell_surface_interface;
+const struct wl_interface *wl_surface_interface;
+
+
+// Function pointers
+struct wl_display;
+struct wl_proxy;
+
+struct wl_display *
+(*wl_display_connect)(const char *name);
+
+void
+(*wl_display_disconnect)(struct wl_display *display);
+
+int
+(*wl_display_roundtrip)(struct wl_display *display);
+
+
+void
+(*wl_proxy_destroy)(struct wl_proxy *proxy);
+
+int
+(*wl_proxy_add_listener)(struct wl_proxy *proxy,
+                         void (**implementation)(void), void *data);
+
+void
+(*wl_proxy_marshal)(struct wl_proxy *p, uint32_t opcode, ...);
+struct wl_proxy *
+(*wl_proxy_marshal_constructor)(struct wl_proxy *proxy,
+                                uint32_t opcode,
+                                const struct wl_interface *interface,
+                                ...);
+
+
+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)                            \
+    S = (__typeof__(S))dlsym(dl_wl_client, #S);                 \
+    if (!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..717ae7b
--- /dev/null
+++ b/src/waffle/wayland/wayland_wrapper.h
@@ -0,0 +1,32 @@
+// 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
+
+bool
+wayland_wrapper_init(void);
+
+bool
+wayland_wrapper_teardown(void);
-- 
2.3.0



More information about the waffle mailing list