[tracker/wip/carlosg/two-spoonfuls-of-soup] libtracker-sparql: Allow building against multiple versions of libsoup
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/two-spoonfuls-of-soup] libtracker-sparql: Allow building against multiple versions of libsoup
- Date: Wed, 28 Jul 2021 21:01:28 +0000 (UTC)
commit 87b89b99a3f0cdf708d6c5f85acd64f6bfd26ca1
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Jul 28 12:53:47 2021 +0200
libtracker-sparql: Allow building against multiple versions of libsoup
Tracker is an innocent bystander hindering libsoup3 port, since the
libsoup2/3->tracker->gtk3 dependency chain imposes a libsoup version,
graphical applications using libsoup cannot port at their own pace.
Make our remote code (connection & endpoint) be a private module
that is built against both versions of libsoup (if found), then we
pick one at runtime, with a preference on libsoup3 if libsoup2 .so
file is not seen in the already loaded libraries.
This patch should be reverted ASAP, once we can consider libsoup2
deprecated.
Fixes: https://gitlab.gnome.org/GNOME/tracker/-/issues/320
config.h.meson.in | 3 +
meson.build | 27 ++++--
meson_options.txt | 4 +-
src/libtracker-sparql/meson.build | 60 ++++++++++++--
src/libtracker-sparql/remote/meson.build | 36 --------
src/libtracker-sparql/tracker-backend.vala | 5 --
src/libtracker-sparql/tracker-remote-module.c | 115 ++++++++++++++++++++++++++
7 files changed, 195 insertions(+), 55 deletions(-)
---
diff --git a/config.h.meson.in b/config.h.meson.in
index 9d1439e91..4aff15f72 100644
--- a/config.h.meson.in
+++ b/config.h.meson.in
@@ -57,3 +57,6 @@
/* Define to the Tracker minor version */
#mesondefine TRACKER_MINOR_VERSION
+
+/* Whether RTLD_NOLOAD is defined */
+#mesondefine HAVE_RTLD_NOLOAD
diff --git a/meson.build b/meson.build
index aae611bca..ed8fdd3ff 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
project('tracker', 'c', 'vala',
version: '3.2.0.alpha.1',
- meson_version: '>=0.51',
+ meson_version: '>=0.56',
default_options: [
'c_std=c99',
'warning_level=2'])
@@ -44,6 +44,7 @@ sqlite_required = '3.15.0'
gio = dependency('gio-2.0', version: '>' + glib_required)
gio_unix = dependency('gio-unix-2.0', version: '>' + glib_required)
glib = dependency('glib-2.0', version: '>' + glib_required)
+gmodule = dependency('gmodule-2.0', version: '>' + glib_required)
gobject = dependency('gobject-2.0', version: '>' + glib_required)
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
icu_i18n = dependency('icu-i18n', version: '> 4.8.1.1', required: false)
@@ -52,14 +53,23 @@ json_glib = dependency('json-glib-1.0', version: '>= 1.4', required: true)
libxml2 = dependency('libxml-2.0', version: '> 2.6')
sqlite = dependency('sqlite3', version: '>' + sqlite_required)
dbus = dependency('dbus-1')
+libsoup2 = dependency('libsoup-2.4', version: '> 2.40', required: false)
+libsoup3 = dependency('libsoup-3.0', version: '>= 2.99.2', required: false)
-if get_option('soup2')
- libsoup = dependency('libsoup-2.4', version: '> 2.40', required: true)
-else
- libsoup = dependency('libsoup-3.0', version: '>= 2.99.2', required: true)
+libmath = cc.find_library('m', required: false)
+libdl = cc.find_library('dl')
+
+soup_backends = ''
+if libsoup2.found()
+ soup_backends = soup_backends + '2.x '
+endif
+if libsoup3.found()
+ soup_backends = soup_backends + '3.x '
endif
-libmath = cc.find_library('m', required: false)
+if not libsoup2.found() and not libsoup3.found()
+ error('At least one of libsoup2 or libsoup3 is required')
+endif
if get_option('man')
asciidoc = find_program('asciidoc')
@@ -293,6 +303,10 @@ conf.set('TRACKER_MICRO_VERSION', tracker_micro_version)
conf.set('TRACKER_INTERFACE_AGE', 0)
conf.set('TRACKER_BINARY_AGE', 100 * tracker_minor_version + tracker_micro_version)
+# Check for RTLD_NOLOAD
+have_rtld_noload = cc.has_header_symbol('dlfcn.h', 'RTLD_NOLOAD')
+conf.set('HAVE_RTLD_NOLOAD', have_rtld_noload)
+
# Config that goes in some other generated files (.desktop, .service, etc)
conf.set('abs_top_builddir', meson.current_build_dir())
conf.set('libexecdir', join_paths(get_option('prefix'), get_option('libexecdir')))
@@ -387,6 +401,7 @@ summary = [
' Build with Stemming support: ' + have_libstemmer.to_string(),
' API documentation: ' + get_option('docs').to_string(),
' CLI documentation (manpages): ' + get_option('man').to_string(),
+ ' Libsoup backends: ' + soup_backends,
]
if get_option('bash_completion')
diff --git a/meson_options.txt b/meson_options.txt
index a5cccb891..a7e647d02 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -26,7 +26,5 @@ option('test_utils_dir', type: 'string', value: '',
description: 'Directory to install trackertestutils Python package (or empty to use the default)')
option('tests_tap_protocol', type: 'boolean', value: false,
description: 'Whether to enable TAP protocol on tests')
-option('soup2', type: 'boolean', value: true,
- description: 'Whether to build with libsoup2')
option('introspection', type: 'feature', value: 'enabled',
- description: 'Whether to enable introspection')
\ No newline at end of file
+ description: 'Whether to enable introspection')
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index 6fcc8a667..4f09d9657 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -20,7 +20,6 @@ libtracker_sparql_c_sources = files(
'tracker-cursor.c',
'tracker-endpoint.c',
'tracker-endpoint-dbus.c',
- 'tracker-endpoint-http.c',
'tracker-error.c',
'tracker-namespace-manager.c',
'tracker-notifier.c',
@@ -54,7 +53,7 @@ libtracker_sparql_c_public_headers = files(
libtracker_sparql_intermediate = static_library('tracker-sparql-intermediate',
enum_types,
libtracker_sparql_c_sources,
- dependencies: [tracker_common_dep, json_glib, libxml2, libsoup],
+ dependencies: [tracker_common_dep, json_glib, libxml2],
gnu_symbol_visibility: 'hidden',
)
@@ -63,7 +62,7 @@ sparqlinc = [include_directories('.'), meson.current_build_dir()]
tracker_sparql_intermediate_dep = declare_dependency(
link_with: [libtracker_sparql_intermediate],
include_directories: [srcinc, include_directories('.')],
- dependencies: [ tracker_sparql_vapi_dep ],
+ dependencies: [ tracker_sparql_vapi_dep, tracker_data_dep ],
sources: enum_types[1],
)
@@ -88,13 +87,61 @@ install_data(
subdir('bus')
subdir('direct')
-subdir('remote')
+
+tracker_remote_dependencies = [json_glib, libxml2]
+
+remote_sources = [
+ 'tracker-endpoint-http.c',
+ 'remote/tracker-json-cursor.vala',
+ 'remote/tracker-xml-cursor.vala',
+ 'remote/tracker-remote.vala',
+]
+
+if libsoup2.found()
+ libtracker_remote_soup2 = shared_module('tracker-remote-soup2', remote_sources,
+ dependencies: tracker_remote_dependencies + [tracker_common_dep, tracker_sparql_intermediate_dep,
libsoup2],
+ c_args: tracker_c_args + [
+ '-include', 'config.h',
+ '-include', 'libtracker-sparql/tracker-private.h',
+ ],
+ vala_args: [
+ '--debug',
+ '--pkg', 'posix',
+ # FIXME: Meson has code to add --target-glib automatically, but it
+ # doesn't seem to work here.
+ '--target-glib', glib_required,
+ '--define=SOUP2',
+ ],
+ install: true,
+ install_dir: tracker_internal_libs_dir,
+ )
+endif
+
+if libsoup3.found()
+ libtracker_remote_soup3 = shared_module('tracker-remote-soup3', remote_sources,
+ dependencies: tracker_remote_dependencies + [tracker_common_dep, tracker_sparql_intermediate_dep,
libsoup3],
+ c_args: tracker_c_args + [
+ '-include', 'config.h',
+ '-include', 'libtracker-sparql/tracker-private.h',
+ ],
+ vala_args: [
+ '--debug',
+ '--pkg', 'posix',
+ # FIXME: Meson has code to add --target-glib automatically, but it
+ # doesn't seem to work here.
+ '--target-glib', glib_required,
+ ],
+ install: true,
+ install_dir: tracker_internal_libs_dir,
+ )
+endif
libtracker_sparql = library('tracker-sparql-' + tracker_api_version,
'../libtracker-common/libtracker-common.vapi',
'../libtracker-data/libtracker-data.vapi',
'direct/tracker-direct.vapi',
'tracker-backend.vala',
+ 'tracker-remote-module.c',
tracker_gresources,
gnu_symbol_visibility: 'hidden',
@@ -107,11 +154,14 @@ libtracker_sparql = library('tracker-sparql-' + tracker_api_version,
c_args: [
'-include', 'libtracker-sparql/tracker-private.h',
+ '-DPRIVATE_LIBDIR="@0@"'.format(tracker_internal_libs_dir),
+ '-DBUILD_LIBDIR="@0@"'.format(meson.current_build_dir()),
+ '-DBUILDROOT="@0@"'.format(meson.project_build_root()),
],
link_whole: [libtracker_sparql_intermediate],
- dependencies: [tracker_common_dep, tracker_sparql_remote_dep, tracker_sparql_bus_dep,
tracker_sparql_direct_dep, tracker_sparql_vapi_dep],
+ dependencies: [tracker_common_dep, tracker_sparql_bus_dep, tracker_sparql_direct_dep,
tracker_sparql_vapi_dep, gmodule, libdl],
)
tracker_sparql_dep = declare_dependency(
diff --git a/src/libtracker-sparql/tracker-backend.vala b/src/libtracker-sparql/tracker-backend.vala
index ae6313118..af1102d5a 100644
--- a/src/libtracker-sparql/tracker-backend.vala
+++ b/src/libtracker-sparql/tracker-backend.vala
@@ -22,11 +22,6 @@
* effect of printing the 'help' message if TRACKER_DEBUG=help is set.
*/
-public static Tracker.Sparql.Connection tracker_sparql_connection_remote_new (string url_base) {
- Tracker.get_debug_flags ();
- return new Tracker.Remote.Connection (url_base);
-}
-
public static Tracker.Sparql.Connection tracker_sparql_connection_bus_new (string service, string?
object_path, DBusConnection? conn) throws Tracker.Sparql.Error, IOError, DBusError, GLib.Error {
Tracker.get_debug_flags ();
diff --git a/src/libtracker-sparql/tracker-remote-module.c b/src/libtracker-sparql/tracker-remote-module.c
new file mode 100644
index 000000000..2ca0fd181
--- /dev/null
+++ b/src/libtracker-sparql/tracker-remote-module.c
@@ -0,0 +1,115 @@
+/* Yuck */
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <tracker-sparql.h>
+#include <dlfcn.h>
+
+#define LIBSOUP_2_SONAME "libsoup-2.4.so.1"
+
+static gboolean initialized = FALSE;
+
+GType (* remote_endpoint_get_type) (void) = NULL;
+
+TrackerEndpoint * (* remote_endpoint_new) (TrackerSparqlConnection *sparql_connection,
+ guint port,
+ GTlsCertificate *certificate,
+ GCancellable *cancellable,
+ GError **error) = NULL;
+TrackerSparqlConnection * (* remote_connection_new) (const gchar *url_base) = NULL;
+
+static void
+tracker_init_remote (void)
+{
+ const char *modules[3] = { 0 };
+ gpointer handle = NULL;
+ gint i = 0;
+
+ if (initialized)
+ return;
+
+ g_assert (g_module_supported ());
+
+#ifdef HAVE_RTLD_NOLOAD
+ if ((handle = dlopen (LIBSOUP_2_SONAME, RTLD_NOW | RTLD_NOLOAD))) {
+ /* Force load of soup2 module */
+ modules[0] = "libtracker-remote-soup2.so";
+ } else
+#endif
+ {
+ modules[0] = "libtracker-remote-soup3.so";
+ modules[1] = "libtracker-remote-soup2.so";
+ }
+
+ g_clear_pointer (&handle, dlclose);
+
+ for (i = 0; modules[i]; i++) {
+ GModule *remote_module;
+ gchar *module_path;
+
+ if (g_strcmp0 (g_get_current_dir (), BUILDROOT) == 0) {
+ /* Detect in-build runtime of this code, this may happen
+ * building introspection information or running tests.
+ * We want the in-tree modules to be loaded then.
+ */
+ module_path = g_strdup_printf (BUILD_LIBDIR "/%s", modules[i]);
+ } else {
+ module_path = g_strdup_printf (PRIVATE_LIBDIR "/%s", modules[i]);
+ }
+
+ remote_module = g_module_open (module_path,
+ G_MODULE_BIND_LAZY |
+ G_MODULE_BIND_LOCAL);
+ g_free (module_path);
+
+ if (!remote_module)
+ continue;
+
+ if (!g_module_symbol (remote_module, "tracker_endpoint_http_get_type", (gpointer *)
&remote_endpoint_get_type) ||
+ !g_module_symbol (remote_module, "tracker_endpoint_http_new", (gpointer *)
&remote_endpoint_new) ||
+ !g_module_symbol (remote_module, "tracker_remote_connection_new", (gpointer *)
&remote_connection_new)) {
+ g_clear_pointer (&remote_module, g_module_close);
+ continue;
+ }
+
+ g_module_make_resident (remote_module);
+ g_module_close (remote_module);
+ initialized = TRUE;
+ return;
+ }
+
+ g_assert_not_reached ();
+}
+
+GType
+tracker_endpoint_http_get_type (void)
+{
+ tracker_init_remote ();
+
+ return remote_endpoint_get_type ();
+}
+
+TrackerEndpointHttp *
+tracker_endpoint_http_new (TrackerSparqlConnection *sparql_connection,
+ guint port,
+ GTlsCertificate *certificate,
+ GCancellable *cancellable,
+ GError **error)
+{
+ tracker_init_remote ();
+
+ return (TrackerEndpointHttp *) remote_endpoint_new (sparql_connection,
+ port,
+ certificate,
+ cancellable,
+ error);
+}
+
+TrackerSparqlConnection *
+tracker_sparql_connection_remote_new (const gchar *url_base)
+{
+ tracker_init_remote ();
+
+ return remote_connection_new (url_base);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]