Skip to content

Commit

Permalink
Add loader config with dependencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
viferga committed Jan 29, 2025
1 parent 0fe2295 commit 50c27f2
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 42 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#

# CMake version
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

# Include cmake modules

Expand Down Expand Up @@ -241,6 +241,9 @@ else()
endif()
endif()

# Export compile commands
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

#
# CTest configuration
#
Expand Down
10 changes: 6 additions & 4 deletions source/configuration/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,19 @@ target_link_libraries(${target}
function(configurations_write config_dir config_path)
set(CONFIGURATION_GLOBAL "{")

if(OPTION_BUILD_LOADERS)
set(CONFIGURATION_GLOBAL_LOADERS 0)
# TODO: Make this automatic for all loaders

if(OPTION_BUILD_LOADERS)
if(OPTION_BUILD_LOADERS_CS)
set(CONFIGURATION_GLOBAL "${CONFIGURATION_GLOBAL}\n\t\"cs_loader\":\"${config_dir}/cs_loader.json\",")
set(CONFIGURATION_GLOBAL_LOADERS 1)
endif()

if(OPTION_BUILD_LOADERS_NODE)
set(CONFIGURATION_GLOBAL "${CONFIGURATION_GLOBAL}\n\t\"node_loader\":\"${config_dir}/node_loader.json\",")
endif()

#if(OPTION_BUILD_LOADERS_JS)
# set(CONFIGURATION_GLOBAL "${CONFIGURATION_GLOBAL}\n\t\"js_loader\":\"${config_dir}/js_loader.json\",")
# set(CONFIGURATION_GLOBAL_LOADERS 1)
#endif()
endif()

Expand Down
173 changes: 146 additions & 27 deletions source/loaders/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,141 @@ option(OPTION_BUILD_LOADERS_RPC "Build cURL Remote Procedure Call loader plugin.
option(OPTION_BUILD_LOADERS_TS "Build TypeScript 3.9.7 Runtime loader plugin." OFF)
option(OPTION_BUILD_LOADERS_WASM "Build WebAssembly Virtual Machine loader plugin." OFF)

#
# Configuration for loaders
#
# The following list of macros is used for generating a configuration file which includes
# dependencies, this is required because now loaders can either load the dependencies or
# use the existing dependencies if MetaCall is being loaded from python.exe, node.exe
# or similar... so we require to delay the loader dependencies until we know if
# their dependencies are already present.
#
# This set of macros provies a flexible way of defining the configuration and dependencies.
#
# 1) The most basic case, let's assume we have the dependencies in the system, like in Python:
#
# loader_configuration_begin(py_loader)
# loader_configuration_deps(python "${Python3_LIBRARY}")
# loader_configuartion_end()
#
# 2) Maybe you want to have multiple paths for a library:
#
# loader_configuration_begin(node_loader)
# loader_configuration_deps(node "/path/to/libnode.so" "/alternative/path/to/libnode.so")
# loader_configuartion_end()
#
# 3) Or the dependencies are compiled by you and you so you have different folders for
# for development (build folder) and for when installing it:
#
# loader_configuration_begin(node_loader)
# loader_configuration_deps(node "/path/to/build/folder/libnode.so")
# loader_configuartion_end_development()
#
# loader_configuration_begin(node_loader)
# loader_configuration_deps(node "/path/to/install/folder/libnode.so")
# loader_configuartion_end_install()
#
# 4) Or you have a custom template because your loader needs a configuration with more fields:
#
# loader_configuration_begin(cs_loader)
# loader_configuration_deps(netcore "/path/to/build/folder/libnetcore.so")
# loader_configuartion_end()
#
# You can do any combination of those for defining the configuration of your loaders.
#

# Define loader template configuration
set(LOADER_CONFIGURATION_DEFAULT_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/loader.json.in")

# Define loader configuration for a specific loader
macro(loader_configuration_begin TARGET)
set(LOADER_DEPENDENCIES "")

# Optional argument for template
if(${ARGV0})
set(LOADER_CONFIGURATION_TEMPLATE "${ARGV0}")
else()
set(LOADER_CONFIGURATION_TEMPLATE "${LOADER_CONFIGURATION_DEFAULT_TEMPLATE}")
endif()

set(LOADER_CONFIGURATION_TARGET "${TARGET}")
endmacro()

# Generate configuration with dependencies for a loader
#
# node_loader:
# "node": [ "/path/to/libnode.so", "/alternative/path/to/libnode.so" ],
#
# c_loader:
# "libffi": [ ... ],
# "libclang": [ ... ],
# "libtcc": [ ... ]
macro(loader_configuration_deps LIBRARY)
# Add new line from previous dependency
if(NOT "${LOADER_DEPENDENCIES}" STREQUAL "")
string(APPEND LOADER_DEPENDENCIES ",\n\t\t")
endif()

# Define the library
string(APPEND LOADER_DEPENDENCIES "\"${LIBRARY}\": [")

# Define the paths
set(FIRST_ARGUMENT 0)
foreach(DEPENDENCY IN ITEMS ${ARGN})
if(${FIRST_ARGUMENT} EQUAL 0)
# Set first path
string(APPEND LOADER_DEPENDENCIES "\"${DEPENDENCY}\"")
set(FIRST_ARGUMENT 1)
else()
# Set the rest of the paths
string(APPEND LOADER_DEPENDENCIES ", \"${DEPENDENCY}\"")
endif()
endforeach()

# Finalize the list
string(APPEND LOADER_DEPENDENCIES "]")
endmacro()

# Commit development version
macro(loader_configuartion_end_development)
if(NOT DEFINED LOADER_CONFIGURATION_TEMPLATE OR NOT DEFINED LOADER_CONFIGURATION_TARGET)
return()
endif()

configure_file(${LOADER_CONFIGURATION_TEMPLATE} ${CONFIGURATION_DIR}/${LOADER_CONFIGURATION_TARGET}.json)

unset(LOADER_DEPENDENCIES)
unset(LOADER_CONFIGURATION_TEMPLATE)
unset(LOADER_CONFIGURATION_TARGET)
endmacro()

# Commit install version
macro(loader_configuartion_end_install)
if(NOT DEFINED LOADER_CONFIGURATION_TEMPLATE OR NOT DEFINED LOADER_CONFIGURATION_TARGET)
return()
endif()

configure_file(${LOADER_CONFIGURATION_TEMPLATE} ${CONFIGURATION_DIR}/install/configurations/${LOADER_CONFIGURATION_TARGET}.json)

unset(LOADER_DEPENDENCIES)
unset(LOADER_CONFIGURATION_TEMPLATE)
unset(LOADER_CONFIGURATION_TARGET)
endmacro()

# Commit both versions
macro(loader_configuartion_end)
if(NOT DEFINED LOADER_CONFIGURATION_TEMPLATE OR NOT DEFINED LOADER_CONFIGURATION_TARGET)
return()
endif()

configure_file(${LOADER_CONFIGURATION_TEMPLATE} ${CONFIGURATION_DIR}/${LOADER_CONFIGURATION_TARGET}.json)
configure_file(${LOADER_CONFIGURATION_TEMPLATE} ${CONFIGURATION_DIR}/install/configurations/${LOADER_CONFIGURATION_TARGET}.json)

unset(LOADER_DEPENDENCIES)
unset(LOADER_CONFIGURATION_TEMPLATE)
unset(LOADER_CONFIGURATION_TARGET)
endmacro()

# Plugin packages
add_subdirectory(c_loader) # Foreign Function Interface library
add_subdirectory(cob_loader) # GNU/Cobol 2.2 Runtime
Expand All @@ -49,34 +184,18 @@ add_subdirectory(rpc_loader) # cURL Remote Procedure Call
add_subdirectory(ts_loader) # TypeScript 3.9.7
add_subdirectory(wasm_loader) # WebAssembly Virtual Machine

# Optionally enable loader dependencies utility
macro(add_loader_dependencies target)
set(loaders_map_c_loader OPTION_BUILD_LOADERS_C)
set(loaders_map_cob_loader OPTION_BUILD_LOADERS_COB)
set(loaders_map_cr_loader OPTION_BUILD_LOADERS_CR)
set(loaders_map_cs_loader OPTION_BUILD_LOADERS_DART)
set(loaders_map_dart_loader OPTION_BUILD_LOADERS_CS)
set(loaders_map_ext_loader OPTION_BUILD_LOADERS_EXT)
set(loaders_map_file_loader OPTION_BUILD_LOADERS_FILE)
set(loaders_map_java_loader OPTION_BUILD_LOADERS_JAVA)
set(loaders_map_jl_loader OPTION_BUILD_LOADERS_JL)
set(loaders_map_jsm_loader OPTION_BUILD_LOADERS_JSM)
set(loaders_map_js_loader OPTION_BUILD_LOADERS_JS)
set(loaders_map_llvm_loader OPTION_BUILD_LOADERS_LLVM)
set(loaders_map_lua_loader OPTION_BUILD_LOADERS_LUA)
set(loaders_map_mock_loader OPTION_BUILD_LOADERS_MOCK)
set(loaders_map_node_loader OPTION_BUILD_LOADERS_NODE)
set(loaders_map_py_loader OPTION_BUILD_LOADERS_PY)
set(loaders_map_rb_loader OPTION_BUILD_LOADERS_RB)
set(loaders_map_rs_loader OPTION_BUILD_LOADERS_RS)
set(loaders_map_rpc_loader OPTION_BUILD_LOADERS_RPC)
set(loaders_map_ts_loader OPTION_BUILD_LOADERS_TS)
set(loaders_map_wasm_loader OPTION_BUILD_LOADERS_WASM)

# Optionally enable loader dependencies utility (for tests)
macro(add_loader_dependencies TARGET)
set(LOADERS_LIST)

foreach(loader ${ARGN})
if(${loaders_map_${loader}})
foreach(LOADER ${ARGN})
# Loaders come in the form of: py_loader, node_loader, ...
# Convert them into OPTION_BUILD_LOADERS_PY, OPTION_BUILD_LOADERS_NODE, ...
string(REPLACE "_loader" "" LOADER_TAG "${LOADER}")
string(TOUPPER "${LOADER_TAG}" LOADER_TAG)

# Check if the loader is enabled
if(${OPTION_BUILD_LOADERS_${LOADER_TAG}})
set(LOADERS_LIST
${LOADERS_LIST}
${loader}
Expand All @@ -85,6 +204,6 @@ macro(add_loader_dependencies target)
endforeach()

if(LOADERS_LIST)
add_dependencies(${target} ${LOADERS_LIST})
add_dependencies(${TARGET} ${LOADERS_LIST})
endif()
endmacro()
13 changes: 9 additions & 4 deletions source/loaders/cs_loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,18 @@ target_link_libraries(${target}
# Configuration
#

set(CS_LOADER_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/data/cs_loader.json.in")
string(REPLACE "\\" "/" DOTNET_CORE_PATH "${DOTNET_CORE_PATH}")

set(DOTNET_CORE_LOADER_ASSEMBLY_PATH ${PROJECT_OUTPUT_DIR}/CSLoader.dll)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/cs_loader.json.in ${CONFIGURATION_DIR}/cs_loader.json)
# Development
loader_configuration_begin(cs_loader "${CS_LOADER_CONFIG_TEMPLATE}")
set(DOTNET_CORE_LOADER_ASSEMBLY_PATH ${PROJECT_OUTPUT_DIR}/CSLoader.dll)
loader_configuartion_end_development()

set(DOTNET_CORE_LOADER_ASSEMBLY_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/CSLoader.dll)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/cs_loader.json.in ${CONFIGURATION_DIR}/install/configurations/cs_loader.json)
# Install
loader_configuration_begin(cs_loader "${CS_LOADER_CONFIG_TEMPLATE}")
set(DOTNET_CORE_LOADER_ASSEMBLY_PATH ${PROJECT_OUTPUT_DIR}/CSLoader.dll)
loader_configuartion_end_install()

#
# Deployment
Expand Down
4 changes: 2 additions & 2 deletions source/loaders/cs_loader/data/cs_loader.json.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dotnet_root":"@DOTNET_CORE_PATH@",
"dotnet_loader_assembly_path":"@DOTNET_CORE_LOADER_ASSEMBLY_PATH@"
"dotnet_root": "@DOTNET_CORE_PATH@",
"dotnet_loader_assembly_path": "@DOTNET_CORE_LOADER_ASSEMBLY_PATH@"
}
5 changes: 5 additions & 0 deletions source/loaders/loader.json.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
@LOADER_DEPENDENCIES@
}
}
27 changes: 24 additions & 3 deletions source/loaders/node_loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ target_link_libraries(${target}
PRIVATE
${META_PROJECT_NAME}::metacall # MetaCall library

# TODO: Implement delayed load
${NodeJS_LIBRARY} # NodeJS library

PUBLIC
${DEFAULT_LIBRARIES}

Expand Down Expand Up @@ -227,6 +224,8 @@ install(TARGETS ${target}
ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT dev
)

set(NodeJS_LIBRARY_DEVELOPMENT "${NodeJS_LIBRARY}")

# Runtime (pack NodeJS DLL in windows)
# TODO: https://cmake.org/cmake/help/latest/command/file.html#get-runtime-dependencies
# TODO: https://gist.github.com/micahsnyder/5d98ac8548b429309ec5a35bca9366da
Expand All @@ -236,10 +235,32 @@ if(NodeJS_LIBRARY_NAME_PATH AND WIN32)
DESTINATION ${INSTALL_LIB}
COMPONENT runtime
)

get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY_NAME_PATH}" NAME)
set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}")
elseif(NodeJS_BUILD_FROM_SOURCE AND NOT WIN32)
install(FILES
"${NodeJS_LIBRARY}"
DESTINATION ${INSTALL_LIB}
COMPONENT runtime
)

get_filename_component(NodeJS_LIBRARY_NAME "${NodeJS_LIBRARY}" NAME)
set(NodeJS_LIBRARY_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}/${NodeJS_LIBRARY_NAME}")
else()
set(NodeJS_LIBRARY_INSTALL "${NodeJS_LIBRARY}")
endif()

#
# Configuration
#

# Development
loader_configuration_begin(node_loader)
loader_configuration_deps(node "${NodeJS_LIBRARY_DEVELOPMENT}")
loader_configuartion_end_development()

# Install
loader_configuration_begin(node_loader)
loader_configuration_deps(node "${NodeJS_LIBRARY_INSTALL}")
loader_configuartion_end_install()
2 changes: 1 addition & 1 deletion source/plugin/source/plugin_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <string.h>

#if defined(WIN32) || defined(_WIN32)
#include <winbase.h>
#include <winbase.h> /* SetDllDirectoryA */
#endif

/* -- Declarations -- */
Expand Down

0 comments on commit 50c27f2

Please sign in to comment.