build: new option to build plugins within the daemon binary

Instead of creating libmm-plugin* and libmm-shared* libraries that are
dlopen()-ed on runtime, allow incorporating all plugins into the
daemon binary itself.

This makes the startup of the daemon much faster and also avoids
issues with builds that require linker namespace isolation.

Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/674
This commit is contained in:
Aleksander Morgado
2022-12-08 14:37:56 +00:00
committed by Aleksander Morgado
parent 1dd70be4c8
commit 1c4da332ee
17 changed files with 594 additions and 147 deletions

View File

@@ -1,9 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
test_plugin_dir = ''
if not enable_builtin_plugins
test_plugin_dir = '--test-plugin-dir="' + build_root + '/src/plugins"'
endif
test_conf = {
'abs_top_builddir': build_root,
'PLUGIN_BUILD_SUBDIR': 'src/plugins/',
'test_plugin_dir': test_plugin_dir,
}
configure_file(

View File

@@ -2,4 +2,4 @@
[D-BUS Service]
Name=org.freedesktop.ModemManager1
Exec=@abs_top_builddir@/src/ModemManager --test-session --no-auto-scan --test-enable --test-plugin-dir="@abs_top_builddir@/@PLUGIN_BUILD_SUBDIR@" --debug
Exec=@abs_top_builddir@/src/ModemManager --test-session --no-auto-scan --test-enable @test_plugin_dir@ --debug

View File

@@ -242,6 +242,10 @@ config_h.set('WITH_POLKIT', enable_polkit)
enable_at_command_via_dbus = get_option('at_command_via_dbus')
config_h.set('WITH_AT_COMMAND_VIA_DBUS', enable_at_command_via_dbus)
# Builtin plugin support (disabled by default)
enable_builtin_plugins = get_option('builtin_plugins')
config_h.set('WITH_BUILTIN_PLUGINS', enable_builtin_plugins)
# MBIM support (enabled by default)
enable_mbim = get_option('mbim')
if enable_mbim
@@ -444,6 +448,7 @@ summary({
'powerd suspend/resume': enable_powerd_suspend_resume,
'systemd journal': enable_systemd_journal,
'at command via dbus': enable_at_command_via_dbus,
'builtin plugins': enable_builtin_plugins,
}, section: 'Features')
summary(plugins_shared, section: 'Shared utils')

View File

@@ -17,6 +17,8 @@ option('polkit', type: 'combo', choices: ['strict', 'permissive', 'no'], value:
option('at_command_via_dbus', type: 'boolean', value: false, description: 'enable at commands vida d-bus')
option('builtin_plugins', type: 'boolean', value: false, description: 'integrate all built plugins within the daemon binary')
option('mbim', type: 'boolean', value: true, description: 'enable MBIM support')
option('qmi', type: 'boolean', value: true, description: 'enable QMI support')
option('qrtr', type: 'boolean', value: true, description: 'enable QRTR support')

View File

@@ -93,7 +93,9 @@ bus_acquired_cb (GDBusConnection *connection,
/* Create Manager object */
g_assert (!manager);
manager = mm_base_manager_new (connection,
#if !defined WITH_BUILTIN_PLUGINS
mm_context_get_test_plugin_dir (),
#endif
!mm_context_get_no_auto_scan (),
mm_context_get_filter_policy (),
mm_context_get_initial_kernel_events (),

View File

@@ -4,6 +4,7 @@
# helpers library
src_inc = include_directories('.')
kerneldevice_inc = include_directories('kerneldevice')
plugins_inc = include_directories('plugins')
headers = files(
'mm-modem-helpers.h',
@@ -177,6 +178,9 @@ libport_dep = declare_dependency(
link_with: libport,
)
# Additional vendor plugins
subdir('plugins')
# ModemManager daemon
headers = files(
'mm-base-bearer.h',
@@ -229,15 +233,14 @@ sources = files(
enums_types = 'mm-daemon-enums-types'
daemon_enums_sources = []
daemon_enums_sources += gnome.mkenums(
sources += gnome.mkenums(
enums_types + '.c',
sources: headers,
c_template: build_aux_dir / enums_types + '.c.template',
fhead: '#include "mm-daemon-enums-types.h"',
)
daemon_enums_sources += gnome.mkenums(
sources += gnome.mkenums(
enums_types + '.h',
sources: headers,
h_template: build_aux_dir / enums_types + '.h.template',
@@ -309,20 +312,13 @@ if enable_mbim
)
endif
# Daemon related variables before processing plugins
daemon_sources = sources + daemon_enums_sources
daemon_deps = deps
daemon_c_args = c_args
# Additional vendor plugins
subdir('plugins')
executable(
'ModemManager',
sources: daemon_sources,
include_directories: top_inc,
dependencies: daemon_deps,
c_args: daemon_c_args,
sources: [sources, builtin_sources],
include_directories: [ top_inc, plugins_inc ],
dependencies: deps,
c_args: c_args,
link_whole: builtin_plugins,
install: true,
install_dir: mm_sbindir,
)

View File

@@ -68,7 +68,9 @@ enum {
PROP_CONNECTION,
PROP_AUTO_SCAN,
PROP_FILTER_POLICY,
#if !defined WITH_BUILTIN_PLUGINS
PROP_PLUGIN_DIR,
#endif
PROP_INITIAL_KERNEL_EVENTS,
#if defined WITH_TESTS
PROP_ENABLE_TEST,
@@ -83,8 +85,10 @@ struct _MMBaseManagerPrivate {
gboolean auto_scan;
/* Filter policy (mask of enabled rules) */
MMFilterRule filter_policy;
#if !defined WITH_BUILTIN_PLUGINS
/* Path to look for plugins */
gchar *plugin_dir;
#endif
/* Path to the list of initial kernel events */
gchar *initial_kernel_events;
/* The authorization provider */
@@ -1380,7 +1384,9 @@ log_object_build_id (MMLogObject *_self)
MMBaseManager *
mm_base_manager_new (GDBusConnection *connection,
#if !defined WITH_BUILTIN_PLUGINS
const gchar *plugin_dir,
#endif
gboolean auto_scan,
MMFilterRule filter_policy,
const gchar *initial_kernel_events,
@@ -1395,7 +1401,9 @@ mm_base_manager_new (GDBusConnection *connection,
NULL, /* cancellable */
error,
MM_BASE_MANAGER_CONNECTION, connection,
#if !defined WITH_BUILTIN_PLUGINS
MM_BASE_MANAGER_PLUGIN_DIR, plugin_dir,
#endif
MM_BASE_MANAGER_AUTO_SCAN, auto_scan,
MM_BASE_MANAGER_FILTER_POLICY, filter_policy,
MM_BASE_MANAGER_INITIAL_KERNEL_EVENTS, initial_kernel_events,
@@ -1445,10 +1453,12 @@ set_property (GObject *object,
case PROP_FILTER_POLICY:
self->priv->filter_policy = g_value_get_flags (value);
break;
#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_free (self->priv->plugin_dir);
self->priv->plugin_dir = g_value_dup_string (value);
break;
#endif
case PROP_INITIAL_KERNEL_EVENTS:
g_free (self->priv->initial_kernel_events);
self->priv->initial_kernel_events = g_value_dup_string (value);
@@ -1482,9 +1492,11 @@ get_property (GObject *object,
case PROP_FILTER_POLICY:
g_value_set_flags (value, self->priv->filter_policy);
break;
#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_value_set_string (value, self->priv->plugin_dir);
break;
#endif
case PROP_INITIAL_KERNEL_EVENTS:
g_value_set_string (value, self->priv->initial_kernel_events);
break;
@@ -1548,7 +1560,11 @@ initable_init (GInitable *initable,
return FALSE;
/* Create plugin manager */
self->priv->plugin_manager = mm_plugin_manager_new (self->priv->plugin_dir, self->priv->filter, error);
self->priv->plugin_manager = mm_plugin_manager_new (self->priv->filter,
#if !defined WITH_BUILTIN_PLUGINS
self->priv->plugin_dir,
#endif
error);
if (!self->priv->plugin_manager)
return FALSE;
@@ -1613,7 +1629,9 @@ finalize (GObject *object)
MMBaseManager *self = MM_BASE_MANAGER (object);
g_free (self->priv->initial_kernel_events);
#if !defined WITH_BUILTIN_PLUGINS
g_free (self->priv->plugin_dir);
#endif
g_hash_table_destroy (self->priv->inhibited_devices);
g_hash_table_destroy (self->priv->devices);
@@ -1704,6 +1722,7 @@ mm_base_manager_class_init (MMBaseManagerClass *manager_class)
MM_FILTER_RULE_NONE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
#if !defined WITH_BUILTIN_PLUGINS
g_object_class_install_property
(object_class, PROP_PLUGIN_DIR,
g_param_spec_string (MM_BASE_MANAGER_PLUGIN_DIR,
@@ -1711,6 +1730,7 @@ mm_base_manager_class_init (MMBaseManagerClass *manager_class)
"Where to look for plugins",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
#endif
g_object_class_install_property
(object_class, PROP_INITIAL_KERNEL_EVENTS,

View File

@@ -57,7 +57,9 @@ GType mm_base_manager_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBaseManager, g_object_unref)
MMBaseManager *mm_base_manager_new (GDBusConnection *bus,
#if !defined WITH_BUILTIN_PLUGINS
const gchar *plugin_dir,
#endif
gboolean auto_scan,
MMFilterRule filter_policy,
const gchar *initial_kernel_events,

View File

@@ -229,7 +229,9 @@ static gboolean test_session;
#if defined WITH_TESTS
static gboolean test_enable;
#endif
#if !defined WITH_BUILTIN_PLUGINS
static gchar *test_plugin_dir;
#endif
#if defined WITH_UDEV
static gboolean test_no_udev;
#endif
@@ -258,11 +260,13 @@ static const GOptionEntry test_entries[] = {
NULL
},
#endif
#if !defined WITH_BUILTIN_PLUGINS
{
"test-plugin-dir", 0, 0, G_OPTION_ARG_FILENAME, &test_plugin_dir,
"Path to look for plugins",
"[PATH]"
},
#endif
#if defined WITH_UDEV
{
"test-no-udev", 0, 0, G_OPTION_ARG_NONE, &test_no_udev,
@@ -332,11 +336,13 @@ mm_context_get_test_enable (void)
}
#endif
#if !defined WITH_BUILTIN_PLUGINS
const gchar *
mm_context_get_test_plugin_dir (void)
{
return test_plugin_dir ? test_plugin_dir : PLUGINDIR;
}
#endif
#if defined WITH_UDEV
gboolean

View File

@@ -48,7 +48,9 @@ gboolean mm_context_get_test_session (void);
#if defined WITH_TESTS
gboolean mm_context_get_test_enable (void);
#endif
#if !defined WITH_BUILTIN_PLUGINS
const gchar *mm_context_get_test_plugin_dir (void);
#endif
#if defined WITH_UDEV
gboolean mm_context_get_test_no_udev (void);
#endif

View File

@@ -33,8 +33,12 @@
#include "mm-utils.h"
#include "mm-log-object.h"
#define SHARED_PREFIX "libmm-shared"
#define PLUGIN_PREFIX "libmm-plugin"
#if defined WITH_BUILTIN_PLUGINS
# include "mm-builtin-plugins.h"
#else
# define SHARED_PREFIX "libmm-shared"
# define PLUGIN_PREFIX "libmm-plugin"
#endif
static void initable_iface_init (GInitableIface *iface);
static void log_object_iface_init (MMLogObjectInterface *iface);
@@ -45,14 +49,19 @@ G_DEFINE_TYPE_EXTENDED (MMPluginManager, mm_plugin_manager, G_TYPE_OBJECT, 0,
enum {
PROP_0,
#if !defined WITH_BUILTIN_PLUGINS
PROP_PLUGIN_DIR,
#endif
PROP_FILTER,
LAST_PROP
};
struct _MMPluginManagerPrivate {
#if !defined WITH_BUILTIN_PLUGINS
/* Path to look for plugins */
gchar *plugin_dir;
#endif
/* Device filter */
MMFilter *filter;
@@ -1681,8 +1690,89 @@ register_plugin_allowlist_subsystem_vendor_ids (MMPluginManager *self,
mm_filter_register_plugin_allowlist_subsystem_vendor_id (self->priv->filter, subsystem_vendor_ids[i].l, subsystem_vendor_ids[i].r);
}
static gboolean
track_plugin (MMPluginManager *self,
MMPlugin *plugin,
GPtrArray **subsystems,
GError **error)
{
const gchar **plugin_subsystems;
guint i;
/* Ignore plugins that don't specify subsystems */
plugin_subsystems = mm_plugin_get_allowed_subsystems (plugin);
if (!plugin_subsystems) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Allowed subsystems not specified");
return FALSE;
}
/* Process generic plugin */
if (mm_plugin_is_generic (plugin)) {
if (self->priv->generic) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Another generic plugin already registered");
return FALSE;
}
self->priv->generic = g_object_ref (plugin);
} else
self->priv->plugins = g_list_append (self->priv->plugins, g_object_ref (plugin));
/* Track required subsystems, avoiding duplicates in the list */
for (i = 0; plugin_subsystems[i]; i++) {
if (!g_ptr_array_find_with_equal_func (*subsystems, plugin_subsystems[i], g_str_equal, NULL))
g_ptr_array_add (*subsystems, g_strdup (plugin_subsystems[i]));
}
/* Register plugin allowlist rules in filter, if any */
register_plugin_allowlist_tags (self, plugin);
register_plugin_allowlist_vendor_ids (self, plugin);
register_plugin_allowlist_product_ids (self, plugin);
register_plugin_allowlist_subsystem_vendor_ids (self, plugin);
return TRUE;
}
static gboolean
validate_tracked_plugins (MMPluginManager *self,
GPtrArray *subsystems_take,
GError **error)
{
g_autofree gchar *subsystems_str = NULL;
/* Check the generic plugin once all looped */
if (!self->priv->generic)
mm_obj_dbg (self, "generic plugin not loaded");
/* Treat as error if we don't find any plugin */
if (!self->priv->plugins && !self->priv->generic) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS, "no plugins found");
return FALSE;
}
/* Validate required subsystems */
if (!subsystems_take->len) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS,
"empty list of subsystems required by plugins");
return FALSE;
}
/* Add trailing NULL and store as GStrv */
g_ptr_array_add (subsystems_take, NULL);
self->priv->subsystems = (gchar **) g_ptr_array_free (subsystems_take, FALSE);
subsystems_str = g_strjoinv (", ", self->priv->subsystems);
mm_obj_dbg (self, "successfully loaded %u plugins registering %u subsystems: %s",
g_list_length (self->priv->plugins) + !!self->priv->generic,
g_strv_length (self->priv->subsystems), subsystems_str);
return TRUE;
}
#if !defined WITH_BUILTIN_PLUGINS
static MMPlugin *
load_plugin (MMPluginManager *self,
load_external_plugin (MMPluginManager *self,
const gchar *path)
{
MMPlugin *plugin = NULL;
@@ -1729,10 +1819,9 @@ load_plugin (MMPluginManager *self,
}
plugin = (*plugin_create_func) ();
if (plugin) {
if (plugin)
mm_obj_dbg (self, "loaded plugin '%s' from '%s'", mm_plugin_get_name (plugin), path_display);
g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
} else
else
mm_obj_warn (self, "could not load plugin '%s': initialization failed", path_display);
out:
@@ -1745,7 +1834,7 @@ out:
}
static void
load_shared (MMPluginManager *self,
load_external_shared (MMPluginManager *self,
const gchar *path)
{
GModule *module;
@@ -1802,7 +1891,7 @@ out:
}
static gboolean
load_plugins (MMPluginManager *self,
load_external_plugins (MMPluginManager *self,
GError **error)
{
GDir *dir = NULL;
@@ -1811,8 +1900,8 @@ load_plugins (MMPluginManager *self,
GList *plugin_paths = NULL;
GList *l;
GPtrArray *subsystems = NULL;
g_autofree gchar *subsystems_str = NULL;
g_autofree gchar *plugindir_display = NULL;
gboolean valid_plugins = FALSE;
if (!g_module_supported ()) {
g_set_error (error,
@@ -1828,11 +1917,8 @@ load_plugins (MMPluginManager *self,
mm_obj_dbg (self, "looking for plugins in '%s'", plugindir_display);
dir = g_dir_open (self->priv->plugin_dir, 0, NULL);
if (!dir) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_NO_PLUGINS,
"plugin directory '%s' not found",
plugindir_display);
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NO_PLUGINS,
"plugin directory '%s' not found", plugindir_display);
goto out;
}
@@ -1847,81 +1933,23 @@ load_plugins (MMPluginManager *self,
/* Load all shared utils */
for (l = shared_paths; l; l = g_list_next (l))
load_shared (self, (const gchar *)(l->data));
load_external_shared (self, (const gchar *)(l->data));
/* Load all plugins */
subsystems = g_ptr_array_new ();
for (l = plugin_paths; l; l = g_list_next (l)) {
MMPlugin *plugin;
const gchar **plugin_subsystems;
guint i;
g_autoptr(MMPlugin) plugin = NULL;
g_autoptr(GError) inner_error = NULL;
plugin = load_plugin (self, (const gchar *)(l->data));
plugin = load_external_plugin (self, (const gchar *)(l->data));
if (!plugin)
continue;
/* Ignore plugins that don't specify subsystems */
plugin_subsystems = mm_plugin_get_allowed_subsystems (plugin);
if (!plugin_subsystems) {
mm_obj_warn (self, "plugin '%s' doesn't specify allowed subsystems: ignored",
mm_plugin_get_name (plugin));
continue;
if (!track_plugin (self, plugin, &subsystems, &inner_error))
mm_obj_warn (self, "ignored plugin '%s': %s", mm_plugin_get_name (plugin), inner_error->message);
}
/* Process generic plugin */
if (mm_plugin_is_generic (plugin)) {
if (self->priv->generic) {
mm_obj_warn (self, "plugin '%s' is generic and another one is already registered: ignored",
mm_plugin_get_name (plugin));
continue;
}
self->priv->generic = plugin;
} else
self->priv->plugins = g_list_append (self->priv->plugins, plugin);
/* Track required subsystems, avoiding duplicates in the list */
for (i = 0; plugin_subsystems[i]; i++) {
if (!g_ptr_array_find_with_equal_func (subsystems, plugin_subsystems[i], g_str_equal, NULL))
g_ptr_array_add (subsystems, g_strdup (plugin_subsystems[i]));
}
/* Register plugin allowlist rules in filter, if any */
register_plugin_allowlist_tags (self, plugin);
register_plugin_allowlist_vendor_ids (self, plugin);
register_plugin_allowlist_product_ids (self, plugin);
register_plugin_allowlist_subsystem_vendor_ids (self, plugin);
}
/* Check the generic plugin once all looped */
if (!self->priv->generic)
mm_obj_dbg (self, "generic plugin not loaded");
/* Treat as error if we don't find any plugin */
if (!self->priv->plugins && !self->priv->generic) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_NO_PLUGINS,
"no plugins found in plugin directory '%s'",
plugindir_display);
goto out;
}
/* Validate required subsystems */
if (!subsystems->len) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_NO_PLUGINS,
"empty list of subsystems required by plugins");
goto out;
}
/* Add trailing NULL and store as GStrv */
g_ptr_array_add (subsystems, NULL);
self->priv->subsystems = (gchar **) g_ptr_array_free (subsystems, FALSE);
subsystems_str = g_strjoinv (", ", self->priv->subsystems);
mm_obj_dbg (self, "successfully loaded %u plugins registering %u subsystems: %s",
g_list_length (self->priv->plugins) + !!self->priv->generic,
g_strv_length (self->priv->subsystems), subsystems_str);
valid_plugins = validate_tracked_plugins (self, subsystems, error);
out:
g_list_free_full (shared_paths, g_free);
@@ -1929,10 +1957,38 @@ out:
if (dir)
g_dir_close (dir);
/* Return TRUE if at least one plugin found */
return (self->priv->plugins || self->priv->generic);
return valid_plugins;
}
#else
static gboolean
load_builtin_plugins (MMPluginManager *self,
GError **error)
{
GList *builtin_plugins;
GList *l;
GPtrArray *subsystems = NULL;
subsystems = g_ptr_array_new ();
builtin_plugins = mm_builtin_plugins_load ();
for (l = builtin_plugins; l; l = g_list_next (l)) {
gboolean tracked;
MMPlugin *plugin;
plugin = MM_PLUGIN (l->data);
mm_obj_dbg (self, "loaded builtin plugin '%s'", mm_plugin_get_name (plugin));
tracked = track_plugin (self, plugin, &subsystems, NULL);
g_assert (tracked);
}
g_list_free_full (builtin_plugins, (GDestroyNotify)g_object_unref);
return validate_tracked_plugins (self, subsystems, error);
}
#endif /* !WITH_BUILTIN_PLUGINS */
/*****************************************************************************/
static gchar *
@@ -1944,15 +2000,19 @@ log_object_build_id (MMLogObject *_self)
/*****************************************************************************/
MMPluginManager *
mm_plugin_manager_new (const gchar *plugin_dir,
MMFilter *filter,
mm_plugin_manager_new (MMFilter *filter,
#if !defined WITH_BUILTIN_PLUGINS
const gchar *plugin_dir,
#endif
GError **error)
{
return g_initable_new (MM_TYPE_PLUGIN_MANAGER,
NULL,
error,
MM_PLUGIN_MANAGER_PLUGIN_DIR, plugin_dir,
MM_PLUGIN_MANAGER_FILTER, filter,
#if !defined WITH_BUILTIN_PLUGINS
MM_PLUGIN_MANAGER_PLUGIN_DIR, plugin_dir,
#endif
NULL);
}
@@ -1974,10 +2034,12 @@ set_property (GObject *object,
MMPluginManagerPrivate *priv = MM_PLUGIN_MANAGER (object)->priv;
switch (prop_id) {
#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_free (priv->plugin_dir);
priv->plugin_dir = g_value_dup_string (value);
break;
#endif
case PROP_FILTER:
priv->filter = g_value_dup_object (value);
break;
@@ -1996,9 +2058,11 @@ get_property (GObject *object,
MMPluginManagerPrivate *priv = MM_PLUGIN_MANAGER (object)->priv;
switch (prop_id) {
#if !defined WITH_BUILTIN_PLUGINS
case PROP_PLUGIN_DIR:
g_value_set_string (value, priv->plugin_dir);
break;
#endif
case PROP_FILTER:
g_value_set_object (value, priv->filter);
break;
@@ -2013,8 +2077,12 @@ initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
/* Load the list of plugins */
return load_plugins (MM_PLUGIN_MANAGER (initable), error);
#if defined WITH_BUILTIN_PLUGINS
return load_builtin_plugins (MM_PLUGIN_MANAGER (initable), error);
#else
/* Load the list of plugins from the filesystem*/
return load_external_plugins (MM_PLUGIN_MANAGER (initable), error);
#endif
}
static void
@@ -2024,9 +2092,11 @@ dispose (GObject *object)
g_list_free_full (g_steal_pointer (&self->priv->plugins), g_object_unref);
g_clear_object (&self->priv->generic);
g_clear_pointer (&self->priv->plugin_dir, g_free);
g_clear_object (&self->priv->filter);
g_clear_pointer (&self->priv->subsystems, g_strfreev);
#if !defined WITH_BUILTIN_PLUGINS
g_clear_pointer (&self->priv->plugin_dir, g_free);
#endif
G_OBJECT_CLASS (mm_plugin_manager_parent_class)->dispose (object);
}
@@ -2056,6 +2126,7 @@ mm_plugin_manager_class_init (MMPluginManagerClass *manager_class)
object_class->get_property = get_property;
/* Properties */
#if !defined WITH_BUILTIN_PLUGINS
g_object_class_install_property
(object_class, PROP_PLUGIN_DIR,
g_param_spec_string (MM_PLUGIN_MANAGER_PLUGIN_DIR,
@@ -2063,6 +2134,8 @@ mm_plugin_manager_class_init (MMPluginManagerClass *manager_class)
"Where to look for plugins",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
#endif
g_object_class_install_property
(object_class, PROP_FILTER,
g_param_spec_object (MM_PLUGIN_MANAGER_FILTER,

View File

@@ -32,7 +32,9 @@
#define MM_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), MM_TYPE_PLUGIN_MANAGER))
#define MM_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_MANAGER, MMPluginManagerClass))
#define MM_PLUGIN_MANAGER_PLUGIN_DIR "plugin-dir" /* Construct-only */
#if !defined WITH_BUILTIN_PLUGINS
# define MM_PLUGIN_MANAGER_PLUGIN_DIR "plugin-dir" /* Construct-only */
#endif
#define MM_PLUGIN_MANAGER_FILTER "filter" /* Construct-only */
typedef struct _MMPluginManager MMPluginManager;
@@ -51,8 +53,10 @@ struct _MMPluginManagerClass {
GType mm_plugin_manager_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPluginManager, g_object_unref)
MMPluginManager *mm_plugin_manager_new (const gchar *plugindir,
MMFilter *filter,
MMPluginManager *mm_plugin_manager_new (MMFilter *filter,
#if !defined WITH_BUILTIN_PLUGINS
const gchar *plugindir,
#endif
GError **error);
void mm_plugin_manager_device_support_check (MMPluginManager *self,
MMDevice *device,

View File

@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2021 Iñigo Martinez <inigomartinez@gmail.com>
symbol_map = plugins_dir / 'symbol.map'
ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map))
if not enable_builtin_plugins
symbol_map = plugins_dir / 'symbol.map'
ldflags = cc.get_supported_link_arguments('-Wl,--version-script,@0@'.format(symbol_map))
endif
# common service test support
plugins_common_test_dep = []
@@ -36,7 +38,6 @@ if enable_tests
endif
# plugins
plugins_inc = include_directories('.')
plugins = {}
plugins_data = []
plugins_udev_rules = []
@@ -958,6 +959,13 @@ if plugins_options['zte']
plugins_udev_rules += files('zte/77-mm-zte-port-types.rules')
endif
builtin_sources = []
builtin_plugins = []
if enable_builtin_plugins
builtin_sources += files('mm-builtin-plugins.c')
endif
foreach plugin_name, plugin_data: plugins
libpluginhelpers = []
if plugin_data.has_key('helper')
@@ -969,6 +977,7 @@ foreach plugin_name, plugin_data: plugins
endif
module_args = plugin_data['module']
if not enable_builtin_plugins
if plugin_data['plugin']
module_args += {
'link_args': ldflags,
@@ -984,6 +993,15 @@ foreach plugin_name, plugin_data: plugins
install: true,
install_dir: mm_pkglibdir,
)
else
libplugin = static_library(
'mm-' + plugin_name,
dependencies: plugins_deps,
link_with: libpluginhelpers,
kwargs: module_args,
)
builtin_plugins += libplugin
endif
if enable_tests
if plugin_data.has_key('test')

View File

@@ -0,0 +1,273 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2022 Google Inc.
*/
#include <config.h>
#include <glib.h>
#include "mm-plugin.h"
#include "mm-builtin-plugins.h"
#if defined ENABLE_PLUGIN_ALTAIR_LTE
MMPlugin *mm_plugin_create_altair_lte (void);
#endif
#if defined ENABLE_PLUGIN_ANYDATA
MMPlugin *mm_plugin_create_anydata (void);
#endif
#if defined ENABLE_PLUGIN_BROADMOBI
MMPlugin *mm_plugin_create_broadmobi (void);
#endif
#if defined ENABLE_PLUGIN_CINTERION
MMPlugin *mm_plugin_create_cinterion (void);
#endif
#if defined ENABLE_PLUGIN_DELL
MMPlugin *mm_plugin_create_dell (void);
#endif
#if defined ENABLE_PLUGIN_DLINK
MMPlugin *mm_plugin_create_dlink (void);
#endif
#if defined ENABLE_PLUGIN_FIBOCOM
MMPlugin *mm_plugin_create_fibocom (void);
#endif
#if defined ENABLE_PLUGIN_FOXCONN
MMPlugin *mm_plugin_create_foxconn (void);
#endif
#if defined ENABLE_PLUGIN_GENERIC
MMPlugin *mm_plugin_create_generic (void);
#endif
#if defined ENABLE_PLUGIN_GOSUNCN
MMPlugin *mm_plugin_create_gosuncn (void);
#endif
#if defined ENABLE_PLUGIN_HAIER
MMPlugin *mm_plugin_create_haier (void);
#endif
#if defined ENABLE_PLUGIN_HUAWEI
MMPlugin *mm_plugin_create_huawei (void);
#endif
#if defined ENABLE_PLUGIN_INTEL
MMPlugin *mm_plugin_create_intel (void);
#endif
#if defined ENABLE_PLUGIN_IRIDIUM
MMPlugin *mm_plugin_create_iridium (void);
#endif
#if defined ENABLE_PLUGIN_LINKTOP
MMPlugin *mm_plugin_create_linktop (void);
#endif
#if defined ENABLE_PLUGIN_LONGCHEER
MMPlugin *mm_plugin_create_longcheer (void);
#endif
#if defined ENABLE_PLUGIN_MBM
MMPlugin *mm_plugin_create_mbm (void);
#endif
#if defined ENABLE_PLUGIN_MOTOROLA
MMPlugin *mm_plugin_create_motorola (void);
#endif
#if defined ENABLE_PLUGIN_MTK
MMPlugin *mm_plugin_create_mtk (void);
#endif
#if defined ENABLE_PLUGIN_NOKIA
MMPlugin *mm_plugin_create_nokia (void);
#endif
#if defined ENABLE_PLUGIN_NOKIA_ICERA
MMPlugin *mm_plugin_create_nokia_icera (void);
#endif
#if defined ENABLE_PLUGIN_NOVATEL
MMPlugin *mm_plugin_create_novatel (void);
#endif
#if defined ENABLE_PLUGIN_NOVATEL_LTE
MMPlugin *mm_plugin_create_novatel_lte (void);
#endif
#if defined ENABLE_PLUGIN_OPTION
MMPlugin *mm_plugin_create_option (void);
#endif
#if defined ENABLE_PLUGIN_OPTION_HSO
MMPlugin *mm_plugin_create_hso (void);
#endif
#if defined ENABLE_PLUGIN_PANTECH
MMPlugin *mm_plugin_create_pantech (void);
#endif
#if defined ENABLE_PLUGIN_QCOM_SOC
MMPlugin *mm_plugin_create_qcom_soc (void);
#endif
#if defined ENABLE_PLUGIN_QUECTEL
MMPlugin *mm_plugin_create_quectel (void);
#endif
#if defined ENABLE_PLUGIN_SAMSUNG
MMPlugin *mm_plugin_create_samsung (void);
#endif
#if defined ENABLE_PLUGIN_SIERRA
MMPlugin *mm_plugin_create_sierra (void);
#endif
#if defined ENABLE_PLUGIN_SIERRA_LEGACY
MMPlugin *mm_plugin_create_sierra_legacy (void);
#endif
#if defined ENABLE_PLUGIN_SIMTECH
MMPlugin *mm_plugin_create_simtech (void);
#endif
#if defined ENABLE_PLUGIN_TELIT
MMPlugin *mm_plugin_create_telit (void);
#endif
#if defined ENABLE_PLUGIN_THURAYA
MMPlugin *mm_plugin_create_thuraya (void);
#endif
#if defined ENABLE_PLUGIN_TPLINK
MMPlugin *mm_plugin_create_tplink (void);
#endif
#if defined ENABLE_PLUGIN_UBLOX
MMPlugin *mm_plugin_create_ublox (void);
#endif
#if defined ENABLE_PLUGIN_VIA
MMPlugin *mm_plugin_create_via (void);
#endif
#if defined ENABLE_PLUGIN_WAVECOM
MMPlugin *mm_plugin_create_wavecom (void);
#endif
#if defined ENABLE_PLUGIN_X22X
MMPlugin *mm_plugin_create_x22x (void);
#endif
#if defined ENABLE_PLUGIN_ZTE
MMPlugin *mm_plugin_create_zte (void);
#endif
GList *
mm_builtin_plugins_load (void)
{
GList *builtin_plugins = NULL;
#define PREPEND_PLUGIN(my_plugin) \
builtin_plugins = g_list_prepend (builtin_plugins, mm_plugin_create_##my_plugin ())
#if defined ENABLE_PLUGIN_ALTAIR_LTE
PREPEND_PLUGIN (altair_lte);
#endif
#if defined ENABLE_PLUGIN_ANYDATA
PREPEND_PLUGIN (anydata);
#endif
#if defined ENABLE_PLUGIN_BROADMOBI
PREPEND_PLUGIN (broadmobi);
#endif
#if defined ENABLE_PLUGIN_CINTERION
PREPEND_PLUGIN (cinterion);
#endif
#if defined ENABLE_PLUGIN_DELL
PREPEND_PLUGIN (dell);
#endif
#if defined ENABLE_PLUGIN_DLINK
PREPEND_PLUGIN (dlink);
#endif
#if defined ENABLE_PLUGIN_FIBOCOM
PREPEND_PLUGIN (fibocom);
#endif
#if defined ENABLE_PLUGIN_FOXCONN
PREPEND_PLUGIN (foxconn);
#endif
#if defined ENABLE_PLUGIN_GENERIC
PREPEND_PLUGIN (generic);
#endif
#if defined ENABLE_PLUGIN_GOSUNCN
PREPEND_PLUGIN (gosuncn);
#endif
#if defined ENABLE_PLUGIN_HAIER
PREPEND_PLUGIN (haier);
#endif
#if defined ENABLE_PLUGIN_HUAWEI
PREPEND_PLUGIN (huawei);
#endif
#if defined ENABLE_PLUGIN_INTEL
PREPEND_PLUGIN (intel);
#endif
#if defined ENABLE_PLUGIN_IRIDIUM
PREPEND_PLUGIN (iridium);
#endif
#if defined ENABLE_PLUGIN_LINKTOP
PREPEND_PLUGIN (linktop);
#endif
#if defined ENABLE_PLUGIN_LONGCHEER
PREPEND_PLUGIN (longcheer);
#endif
#if defined ENABLE_PLUGIN_MBM
PREPEND_PLUGIN (mbm);
#endif
#if defined ENABLE_PLUGIN_MOTOROLA
PREPEND_PLUGIN (motorola);
#endif
#if defined ENABLE_PLUGIN_MTK
PREPEND_PLUGIN (mtk);
#endif
#if defined ENABLE_PLUGIN_NOKIA
PREPEND_PLUGIN (nokia);
#endif
#if defined ENABLE_PLUGIN_NOKIA_ICERA
PREPEND_PLUGIN (nokia_icera);
#endif
#if defined ENABLE_PLUGIN_NOVATEL
PREPEND_PLUGIN (novatel);
#endif
#if defined ENABLE_PLUGIN_NOVATEL_LTE
PREPEND_PLUGIN (novatel_lte);
#endif
#if defined ENABLE_PLUGIN_OPTION
PREPEND_PLUGIN (option);
#endif
#if defined ENABLE_PLUGIN_OPTION_HSO
PREPEND_PLUGIN (hso);
#endif
#if defined ENABLE_PLUGIN_PANTECH
PREPEND_PLUGIN (pantech);
#endif
#if defined ENABLE_PLUGIN_QCOM_SOC
PREPEND_PLUGIN (qcom_soc);
#endif
#if defined ENABLE_PLUGIN_QUECTEL
PREPEND_PLUGIN (quectel);
#endif
#if defined ENABLE_PLUGIN_SAMSUNG
PREPEND_PLUGIN (samsung);
#endif
#if defined ENABLE_PLUGIN_SIERRA
PREPEND_PLUGIN (sierra);
#endif
#if defined ENABLE_PLUGIN_SIERRA_LEGACY
PREPEND_PLUGIN (sierra_legacy);
#endif
#if defined ENABLE_PLUGIN_SIMTECH
PREPEND_PLUGIN (simtech);
#endif
#if defined ENABLE_PLUGIN_TELIT
PREPEND_PLUGIN (telit);
#endif
#if defined ENABLE_PLUGIN_THURAYA
PREPEND_PLUGIN (thuraya);
#endif
#if defined ENABLE_PLUGIN_TPLINK
PREPEND_PLUGIN (tplink);
#endif
#if defined ENABLE_PLUGIN_UBLOX
PREPEND_PLUGIN (ublox);
#endif
#if defined ENABLE_PLUGIN_VIA
PREPEND_PLUGIN (via);
#endif
#if defined ENABLE_PLUGIN_WAVECOM
PREPEND_PLUGIN (wavecom);
#endif
#if defined ENABLE_PLUGIN_X22X
PREPEND_PLUGIN (x22x);
#endif
#if defined ENABLE_PLUGIN_ZTE
PREPEND_PLUGIN (zte);
#endif
#undef PREPEND_PLUGIN
return builtin_plugins;
}

View File

@@ -0,0 +1,28 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2022 Google Inc.
*/
#ifndef MM_BUILTIN_PLUGINS_H
#define MM_BUILTIN_PLUGINS_H
#include <config.h>
#include <glib.h>
#if !defined WITH_BUILTIN_PLUGINS
# error Build with builtin plugins was not enabled
#endif
GList *mm_builtin_plugins_load (void);
#endif /* MM_BUILTIN_PLUGINS_H */

View File

@@ -26,20 +26,28 @@
#include "mm-plugin.h"
#define MM_PLUGIN_NAMED_CREATOR_SCOPE static
#if defined (G_HAVE_GNUC_VISIBILITY)
# define MM_VISIBILITY __attribute__((visibility("protected")))
#else
# define MM_VISIBILITY
#endif
#define MM_PLUGIN_CREATOR(my_plugin) \
#if defined WITH_BUILTIN_PLUGINS
# define MM_PLUGIN_VERSION
# define MM_PLUGIN_NAMED_CREATOR_SCOPE
# define MM_PLUGIN_CREATOR(unused)
#else
# define MM_PLUGIN_VERSION \
MM_VISIBILITY int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION; \
MM_VISIBILITY int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
# define MM_PLUGIN_NAMED_CREATOR_SCOPE static
# define MM_PLUGIN_CREATOR(my_plugin) \
G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); \
G_MODULE_EXPORT MMPlugin * \
mm_plugin_create (void) \
{ \
return mm_plugin_create_##my_plugin (); \
}
#if defined (G_HAVE_GNUC_VISIBILITY)
# define MM_VISIBILITY __attribute__((visibility("protected")))
#else
# define MM_VISIBILITY
#endif
#define MM_DEFINE_PLUGIN(MY_PLUGIN, my_plugin, MyPlugin) \
@@ -49,8 +57,7 @@
}; \
G_DEFINE_TYPE (MMPlugin##MyPlugin, mm_plugin_##my_plugin, MM_TYPE_PLUGIN) \
\
MM_VISIBILITY int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION; \
MM_VISIBILITY int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION; \
MM_PLUGIN_VERSION \
\
MM_PLUGIN_NAMED_CREATOR_SCOPE MMPlugin *mm_plugin_create_##my_plugin (void); \
MM_PLUGIN_CREATOR(my_plugin)

View File

@@ -33,9 +33,13 @@
#define MM_VISIBILITY
#endif
#define MM_DEFINE_SHARED(MyShared) \
#if defined WITH_BUILTIN_PLUGINS
# define MM_DEFINE_SHARED(unused)
#else
# define MM_DEFINE_SHARED(MyShared) \
MM_VISIBILITY int mm_shared_major_version = MM_SHARED_MAJOR_VERSION; \
MM_VISIBILITY int mm_shared_minor_version = MM_SHARED_MINOR_VERSION; \
MM_VISIBILITY const char *mm_shared_name = #MyShared;
#endif
#endif /* MM_SHARED_COMMON_H */