From 47018104da1982b63fd8881eab5796df42289979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 13 Jan 2019 11:13:47 +0100 Subject: [PATCH] particles: compile as shared libraries (plugins) --- CMakeLists.txt | 15 ++------ config-verify.c | 74 ++++++---------------------------------- config.c | 48 +++++++++++--------------- modules/CMakeLists.txt | 6 ++++ particles/CMakeLists.txt | 24 +++++++++++++ particles/empty.c | 2 +- particles/list.c | 2 +- particles/map.c | 2 +- particles/progress-bar.c | 2 +- particles/ramp.c | 2 +- particles/string.c | 2 +- plugin.c | 28 +++++---------- plugin.h | 12 +++++++ 13 files changed, 89 insertions(+), 130 deletions(-) create mode 100644 particles/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9ed27..9bf63d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,12 +40,6 @@ add_executable(f00bar decorations/underline.c decorations/underline.h particles/dynlist.c particles/dynlist.h - particles/empty.c particles/empty.h - particles/list.c particles/list.h - particles/map.c particles/map.h - particles/progress-bar.c particles/progress-bar.h - particles/ramp.c particles/ramp.h - particles/string.c particles/string.h ) # TODO: directory global @@ -78,15 +72,10 @@ target_link_libraries(f00bar ${YAML_LIBRARIES} ) -add_library(module-sdk INTERFACE) -target_compile_definitions(module-sdk INTERFACE _GNU_SOURCE) -target_compile_options(module-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) -target_include_directories(module-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) -target_link_libraries(module-sdk INTERFACE ${CMAKE_THREAD_LIBS_INIT}) - set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar) -set_property(TARGET f00bar PROPERTY BUILD_RPATH \$ORIGIN/modules) +set_property(TARGET f00bar PROPERTY BUILD_RPATH "\$ORIGIN/modules;\$ORIGIN/particles") install(TARGETS f00bar DESTINATION bin) +add_subdirectory(particles) add_subdirectory(modules) diff --git a/config-verify.c b/config-verify.c index 64efae4..f592520 100644 --- a/config-verify.c +++ b/config-verify.c @@ -9,13 +9,6 @@ #include "plugin.h" #include "tllist.h" -#include "particles/empty.h" -#include "particles/list.h" -#include "particles/map.h" -#include "particles/progress-bar.h" -#include "particles/ramp.h" -#include "particles/string.h" - const char * conf_err_prefix(const keychain_t *chain, const struct yml_node *node) { @@ -285,65 +278,20 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node) return false; } -#define COMMON_ATTRS \ - {"margin", false, &conf_verify_int}, \ - {"left-margin", false, &conf_verify_int}, \ - {"right-margin", false, &conf_verify_int}, \ - {"on-click", false, &conf_verify_string}, - -#undef COMMON_ATTRS - - static const struct { - const char *name; - const struct particle_info *info; - } particles_v2[] = { - {"empty", &particle_empty}, - {"list", &particle_list}, - {"map", &particle_map}, - {"progress-bar", &particle_progress_bar}, - {"ramp", &particle_ramp}, - {"string", &particle_string}, - }; - - static const struct { - const char *name; - const struct attr_info *attrs; - size_t count; - } particles[] = { - }; - - for (size_t i = 0; i < sizeof(particles_v2) / sizeof(particles_v2[0]); i++) { - if (strcmp(particles_v2[i].name, particle_name) != 0) - continue; - - if (!conf_verify_dict(chain_push(chain, particle_name), values, - particles_v2[i].info->attrs, - particles_v2[i].info->attr_count)) - { - return false; - } - - chain_pop(chain); - return true; + const struct particle_info *info = plugin_load_particle(particle_name); + if (info == NULL) { + LOG_ERR( + "%s: invalid particle name: %s", + conf_err_prefix(chain, particle), particle_name); + return false; } - for (size_t i = 0; i < sizeof(particles) / sizeof(particles[0]); i++) { - if (strcmp(particles[i].name, particle_name) != 0) - continue; + if (!conf_verify_dict(chain_push(chain, particle_name), values, + info->attrs, info->attr_count)) + return false; - if (!conf_verify_dict(chain_push(chain, particle_name), values, - particles[i].attrs, particles[i].count)) - { - return false; - } - - chain_pop(chain); - return true; - } - - LOG_ERR( - "%s: invalid particle name: %s", conf_err_prefix(chain, particle), particle_name); - return false; + chain_pop(chain); + return true; } bool diff --git a/config.c b/config.c index e6441ef..1ccc026 100644 --- a/config.c +++ b/config.c @@ -5,6 +5,8 @@ #include #include +#include + #include "color.h" #include "decoration.h" @@ -12,14 +14,6 @@ #include "decorations/stack.h" #include "decorations/underline.h" -#include "particle.h" -#include "particles/empty.h" -#include "particles/list.h" -#include "particles/map.h" -#include "particles/progress-bar.h" -#include "particles/ramp.h" -#include "particles/string.h" - #include "module.h" #include "config-verify.h" #include "plugin.h" @@ -153,6 +147,18 @@ particle_simple_list_from_config(const struct yml_node *node, parts[idx] = conf_to_particle(it.node, parent_font); } + /* Lazy-loaded function pointer to particle_list_new() */ + static struct particle *(*particle_list_new)( + struct particle *particles[], size_t count, + int left_spacing, int right_spacing, int left_margin, int right_margin, + const char *on_click_template) = NULL; + + if (particle_list_new == NULL) { + const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE); + particle_list_new = dlsym(plug->lib, "particle_list_new"); + assert(particle_list_new != NULL); + } + return particle_list_new(parts, count, 0, 2, 0, 0, NULL); } @@ -178,27 +184,11 @@ conf_to_particle(const struct yml_node *node, const struct font *parent_font) const char *on_click_template = on_click != NULL ? yml_value_as_string(on_click) : NULL; - struct particle *ret = NULL; - if (strcmp(type, "empty") == 0) - ret = particle_empty.from_conf( - pair.value, parent_font, left, right, on_click_template); - else if (strcmp(type, "list") == 0) - ret = particle_list.from_conf( - pair.value, parent_font, left, right, on_click_template); - else if (strcmp(type, "map") == 0) - ret = particle_map.from_conf( - pair.value, parent_font, left, right, on_click_template); - else if (strcmp(type, "progress-bar") == 0) - ret = particle_progress_bar.from_conf( - pair.value, parent_font, left, right, on_click_template); - else if (strcmp(type, "ramp") == 0) - ret = particle_ramp.from_conf( - pair.value, parent_font, left, right, on_click_template); - else if (strcmp(type, "string") == 0) - ret = particle_string.from_conf( - pair.value, parent_font, left, right, on_click_template); - else - assert(false); + const struct particle_info *info = plugin_load_particle(type); + assert(info != NULL); + + struct particle *ret = info->from_conf( + pair.value, parent_font, left, right, on_click_template); const struct yml_node *deco_node = yml_get_value(pair.value, "deco"); diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 9ea7116..f700181 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13) +add_library(module-sdk INTERFACE) +target_compile_definitions(module-sdk INTERFACE _GNU_SOURCE) +target_compile_options(module-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) +target_include_directories(module-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) +target_link_libraries(module-sdk INTERFACE ${CMAKE_THREAD_LIBS_INIT}) + pkg_check_modules(ALSA REQUIRED alsa) add_library(alsa MODULE alsa.c) target_compile_options(alsa PRIVATE ${ALSA_CFLAGS_OTHER}) diff --git a/particles/CMakeLists.txt b/particles/CMakeLists.txt new file mode 100644 index 0000000..3a5f348 --- /dev/null +++ b/particles/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.13) + +add_library(particle-sdk INTERFACE) +target_compile_definitions(particle-sdk INTERFACE _GNU_SOURCE) +target_compile_options(particle-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) +target_include_directories(particle-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) + +add_library(empty MODULE empty.c empty.h) +target_link_libraries(empty particle-sdk) + +add_library(list MODULE list.c list.h) +target_link_libraries(list particle-sdk) + +add_library(map MODULE map.c map.h) +target_link_libraries(map particle-sdk) + +add_library(progress-bar MODULE progress-bar.c progress-bar.h) +target_link_libraries(progress-bar particle-sdk) + +add_library(ramp MODULE ramp.c ramp.h) +target_link_libraries(ramp particle-sdk) + +add_library(string MODULE string.c string.h) +target_link_libraries(string particle-sdk) diff --git a/particles/empty.c b/particles/empty.c index 0ab63a2..184ce78 100644 --- a/particles/empty.c +++ b/particles/empty.c @@ -48,7 +48,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, return empty_new(left_margin, right_margin, on_click_template); } -const struct particle_info particle_empty = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 0, .attrs = { diff --git a/particles/list.c b/particles/list.c index e427c0c..90ba4ac 100644 --- a/particles/list.c +++ b/particles/list.c @@ -198,7 +198,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, on_click_template); } -const struct particle_info particle_list = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 4, .attrs = { diff --git a/particles/map.c b/particles/map.c index fee606b..3e023a1 100644 --- a/particles/map.c +++ b/particles/map.c @@ -228,7 +228,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, default_particle, left_margin, right_margin, on_click_template); } -const struct particle_info particle_map = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 3, .attrs = { diff --git a/particles/progress-bar.c b/particles/progress-bar.c index d90a8a6..68b0d0f 100644 --- a/particles/progress-bar.c +++ b/particles/progress-bar.c @@ -257,7 +257,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, left_margin, right_margin, on_click_template); } -const struct particle_info particle_progress_bar = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 7, .attrs = { diff --git a/particles/ramp.c b/particles/ramp.c index 60f6b11..2e51cb7 100644 --- a/particles/ramp.c +++ b/particles/ramp.c @@ -178,7 +178,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, on_click_template); } -const struct particle_info particle_ramp = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 2, .attrs = { diff --git a/particles/string.c b/particles/string.c index 5731692..eef9d6b 100644 --- a/particles/string.c +++ b/particles/string.c @@ -171,7 +171,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font, fg_color, left_margin, right_margin, on_click_template); } -const struct particle_info particle_string = { +const struct particle_info plugin_info = { .from_conf = &from_conf, .attr_count = PARTICLE_COMMON_ATTRS_COUNT + 5, .attrs = { diff --git a/plugin.c b/plugin.c index 0ed13e4..38bc0e2 100644 --- a/plugin.c +++ b/plugin.c @@ -9,16 +9,6 @@ #include "config.h" #include "tllist.h" -enum plugin_type { PLUGIN_MODULE, PLUGIN_PARTICLE }; - -struct plugin { - char *name; - enum plugin_type type; - - void *lib; - const void *sym; -}; - static tll(struct plugin) plugins = tll_init(); static const char * @@ -51,15 +41,14 @@ fini(void) tll_free_and_free(plugins, free_plugin); } -static const void * -_load_plugin(const char *name, enum plugin_type type) +const struct plugin * +plugin_load(const char *name, enum plugin_type type) { - /* Have we already loaded it? */ tll_foreach(plugins, plug) { if (plug->item.type == type && strcmp(plug->item.name, name) == 0) { LOG_DBG("%s: %s already loaded: %p", type2str(type), name, plug->item.lib); assert(plug->item.sym != NULL); - return plug->item.sym; + return &plug->item; } } @@ -80,7 +69,7 @@ _load_plugin(const char *name, enum plugin_type type) /* TODO: rename to plugin_info or so, in both modules and particles */ dlerror(); /* Clear previous error */ - plug->sym = dlsym(lib, type == PLUGIN_MODULE ? "module_info" : "particle_info"); + plug->sym = dlsym(lib, type == PLUGIN_MODULE ? "module_info" : "plugin_info"); const char *dlsym_error = dlerror(); if (dlsym_error != NULL) { @@ -88,18 +77,19 @@ _load_plugin(const char *name, enum plugin_type type) return NULL; } - assert(plug->sym != NULL); - return plug->sym; + return plug; } const struct module_info * plugin_load_module(const char *name) { - return _load_plugin(name, PLUGIN_MODULE); + const struct plugin *plug = plugin_load(name, PLUGIN_MODULE); + return plug != NULL ? plug->sym : NULL; } const struct particle_info * plugin_load_particle(const char *name) { - return _load_plugin(name, PLUGIN_PARTICLE); + const struct plugin *plug = plugin_load(name, PLUGIN_PARTICLE); + return plug != NULL ? plug->sym : NULL; } diff --git a/plugin.h b/plugin.h index 58e4421..aaa84c4 100644 --- a/plugin.h +++ b/plugin.h @@ -5,3 +5,15 @@ const struct module_info *plugin_load_module(const char *name); const struct particle_info *plugin_load_particle(const char *name); + +enum plugin_type { PLUGIN_MODULE, PLUGIN_PARTICLE }; + +struct plugin { + char *name; + enum plugin_type type; + + void *lib; + const void *sym; +}; + +const struct plugin *plugin_load(const char *name, enum plugin_type type);