Skip to content

Commit 4c32a6a

Browse files
committed
Look for backend implementations in a specific directory
Make the backend loader search for implementations in the <libdir>/wpe-<apiversion> directory (typically /usr/lib/wpe-1.0) when a relative path is passed to wpe_loader_init(). Fixes #59
1 parent da9540e commit 4c32a6a

File tree

6 files changed

+83
-38
lines changed

6 files changed

+83
-38
lines changed

CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(LIBWPE 5 0 4)
1919
project(libwpe VERSION "${PROJECT_VERSION}")
2020

2121
set(WPE_BACKEND "" CACHE STRING
22-
"Name of the backend library to load, instead of libWPEBackend-default.so")
22+
"Path of a fixed backend library to load, instead of libWPEBackend-default.so")
2323

2424
include(CheckCCompilerFlag)
2525
include(CheckCXXCompilerFlag)
@@ -86,6 +86,7 @@ target_include_directories(wpe PRIVATE
8686
)
8787
target_compile_definitions(wpe PRIVATE
8888
WPE_COMPILATION
89+
WPE_BACKENDS_DIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/wpe-${WPE_API_VERSION}\"
8990
$<TARGET_PROPERTY:GL::egl,INTERFACE_COMPILE_DEFINITIONS>
9091
)
9192
if (WPE_BACKEND)

docs/backend-implementing.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Implementing Backends
2+
3+
## Installation
4+
5+
Backend implementations must be installed to a specific directory. The
6+
location is determined at build time to be `<prefix>/lib/wpe-<apiversion>`,
7+
with `<prefix>` being the base directory where *libwpe* is installed, and
8+
`<apiversion>` the public API version.
9+
10+
The `pkg-config` tool can be used to query the `backendsdir` variable,
11+
which contains the location where backend implementations will be searched
12+
for:
13+
14+
```sh
15+
pkg-config wpe-1.0 --variable=backendsdir
16+
```
17+
18+
For example, the following Make snippet will install a backend in the
19+
correct location:
20+
21+
```make
22+
install: libMyBackend.so
23+
install -Dm755 -t "$$(pkg-config wpe-1.0 --variable=backendsdir)" $<
24+
```

docs/sitemap.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
index.md
2+
backend-implementing.md
23
c-index

include/wpe/loader.h

+13-4
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,15 @@ struct wpe_loader_interface {
6969
* @impl_library_name: (transfer none): Name of the shared library object
7070
* to load as WPE backend implementation.
7171
*
72-
* Initializes the `libwpe` object loader
72+
* Initializes the `libwpe` object loader. If the @impl_library_name is a
73+
* full path it will be used as-is, while a relative path will cause the
74+
* backend implementation library to be searched for in a fixed location.
75+
*
76+
* The backends location is determined at build time, and typically will
77+
* be `<prefix>/lib/wpe-<apiversion>`, where `<prefix>` is the installation
78+
* prefix and `<apiversion>` is the libwpe API version being used. See the
79+
* [backend implementation
80+
* documentation](backend-implementing.md#Installation) for more.
7381
*
7482
* Returns: Whether initialization succeeded.
7583
*/
@@ -81,10 +89,11 @@ wpe_loader_init(const char* impl_library_name);
8189
* wpe_loader_get_loaded_implementation_library_name:
8290
*
8391
* Obtain the name of the shared library object loaded as WPE backend
84-
* implementation. Note that in general this will return the value passed
85-
* to wpe_loader_init(), but that is not guaranteed.
92+
* implementation. Note that in general this will return the actual location
93+
* of the backend being used, which may not be the same value passed to
94+
* wpe_loader_init().
8695
*
87-
* Returns: (transfer none): Name of the shared library object for the
96+
* Returns: (transfer none): Path of the shared library object for the
8897
* backend implementation.
8998
*/
9099
WPE_EXPORT

src/loader.c

+42-33
Original file line numberDiff line numberDiff line change
@@ -31,68 +31,67 @@
3131
#include <stdlib.h>
3232
#include <string.h>
3333

34+
#define LENGTHOF(array) (sizeof(array) / sizeof(array[0]))
35+
3436
static void* s_impl_library = 0;
3537
static struct wpe_loader_interface* s_impl_loader = 0;
3638

3739
#ifndef WPE_BACKEND
38-
#define IMPL_LIBRARY_NAME_BUFFER_SIZE 512
39-
static char* s_impl_library_name;
40-
static char s_impl_library_name_buffer[IMPL_LIBRARY_NAME_BUFFER_SIZE];
40+
static char* s_impl_library_path = NULL;
41+
static char s_impl_library_path_buffer[512];
4142
#endif
4243

4344
#ifndef WPE_BACKEND
4445
static void
45-
wpe_loader_set_impl_library_name(const char* impl_library_name)
46+
wpe_loader_set_impl_library_path(const char* impl_library_path)
4647
{
47-
size_t len;
48-
49-
if (!impl_library_name)
48+
if (!impl_library_path)
5049
return;
5150

52-
len = strlen(impl_library_name) + 1;
51+
size_t len = strlen(impl_library_path) + 1;
5352
if (len == 1)
5453
return;
5554

56-
if (len > IMPL_LIBRARY_NAME_BUFFER_SIZE)
57-
s_impl_library_name = (char *)malloc(len);
55+
if (len > LENGTHOF(s_impl_library_path_buffer))
56+
s_impl_library_path = malloc(len);
5857
else
59-
s_impl_library_name = s_impl_library_name_buffer;
60-
memcpy(s_impl_library_name, impl_library_name, len);
58+
s_impl_library_path = s_impl_library_path_buffer;
59+
memcpy(s_impl_library_path, impl_library_path, len);
6160
}
62-
#endif
61+
#endif /* !WPE_BACKEND */
6362

6463
void
65-
load_impl_library()
64+
load_impl_library(void)
6665
{
6766
#ifdef WPE_BACKEND
6867
s_impl_library = dlopen(WPE_BACKEND, RTLD_NOW);
6968
if (!s_impl_library) {
7069
fprintf(stderr, "wpe: could not load compile-time defined WPE_BACKEND: %s\n", dlerror());
7170
abort();
7271
}
73-
#else
72+
#else /* !WPE_BACKEND */
7473
#ifndef NDEBUG
7574
// Get the impl library from an environment variable, if available.
76-
char* env_library_name = getenv("WPE_BACKEND_LIBRARY");
77-
if (env_library_name) {
78-
s_impl_library = dlopen(env_library_name, RTLD_NOW);
75+
const char* env_library_path = getenv("WPE_BACKEND_LIBRARY");
76+
if (env_library_path) {
77+
s_impl_library = dlopen(env_library_path, RTLD_NOW);
7978
if (!s_impl_library) {
8079
fprintf(stderr, "wpe: could not load specified WPE_BACKEND_LIBRARY: %s\n", dlerror());
8180
abort();
8281
}
83-
wpe_loader_set_impl_library_name(env_library_name);
82+
wpe_loader_set_impl_library_path(env_library_path);
8483
}
85-
#endif
84+
#endif /* !NDEBUG */
8685
if (!s_impl_library) {
8786
// Load libWPEBackend-default.so by ... default.
88-
s_impl_library = dlopen("libWPEBackend-default.so", RTLD_NOW);
87+
s_impl_library = dlopen(WPE_BACKENDS_DIR "/libWPEBackend-default.so", RTLD_NOW);
8988
if (!s_impl_library) {
9089
fprintf(stderr, "wpe: could not load the impl library. Is there any backend installed?: %s\n", dlerror());
9190
abort();
9291
}
93-
wpe_loader_set_impl_library_name("libWPEBackend-default.so");
92+
wpe_loader_set_impl_library_path(WPE_BACKENDS_DIR "/libWPEBackend-default.so");
9493
}
95-
#endif
94+
#endif /* WPE_BACKEND */
9695

9796
s_impl_loader = dlsym(s_impl_library, "_wpe_loader_interface");
9897
}
@@ -101,41 +100,51 @@ bool
101100
wpe_loader_init(const char* impl_library_name)
102101
{
103102
#ifndef WPE_BACKEND
104-
if (!impl_library_name) {
103+
if (!(impl_library_name && impl_library_name[0] != '\0')) {
105104
fprintf(stderr, "wpe_loader_init: invalid implementation library name\n");
106105
abort();
107106
}
108107

108+
const bool relative_path = (impl_library_name[0] != '/');
109+
110+
size_t len = strlen(impl_library_name) + 1 + (relative_path ? LENGTHOF(WPE_BACKENDS_DIR) : 0);
111+
char impl_library_path[len];
112+
113+
if (relative_path)
114+
snprintf(impl_library_path, len, WPE_BACKENDS_DIR "/%s", impl_library_name);
115+
else
116+
strncpy(impl_library_path, impl_library_name, len);
117+
109118
if (s_impl_library) {
110-
if (!s_impl_library_name || strcmp(s_impl_library_name, impl_library_name) != 0) {
119+
if (!s_impl_library_path || strcmp(s_impl_library_path, impl_library_path) != 0) {
111120
fprintf(stderr, "wpe_loader_init: already initialized\n");
112121
return false;
113122
}
114123
return true;
115124
}
116125

117-
s_impl_library = dlopen(impl_library_name, RTLD_NOW);
126+
s_impl_library = dlopen(impl_library_path, RTLD_NOW);
118127
if (!s_impl_library) {
119-
fprintf(stderr, "wpe_loader_init could not load the library '%s': %s\n", impl_library_name, dlerror());
128+
fprintf(stderr, "wpe_loader_init could not load the library '%s': %s\n", impl_library_path, dlerror());
120129
return false;
121130
}
122-
wpe_loader_set_impl_library_name(impl_library_name);
131+
wpe_loader_set_impl_library_path(impl_library_path);
123132

124133
s_impl_loader = dlsym(s_impl_library, "_wpe_loader_interface");
125134
return true;
126-
#else
135+
#else /* WPE_BACKEND */
127136
return false;
128-
#endif
137+
#endif /* !WPE_BACKEND */
129138
}
130139

131140
const char*
132141
wpe_loader_get_loaded_implementation_library_name(void)
133142
{
134143
#ifdef WPE_BACKEND
135144
return s_impl_library ? WPE_BACKEND : NULL;
136-
#else
137-
return s_impl_library_name;
138-
#endif
145+
#else /* !WPE_BACKEND */
146+
return s_impl_library_path;
147+
#endif /* WPE_BACKEND */
139148
}
140149

141150
void*

wpe.pc.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ prefix=@CMAKE_INSTALL_PREFIX@
22
exec_prefix=${prefix}
33
includedir=${prefix}/include
44
libdir=${exec_prefix}/lib
5+
backendsdir=${libdir}/wpe-@WPE_API_VERSION@
56

67
Name: wpe-@WPE_API_VERSION@
78
Description: The wpe library

0 commit comments

Comments
 (0)