AC_DEFINE([ENABLE_DEBUG_INFO], [1], [Define to 1 if you enable the 'debug info' feature])
], [])
+AC_ARG_VAR([BUILT_IN_PLUGINS], [Statically-link in-tree plug-ins into the babeltrace binary])
+AS_IF([test "x$BUILT_IN_PLUGINS" != x], [
+# Built-in plug-ins are only available when the --disable-shared --enable-static options are used.
+ AS_IF([test "x$enable_static" != "xyes"], [AC_MSG_ERROR(--enable-static must be used to bundle plug-ins in the babeltrace executable)])
+ AS_IF([test "x$enable_shared" = "xyes"], [AC_MSG_ERROR(--disable-shared must be used to bundle plug-ins in the babeltrace executable)])
+ built_in_plugins=yes
+ AC_DEFINE([BT_BUILT_IN_PLUGINS], [1], [Define to 1 to register plug-in attributes in static executable sections])
+])
+AM_CONDITIONAL([BUILT_IN_PLUGINS], [test "x$built_in_plugins" = "xyes"])
+
PKG_CHECK_MODULES(GMODULE, [gmodule-2.0 >= 2.0.0])
LIBS="$LIBS $GMODULE_LIBS"
test "x$_enable_debug_info" = "xyes" && value=1 || value=0
PPRINT_PROP_BOOL([Debug information output], $value)
+# built-in plug-ins enabled/disabled
+test "x$built_in_plugins" = "xyes" && value=1 || value=0
+PPRINT_PROP_BOOL([Built-in plug-ins], $value)
report_bindir="`eval eval echo $bindir`"
report_libdir="`eval eval echo $libdir`"
babeltrace_LDADD += $(top_builddir)/lib/libdebug-info.la
endif
+if BUILT_IN_PLUGINS
+babeltrace_LDFLAGS += -Wl,--whole-archive,$(top_builddir)/plugins/ctf/.libs/libbabeltrace-plugin-ctf.a,$(top_builddir)/plugins/text/.libs/libbabeltrace-plugin-ctf-text.a,$(top_builddir)/plugins/muxer/.libs/libbabeltrace-plugin-muxer.a,--no-whole-archive
+endif
+
babeltrace_log_SOURCES = babeltrace-log.c
babeltrace_log_LDADD = \
goto end;
}
+ ret = bt_component_factory_load_static(component_factory);
+ if (ret) {
+ fprintf(stderr, "Failed to load static plugins.\n");
+ goto end;
+ }
+
print_component_classes_found(component_factory);
source_class = bt_component_factory_get_component_class(
component_factory, "ctf", BT_COMPONENT_TYPE_SOURCE,
#include <babeltrace/plugin/plugin.h>
#include <glib.h>
+#define SECTION_BEGIN(_name) &__start_##_name
+#define SECTION_END(_name) &__stop_##_name
+
+#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
+
+#define DECLARE_SECTION(_type, _name) \
+ extern _type const __start_##_name __attribute((weak)); \
+ extern _type const __stop_##_name __attribute((weak))
+
+#define DECLARE_PLUG_IN_SECTIONS \
+ DECLARE_SECTION(bt_plugin_register_func, __plugin_register_funcs); \
+ DECLARE_SECTION(const char *, __plugin_names); \
+ DECLARE_SECTION(const char *, __plugin_authors); \
+ DECLARE_SECTION(const char *, __plugin_licenses); \
+ DECLARE_SECTION(const char *, __plugin_descriptions)
+
+#define PRINT_SECTION(_printer, _name) \
+ _printer("Section " #_name " [%p - %p], (%zu elements)\n", \
+ SECTION_BEGIN(_name), SECTION_END(_name), SECTION_ELEMENT_COUNT(_name))
+
+#define PRINT_PLUG_IN_SECTIONS(_printer) \
+ PRINT_SECTION(_printer, __plugin_register_funcs); \
+ PRINT_SECTION(_printer, __plugin_names); \
+ PRINT_SECTION(_printer, __plugin_authors); \
+ PRINT_SECTION(_printer, __plugin_licenses); \
+ PRINT_SECTION(_printer, __plugin_descriptions)
+
struct bt_component_factory {
struct bt_object base;
/** Array of pointers to struct bt_component_class */
extern enum bt_component_factory_status bt_component_factory_load_recursive(
struct bt_component_factory *factory, const char *path);
+/**
+ * Load and register Babeltrace plugins statically-linked to the executable.
+ *
+ * @param factory A component factory instance
+ * @returns One of #bt_component_factory_status values
+ */
+extern enum bt_component_factory_status bt_component_factory_load_static(
+ struct bt_component_factory *factory);
+
extern enum bt_component_factory_status
bt_component_factory_register_source_component_class(
struct bt_component_factory *factory, const char *name,
const char *license;
const char *description;
GString *path;
- bt_plugin_init_func init;
- bt_plugin_exit_func exit;
+ bt_plugin_register_func _register;
GModule *module;
};
BT_HIDDEN
-struct bt_plugin *bt_plugin_create(GModule *module, const char *path);
+struct bt_plugin *bt_plugin_create_from_module(GModule *module, const char *path);
+
+BT_HIDDEN
+struct bt_plugin *bt_plugin_create_from_static(size_t i);
BT_HIDDEN
enum bt_component_status bt_plugin_register_component_classes(
#include <babeltrace/plugin/component-factory.h>
#include <babeltrace/plugin/component.h>
+#include <babeltrace/plugin/plugin.h>
-/* A plugin must define the __bt_plugin_init symbol */
+#ifndef BT_BUILT_IN_PLUGINS
+
+#define BT_PLUGIN_REGISTER(_x) bt_plugin_register_func __bt_plugin_register = (_x)
#define BT_PLUGIN_NAME(_x) const char __bt_plugin_name[] = (_x)
#define BT_PLUGIN_AUTHOR(_x) const char __bt_plugin_author[] = (_x)
#define BT_PLUGIN_LICENSE(_x) const char __bt_plugin_license[] = (_x)
#define BT_PLUGIN_DESCRIPTION(_x) const char __bt_plugin_description[] = (_x)
-#define BT_PLUGIN_INIT(_x) bt_plugin_init_func __bt_plugin_init = (_x)
-#define BT_PLUGIN_EXIT(_x) bt_plugin_exit_func __bt_plugin_exit = (_x)
+
+#else /* BT_BUILT_IN_PLUGINS */
+
+/*
+ * Statically-linked plug-in symbol types are stored in separate sections and
+ * which are read using the bt_component_factory interface.
+ */
+#define BT_PLUGIN_REGISTER(_x) static bt_plugin_register_func __attribute__((section("__plugin_register_funcs"), used)) __plugin_register = (_x)
+#define BT_PLUGIN_NAME(_x) static const char *__plugin_name __attribute__((section("__plugin_names"), used)) = (_x)
+#define BT_PLUGIN_AUTHOR(_x) static const char *__plugin_author __attribute__((section("__plugin_authors"), used)) = (_x)
+#define BT_PLUGIN_LICENSE(_x) static const char *__plugin_license __attribute__((section("__plugin_licenses"), used)) = (_x)
+#define BT_PLUGIN_DESCRIPTION(_x) static const char *__plugin_description __attribute__((section("__plugin_descriptions"), used)) = (_x)
+
+#endif /* BT_BUILT_IN_PLUGINS */
#define BT_PLUGIN_COMPONENT_CLASSES_BEGIN \
static enum bt_component_status __bt_plugin_register_component_classes( \
return BT_COMPONENT_STATUS_OK; \
} \
\
- BT_PLUGIN_INIT(__bt_plugin_register_component_classes); \
+ BT_PLUGIN_REGISTER(__bt_plugin_register_component_classes); \
#endif /* BABELTRACE_PLUGIN_MACROS_H */
struct bt_component_factory;
struct bt_value;
-typedef enum bt_component_status (*bt_plugin_init_func)(
+typedef enum bt_component_status (*bt_plugin_register_func)(
struct bt_component_factory *factory);
-typedef void (*bt_plugin_exit_func)(void);
/**
* Component private data deallocation function type.
#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
sizeof(LIBTOOL_PLUGIN_SUFFIX))
+DECLARE_PLUG_IN_SECTIONS;
+
/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
static
struct dirent *alloc_dirent(const char *path)
return entry;
}
+static
+enum bt_component_factory_status init_plugin(
+ struct bt_component_factory *factory, struct bt_plugin *plugin)
+{
+ enum bt_component_status component_status;
+ enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+
+ BT_MOVE(factory->current_plugin, plugin);
+ component_status = bt_plugin_register_component_classes(
+ factory->current_plugin, factory);
+ BT_PUT(factory->current_plugin);
+ if (component_status != BT_COMPONENT_STATUS_OK) {
+ switch (component_status) {
+ case BT_COMPONENT_STATUS_NOMEM:
+ ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
+ break;
+ default:
+ ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
+ break;
+ }
+ }
+ return ret;
+}
+
static
enum bt_component_factory_status
bt_component_factory_load_file(struct bt_component_factory *factory,
const char *path)
{
enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
- enum bt_component_status component_status;
size_t path_len;
GModule *module;
struct bt_plugin *plugin;
goto end;
}
- /* Load plugin and make sure it defines the required entry points */
- plugin = bt_plugin_create(module, path);
+ /* Load plugin and make sure it defines the required entry points. */
+ plugin = bt_plugin_create_from_module(module, path);
if (!plugin) {
ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
if (!g_module_close(module)) {
- printf_error("Module close error: %s",
+ printf_error("Module close error: %s\n",
g_module_error());
}
goto end;
}
-
- BT_MOVE(factory->current_plugin, plugin);
- component_status = bt_plugin_register_component_classes(
- factory->current_plugin, factory);
- BT_PUT(factory->current_plugin);
- if (component_status != BT_COMPONENT_STATUS_OK) {
- switch (component_status) {
- case BT_COMPONENT_STATUS_NOMEM:
- ret = BT_COMPONENT_FACTORY_STATUS_NOMEM;
- break;
- default:
- ret = BT_COMPONENT_FACTORY_STATUS_ERROR;
- break;
- }
-
- goto end;
- }
+ ret = init_plugin(factory, plugin);
end:
return ret;
}
return _bt_component_factory_load(factory, path, false);
}
+enum bt_component_factory_status bt_component_factory_load_static(
+ struct bt_component_factory *factory)
+{
+ size_t count, i;
+ enum bt_component_factory_status ret = BT_COMPONENT_FACTORY_STATUS_OK;
+
+ PRINT_PLUG_IN_SECTIONS(printf_verbose);
+
+ count = SECTION_ELEMENT_COUNT(__plugin_register_funcs);
+ if (SECTION_ELEMENT_COUNT(__plugin_register_funcs) != count ||
+ SECTION_ELEMENT_COUNT(__plugin_names) != count ||
+ SECTION_ELEMENT_COUNT(__plugin_authors) != count ||
+ SECTION_ELEMENT_COUNT(__plugin_licenses) != count ||
+ SECTION_ELEMENT_COUNT(__plugin_descriptions) != count) {
+ printf_error("Some statically-linked plug-ins do not define all mandatory symbols\n");
+ ret = BT_COMPONENT_FACTORY_STATUS_INVAL_PLUGIN;
+ goto end;
+ }
+ printf_verbose("Detected %zu statically-linked plug-ins\n", count);
+
+ for (i = 0; i < count; i++) {
+ struct bt_plugin *plugin = bt_plugin_create_from_static(i);
+
+ if (!plugin) {
+ continue;
+ }
+
+ (void) init_plugin(factory, plugin);
+ }
+end:
+ return ret;
+}
+
static
enum bt_component_factory_status
add_component_class(struct bt_component_factory *factory, const char *name,
#include <babeltrace/compiler.h>
#include <babeltrace/ref.h>
#include <babeltrace/plugin/plugin-internal.h>
+#include <babeltrace/plugin/component-factory-internal.h>
#include <glib.h>
#define PLUGIN_SYMBOL_NAME "__bt_plugin_name"
#define PLUGIN_SYMBOL_AUTHOR "__bt_plugin_author"
#define PLUGIN_SYMBOL_LICENSE "__bt_plugin_license"
-#define PLUGIN_SYMBOL_INIT "__bt_plugin_init"
-#define PLUGIN_SYMBOL_EXIT "__bt_plugin_exit"
+#define PLUGIN_SYMBOL_REGISTER "__bt_plugin_register"
#define PLUGIN_SYMBOL_DESCRIPTION "__bt_plugin_description"
+DECLARE_PLUG_IN_SECTIONS;
+
static
void bt_plugin_destroy(struct bt_object *obj)
{
assert(obj);
plugin = container_of(obj, struct bt_plugin, base);
- if (plugin->exit) {
- plugin->exit();
- }
-
if (plugin->module) {
if (!g_module_close(plugin->module)) {
- printf_error("Module close error: %s",
+ printf_error("Module close error: %s\n",
g_module_error());
}
}
- g_string_free(plugin->path, TRUE);
+ if (plugin->path) {
+ g_string_free(plugin->path, TRUE);
+ }
g_free(plugin);
}
BT_HIDDEN
-struct bt_plugin *bt_plugin_create(GModule *module, const char *path)
+struct bt_plugin *bt_plugin_create_from_module(GModule *module,
+ const char *path)
{
struct bt_plugin *plugin = NULL;
gpointer symbol = NULL;
PLUGIN_SYMBOL_LICENSE, g_module_name(module));
goto error;
}
- if (!g_module_symbol(module, PLUGIN_SYMBOL_INIT, &symbol)) {
- printf_error("Unable to resolve plugin symbol %s from %s",
- PLUGIN_SYMBOL_INIT, g_module_name(module));
+ if (!g_module_symbol(module, PLUGIN_SYMBOL_AUTHOR,
+ (gpointer *) &plugin->author)) {
+ printf_verbose("Unable to resolve plugin symbol %s from %s\n",
+ PLUGIN_SYMBOL_AUTHOR, g_module_name(module));
+ goto error;
+ }
+ if (!g_module_symbol(module, PLUGIN_SYMBOL_DESCRIPTION,
+ (gpointer *) &plugin->description)) {
+ printf_verbose("Unable to resolve plugin symbol %s from %s\n",
+ PLUGIN_SYMBOL_DESCRIPTION,
+ g_module_name(module));
+ goto error;
+ }
+ if (!g_module_symbol(module, PLUGIN_SYMBOL_REGISTER, &symbol)) {
+ printf_verbose("Unable to resolve plugin symbol %s from %s\n",
+ PLUGIN_SYMBOL_REGISTER, g_module_name(module));
goto error;
} else {
- plugin->init = *((bt_plugin_init_func *) symbol);
- if (!plugin->init) {
- printf_error("NULL %s symbol target",
- PLUGIN_SYMBOL_INIT);
+ plugin->_register = *((bt_plugin_register_func *) symbol);
+ if (!plugin->_register) {
+ printf_verbose("NULL %s symbol target\n",
+ PLUGIN_SYMBOL_REGISTER);
goto error;
}
}
- /* Optional */
- if (g_module_symbol(module, PLUGIN_SYMBOL_EXIT,
- (gpointer *) &symbol)) {
- plugin->exit = *((bt_plugin_exit_func *) symbol);
+ return plugin;
+error:
+ BT_PUT(plugin);
+ return plugin;
+}
+
+BT_HIDDEN
+struct bt_plugin *bt_plugin_create_from_static(size_t i)
+{
+ struct bt_plugin *plugin = NULL;
+
+ plugin = g_new0(struct bt_plugin, 1);
+ if (!plugin) {
+ goto error;
}
- g_module_symbol(module, PLUGIN_SYMBOL_AUTHOR,
- (gpointer *) &plugin->author);
- g_module_symbol(module, PLUGIN_SYMBOL_DESCRIPTION,
- (gpointer *) &plugin->description);
+ bt_object_init(plugin, bt_plugin_destroy);
+ plugin->_register = (SECTION_BEGIN(__plugin_register_funcs))[i];
+ if (!plugin->_register) {
+ goto error;
+ }
+ plugin->name = (SECTION_BEGIN(__plugin_names))[i];
+ plugin->author = (SECTION_BEGIN(__plugin_authors))[i];
+ plugin->license = (SECTION_BEGIN(__plugin_licenses))[i];
+ plugin->description = (SECTION_BEGIN(__plugin_descriptions))[i];
return plugin;
error:
- BT_PUT(plugin);
+ BT_PUT(plugin);
return plugin;
}
struct bt_plugin *plugin, struct bt_component_factory *factory)
{
assert(plugin && factory);
- return plugin->init(factory);
+ return plugin->_register(factory);
}
const char *bt_plugin_get_name(struct bt_plugin *plugin)
const char *bt_plugin_get_path(struct bt_plugin *plugin)
{
- return plugin ? plugin->path->str : NULL;
+ return (plugin && plugin->path) ? plugin->path->str : NULL;
}
const char *bt_plugin_get_description(struct bt_plugin *plugin)