Skip to content

Commit

Permalink
Implement dependencies for loaders.
Browse files Browse the repository at this point in the history
  • Loading branch information
viferga committed Jan 30, 2025
1 parent 911e7a3 commit aa13d6c
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 32 deletions.
15 changes: 15 additions & 0 deletions source/dynlink/include/dynlink/dynlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ DYNLINK_API const char *dynlink_extension(void);
*/
DYNLINK_API dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags);

/**
* @brief
* Load a dynamically linked shared object with absolute path
*
* @param[in] path
* Path where is located the shared object (absolute)
*
* @param[in] flags
* Dynamic linking flags
*
* @return
* A handle to the dynamically linked shared object
*/
DYNLINK_API dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags);

/**
* @brief
* Retreive the name of the dynamically linked shared object
Expand Down
24 changes: 24 additions & 0 deletions source/dynlink/source/dynlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,30 @@ dynlink dynlink_load(dynlink_path path, dynlink_name name, dynlink_flags flags)
return NULL;
}

dynlink dynlink_load_absolute(dynlink_path path, dynlink_flags flags)
{
dynlink handle = malloc(sizeof(struct dynlink_type));

if (handle == NULL)
{
return NULL;
}

strncpy(handle->name_impl, path, strnlen(path, PORTABILITY_PATH_SIZE) + 1);

handle->flags = flags;

handle->impl = dynlink_impl_load(handle);

if (handle->impl == NULL)
{
free(handle);
return NULL;
}

return handle;
}

dynlink_name dynlink_get_name(dynlink handle)
{
if (handle != NULL)
Expand Down
2 changes: 2 additions & 0 deletions source/loader/include/loader/loader_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ LOADER_API loader_impl loader_impl_create(const loader_tag tag);

LOADER_API loader_impl loader_impl_create_host(const loader_tag tag);

LOADER_API int loader_impl_dependencies(loader_impl impl);

LOADER_API void loader_impl_attach(loader_impl impl, plugin p);

LOADER_API plugin loader_impl_plugin(loader_impl impl);
Expand Down
2 changes: 0 additions & 2 deletions source/loader/include/loader/loader_impl_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
extern "C" {
#endif

#include <stdlib.h>

struct loader_impl_type;

typedef struct loader_impl_type *loader_impl;
Expand Down
7 changes: 7 additions & 0 deletions source/loader/source/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ plugin loader_get_impl_plugin(const loader_tag tag)
goto loader_create_error;
}

/* Dynamic link loader dependencies if it is not host */
if (loader_impl_get_option_host(impl) == 0)
{
loader_impl_dependencies(impl);
}

/* Dynamic link the loader */
p = plugin_manager_create(&loader_manager, tag, impl, &loader_impl_destroy_dtor);

if (p == NULL)
Expand Down
116 changes: 88 additions & 28 deletions source/loader/source/loader_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct loader_impl_type
set type_info_map; /* Stores a set indexed by type name of all of the types existing in the loader (global scope (TODO: may need refactor per handle)) */
value options; /* Additional initialization options passed in the initialize phase */
set exec_path_map; /* Set of execution paths passed by the end user */
configuration config; /* Reference to the loader configuration, it contains execution_paths, dependencies and additional info */
};

struct loader_handle_impl_type
Expand Down Expand Up @@ -119,7 +120,7 @@ struct loader_impl_metadata_cb_iterator_type

static loader_impl loader_impl_allocate(const loader_tag tag);

static configuration loader_impl_initialize_configuration(plugin p);
static configuration loader_impl_initialize_configuration(const loader_tag tag);

static int loader_impl_initialize_registered(plugin_manager manager, plugin p);

Expand Down Expand Up @@ -258,50 +259,110 @@ plugin loader_impl_plugin(loader_impl impl)
return NULL;
}

void loader_impl_configuration(loader_impl_interface iface, loader_impl impl, configuration config)
void loader_impl_configuration_execution_paths(loader_impl_interface iface, loader_impl impl)
{
value execution_paths_value = configuration_value_type(config, "execution_paths", TYPE_ARRAY);
value execution_paths_value = configuration_value_type(impl->config, "execution_paths", TYPE_ARRAY);

if (execution_paths_value != NULL)
{
size_t size = value_type_count(execution_paths_value);
value *execution_paths_array = value_to_array(execution_paths_value);
size_t iterator;

if (execution_paths_array != NULL)
for (iterator = 0; iterator < size; ++iterator)
{
size_t iterator;
if (value_type_id(execution_paths_array[iterator]) == TYPE_STRING)
{
const char *str = value_to_string(execution_paths_array[iterator]);
size_t str_size = value_type_size(execution_paths_array[iterator]);

if (str != NULL)
{
loader_path execution_path;

strncpy(execution_path, str, str_size > LOADER_PATH_SIZE ? LOADER_PATH_SIZE : str_size);

iface->execution_path(impl, execution_path);
}
}
}
}
}

int loader_impl_dependencies(loader_impl impl)
{
/* Dependencies have the following format */
/*
{
"dependencies": {
"node": ["/usr/lib/x86_64-linux-gnu/libnode.so.72"]
}
}
*/
value dependencies_value = configuration_value_type(impl->config, "dependencies", TYPE_MAP);

for (iterator = 0; iterator < size; ++iterator)
if (dependencies_value != NULL)
{
size_t size = value_type_count(dependencies_value);
value *dependencies_map = value_to_map(dependencies_value);
size_t iterator;

for (iterator = 0; iterator < size; ++iterator)
{
if (value_type_id(dependencies_map[iterator]) == TYPE_ARRAY)
{
if (execution_paths_array[iterator] != NULL)
value *library_tuple = value_to_array(dependencies_map[iterator]);

if (value_type_id(library_tuple[1]) == TYPE_ARRAY)
{
const char *str = value_to_string(execution_paths_array[iterator]);
size_t str_size = value_type_size(execution_paths_array[iterator]);
value *paths_array = value_to_array(library_tuple[1]);
size_t paths_size = value_type_count(library_tuple[1]);
size_t path;
int found = 0;

if (str != NULL)
for (path = 0; path < paths_size; ++path)
{
loader_path execution_path;
if (value_type_id(paths_array[iterator]) == TYPE_STRING)
{
const char *library_path = value_to_string(paths_array[iterator]);

strncpy(execution_path, str, str_size > LOADER_PATH_SIZE ? LOADER_PATH_SIZE : str_size);
if (library_path != NULL)
{
dynlink handle = dynlink_load_absolute(library_path, DYNLINK_FLAGS_BIND_LAZY | DYNLINK_FLAGS_BIND_GLOBAL);

iface->execution_path(impl, execution_path);
if (handle != NULL)
{
found = 1;
break;
}
}
}
}

if (!found)
{
const char *dependency = value_type_id(library_tuple[0]) == TYPE_STRING ? value_to_string(library_tuple[0]) : "unknown_library";
log_write("metacall", LOG_LEVEL_ERROR, "Failed to load dependency '%s' from loader configuration '%s.json'", dependency, plugin_name(impl->p));
return 1;
}
}
}
}
}

return 0;
}

configuration loader_impl_initialize_configuration(plugin p)
configuration loader_impl_initialize_configuration(const loader_tag tag)
{
static const char configuration_key_suffix[] = "_loader";
#define CONFIGURATION_KEY_SIZE ((size_t)sizeof(configuration_key_suffix) + LOADER_TAG_SIZE - 1)
char configuration_key[CONFIGURATION_KEY_SIZE];

/* Retrieve the configuration key: <tag>_loader */
size_t tag_size = strnlen(plugin_name(p), LOADER_TAG_SIZE) + 1;
size_t tag_size = strnlen(tag, LOADER_TAG_SIZE) + 1;

strncpy(configuration_key, plugin_name(p), tag_size);
strncpy(configuration_key, tag, tag_size);

strncat(configuration_key, configuration_key_suffix, CONFIGURATION_KEY_SIZE - tag_size);
#undef CONFIGURATION_KEY_SIZE
Expand Down Expand Up @@ -331,7 +392,6 @@ int loader_impl_initialize_registered(plugin_manager manager, plugin p)
int loader_impl_initialize(plugin_manager manager, plugin p, loader_impl impl)
{
static const char loader_library_path[] = "loader_library_path";
configuration config;
value loader_library_path_value = NULL;
char *library_path = NULL;
vector script_paths, paths;
Expand All @@ -341,9 +401,6 @@ int loader_impl_initialize(plugin_manager manager, plugin p, loader_impl impl)
return 0;
}

/* Get the configuration of the loader */
config = loader_impl_initialize_configuration(p);

/* Retrieve the library path */
library_path = plugin_manager_library_path(manager);

Expand All @@ -355,19 +412,19 @@ int loader_impl_initialize(plugin_manager manager, plugin p, loader_impl impl)
*/

/* Check if the configuration has a custom loader_library_path, otherwise set it up */
if (config != NULL && configuration_value_type(config, loader_library_path, TYPE_STRING) == NULL)
if (impl->config != NULL && configuration_value_type(impl->config, loader_library_path, TYPE_STRING) == NULL)
{
loader_library_path_value = value_create_string(library_path, strnlen(library_path, LOADER_PATH_SIZE));
configuration_define(config, loader_library_path, loader_library_path_value);
configuration_define(impl->config, loader_library_path, loader_library_path_value);
}

/* Call to the loader initialize method */
impl->data = loader_iface(p)->initialize(impl, config);
impl->data = loader_iface(p)->initialize(impl, impl->config);

/* Undefine the library path field from config */
if (config != NULL && loader_library_path_value != NULL)
if (impl->config != NULL && loader_library_path_value != NULL)
{
configuration_undefine(config, loader_library_path);
configuration_undefine(impl->config, loader_library_path);
value_type_destroy(loader_library_path_value);
}

Expand All @@ -390,9 +447,9 @@ int loader_impl_initialize(plugin_manager manager, plugin p, loader_impl impl)

impl->init = 0;

if (config != NULL)
if (impl->config != NULL)
{
loader_impl_configuration(loader_iface(p), impl, config);
loader_impl_configuration_execution_paths(loader_iface(p), impl);
}

/* The scripts path priority order is the following:
Expand All @@ -402,7 +459,7 @@ int loader_impl_initialize(plugin_manager manager, plugin p, loader_impl impl)
*/

/* Load the library path as execution path */
loader_library_path_value = configuration_value_type(config, loader_library_path, TYPE_STRING);
loader_library_path_value = configuration_value_type(impl->config, loader_library_path, TYPE_STRING);

if (loader_library_path_value != NULL)
{
Expand Down Expand Up @@ -470,6 +527,9 @@ loader_impl loader_impl_create(const loader_tag tag)
impl->init = 1;
impl->options = NULL;

/* Get the configuration of the loader */
impl->config = loader_impl_initialize_configuration(tag);

return impl;
}

Expand Down
5 changes: 3 additions & 2 deletions source/loaders/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ set(LOADER_CONFIGURATION_DEFAULT_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/loader.js
# Define loader configuration for a specific loader
macro(loader_configuration_begin TARGET)
set(LOADER_DEPENDENCIES "")
set(OPTIONAL_TEMPLATE "${ARGV1}")

# Optional argument for template
if(${ARGV0})
set(LOADER_CONFIGURATION_TEMPLATE "${ARGV0}")
if(NOT "${ARGV1}" STREQUAL "")
set(LOADER_CONFIGURATION_TEMPLATE "${ARGV1}")
else()
set(LOADER_CONFIGURATION_TEMPLATE "${LOADER_CONFIGURATION_DEFAULT_TEMPLATE}")
endif()
Expand Down

0 comments on commit aa13d6c

Please sign in to comment.