Load modules at run time

parent c6648544
......@@ -81,18 +81,12 @@ include_directories("${CMAKE_BINARY_DIR}/src")
#Melano modules
set_property(GLOBAL PROPERTY MELANOMODULES "")
set_property(GLOBAL PROPERTY MELANOMODULES_INIT "")
set_property(GLOBAL PROPERTY MELANOMODULES_DECLARE "")
macro(melanomodule name description default)
string(TOUPPER "MODULE_${name}" OPTION_NAME)
option (${OPTION_NAME} ${description} ${default})
set(MODULE_NAME "melanomodule_${name}")
if (${${OPTION_NAME}})
set_property(GLOBAL APPEND PROPERTY MELANOMODULES ${MODULE_NAME})
set_property(GLOBAL APPEND_STRING PROPERTY MELANOMODULES_DECLARE "
Melanomodule ${MODULE_NAME}(const Settings&);")
set_property(GLOBAL APPEND_STRING PROPERTY MELANOMODULES_INIT "\\
modules.push_back(${MODULE_NAME}(settings));")
message(STATUS "Enabled module ${name}: ${description}")
endif()
endmacro()
......@@ -100,17 +94,12 @@ endmacro()
add_subdirectory(modules lib)
get_property(MELANOMODULES GLOBAL PROPERTY MELANOMODULES)
get_property(MELANOMODULES_INIT GLOBAL PROPERTY MELANOMODULES_INIT)
get_property(MELANOMODULES_DECLARE GLOBAL PROPERTY MELANOMODULES_DECLARE)
if (NOT MELANOMODULES)
message(STATUS "No modules enabled")
else()
message(STATUS "Loaded Modules: ${MELANOMODULES}")
endif()
set(MELANOMODULE_HEADER "${PROJECT_BINARY_DIR}/src/melanomodules.hpp")
configure_file ("${PROJECT_SOURCE_DIR}/src/melanomodules.hpp.in" ${MELANOMODULE_HEADER})
# Binary
add_subdirectory(src bin)
......
......@@ -14,6 +14,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
include_directories("${CMAKE_SOURCE_DIR}/modules")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
link_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB SUBDIRS RELATIVE "${CMAKE_SOURCE_DIR}/modules" ${CMAKE_SOURCE_DIR}/modules/*)
foreach(subdir ${SUBDIRS})
......@@ -21,3 +23,5 @@ foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endif()
endforeach()
target_link_libraries(${MODULE_NAME} melanomodule_core)
......@@ -16,5 +16,5 @@ melanomodule(core "Core module, should always be enabled" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
......@@ -27,46 +27,48 @@
/**
* \brief Defines the core module
*/
Melanomodule melanomodule_core(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_core_metadata()
{
Melanomodule module {"core", "Core module"};
return {"core", "Core module"};
}
module.register_log_type("sys",color::dark_red);
module.register_handler<core::AdminQuit>("Quit");
module.register_handler<core::AdminGroup>("AdminGroup");
module.register_handler<core::FilterGroup>("FilterGroup");
module.register_handler<core::AdminReconnect>("Reconnect");
module.register_handler<core::AdminConnect>("Connect");
module.register_handler<core::AdminDisconnect>("Disconnect");
module.register_handler<core::Chanhax>("Chanhax");
MELANOMODULE_ENTRY_POINT void melanomodule_core_initialize(const Settings&)
{
module::register_log_type("sys",color::dark_red);
module.register_handler<core::Bridge>("Bridge");
module.register_handler<core::BridgeChat>("BridgeChat");
module.register_handler<core::BridgeAttach>("BridgeAttach");
module.register_handler<core::BridgeAttachChannel>("BridgeAttachChannel");
module::register_handler<core::AdminQuit>("Quit");
module::register_handler<core::AdminGroup>("AdminGroup");
module::register_handler<core::FilterGroup>("FilterGroup");
module::register_handler<core::AdminReconnect>("Reconnect");
module::register_handler<core::AdminConnect>("Connect");
module::register_handler<core::AdminDisconnect>("Disconnect");
module::register_handler<core::Chanhax>("Chanhax");
module.register_handler<core::MonitorServerStatus>("MonitorServerStatus");
module.register_handler<core::MonitorReply>("MonitorReply");
module::register_handler<core::Bridge>("Bridge");
module::register_handler<core::BridgeChat>("BridgeChat");
module::register_handler<core::BridgeAttach>("BridgeAttach");
module::register_handler<core::BridgeAttachChannel>("BridgeAttachChannel");
module.register_handler<core::JoinMessage>("JoinMessage");
module.register_handler<core::PartMessage>("PartMessage");
module.register_handler<core::KickMessage>("KickMessage");
module.register_handler<core::RenameMessage>("RenameMessage");
module::register_handler<core::MonitorServerStatus>("MonitorServerStatus");
module::register_handler<core::MonitorReply>("MonitorReply");
module.register_handler<core::License>("License");
module.register_handler<core::Help>("Help");
module.register_handler<core::Echo>("Echo");
module.register_handler<core::ServerHost>("ServerHost");
module.register_handler<core::Cointoss>("Cointoss");
module.register_handler<core::Reply>("Reply");
module.register_handler<core::Action>("Action");
module.register_handler<core::Command>("Command");
module.register_handler<core::Time>("Time");
module::register_handler<core::JoinMessage>("JoinMessage");
module::register_handler<core::PartMessage>("PartMessage");
module::register_handler<core::KickMessage>("KickMessage");
module::register_handler<core::RenameMessage>("RenameMessage");
module.register_handler<core::Group>("Group");
module.register_handler<core::Multi>("Multi");
module.register_handler<core::IfSet>("IfSet");
module::register_handler<core::License>("License");
module::register_handler<core::Help>("Help");
module::register_handler<core::Echo>("Echo");
module::register_handler<core::ServerHost>("ServerHost");
module::register_handler<core::Cointoss>("Cointoss");
module::register_handler<core::Reply>("Reply");
module::register_handler<core::Action>("Action");
module::register_handler<core::Command>("Command");
module::register_handler<core::Time>("Time");
return module;
module::register_handler<core::Group>("Group");
module::register_handler<core::Multi>("Multi");
module::register_handler<core::IfSet>("IfSet");
}
......@@ -16,4 +16,4 @@ melanomodule(file_storage "Plain file-based storage" OFF)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
......@@ -23,14 +23,15 @@
/**
* \brief Initializes the file storage module
*/
Melanomodule melanomodule_file_storage(const Settings& settings)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_file_storage_metadata()
{
Melanomodule module{"file_storage","Plain file-based storage"};
return {"file_storage","Plain file-based storage"};
}
MELANOMODULE_ENTRY_POINT void melanomodule_file_storage_initialize(const Settings& settings)
{
storage::set_storage(std::make_unique<storage::file::Storage>(
settings.get_child("storage",{})
));
return module;
}
......@@ -12,9 +12,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
melanomodule(fun "Possibly useless yet silly stuff" ON)
melanomodule(fun "Possibly useless yet silly stuff" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
target_link_libraries(${MODULE_NAME} melanomodule_core)
target_link_libraries(${MODULE_NAME} melanomodule_web)
......@@ -22,20 +22,22 @@
/**
* \brief Registers the fun handlers
*/
Melanomodule melanomodule_fun(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_fun_metadata()
{
Melanomodule module{"fun","Fun handlers"};
module.register_handler<fun::AnswerQuestions>("AnswerQuestions");
module.register_handler<fun::ChuckNorris>("ChuckNorris");
module.register_handler<fun::ReverseText>("ReverseText");
module.register_handler<fun::Morse>("Morse");
module.register_handler<fun::RainbowBridgeChat>("RainbowBridgeChat");
module.register_handler<fun::Slap>("Slap");
module.register_handler<fun::Discord>("Discord");
return {"fun", "Fun handlers", 0, {{"web"}, {"core"}}};
}
MELANOMODULE_ENTRY_POINT void melanomodule_fun_initialize(const Settings&)
{
module::register_handler<fun::AnswerQuestions>("AnswerQuestions");
module::register_handler<fun::ChuckNorris>("ChuckNorris");
module::register_handler<fun::ReverseText>("ReverseText");
module::register_handler<fun::Morse>("Morse");
module::register_handler<fun::RainbowBridgeChat>("RainbowBridgeChat");
module::register_handler<fun::Slap>("Slap");
module::register_handler<fun::Discord>("Discord");
module.register_handler<fun::RenderPony>("RenderPony");
module.register_handler<fun::PonyCountDown>("PonyCountDown");
module.register_handler<fun::PonyFace>("PonyFace");
return module;
module::register_handler<fun::RenderPony>("RenderPony");
module::register_handler<fun::PonyCountDown>("PonyCountDown");
module::register_handler<fun::PonyFace>("PonyFace");
}
......@@ -12,9 +12,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
melanomodule(irc "Internet Relay Chat support" ON)
melanomodule(irc "Internet Relay Chat support" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
target_link_libraries(${MODULE_NAME} melanomodule_core)
......@@ -27,37 +27,39 @@
/**
* \brief Initializes the IRC module
*/
Melanomodule melanomodule_irc(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_irc_metadata()
{
Melanomodule module{"irc","IRC integration"};
module.register_connection<irc::IrcConnection>("irc");
module.register_log_type("irc",color::dark_magenta);
module.register_formatter<irc::FormatterIrc>();
module.register_formatter<irc::FormatterIrcWhite>();
return {"irc","IRC integration"};
}
module.register_handler<irc::handler::CtcpVersion>("CtcpVersion");
module.register_handler<irc::handler::CtcpSource>("CtcpSource");
module.register_handler<irc::handler::CtcpUserInfo>("CtcpUserInfo");
module.register_handler<irc::handler::CtcpPing>("CtcpPing");
module.register_handler<irc::handler::CtcpTime>("CtcpTime");
module.register_handler<irc::handler::CtcpClientInfo>("CtcpClientInfo");
module.register_handler<irc::handler::Ctcp>("Ctcp");
MELANOMODULE_ENTRY_POINT void melanomodule_irc_initialize(const Settings&)
{
module::register_connection<irc::IrcConnection>("irc");
module::register_log_type("irc",color::dark_magenta);
module::register_formatter<irc::FormatterIrc>();
module::register_formatter<irc::FormatterIrcWhite>();
module.register_handler<irc::handler::IrcKickRejoin>("IrcKickRejoin");
module::register_handler<irc::handler::CtcpVersion>("CtcpVersion");
module::register_handler<irc::handler::CtcpSource>("CtcpSource");
module::register_handler<irc::handler::CtcpUserInfo>("CtcpUserInfo");
module::register_handler<irc::handler::CtcpPing>("CtcpPing");
module::register_handler<irc::handler::CtcpTime>("CtcpTime");
module::register_handler<irc::handler::CtcpClientInfo>("CtcpClientInfo");
module::register_handler<irc::handler::Ctcp>("Ctcp");
module.register_handler<irc::handler::AdminNick>("Nick");
module.register_handler<irc::handler::AdminJoin>("Join");
module.register_handler<irc::handler::AdminPart>("Part");
module.register_handler<irc::handler::AcceptInvite>("AcceptInvite");
module.register_handler<irc::handler::AdminRaw>("Raw");
module.register_handler<irc::handler::ClearBuffer>("ClearBuffer");
module::register_handler<irc::handler::IrcKickRejoin>("IrcKickRejoin");
module.register_handler<irc::handler::Whois330>("Whois330");
module.register_handler<irc::handler::QSendWhois>("QSendWhois");
module.register_handler<irc::handler::QGetWhois>("QGetWhois");
module.register_handler<irc::handler::QWhois>("QWhois");
module.register_handler<irc::handler::WhoisCheckMe>("WhoisCheckMe");
module.register_handler<irc::handler::IrcIdentify>("IrcIdentify");
module::register_handler<irc::handler::AdminNick>("Nick");
module::register_handler<irc::handler::AdminJoin>("Join");
module::register_handler<irc::handler::AdminPart>("Part");
module::register_handler<irc::handler::AcceptInvite>("AcceptInvite");
module::register_handler<irc::handler::AdminRaw>("Raw");
module::register_handler<irc::handler::ClearBuffer>("ClearBuffer");
return module;
module::register_handler<irc::handler::Whois330>("Whois330");
module::register_handler<irc::handler::QSendWhois>("QSendWhois");
module::register_handler<irc::handler::QGetWhois>("QGetWhois");
module::register_handler<irc::handler::QWhois>("QWhois");
module::register_handler<irc::handler::WhoisCheckMe>("WhoisCheckMe");
module::register_handler<irc::handler::IrcIdentify>("IrcIdentify");
}
......@@ -16,4 +16,6 @@ melanomodule(lists "Manage ToDo Lists and similar" OFF)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
target_link_libraries(${MODULE_NAME} melanomodule_core)
......@@ -24,17 +24,18 @@
/**
* \brief Initializes the lists module
*/
Melanomodule melanomodule_lists(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_lists_metadata()
{
Melanomodule module{"lists","Manage ToDo Lists and similar"};
module.register_handler<lists::FixedList>("FixedList");
module.register_handler<lists::DynamicReply>("DynamicReply");
module.register_handler<lists::DynamicReplyManager>("DynamicReplyManager");
return {"lists", "Manage ToDo Lists and similar"};
}
module.register_handler<lists::InventoryManager>("InventoryManager");
module.register_handler<lists::InventoryPut>("InventoryPut");
module.register_handler<lists::InventoryTake>("InventoryTake");
MELANOMODULE_ENTRY_POINT void melanomodule_lists_initialize(const Settings&)
{
module::register_handler<lists::FixedList>("FixedList");
module::register_handler<lists::DynamicReply>("DynamicReply");
module::register_handler<lists::DynamicReplyManager>("DynamicReplyManager");
return module;
module::register_handler<lists::InventoryManager>("InventoryManager");
module::register_handler<lists::InventoryPut>("InventoryPut");
module::register_handler<lists::InventoryTake>("InventoryTake");
}
......@@ -16,4 +16,4 @@ melanomodule(posix "Extra features for POSIX systems" OFF)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
......@@ -23,13 +23,16 @@
/**
* \brief POSIX module initialization
*/
Melanomodule melanomodule_posix(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_posix_metadata()
{
Melanomodule module{"posix","POSIX extensions"};
module.register_connection<posix::StdinConnection>("stdin");
module.register_handler<posix::MelanobotShAction>("MelanobotShAction");
module.register_handler<posix::MelanobotShRestart>("MelanobotShRestart");
module.register_handler<posix::MelanobotShQuit>("MelanobotShQuit");
module.register_log_type("std",color::white);
return module;
return {"posix","POSIX extensions"};
}
MELANOMODULE_ENTRY_POINT void melanomodule_posix_initialize(const Settings&)
{
module::register_connection<posix::StdinConnection>("stdin");
module::register_handler<posix::MelanobotShAction>("MelanobotShAction");
module::register_handler<posix::MelanobotShRestart>("MelanobotShRestart");
module::register_handler<posix::MelanobotShQuit>("MelanobotShQuit");
module::register_log_type("std",color::white);
}
......@@ -16,7 +16,7 @@ melanomodule(script "Scripting interface" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
# Boost
find_package (Boost COMPONENTS python REQUIRED)
......
......@@ -24,13 +24,15 @@
* \brief Scripting module initialization
* \todo Have the Python version available somewhere
*/
Melanomodule melanomodule_script(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_script_metadata()
{
Melanomodule module{"script","Scripting interface"};
module.register_log_type("py",color::dark_yellow);
return {"script", "Scripting interface"};
}
module.register_handler<python::SimpleScript>("SimpleScript");
module.register_handler<python::StructuredScript>("StructuredScript");
MELANOMODULE_ENTRY_POINT void melanomodule_script_initialize(const Settings&)
{
module::register_log_type("py",color::dark_yellow);
return module;
module::register_handler<python::SimpleScript>("SimpleScript");
module::register_handler<python::StructuredScript>("StructuredScript");
}
......@@ -16,24 +16,31 @@ melanomodule(web "Web stuff (HTTP and friends)" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
# cpr
# set(CPR_VERSION 1.2.0)
include(ExternalProject)
ExternalProject_Add(cpr
ExternalProject_Add(cpr_sources
PREFIX lib
GIT_REPOSITORY https://github.com/whoshuu/cpr.git
# GIT_TAG ${CPR_VERSION}
GIT_SUBMODULES opt/mongoose
CMAKE_ARGS -DBUILD_CPR_TESTS=OFF -DUSE_SYSTEM_CURL=ON -DBUILD_CURL_TESTS=OFF
CMAKE_ARGS -DBUILD_CPR_TESTS=OFF -DUSE_SYSTEM_CURL=ON -DBUILD_CURL_TESTS=OFF -DCMAKE_CXX_FLAGS=-fPIC
INSTALL_COMMAND ""
)
set(CPR_ROOT ${CMAKE_CURRENT_BINARY_DIR}/lib/src/cpr)
set(CPR_ROOT ${CMAKE_CURRENT_BINARY_DIR}/lib/src/cpr_sources)
include_directories(${CPR_ROOT}/include)
target_link_libraries(${MODULE_NAME} ${CPR_ROOT}-build/lib/libcpr.a)
link_directories(${CPR_ROOT}-build/lib)
add_library(${MODULE_NAME} MODULE ${SOURCES})
# cpr [cont]
# target_link_libraries(${MODULE_NAME} cpr)
target_link_libraries(${MODULE_NAME} ${CPR_ROOT}-build/lib/libcpr.a)
add_dependencies(${MODULE_NAME} cpr_sources)
# cURL
find_package (cURL REQUIRED)
target_link_libraries(${MODULE_NAME} ${cURL_LIBRARIES})
......
......@@ -23,19 +23,21 @@
/**
* \brief Initializes the web module
*/
Melanomodule melanomodule_web(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_web_metadata()
{
Melanomodule module{"web","Web services"};
module.register_log_type("web",color::dark_blue);
module.register_service<network::http::HttpService>("web");
return {"web","Web services"};
}
module.register_handler<web::SearchVideoYoutube>("SearchVideoYoutube");
module.register_handler<web::SearchImageGoogle>("SearchImageGoogle");
module.register_handler<web::UrbanDictionary>("UrbanDictionary");
module.register_handler<web::SearchWebSearx>("SearchWebSearx");
module.register_handler<web::VideoInfo>("VideoInfo");
module.register_handler<web::MediaWiki>("MediaWiki");
module.register_handler<web::MediaWikiTitles>("MediaWikiTitles");
MELANOMODULE_ENTRY_POINT void melanomodule_web_initialize(const Settings&)
{
module::register_log_type("web",color::dark_blue);
module::register_service<network::http::HttpService>("web");
return module;
module::register_handler<web::SearchVideoYoutube>("SearchVideoYoutube");
module::register_handler<web::SearchImageGoogle>("SearchImageGoogle");
module::register_handler<web::UrbanDictionary>("UrbanDictionary");
module::register_handler<web::SearchWebSearx>("SearchWebSearx");
module::register_handler<web::VideoInfo>("VideoInfo");
module::register_handler<web::MediaWiki>("MediaWiki");
module::register_handler<web::MediaWikiTitles>("MediaWikiTitles");
}
......@@ -16,8 +16,10 @@ melanomodule(xonotic "Xonotic integration" ON)
file(GLOB_RECURSE SOURCES *.cpp)
add_library(${MODULE_NAME} ${SOURCES})
add_library(${MODULE_NAME} MODULE ${SOURCES})
find_package(OpenSSL REQUIRED)
target_link_libraries(${MODULE_NAME} ${OPENSSL_CRYPTO_LIBRARY})
include_directories (${OpenSSL_INCLUDE_DIRS})
target_link_libraries(${MODULE_NAME} melanomodule_core)
......@@ -27,38 +27,40 @@
/**
* \brief Initializes the Xonotic module
*/
Melanomodule melanomodule_xonotic(const Settings&)
MELANOMODULE_ENTRY_POINT module::Melanomodule melanomodule_xonotic_metadata()
{
Melanomodule module{"xonotic","Xonotic integration"};
module.register_formatter<xonotic::Formatter>();
module.register_log_type("xon",color::dark_cyan);
module.register_connection<xonotic::XonoticConnection>("xonotic");
return {"xonotic","Xonotic integration"};
}
MELANOMODULE_ENTRY_POINT void melanomodule_xonotic_initialize(const Settings&)
{
module::register_formatter<xonotic::Formatter>();
module::register_log_type("xon",color::dark_cyan);
module::register_connection<xonotic::XonoticConnection>("xonotic");
module.register_handler<xonotic::RconCommand>("RconCommand");
module.register_handler<xonotic::XonoticVCall>("XonoticVCall");
module.register_handler<xonotic::XonoticVStop>("XonoticVStop");
module::register_handler<xonotic::RconCommand>("RconCommand");
module::register_handler<xonotic::XonoticVCall>("XonoticVCall");
module::register_handler<xonotic::XonoticVStop>("XonoticVStop");
module.register_handler<xonotic::ConnectionEvents>("ConnectionEvents");
module.register_handler<xonotic::XonoticJoinPart>("XonoticJoinPart");
module::register_handler<xonotic::ConnectionEvents>("ConnectionEvents");
module::register_handler<xonotic::XonoticJoinPart>("XonoticJoinPart");
module.register_handler<xonotic::XonoticMatchStart>("XonoticMatchStart");
module.register_handler<xonotic::ShowVoteCall>("ShowVoteCall");
module.register_handler<xonotic::ShowVoteLogin>("ShowVoteLogin");
module.register_handler<xonotic::ShowVoteDo>("ShowVoteDo");
module.register_handler<xonotic::ShowVoteResult>("ShowVoteResult");
module.register_handler<xonotic::ShowVoteStop>("ShowVoteStop");
module.register_handler<xonotic::ShowVotes>("ShowVotes");
module.register_handler<xonotic::XonoticMatchScore>("XonoticMatchScore");
module.register_handler<xonotic::XonoticHostError>("XonoticHostError");
module.register_handler<xonotic::XonoticUpdateBans>("XonoticUpdateBans");
module::register_handler<xonotic::XonoticMatchStart>("XonoticMatchStart");
module::register_handler<xonotic::ShowVoteCall>("ShowVoteCall");
module::register_handler<xonotic::ShowVoteLogin>("ShowVoteLogin");
module::register_handler<xonotic::ShowVoteDo>("ShowVoteDo");
module::register_handler<xonotic::ShowVoteResult>("ShowVoteResult");
module::register_handler<xonotic::ShowVoteStop>("ShowVoteStop");
module::register_handler<xonotic::ShowVotes>("ShowVotes");
module::register_handler<xonotic::XonoticMatchScore>("XonoticMatchScore");
module::register_handler<xonotic::XonoticHostError>("XonoticHostError");
module::register_handler<xonotic::XonoticUpdateBans>("XonoticUpdateBans");
module.register_handler<xonotic::ListPlayers>("ListPlayers");
module.register_handler<xonotic::XonoticStatus>("XonoticStatus");
module.register_handler<xonotic::XonoticMaps>("XonoticMaps");
module.register_handler<xonotic::XonoticBan>("XonoticBan");
module.register_handler<xonotic::XonoticKick>("XonoticKick");
return module;
module::register_handler<xonotic::ListPlayers>("ListPlayers");
module::register_handler<xonotic::XonoticStatus>("XonoticStatus");
module::register_handler<xonotic::XonoticMaps>("XonoticMaps");
module::register_handler<xonotic::XonoticBan>("XonoticBan");
module::register_handler<xonotic::XonoticKick>("XonoticKick");
}
namespace xonotic {
......
......@@ -31,7 +31,3 @@ if(Iconv_FOUND)
endif()
target_link_libraries(${EXECUTABLE_NAME} ${CMAKE_DL_LIBS})
if (MELANOMODULES)
target_link_libraries(${EXECUTABLE_NAME} ${MELANOMODULES})
endif()
......@@ -37,21 +37,45 @@ public:
{
error_string = dlerror();
}
void close()
{
dlclose(handle);
}
void open(LoadFlags flags)
{
bool throws = flags & LoadThrows;
flags &= ~LoadThrows;
handle = dlopen(filename.c_str(), flags);
if ( !handle )
{
gather_error();
if ( throws )
throw LibraryError(filename, error_string);
}
}
void* resolve(const std::string& symbol)
{
auto ret = dlsym(handle, symbol.c_str());
if ( !ret )
gather_error();
return ret;
}
};
Library::Library(const std::string& library_file, LoadFlags flags)
: p(std::make_shared<Private>())
{
p->filename = library_file;
p->handle = dlopen(library_file.c_str(), flags);
if ( !p->handle )
p->gather_error();
p->open(flags);
}
Library::~Library()
{
if ( p.unique() && p->handle )
dlclose(p->handle);
if ( p.unique() )
p->close();
}
bool Library::error() const
......@@ -71,10 +95,14 @@ std::string Library::filename() const
void* Library::resolve_raw(const std::string& name) const
{
auto ret = dlsym(p->handle, name.c_str());
if ( !ret )
p->gather_error();
return ret;
return p->resolve(name);
}
void Library::reload(library::LoadFlags flags) const
{
p->close();
p->open(flags);
}
} // namespace library
......@@ -39,12 +39,21 @@ enum LoadFlagsEnum
ExportLocal = 0x0000, ///< Don't make symbols in the library available to other libraries
DeepBind = 0x0008, ///< Prefer library symbol definitions over clashing global symbols
NoUnload = 0x1000, ///< Don't unload the library when it's closed
LoadThrows = 0x0010, ///< Loading a library throws an exception on error
};
struct SymbolNotFoundError : public std::runtime_error
struct LibraryError : public std::runtime_error
{
LibraryError(const std::string& message, std::string library_file)
: runtime_error(message), library_file(std::move(library_file)) {}
std::string library_file;
};
struct SymbolNotFoundError : LibraryError
{
SymbolNotFoundError(const std::string& symbol, const std::string& library)
: runtime_error(library + ": " + "could not resolve \"" + symbol + '\"')
: LibraryError("could not resolve \"" + symbol + '\"', library)
{}
};
......@@ -54,18 +63,23 @@ struct SymbolNotFoundError : public std::runtime_error
class Library
{
public:
static constexpr LoadFlags default_load_flags = LoadLazy|ExportLocal|DeepBind;
/**
* \brief Loads the given library
*/
explicit Library(const std::string& library_file, library::LoadFlags flags = default_load_flags);
explicit Library(const std::string& library_file, library::LoadFlags flags);
/**
* \brief Closes the library
*/
~Library();
/**
* \brief Closes and -re opens the library
*/
void reload(library::LoadFlags flags) const;
/**
* \brief Name of the file this library has been loaded from
*/
......
/**
* \file
*
* \author Mattia Basaglia
*
* \copyright Copyright (C) 2015 Mattia Basaglia
*