Refactor the plugin registration and loading machinery
This patch refactors the plugin registration and loading machinery: the
different, specific symbol names found in the shared object are dropped
in favor of two sections.
The goals of this refactoring are:
1. To allow optional plugin attributes now and in the future.
2. To allow optional component class attributes now and in the future.
3. To make backward and forward compatibility easier.
4. To simplify the plugin development API from a user's perspective.
5. To use the same mechanism to load plugins from a shared object and
statically from the `babeltrace` binary.
You can still find the macros used to define plugins, plugin attributes,
and component classes in `babeltrace/plugin/plugin-dev`.
We introduce four (IV) new structures to the plugin subsystem:
* A *plugin descriptor* describes a single plugin. Note that one shared
object can contain one or more plugin descriptors, thus it can contain
one or more plugins.
A plugin descriptor contains the interface version of the plugin it
describes as well as its name (a C string).
The BT_PLUGIN_WITH_ID() macro creates a plugin descriptor structure
with a specific identifier in its variable name. It also creates a
pointer to this structure which is added to the plugin descriptor
section (`__bt_plugin_descriptors`).
The BT_PLUGIN() macro is an easy-to-use version of
BT_PLUGIN_WITH_ID(): it accepts a C identifier which is the name of
the plugin. Its plugin descriptor ID is `auto`.
* A *plugin descriptor attribute* is an optional attribute attached to a
specific plugin descriptor.
A plugin descriptor attribute structure has a type (its key) as well
as a value (the value's type depends on the attribute type). For debug
purposes, we also put a string in this structure which is the name of
the attribute type. This can be used by the plugin subsystem to give
more information when it warns that an attribute with an unknown type
was found (use case: current Babeltrace loading a future plugin).
A plugin descriptor attribute also has a member pointing to its
"parent" plugin descriptor.
The following macros each create a plugin descriptor attribute
structure and a pointer to this structure which is added to the plugin
attribute section. Each macro accepts a plugin descriptor ID (to
attach the attribute to the appropriate descriptor) and a value:
* BT_PLUGIN_INIT_WITH_ID(): Initialization function.
* BT_PLUGIN_EXIT_WITH_ID(): Exit function.
* BT_PLUGIN_AUTHOR_WITH_ID(): Author.
* BT_PLUGIN_LICENSE_WITH_ID(): License.
* BT_PLUGIN_DESCRIPTION_WITH_ID(): Description.
You can use the macros above in any order, but you need to use them
after BT_PLUGIN_INIT*().
There's an equivalent, easy-to-use macro for each of the macros above
without the `_WITH_ID` suffix which uses the `auto` plugin descriptor.
* A *component class descriptor* describes a single component class
attached to a specific plugin descriptor.
The structure contains the mandatory attributes needed to build a
component class (name, component type, component initialization
function).
The BT_PLUGIN_COMPONENT_CLASS_WITH_ID() macro creates a component
class descriptor structure with a specific component class descriptor
identifier in its variable name. The component source type is also
part of the variable name, as well as the specified plugin descriptor
ID. The macro also creates a pointer to this structure which is added
to the component class descriptor section
(`__bt_plugin_component_descriptors`).
The easy-to-use BT_PLUGIN_COMPONENT_CLASS() macro uses the `auto`
plugin descriptor and the name of the component class as the component
class descriptor ID (a C identifier in this version, to allow this).
With this new mechanism, the BT_PLUGIN_COMPONENT_CLASSES_BEGIN and
BT_PLUGIN_COMPONENT_CLASSES_END macros do not exist anymore: you can
use BT_PLUGIN_COMPONENT_CLASS*() macros anywhere, in any order, as
long as they appear after BT_PLUGIN_INIT*().
* A *component class descriptor attribute* is an optional attribute
attached to a specific component class descriptor.
A component class descriptor attribute structure has a type (its key)
as well as a value (the value's type depends on the attribute type).
For debug purposes, we also put a string in this structure which is
the name of the attribute type.
A component class descriptor attribute also has a member pointing to
its "parent" component class descriptor (which itself, as stated
above, as a member pointing to its "parent" plugin descriptor).
As of this patch, the only available component class descriptor
attribute is its optional description. The
BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION_WITH_ID() macro creates such an
attribute. BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION() is the easy-to-use
version which uses the `auto` plugin descriptor.
You need to place BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION*() after
the associated BT_PLUGIN_COMPONENT_CLASS*().
We also add the macro BT_PLUGIN_DECLARE() to declare an `extern` plugin
descriptor structure to add plugin attributes to the same plugin
descriptor from different compilation units. Thanks to this, the simple
fact of linking a given object file or not to a shared object is enough
to conditionally add or not one or more component classes.
This approach also has the somewhat interesting side effect of refusing
to build if you define a plugin descriptor attribute without using
BT_PLUGIN_INIT*() (missing name) or if you define the same attribute
twice, since the macros create actual variables which must have unique
names.
When the plugin subsystem loads a shared object, it looks for the
beginning and end symbols for the four sections:
* Plugin descriptors.
* Plugin descriptor attributes.
* Component class descriptors.
* Component class descriptor attributes.
Those are enough to provide everything that is needed to create a plugin
object. A plugin's initialization function is called first, and then its
component classes are created and added sequentially according to the
discovered component class descriptors.
Since a single shared object file can now contain more than one plugin
(descriptor), the following function:
struct bt_plugin *bt_plugin_create_from_file(const char *path);
is changed to this:
struct bt_plugin **bt_plugin_create_all_from_file(const char *path);
In other words, the function returns a NULL-terminated array of plugin
objects, just like bt_plugin_create_append_all_from_dir() does.
All the existing plugins and tests are updated to follow the changes.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
17 files changed:
This page took 0.029799 seconds and 4 git commands to generate.